From 9a6c8ed93a5c39eb6fee5f996b4d5d9ff8445883 Mon Sep 17 00:00:00 2001 From: Matthias Andreas Benkard Date: Tue, 28 Dec 2021 01:00:22 +0100 Subject: Add Decoder#ofDictionary. Change-Id: I53873f743ce84d9bf50da4cb5238a6f4d82de986 --- .../main/java/eu/mulk/jgvariant/core/Decoder.java | 40 ++++++++++++++++++++++ .../java/eu/mulk/jgvariant/core/DecoderTest.java | 34 ++++++++++++++++++ 2 files changed, 74 insertions(+) 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; @@ -109,6 +111,18 @@ public abstract class Decoder { return new ArrayDecoder<>(elementDecoder); } + /** + * 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 Decoder> ofDictionary( + Decoder keyDecoder, Decoder 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 { } } + private static class DictionaryDecoder extends Decoder> { + + private final ArrayDecoder> entryArrayDecoder; + + DictionaryDecoder(Decoder keyDecoder, Decoder 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 decode(ByteBuffer byteSlice) { + List> entries = entryArrayDecoder.decode(byteSlice); + return entries.stream().collect(toMap(Entry::getKey, Entry::getValue)); + } + } + private static class ByteArrayDecoder extends Decoder { 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 @@ -98,6 +98,40 @@ class DecoderTest { decoder.decode(ByteBuffer.wrap(data))); } + @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 = -- cgit v1.2.3