blob: 068b0519ddb848d3fe9e6934cc5ea715b7ff0cad [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 Benkard261532a2021-12-12 20:09:27 +010017import java.util.List;
Matthias Andreas Benkardcd924f62021-12-28 00:46:06 +010018import java.util.Map;
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010019import java.util.Optional;
20import org.junit.jupiter.api.Test;
21
22/**
23 * Tests based on the examples given in <a
24 * href="https://people.gnome.org/~desrt/gvariant-serialisation.pdf">~desrt/gvariant-serialisation.pdf</a>.
25 */
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +020026@SuppressWarnings({
27 "ImmutableListOf",
28 "ImmutableListOf1",
29 "ImmutableListOf2",
30 "ImmutableListOf3",
31 "ImmutableListOf4",
32 "ImmutableListOf5",
33 "ImmutableMapOf2"
34})
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010035class DecoderTest {
36
37 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +020038 void string() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010039 var data = new byte[] {0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x00};
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +010040 var decoder = Decoder.ofString(UTF_8);
41 assertEquals("hello world", decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010042 }
43
44 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +020045 void maybe() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010046 var data =
47 new byte[] {0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x00, 0x00};
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +010048 var decoder = Decoder.ofMaybe(Decoder.ofString(UTF_8));
49 assertEquals(Optional.of("hello world"), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010050 }
51
52 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +020053 void booleanArray() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010054 var data = new byte[] {0x01, 0x00, 0x00, 0x01, 0x01};
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +010055 var decoder = Decoder.ofArray(Decoder.ofBoolean());
56 assertEquals(List.of(true, false, false, true, true), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010057 }
58
59 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +020060 void structure() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010061 var data =
62 new byte[] {
63 0x66, 0x6F, 0x6F, 0x00, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, 0x04
64 };
65
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +010066 record TestRecord(String s, int i) {}
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010067
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +010068 var decoder = Decoder.ofStructure(TestRecord.class, Decoder.ofString(UTF_8), Decoder.ofInt());
69 assertEquals(new TestRecord("foo", -1), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010070 }
71
72 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +020073 void complexStructureArray() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +010074 var data =
75 new byte[] {
76 0x68,
77 0x69,
78 0x00,
79 0x00,
80 (byte) 0xfe,
81 (byte) 0xff,
82 (byte) 0xff,
83 (byte) 0xff,
84 0x03,
85 0x00,
86 0x00,
87 0x00,
88 0x62,
89 0x79,
90 0x65,
91 0x00,
92 (byte) 0xff,
93 (byte) 0xff,
94 (byte) 0xff,
95 (byte) 0xff,
96 0x04,
97 0x09,
98 0x15
99 };
100
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100101 record TestRecord(String s, int i) {}
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100102
103 var decoder =
104 Decoder.ofArray(
105 Decoder.ofStructure(
106 TestRecord.class,
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100107 Decoder.ofString(UTF_8),
108 Decoder.ofInt().withByteOrder(LITTLE_ENDIAN)));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100109 assertEquals(
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100110 List.of(new TestRecord("hi", -2), new TestRecord("bye", -1)),
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100111 decoder.decode(ByteBuffer.wrap(data)));
112 }
113
114 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200115 void dictionary() {
Matthias Andreas Benkard9a6c8ed2021-12-28 01:00:22 +0100116 var data =
117 new byte[] {
118 0x68,
119 0x69,
120 0x00,
121 0x00,
122 (byte) 0xfe,
123 (byte) 0xff,
124 (byte) 0xff,
125 (byte) 0xff,
126 0x03,
127 0x00,
128 0x00,
129 0x00,
130 0x62,
131 0x79,
132 0x65,
133 0x00,
134 (byte) 0xff,
135 (byte) 0xff,
136 (byte) 0xff,
137 (byte) 0xff,
138 0x04,
139 0x09,
140 0x15
141 };
142
143 var decoder =
144 Decoder.ofDictionary(Decoder.ofString(UTF_8), Decoder.ofInt().withByteOrder(LITTLE_ENDIAN));
145 assertEquals(Map.of("hi", -2, "bye", -1), decoder.decode(ByteBuffer.wrap(data)));
146 }
147
148 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200149 void stringArray() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100150 var data =
151 new byte[] {
152 0x69, 0x00, 0x63, 0x61, 0x6E, 0x00, 0x68, 0x61, 0x73, 0x00, 0x73, 0x74, 0x72, 0x69, 0x6E,
153 0x67, 0x73, 0x3F, 0x00, 0x02, 0x06, 0x0a, 0x13
154 };
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100155 var decoder = Decoder.ofArray(Decoder.ofString(UTF_8));
156 assertEquals(List.of("i", "can", "has", "strings?"), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100157 }
158
159 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200160 void nestedStructure() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100161 var data =
162 new byte[] {
163 0x69, 0x63, 0x61, 0x6E, 0x00, 0x68, 0x61, 0x73, 0x00, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
164 0x73, 0x3F, 0x00, 0x04, 0x0d, 0x05
165 };
166
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100167 record TestChild(byte b, String s) {}
168 record TestParent(TestChild tc, List<String> as) {}
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100169
170 var decoder =
171 Decoder.ofStructure(
172 TestParent.class,
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100173 Decoder.ofStructure(TestChild.class, Decoder.ofByte(), Decoder.ofString(UTF_8)),
174 Decoder.ofArray(Decoder.ofString(UTF_8)));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100175
176 assertEquals(
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100177 new TestParent(new TestChild((byte) 0x69, "can"), List.of("has", "strings?")),
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100178 decoder.decode(ByteBuffer.wrap(data)));
179 }
180
181 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200182 void nestedStructureVariant() {
Matthias Andreas Benkard55c34812021-12-14 21:51:10 +0100183 var data =
184 new byte[] {
185 0x69, 0x63, 0x61, 0x6E, 0x00, 0x68, 0x61, 0x73, 0x00, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
186 0x73, 0x3F, 0x00, 0x04, 0x0d, 0x05, 0x00, 0x28, 0x28, 0x79, 0x73, 0x29, 0x61, 0x73, 0x29
187 };
188
189 var decoder = Decoder.ofVariant();
Matthias Andreas Benkard31c61e72021-12-16 20:06:39 +0100190 var variant = decoder.decode(ByteBuffer.wrap(data));
191 var result = (Object[]) variant.value();
Matthias Andreas Benkard55c34812021-12-14 21:51:10 +0100192
193 assertAll(
Matthias Andreas Benkard31c61e72021-12-16 20:06:39 +0100194 () -> assertEquals(Signature.parse("((ys)as)"), variant.signature()),
Matthias Andreas Benkard55c34812021-12-14 21:51:10 +0100195 () -> assertEquals(2, result.length),
196 () -> assertArrayEquals(new Object[] {(byte) 0x69, "can"}, (Object[]) result[0]),
197 () -> assertEquals(List.of("has", "strings?"), result[1]));
198 }
199
200 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200201 void simpleStructure() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100202 var data = new byte[] {0x60, 0x70};
203
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100204 record TestRecord(byte b1, byte b2) {}
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100205
206 var decoder =
207 Decoder.ofStructure(
208 TestRecord.class,
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100209 Decoder.ofByte().withByteOrder(LITTLE_ENDIAN),
210 Decoder.ofByte().withByteOrder(LITTLE_ENDIAN));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100211
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100212 assertEquals(new TestRecord((byte) 0x60, (byte) 0x70), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100213 }
214
215 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200216 void paddedStructureRight() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100217 var data = new byte[] {0x60, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00};
218
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100219 record TestRecord(int b1, byte b2) {}
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100220
221 var decoder =
222 Decoder.ofStructure(
223 TestRecord.class,
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100224 Decoder.ofInt().withByteOrder(LITTLE_ENDIAN),
225 Decoder.ofByte().withByteOrder(LITTLE_ENDIAN));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100226
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100227 assertEquals(new TestRecord(0x60, (byte) 0x70), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100228 }
229
230 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200231 void paddedStructureLeft() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100232 var data = new byte[] {0x60, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00};
233
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100234 record TestRecord(byte b1, int b2) {}
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100235
236 var decoder =
237 Decoder.ofStructure(
238 TestRecord.class,
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100239 Decoder.ofByte().withByteOrder(LITTLE_ENDIAN),
240 Decoder.ofInt().withByteOrder(LITTLE_ENDIAN));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100241
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100242 assertEquals(new TestRecord((byte) 0x60, 0x70), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100243 }
244
245 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200246 void simpleStructureArray() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100247 var data =
248 new byte[] {
249 0x60,
250 0x00,
251 0x00,
252 0x00,
253 0x70,
254 0x00,
255 0x00,
256 0x00,
257 (byte) 0x88,
258 0x02,
259 0x00,
260 0x00,
261 (byte) 0xF7,
262 0x00,
263 0x00,
264 0x00
265 };
266
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100267 record TestRecord(int b1, byte b2) {}
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100268
269 var decoder =
270 Decoder.ofArray(
271 Decoder.ofStructure(
272 TestRecord.class,
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100273 Decoder.ofInt().withByteOrder(LITTLE_ENDIAN),
274 Decoder.ofByte().withByteOrder(LITTLE_ENDIAN)));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100275
276 assertEquals(
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100277 List.of(new TestRecord(96, (byte) 0x70), new TestRecord(648, (byte) 0xf7)),
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100278 decoder.decode(ByteBuffer.wrap(data)));
279 }
280
281 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200282 void byteArray() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100283 var data = new byte[] {0x04, 0x05, 0x06, 0x07};
284
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100285 var decoder = Decoder.ofArray(Decoder.ofByte());
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100286
287 assertEquals(
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100288 List.of((byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07),
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100289 decoder.decode(ByteBuffer.wrap(data)));
290 }
291
292 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200293 void primitiveByteArray() {
Matthias Andreas Benkard4e8423d2021-12-19 22:56:09 +0100294 var data = new byte[] {0x04, 0x05, 0x06, 0x07};
295
296 var decoder = Decoder.ofByteArray();
297
298 assertArrayEquals(data, decoder.decode(ByteBuffer.wrap(data)));
299 }
300
301 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200302 void primitiveByteArrayRecord() {
Matthias Andreas Benkard4e8423d2021-12-19 22:56:09 +0100303 var data = new byte[] {0x04, 0x05, 0x06, 0x07};
304
305 record TestRecord(byte[] bytes) {}
306
307 var decoder = Decoder.ofStructure(TestRecord.class, Decoder.ofByteArray());
308
309 assertArrayEquals(data, decoder.decode(ByteBuffer.wrap(data)).bytes());
310 }
311
312 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200313 void integerArray() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100314 var data = new byte[] {0x04, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00};
315
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100316 var decoder = Decoder.ofArray(Decoder.ofInt().withByteOrder(LITTLE_ENDIAN));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100317
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100318 assertEquals(List.of(4, 258), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100319 }
320
321 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200322 void dictionaryEntryAsMapEntry() {
Matthias Andreas Benkardcd924f62021-12-28 00:46:06 +0100323 var data =
324 new byte[] {0x61, 0x20, 0x6B, 0x65, 0x79, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x06};
325
326 var decoder =
327 Decoder.ofDictionaryEntry(
328 Decoder.ofString(UTF_8), Decoder.ofInt().withByteOrder(LITTLE_ENDIAN));
329 assertEquals(Map.entry("a key", 514), decoder.decode(ByteBuffer.wrap(data)));
330 }
331
332 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200333 void dictionaryEntryAsRecord() {
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100334 var data =
335 new byte[] {0x61, 0x20, 0x6B, 0x65, 0x79, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x06};
336
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100337 record TestEntry(String key, int value) {}
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100338
339 var decoder =
340 Decoder.ofStructure(
Matthias Andreas Benkard35f7a202021-12-14 19:29:26 +0100341 TestEntry.class, Decoder.ofString(UTF_8), Decoder.ofInt().withByteOrder(LITTLE_ENDIAN));
342 assertEquals(new TestEntry("a key", 514), decoder.decode(ByteBuffer.wrap(data)));
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100343 }
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100344
345 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200346 void paddedPrimitives() {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100347 var data =
348 new byte[] {
349 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
350 0x00, 0x40, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
351 };
352
353 record TestRecord(short s, long l, double d) {}
354
355 var decoder =
356 Decoder.ofStructure(
357 TestRecord.class,
358 Decoder.ofShort().withByteOrder(BIG_ENDIAN),
359 Decoder.ofLong().withByteOrder(LITTLE_ENDIAN),
360 Decoder.ofDouble());
361 assertEquals(new TestRecord((short) 1, 2, 3.25), decoder.decode(ByteBuffer.wrap(data)));
362 }
363
364 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200365 void embeddedMaybe() {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100366 var data = new byte[] {0x01, 0x01};
367
368 record TestRecord(Optional<Byte> set, Optional<Byte> unset) {}
369
370 var decoder =
371 Decoder.ofStructure(
372 TestRecord.class, Decoder.ofMaybe(Decoder.ofByte()), Decoder.ofMaybe(Decoder.ofByte()));
373 assertEquals(
374 new TestRecord(Optional.of((byte) 1), Optional.empty()),
375 decoder.decode(ByteBuffer.wrap(data)));
376 }
377
378 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200379 void recordComponentMismatch() {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100380 record TestRecord(Optional<Byte> set) {}
381
382 var maybeDecoder = Decoder.ofMaybe(Decoder.ofByte());
383 assertThrows(
384 IllegalArgumentException.class,
385 () -> Decoder.ofStructure(TestRecord.class, maybeDecoder, maybeDecoder));
386 }
387
388 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200389 void trivialRecord() {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100390 var data = new byte[] {0x00};
391
392 record TestRecord() {}
393
394 var decoder = Decoder.ofStructure(TestRecord.class);
395 assertEquals(new TestRecord(), decoder.decode(ByteBuffer.wrap(data)));
396 }
397
398 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200399 void twoElementTrivialRecordArray() {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100400 var data = new byte[] {0x00, 0x00};
401
402 record TestRecord() {}
403
404 var decoder = Decoder.ofArray(Decoder.ofStructure(TestRecord.class));
405 assertEquals(
406 List.of(new TestRecord(), new TestRecord()), decoder.decode(ByteBuffer.wrap(data)));
407 }
408
409 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200410 void singletonTrivialRecordArray() {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100411 var data = new byte[] {0x00};
412
413 record TestRecord() {}
414
415 var decoder = Decoder.ofArray(Decoder.ofStructure(TestRecord.class));
416 assertEquals(List.of(new TestRecord()), decoder.decode(ByteBuffer.wrap(data)));
417 }
418
419 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200420 void emptyTrivialRecordArray() {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100421 var data = new byte[] {};
422
423 record TestRecord() {}
424
425 var decoder = Decoder.ofArray(Decoder.ofStructure(TestRecord.class));
426 assertEquals(List.of(), decoder.decode(ByteBuffer.wrap(data)));
427 }
428
429 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200430 void variantArray() {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100431 var data = new byte[] {};
432
433 record TestRecord() {}
434
435 var decoder = Decoder.ofArray(Decoder.ofStructure(TestRecord.class));
436 assertEquals(List.of(), decoder.decode(ByteBuffer.wrap(data)));
437 }
438
439 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200440 void invalidVariantSignature() {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100441 var data = new byte[] {0x00, 0x00, 0x2E};
442
443 var decoder = Decoder.ofVariant();
444 assertThrows(IllegalArgumentException.class, () -> decoder.decode(ByteBuffer.wrap(data)));
445 }
446
447 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200448 void missingVariantSignature() {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100449 var data = new byte[] {0x01};
450
451 var decoder = Decoder.ofVariant();
452 assertThrows(IllegalArgumentException.class, () -> decoder.decode(ByteBuffer.wrap(data)));
453 }
454
455 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200456 void simpleVariantRecord() throws ParseException {
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100457 // signature: "(bynqiuxtdsogvmiai)"
458 var data =
459 new byte[] {
460 0x01, // b
461 0x02, // y
462 0x00, 0x03, // n
463 0x00, 0x04, // q
464 0x00, 0x00, // (padding)
465 0x00, 0x00, 0x00, 0x05, // i
466 0x00, 0x00, 0x00, 0x06, // u
467 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, // x
468 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, // t
469 0x40, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // d
470 0x68, 0x69, 0x00, // s
471 0x68, 0x69, 0x00, // o
472 0x68, 0x69, 0x00, // g
473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (padding)
474 0x00, 0x00, 0x00, 0x09, 0x00, 0x69, // v
475 0x00, 0x00, // (padding)
476 0x00, 0x00, 0x00, 0x0a, // mi
477 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, // ai
478 68, 62, 49, 46, 43, // framing offsets
479 0x00, 0x28, 0x62, 0x79, 0x6E, 0x71, 0x69, 0x75, 0x78, 0x74, 0x64, 0x73, 0x6F, 0x67, 0x76,
480 0x6D, 0x69, 0x61, 0x69, 0x29
481 };
482
483 var decoder = Decoder.ofVariant();
484 assertArrayEquals(
485 new Object[] {
486 true,
487 (byte) 2,
488 (short) 3,
489 (short) 4,
490 (int) 5,
491 (int) 6,
492 (long) 7,
493 (long) 8,
494 (double) 3.25,
495 "hi",
496 "hi",
497 "hi",
Matthias Andreas Benkard31c61e72021-12-16 20:06:39 +0100498 new Variant(Signature.parse("i"), 9),
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100499 Optional.of(10),
500 List.of(11, 12)
501 },
Matthias Andreas Benkard31c61e72021-12-16 20:06:39 +0100502 (Object[]) decoder.decode(ByteBuffer.wrap(data)).value());
503 }
504
505 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200506 void signatureString() throws ParseException {
Matthias Andreas Benkard31c61e72021-12-16 20:06:39 +0100507 var data =
508 new byte[] {
509 0x28, 0x62, 0x79, 0x6E, 0x71, 0x69, 0x75, 0x78, 0x74, 0x64, 0x73, 0x6F, 0x67, 0x76, 0x6D,
510 0x69, 0x61, 0x69, 0x29
511 };
512
513 var signature = Signature.parse(ByteBuffer.wrap(data));
514 assertEquals("(bynqiuxtdsogvmiai)", signature.toString());
Matthias Andreas Benkarde5a5c752021-12-15 19:53:55 +0100515 }
Matthias Andreas Benkard4e8423d2021-12-19 22:56:09 +0100516
517 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200518 void map() {
Matthias Andreas Benkard4e8423d2021-12-19 22:56:09 +0100519 var data = new byte[] {0x0A, 0x0B, 0x0C};
Matthias Andreas Benkardaa11d822023-12-10 09:20:48 +0100520 var decoder =
521 Decoder.ofByteArray()
522 .map(
523 bytes -> bytes.length,
524 len -> {
525 throw new UnsupportedOperationException();
526 });
Matthias Andreas Benkard4e8423d2021-12-19 22:56:09 +0100527 assertEquals(3, decoder.decode(ByteBuffer.wrap(data)));
528 }
Matthias Andreas Benkard44df94e2021-12-30 18:43:33 +0100529
530 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200531 void contramap() {
Matthias Andreas Benkard44df94e2021-12-30 18:43:33 +0100532 var data = new byte[] {0x0A, 0x0B, 0x0C};
Matthias Andreas Benkardaa11d822023-12-10 09:20:48 +0100533 var decoder =
534 Decoder.ofByteArray()
535 .contramap(
536 bytes -> bytes.slice(1, 1),
537 bytes -> {
538 throw new UnsupportedOperationException();
539 });
Matthias Andreas Benkard44df94e2021-12-30 18:43:33 +0100540 assertArrayEquals(new byte[] {0x0B}, decoder.decode(ByteBuffer.wrap(data)));
541 }
542
543 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200544 void predicateTrue() {
Matthias Andreas Benkard44df94e2021-12-30 18:43:33 +0100545 var data = new byte[] {0x00, 0x01, 0x00};
Matthias Andreas Benkardaa11d822023-12-10 09:20:48 +0100546 var innerDecoder =
547 Decoder.ofShort()
548 .contramap(
549 bytes -> bytes.slice(1, 2).order(bytes.order()),
550 bytes -> {
551 throw new UnsupportedOperationException();
552 });
Matthias Andreas Benkard44df94e2021-12-30 18:43:33 +0100553 var decoder =
554 Decoder.ofPredicate(
555 byteBuffer -> byteBuffer.get(0) == 0,
556 innerDecoder.withByteOrder(LITTLE_ENDIAN),
557 innerDecoder.withByteOrder(BIG_ENDIAN));
558 assertEquals((short) 1, decoder.decode(ByteBuffer.wrap(data)));
559 }
560
561 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200562 void predicateFalse() {
Matthias Andreas Benkard44df94e2021-12-30 18:43:33 +0100563 var data = new byte[] {0x01, 0x01, 0x00};
Matthias Andreas Benkardaa11d822023-12-10 09:20:48 +0100564 var innerDecoder =
565 Decoder.ofShort()
566 .contramap(
567 bytes -> bytes.slice(1, 2).order(bytes.order()),
568 bytes -> {
569 throw new UnsupportedOperationException();
570 });
Matthias Andreas Benkard44df94e2021-12-30 18:43:33 +0100571 var decoder =
572 Decoder.ofPredicate(
573 byteBuffer -> byteBuffer.get(0) == 0,
574 innerDecoder.withByteOrder(LITTLE_ENDIAN),
575 innerDecoder.withByteOrder(BIG_ENDIAN));
576 assertEquals((short) 256, decoder.decode(ByteBuffer.wrap(data)));
577 }
578
579 @Test
Matthias Andreas Benkard91dbd742022-10-17 19:38:56 +0200580 void byteOrder() {
Matthias Andreas Benkard44df94e2021-12-30 18:43:33 +0100581 var data =
582 new byte[] {
583 0x01, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x04, 0x05, 0x00, 0x00, 0x06, 0x00, 0x07, 0x08,
584 0x00
585 };
586
587 record TestChild(short s1, short s2) {}
588 record TestParent(TestChild tc1, TestChild tc2, TestChild tc3, TestChild tc4) {}
589
590 var decoder =
591 Decoder.ofStructure(
592 TestParent.class,
593 Decoder.ofStructure(TestChild.class, Decoder.ofShort(), Decoder.ofShort())
594 .withByteOrder(LITTLE_ENDIAN),
595 Decoder.ofStructure(TestChild.class, Decoder.ofShort(), Decoder.ofShort())
596 .withByteOrder(BIG_ENDIAN),
597 Decoder.ofStructure(
598 TestChild.class,
599 Decoder.ofShort().withByteOrder(LITTLE_ENDIAN),
600 Decoder.ofShort())
601 .withByteOrder(BIG_ENDIAN),
602 Decoder.ofStructure(
603 TestChild.class, Decoder.ofShort().withByteOrder(BIG_ENDIAN), Decoder.ofShort())
604 .withByteOrder(LITTLE_ENDIAN));
605
606 assertEquals(
607 new TestParent(
608 new TestChild((short) 1, (short) 2),
609 new TestChild((short) 3, (short) 4),
610 new TestChild((short) 5, (short) 6),
611 new TestChild((short) 7, (short) 8)),
612 decoder.decode(ByteBuffer.wrap(data)));
613 }
Matthias Andreas Benkard261532a2021-12-12 20:09:27 +0100614}