blob: d8fa6a522ea1fd6811e8aa0d4436c91b1a862bc9 [file] [log] [blame]
Matthias Andreas Benkardb5d657a2022-02-03 21:14:30 +01001// SPDX-FileCopyrightText: © 2021 Matthias Andreas Benkard <code@mail.matthias.benkard.de>
2//
3// SPDX-License-Identifier: LGPL-3.0-or-later
4
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +01005package eu.mulk.jgvariant.core;
6
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +01007import static java.nio.ByteOrder.BIG_ENDIAN;
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +01008import static java.nio.ByteOrder.LITTLE_ENDIAN;
9import static java.nio.charset.StandardCharsets.UTF_8;
Matthias Andreas Benkard55c34812021-12-14 21:51:10 +010010import static org.junit.jupiter.api.Assertions.assertAll;
11import static org.junit.jupiter.api.Assertions.assertArrayEquals;
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010012import static org.junit.jupiter.api.Assertions.assertEquals;
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +010013import static org.junit.jupiter.api.Assertions.assertThrows;
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010014
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010015import java.nio.ByteBuffer;
Matthias Andreas Benkard31c61e72021-12-16 20:06:39 +010016import java.text.ParseException;
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +010017import java.util.*;
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010018import org.junit.jupiter.api.Test;
19
20/**
21 * Tests based on the examples given in <a
22 * href="https://people.gnome.org/~desrt/gvariant-serialisation.pdf">~desrt/gvariant-serialisation.pdf</a>.
23 */
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +020024@SuppressWarnings({
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +010025 "ByteBufferBackingArray",
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +020026 "ImmutableListOf",
27 "ImmutableListOf1",
28 "ImmutableListOf2",
29 "ImmutableListOf3",
30 "ImmutableListOf4",
31 "ImmutableListOf5",
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +010032 "ImmutableMapOf2",
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +020033})
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010034class DecoderTest {
35
36 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +020037 void string() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010038 var data = new byte[] {0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x00};
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +010039 var decoder = Decoder.ofString(UTF_8);
40 assertEquals("hello world", decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +010041
42 var roundtripData = decoder.encode("hello world");
43 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010044 }
45
46 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +020047 void maybe() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010048 var data =
49 new byte[] {0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x00, 0x00};
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +010050 var decoder = Decoder.ofMaybe(Decoder.ofString(UTF_8));
51 assertEquals(Optional.of("hello world"), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +010052
53 var roundtripData = decoder.encode(Optional.of("hello world"));
54 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010055 }
56
57 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +020058 void booleanArray() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010059 var data = new byte[] {0x01, 0x00, 0x00, 0x01, 0x01};
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +010060 var decoder = Decoder.ofArray(Decoder.ofBoolean());
61 assertEquals(List.of(true, false, false, true, true), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +010062
63 var roundtripData = decoder.encode(List.of(true, false, false, true, true));
64 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010065 }
66
67 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +020068 void structure() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010069 var data =
70 new byte[] {
71 0x66, 0x6F, 0x6F, 0x00, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, 0x04
72 };
73
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +010074 record TestRecord(String s, int i) {}
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010075
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +010076 var decoder = Decoder.ofStructure(TestRecord.class, Decoder.ofString(UTF_8), Decoder.ofInt());
77 assertEquals(new TestRecord("foo", -1), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +010078
79 var roundtripData = decoder.encode(new TestRecord("foo", -1));
80 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010081 }
82
83 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +020084 void complexStructureArray() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010085 var data =
86 new byte[] {
87 0x68,
88 0x69,
89 0x00,
90 0x00,
91 (byte) 0xfe,
92 (byte) 0xff,
93 (byte) 0xff,
94 (byte) 0xff,
95 0x03,
96 0x00,
97 0x00,
98 0x00,
99 0x62,
100 0x79,
101 0x65,
102 0x00,
103 (byte) 0xff,
104 (byte) 0xff,
105 (byte) 0xff,
106 (byte) 0xff,
107 0x04,
108 0x09,
109 0x15
110 };
111
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100112 record TestRecord(String s, int i) {}
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100113
114 var decoder =
115 Decoder.ofArray(
116 Decoder.ofStructure(
117 TestRecord.class,
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100118 Decoder.ofString(UTF_8),
119 Decoder.ofInt().withByteOrder(LITTLE_ENDIAN)));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100120 assertEquals(
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100121 List.of(new TestRecord("hi", -2), new TestRecord("bye", -1)),
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100122 decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100123
124 var roundtripData =
125 decoder.encode(List.of(new TestRecord("hi", -2), new TestRecord("bye", -1)));
126 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100127 }
128
129 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200130 void dictionary() {
Matthias Andreas Benkard9a6c8ed2021-12-28 01:00:22 +0100131 var data =
132 new byte[] {
133 0x68,
134 0x69,
135 0x00,
136 0x00,
137 (byte) 0xfe,
138 (byte) 0xff,
139 (byte) 0xff,
140 (byte) 0xff,
141 0x03,
142 0x00,
143 0x00,
144 0x00,
145 0x62,
146 0x79,
147 0x65,
148 0x00,
149 (byte) 0xff,
150 (byte) 0xff,
151 (byte) 0xff,
152 (byte) 0xff,
153 0x04,
154 0x09,
155 0x15
156 };
157
158 var decoder =
159 Decoder.ofDictionary(Decoder.ofString(UTF_8), Decoder.ofInt().withByteOrder(LITTLE_ENDIAN));
160 assertEquals(Map.of("hi", -2, "bye", -1), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100161
162 var entity = new LinkedHashMap<String, Integer>();
163 entity.put("hi", -2);
164 entity.put("bye", -1);
165 var roundtripData = decoder.encode(entity);
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100166 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkard9a6c8ed2021-12-28 01:00:22 +0100167 }
168
169 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200170 void stringArray() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100171 var data =
172 new byte[] {
173 0x69, 0x00, 0x63, 0x61, 0x6E, 0x00, 0x68, 0x61, 0x73, 0x00, 0x73, 0x74, 0x72, 0x69, 0x6E,
174 0x67, 0x73, 0x3F, 0x00, 0x02, 0x06, 0x0a, 0x13
175 };
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100176 var decoder = Decoder.ofArray(Decoder.ofString(UTF_8));
177 assertEquals(List.of("i", "can", "has", "strings?"), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100178
179 var roundtripData = decoder.encode(List.of("i", "can", "has", "strings?"));
180 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100181 }
182
183 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200184 void nestedStructure() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100185 var data =
186 new byte[] {
187 0x69, 0x63, 0x61, 0x6E, 0x00, 0x68, 0x61, 0x73, 0x00, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
188 0x73, 0x3F, 0x00, 0x04, 0x0d, 0x05
189 };
190
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100191 record TestChild(byte b, String s) {}
192 record TestParent(TestChild tc, List<String> as) {}
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100193
194 var decoder =
195 Decoder.ofStructure(
196 TestParent.class,
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100197 Decoder.ofStructure(TestChild.class, Decoder.ofByte(), Decoder.ofString(UTF_8)),
198 Decoder.ofArray(Decoder.ofString(UTF_8)));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100199
200 assertEquals(
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100201 new TestParent(new TestChild((byte) 0x69, "can"), List.of("has", "strings?")),
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100202 decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100203
204 var roundtripData =
205 decoder.encode(
206 new TestParent(new TestChild((byte) 0x69, "can"), List.of("has", "strings?")));
207 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100208 }
209
210 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200211 void nestedStructureVariant() {
Matthias Andreas Benkard55c34812021-12-14 21:51:10 +0100212 var data =
213 new byte[] {
214 0x69, 0x63, 0x61, 0x6E, 0x00, 0x68, 0x61, 0x73, 0x00, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
215 0x73, 0x3F, 0x00, 0x04, 0x0d, 0x05, 0x00, 0x28, 0x28, 0x79, 0x73, 0x29, 0x61, 0x73, 0x29
216 };
217
218 var decoder = Decoder.ofVariant();
Matthias Andreas Benkard31c61e72021-12-16 20:06:39 +0100219 var variant = decoder.decode(ByteBuffer.wrap(data));
220 var result = (Object[]) variant.value();
Matthias Andreas Benkard55c34812021-12-14 21:51:10 +0100221
222 assertAll(
Matthias Andreas Benkard31c61e72021-12-16 20:06:39 +0100223 () -> assertEquals(Signature.parse("((ys)as)"), variant.signature()),
Matthias Andreas Benkard55c34812021-12-14 21:51:10 +0100224 () -> assertEquals(2, result.length),
225 () -> assertArrayEquals(new Object[] {(byte) 0x69, "can"}, (Object[]) result[0]),
226 () -> assertEquals(List.of("has", "strings?"), result[1]));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100227
228 var roundtripData = decoder.encode(variant);
229 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkard55c34812021-12-14 21:51:10 +0100230 }
231
232 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200233 void simpleStructure() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100234 var data = new byte[] {0x60, 0x70};
235
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100236 record TestRecord(byte b1, byte b2) {}
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100237
238 var decoder =
239 Decoder.ofStructure(
240 TestRecord.class,
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100241 Decoder.ofByte().withByteOrder(LITTLE_ENDIAN),
242 Decoder.ofByte().withByteOrder(LITTLE_ENDIAN));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100243
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100244 assertEquals(new TestRecord((byte) 0x60, (byte) 0x70), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100245
246 var roundtripData = decoder.encode(new TestRecord((byte) 0x60, (byte) 0x70));
247 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100248 }
249
250 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200251 void paddedStructureRight() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100252 var data = new byte[] {0x60, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00};
253
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100254 record TestRecord(int b1, byte b2) {}
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100255
256 var decoder =
257 Decoder.ofStructure(
258 TestRecord.class,
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100259 Decoder.ofInt().withByteOrder(LITTLE_ENDIAN),
260 Decoder.ofByte().withByteOrder(LITTLE_ENDIAN));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100261
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100262 assertEquals(new TestRecord(0x60, (byte) 0x70), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100263
264 var roundtripData = decoder.encode(new TestRecord(0x60, (byte) 0x70));
265 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100266 }
267
268 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200269 void paddedStructureLeft() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100270 var data = new byte[] {0x60, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00};
271
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100272 record TestRecord(byte b1, int b2) {}
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100273
274 var decoder =
275 Decoder.ofStructure(
276 TestRecord.class,
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100277 Decoder.ofByte().withByteOrder(LITTLE_ENDIAN),
278 Decoder.ofInt().withByteOrder(LITTLE_ENDIAN));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100279
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100280 assertEquals(new TestRecord((byte) 0x60, 0x70), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100281
282 var roundtripData = decoder.encode(new TestRecord((byte) 0x60, 0x70));
283 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100284 }
285
286 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200287 void simpleStructureArray() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100288 var data =
289 new byte[] {
290 0x60,
291 0x00,
292 0x00,
293 0x00,
294 0x70,
295 0x00,
296 0x00,
297 0x00,
298 (byte) 0x88,
299 0x02,
300 0x00,
301 0x00,
302 (byte) 0xF7,
303 0x00,
304 0x00,
305 0x00
306 };
307
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100308 record TestRecord(int b1, byte b2) {}
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100309
310 var decoder =
311 Decoder.ofArray(
312 Decoder.ofStructure(
313 TestRecord.class,
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100314 Decoder.ofInt().withByteOrder(LITTLE_ENDIAN),
315 Decoder.ofByte().withByteOrder(LITTLE_ENDIAN)));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100316
317 assertEquals(
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100318 List.of(new TestRecord(96, (byte) 0x70), new TestRecord(648, (byte) 0xf7)),
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100319 decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100320
321 var roundtripData =
322 decoder.encode(List.of(new TestRecord(96, (byte) 0x70), new TestRecord(648, (byte) 0xf7)));
323 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100324 }
325
326 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200327 void byteArray() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100328 var data = new byte[] {0x04, 0x05, 0x06, 0x07};
329
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100330 var decoder = Decoder.ofArray(Decoder.ofByte());
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100331
332 assertEquals(
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100333 List.of((byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07),
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100334 decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100335
336 var roundtripData = decoder.encode(List.of((byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07));
337 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100338 }
339
340 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200341 void primitiveByteArray() {
Matthias Andreas Benkard4e8423d2021-12-19 22:56:09 +0100342 var data = new byte[] {0x04, 0x05, 0x06, 0x07};
343
344 var decoder = Decoder.ofByteArray();
345
346 assertArrayEquals(data, decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100347
348 var roundtripData = decoder.encode(data);
349 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkard4e8423d2021-12-19 22:56:09 +0100350 }
351
352 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200353 void primitiveByteArrayRecord() {
Matthias Andreas Benkard4e8423d2021-12-19 22:56:09 +0100354 var data = new byte[] {0x04, 0x05, 0x06, 0x07};
355
356 record TestRecord(byte[] bytes) {}
357
358 var decoder = Decoder.ofStructure(TestRecord.class, Decoder.ofByteArray());
359
360 assertArrayEquals(data, decoder.decode(ByteBuffer.wrap(data)).bytes());
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100361
362 var roundtripData = decoder.encode(new TestRecord(data));
363 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkard4e8423d2021-12-19 22:56:09 +0100364 }
365
366 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200367 void integerArray() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100368 var data = new byte[] {0x04, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00};
369
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100370 var decoder = Decoder.ofArray(Decoder.ofInt().withByteOrder(LITTLE_ENDIAN));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100371
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100372 assertEquals(List.of(4, 258), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100373
374 var roundtripData = decoder.encode(List.of(4, 258));
375 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100376 }
377
378 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200379 void dictionaryEntryAsMapEntry() {
Matthias Andreas Benkardcd924f62021-12-28 00:46:06 +0100380 var data =
381 new byte[] {0x61, 0x20, 0x6B, 0x65, 0x79, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x06};
382
383 var decoder =
384 Decoder.ofDictionaryEntry(
385 Decoder.ofString(UTF_8), Decoder.ofInt().withByteOrder(LITTLE_ENDIAN));
386 assertEquals(Map.entry("a key", 514), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100387
388 var roundtripData = decoder.encode(Map.entry("a key", 514));
389 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkardcd924f62021-12-28 00:46:06 +0100390 }
391
392 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200393 void dictionaryEntryAsRecord() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100394 var data =
395 new byte[] {0x61, 0x20, 0x6B, 0x65, 0x79, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x06};
396
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100397 record TestEntry(String key, int value) {}
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100398
399 var decoder =
400 Decoder.ofStructure(
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100401 TestEntry.class, Decoder.ofString(UTF_8), Decoder.ofInt().withByteOrder(LITTLE_ENDIAN));
402 assertEquals(new TestEntry("a key", 514), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100403
404 var roundtripData = decoder.encode(new TestEntry("a key", 514));
405 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100406 }
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100407
408 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200409 void paddedPrimitives() {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100410 var data =
411 new byte[] {
412 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
413 0x00, 0x40, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
414 };
415
416 record TestRecord(short s, long l, double d) {}
417
418 var decoder =
419 Decoder.ofStructure(
420 TestRecord.class,
421 Decoder.ofShort().withByteOrder(BIG_ENDIAN),
422 Decoder.ofLong().withByteOrder(LITTLE_ENDIAN),
423 Decoder.ofDouble());
424 assertEquals(new TestRecord((short) 1, 2, 3.25), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100425
426 var roundtripData = decoder.encode(new TestRecord((short) 1, 2, 3.25));
427
428 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100429 }
430
431 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200432 void embeddedMaybe() {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100433 var data = new byte[] {0x01, 0x01};
434
435 record TestRecord(Optional<Byte> set, Optional<Byte> unset) {}
436
437 var decoder =
438 Decoder.ofStructure(
439 TestRecord.class, Decoder.ofMaybe(Decoder.ofByte()), Decoder.ofMaybe(Decoder.ofByte()));
440 assertEquals(
441 new TestRecord(Optional.of((byte) 1), Optional.empty()),
442 decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100443
444 var roundtripData = decoder.encode(new TestRecord(Optional.of((byte) 1), Optional.empty()));
445 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100446 }
447
448 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200449 void recordComponentMismatch() {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100450 record TestRecord(Optional<Byte> set) {}
451
452 var maybeDecoder = Decoder.ofMaybe(Decoder.ofByte());
453 assertThrows(
454 IllegalArgumentException.class,
455 () -> Decoder.ofStructure(TestRecord.class, maybeDecoder, maybeDecoder));
456 }
457
458 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200459 void trivialRecord() {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100460 var data = new byte[] {0x00};
461
462 record TestRecord() {}
463
464 var decoder = Decoder.ofStructure(TestRecord.class);
465 assertEquals(new TestRecord(), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100466
467 var roundtripData = decoder.encode(new TestRecord());
468 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100469 }
470
471 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200472 void twoElementTrivialRecordArray() {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100473 var data = new byte[] {0x00, 0x00};
474
475 record TestRecord() {}
476
477 var decoder = Decoder.ofArray(Decoder.ofStructure(TestRecord.class));
478 assertEquals(
479 List.of(new TestRecord(), new TestRecord()), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100480
481 var roundtripData = decoder.encode(List.of(new TestRecord(), new TestRecord()));
482 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100483 }
484
485 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200486 void singletonTrivialRecordArray() {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100487 var data = new byte[] {0x00};
488
489 record TestRecord() {}
490
491 var decoder = Decoder.ofArray(Decoder.ofStructure(TestRecord.class));
492 assertEquals(List.of(new TestRecord()), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100493
494 var roundtripData = decoder.encode(List.of(new TestRecord()));
495 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100496 }
497
498 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200499 void emptyTrivialRecordArray() {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100500 var data = new byte[] {};
501
502 record TestRecord() {}
503
504 var decoder = Decoder.ofArray(Decoder.ofStructure(TestRecord.class));
505 assertEquals(List.of(), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100506
507 var roundtripData = decoder.encode(List.of());
508 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100509 }
510
511 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200512 void variantArray() {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100513 var data = new byte[] {};
514
515 record TestRecord() {}
516
517 var decoder = Decoder.ofArray(Decoder.ofStructure(TestRecord.class));
518 assertEquals(List.of(), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100519
520 var roundtripData = decoder.encode(List.of());
521 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100522 }
523
524 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200525 void invalidVariantSignature() {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100526 var data = new byte[] {0x00, 0x00, 0x2E};
527
528 var decoder = Decoder.ofVariant();
529 assertThrows(IllegalArgumentException.class, () -> decoder.decode(ByteBuffer.wrap(data)));
530 }
531
532 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200533 void missingVariantSignature() {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100534 var data = new byte[] {0x01};
535
536 var decoder = Decoder.ofVariant();
537 assertThrows(IllegalArgumentException.class, () -> decoder.decode(ByteBuffer.wrap(data)));
538 }
539
540 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200541 void simpleVariantRecord() throws ParseException {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100542 // signature: "(bynqiuxtdsogvmiai)"
543 var data =
544 new byte[] {
545 0x01, // b
546 0x02, // y
547 0x00, 0x03, // n
548 0x00, 0x04, // q
549 0x00, 0x00, // (padding)
550 0x00, 0x00, 0x00, 0x05, // i
551 0x00, 0x00, 0x00, 0x06, // u
552 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, // x
553 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, // t
554 0x40, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // d
555 0x68, 0x69, 0x00, // s
556 0x68, 0x69, 0x00, // o
557 0x68, 0x69, 0x00, // g
558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (padding)
559 0x00, 0x00, 0x00, 0x09, 0x00, 0x69, // v
560 0x00, 0x00, // (padding)
561 0x00, 0x00, 0x00, 0x0a, // mi
562 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, // ai
563 68, 62, 49, 46, 43, // framing offsets
564 0x00, 0x28, 0x62, 0x79, 0x6E, 0x71, 0x69, 0x75, 0x78, 0x74, 0x64, 0x73, 0x6F, 0x67, 0x76,
565 0x6D, 0x69, 0x61, 0x69, 0x29
566 };
567
568 var decoder = Decoder.ofVariant();
569 assertArrayEquals(
570 new Object[] {
571 true,
572 (byte) 2,
573 (short) 3,
574 (short) 4,
575 (int) 5,
576 (int) 6,
577 (long) 7,
578 (long) 8,
579 (double) 3.25,
580 "hi",
581 "hi",
582 "hi",
Matthias Andreas Benkard31c61e72021-12-16 20:06:39 +0100583 new Variant(Signature.parse("i"), 9),
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100584 Optional.of(10),
585 List.of(11, 12)
586 },
Matthias Andreas Benkard31c61e72021-12-16 20:06:39 +0100587 (Object[]) decoder.decode(ByteBuffer.wrap(data)).value());
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100588
589 var roundtripData = decoder.encode(decoder.decode(ByteBuffer.wrap(data)));
590 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkard31c61e72021-12-16 20:06:39 +0100591 }
592
593 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200594 void signatureString() throws ParseException {
Matthias Andreas Benkard31c61e72021-12-16 20:06:39 +0100595 var data =
596 new byte[] {
597 0x28, 0x62, 0x79, 0x6E, 0x71, 0x69, 0x75, 0x78, 0x74, 0x64, 0x73, 0x6F, 0x67, 0x76, 0x6D,
598 0x69, 0x61, 0x69, 0x29
599 };
600
601 var signature = Signature.parse(ByteBuffer.wrap(data));
602 assertEquals("(bynqiuxtdsogvmiai)", signature.toString());
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100603 }
Matthias Andreas Benkard4e8423d2021-12-19 22:56:09 +0100604
605 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200606 void map() {
Matthias Andreas Benkard4e8423d2021-12-19 22:56:09 +0100607 var data = new byte[] {0x0A, 0x0B, 0x0C};
Matthias Andreas Benkardaa11d822023-12-10 09:20:48 +0100608 var decoder =
609 Decoder.ofByteArray()
610 .map(
611 bytes -> bytes.length,
612 len -> {
613 throw new UnsupportedOperationException();
614 });
Matthias Andreas Benkard4e8423d2021-12-19 22:56:09 +0100615 assertEquals(3, decoder.decode(ByteBuffer.wrap(data)));
616 }
Matthias Andreas Benkard44df94e2021-12-30 18:43:33 +0100617
618 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200619 void contramap() {
Matthias Andreas Benkard44df94e2021-12-30 18:43:33 +0100620 var data = new byte[] {0x0A, 0x0B, 0x0C};
Matthias Andreas Benkardaa11d822023-12-10 09:20:48 +0100621 var decoder =
622 Decoder.ofByteArray()
623 .contramap(
624 bytes -> bytes.slice(1, 1),
625 bytes -> {
626 throw new UnsupportedOperationException();
627 });
Matthias Andreas Benkard44df94e2021-12-30 18:43:33 +0100628 assertArrayEquals(new byte[] {0x0B}, decoder.decode(ByteBuffer.wrap(data)));
629 }
630
631 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200632 void predicateTrue() {
Matthias Andreas Benkard44df94e2021-12-30 18:43:33 +0100633 var data = new byte[] {0x00, 0x01, 0x00};
Matthias Andreas Benkardaa11d822023-12-10 09:20:48 +0100634 var innerDecoder =
635 Decoder.ofShort()
636 .contramap(
637 bytes -> bytes.slice(1, 2).order(bytes.order()),
638 bytes -> {
639 throw new UnsupportedOperationException();
640 });
Matthias Andreas Benkard44df94e2021-12-30 18:43:33 +0100641 var decoder =
642 Decoder.ofPredicate(
643 byteBuffer -> byteBuffer.get(0) == 0,
644 innerDecoder.withByteOrder(LITTLE_ENDIAN),
645 innerDecoder.withByteOrder(BIG_ENDIAN));
646 assertEquals((short) 1, decoder.decode(ByteBuffer.wrap(data)));
647 }
648
649 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200650 void predicateFalse() {
Matthias Andreas Benkard44df94e2021-12-30 18:43:33 +0100651 var data = new byte[] {0x01, 0x01, 0x00};
Matthias Andreas Benkardaa11d822023-12-10 09:20:48 +0100652 var innerDecoder =
653 Decoder.ofShort()
654 .contramap(
655 bytes -> bytes.slice(1, 2).order(bytes.order()),
656 bytes -> {
657 throw new UnsupportedOperationException();
658 });
Matthias Andreas Benkard44df94e2021-12-30 18:43:33 +0100659 var decoder =
660 Decoder.ofPredicate(
661 byteBuffer -> byteBuffer.get(0) == 0,
662 innerDecoder.withByteOrder(LITTLE_ENDIAN),
663 innerDecoder.withByteOrder(BIG_ENDIAN));
664 assertEquals((short) 256, decoder.decode(ByteBuffer.wrap(data)));
665 }
666
667 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200668 void byteOrder() {
Matthias Andreas Benkard44df94e2021-12-30 18:43:33 +0100669 var data =
670 new byte[] {
671 0x01, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x04, 0x05, 0x00, 0x00, 0x06, 0x00, 0x07, 0x08,
672 0x00
673 };
674
675 record TestChild(short s1, short s2) {}
676 record TestParent(TestChild tc1, TestChild tc2, TestChild tc3, TestChild tc4) {}
677
678 var decoder =
679 Decoder.ofStructure(
680 TestParent.class,
681 Decoder.ofStructure(TestChild.class, Decoder.ofShort(), Decoder.ofShort())
682 .withByteOrder(LITTLE_ENDIAN),
683 Decoder.ofStructure(TestChild.class, Decoder.ofShort(), Decoder.ofShort())
684 .withByteOrder(BIG_ENDIAN),
685 Decoder.ofStructure(
686 TestChild.class,
687 Decoder.ofShort().withByteOrder(LITTLE_ENDIAN),
688 Decoder.ofShort())
689 .withByteOrder(BIG_ENDIAN),
690 Decoder.ofStructure(
691 TestChild.class, Decoder.ofShort().withByteOrder(BIG_ENDIAN), Decoder.ofShort())
692 .withByteOrder(LITTLE_ENDIAN));
693
694 assertEquals(
695 new TestParent(
696 new TestChild((short) 1, (short) 2),
697 new TestChild((short) 3, (short) 4),
698 new TestChild((short) 5, (short) 6),
699 new TestChild((short) 7, (short) 8)),
700 decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkarde9440b52023-12-10 15:28:16 +0100701
702 var roundtripData =
703 decoder.encode(
704 new TestParent(
705 new TestChild((short) 1, (short) 2),
706 new TestChild((short) 3, (short) 4),
707 new TestChild((short) 5, (short) 6),
708 new TestChild((short) 7, (short) 8)));
709 assertArrayEquals(data, roundtripData.array());
Matthias Andreas Benkard44df94e2021-12-30 18:43:33 +0100710 }
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100711}