diff options
-rw-r--r-- | jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Decoder.java | 40 | ||||
-rw-r--r-- | jgvariant-core/src/test/java/eu/mulk/jgvariant/core/DecoderTest.java | 34 |
2 files changed, 74 insertions, 0 deletions
diff --git a/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Decoder.java b/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Decoder.java index 96e1332..8297d79 100644 --- a/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Decoder.java +++ b/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Decoder.java @@ -1,6 +1,7 @@ package eu.mulk.jgvariant.core; import static java.nio.ByteOrder.LITTLE_ENDIAN; +import static java.util.stream.Collectors.toMap; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.RecordComponent; @@ -13,6 +14,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Optional; import java.util.function.Function; import org.apiguardian.api.API; @@ -110,6 +112,18 @@ public abstract class Decoder<T> { } /** + * Creates a {@link Decoder} for a {@code Dictionary} type. + * + * @param keyDecoder a {@link Decoder} for the key component of the dictionary entry. + * @param valueDecoder a {@link Decoder} for the value component of the dictionary entry. + * @return a new {@link Decoder}. + */ + public static <K, V> Decoder<Map<K, V>> ofDictionary( + Decoder<K> keyDecoder, Decoder<V> valueDecoder) { + return new DictionaryDecoder<>(keyDecoder, valueDecoder); + } + + /** * Creates a {@link Decoder} for an {@code Array} type of element type {@code byte} into a * primitive {@code byte[]} array. * @@ -346,6 +360,32 @@ public abstract class Decoder<T> { } } + private static class DictionaryDecoder<K, V> extends Decoder<Map<K, V>> { + + private final ArrayDecoder<Map.Entry<K, V>> entryArrayDecoder; + + DictionaryDecoder(Decoder<K> keyDecoder, Decoder<V> valueDecoder) { + this.entryArrayDecoder = + new ArrayDecoder<>(new DictionaryEntryDecoder<>(keyDecoder, valueDecoder)); + } + + @Override + public byte alignment() { + return entryArrayDecoder.alignment(); + } + + @Override + public Integer fixedSize() { + return entryArrayDecoder.fixedSize(); + } + + @Override + public Map<K, V> decode(ByteBuffer byteSlice) { + List<Map.Entry<K, V>> entries = entryArrayDecoder.decode(byteSlice); + return entries.stream().collect(toMap(Entry::getKey, Entry::getValue)); + } + } + private static class ByteArrayDecoder extends Decoder<byte[]> { private static final int ELEMENT_SIZE = 1; diff --git a/jgvariant-core/src/test/java/eu/mulk/jgvariant/core/DecoderTest.java b/jgvariant-core/src/test/java/eu/mulk/jgvariant/core/DecoderTest.java index ab7de44..efbcafa 100644 --- a/jgvariant-core/src/test/java/eu/mulk/jgvariant/core/DecoderTest.java +++ b/jgvariant-core/src/test/java/eu/mulk/jgvariant/core/DecoderTest.java @@ -99,6 +99,40 @@ class DecoderTest { } @Test + void testDictionary() { + var data = + new byte[] { + 0x68, + 0x69, + 0x00, + 0x00, + (byte) 0xfe, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + 0x03, + 0x00, + 0x00, + 0x00, + 0x62, + 0x79, + 0x65, + 0x00, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + 0x04, + 0x09, + 0x15 + }; + + var decoder = + Decoder.ofDictionary(Decoder.ofString(UTF_8), Decoder.ofInt().withByteOrder(LITTLE_ENDIAN)); + assertEquals(Map.of("hi", -2, "bye", -1), decoder.decode(ByteBuffer.wrap(data))); + } + + @Test void testStringArray() { var data = new byte[] { |