1 // __ _____ _____ _____
2 // __| | __| | | | JSON for Modern C++ (supporting code)
3 // | | |__ | | | | | | version 3.11.2
4 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
5 //
6 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
7 // SPDX-License-Identifier: MIT
8
9 #include "doctest_compatibility.h"
10
11 #include <nlohmann/json.hpp>
12 using nlohmann::json;
13
14 #include <iostream>
15 #include <fstream>
16 #include <set>
17 #include "make_test_data_available.hpp"
18 #include "test_utils.hpp"
19
20 namespace
21 {
22 class SaxCountdown
23 {
24 public:
SaxCountdown(const int count)25 explicit SaxCountdown(const int count) : events_left(count)
26 {}
27
null()28 bool null()
29 {
30 return events_left-- > 0;
31 }
32
boolean(bool)33 bool boolean(bool /*unused*/)
34 {
35 return events_left-- > 0;
36 }
37
number_integer(json::number_integer_t)38 bool number_integer(json::number_integer_t /*unused*/)
39 {
40 return events_left-- > 0;
41 }
42
number_unsigned(json::number_unsigned_t)43 bool number_unsigned(json::number_unsigned_t /*unused*/)
44 {
45 return events_left-- > 0;
46 }
47
number_float(json::number_float_t,const std::string &)48 bool number_float(json::number_float_t /*unused*/, const std::string& /*unused*/)
49 {
50 return events_left-- > 0;
51 }
52
string(std::string &)53 bool string(std::string& /*unused*/)
54 {
55 return events_left-- > 0;
56 }
57
binary(std::vector<std::uint8_t> &)58 bool binary(std::vector<std::uint8_t>& /*unused*/)
59 {
60 return events_left-- > 0;
61 }
62
start_object(std::size_t)63 bool start_object(std::size_t /*unused*/)
64 {
65 return events_left-- > 0;
66 }
67
key(std::string &)68 bool key(std::string& /*unused*/)
69 {
70 return events_left-- > 0;
71 }
72
end_object()73 bool end_object()
74 {
75 return events_left-- > 0;
76 }
77
start_array(std::size_t)78 bool start_array(std::size_t /*unused*/)
79 {
80 return events_left-- > 0;
81 }
82
end_array()83 bool end_array()
84 {
85 return events_left-- > 0;
86 }
87
parse_error(std::size_t,const std::string &,const json::exception &)88 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const json::exception& /*unused*/) // NOLINT(readability-convert-member-functions-to-static)
89 {
90 return false;
91 }
92
93 private:
94 int events_left = 0;
95 };
96 } // namespace
97
98 TEST_CASE("UBJSON")
99 {
100 SECTION("individual values")
101 {
102 SECTION("discarded")
103 {
104 // discarded values are not serialized
105 json j = json::value_t::discarded;
106 const auto result = json::to_ubjson(j);
107 CHECK(result.empty());
108 }
109
110 SECTION("null")
111 {
112 json j = nullptr;
113 std::vector<uint8_t> expected = {'Z'};
114 const auto result = json::to_ubjson(j);
115 CHECK(result == expected);
116
117 // roundtrip
118 CHECK(json::from_ubjson(result) == j);
119 CHECK(json::from_ubjson(result, true, false) == j);
120 }
121
122 SECTION("boolean")
123 {
124 SECTION("true")
125 {
126 json j = true;
127 std::vector<uint8_t> expected = {'T'};
128 const auto result = json::to_ubjson(j);
129 CHECK(result == expected);
130
131 // roundtrip
132 CHECK(json::from_ubjson(result) == j);
133 CHECK(json::from_ubjson(result, true, false) == j);
134 }
135
136 SECTION("false")
137 {
138 json j = false;
139 std::vector<uint8_t> expected = {'F'};
140 const auto result = json::to_ubjson(j);
141 CHECK(result == expected);
142
143 // roundtrip
144 CHECK(json::from_ubjson(result) == j);
145 CHECK(json::from_ubjson(result, true, false) == j);
146 }
147 }
148
149 SECTION("number")
150 {
151 SECTION("signed")
152 {
153 SECTION("-9223372036854775808..-2147483649 (int64)")
154 {
155 std::vector<int64_t> numbers;
156 numbers.push_back((std::numeric_limits<int64_t>::min)());
157 numbers.push_back(-1000000000000000000LL);
158 numbers.push_back(-100000000000000000LL);
159 numbers.push_back(-10000000000000000LL);
160 numbers.push_back(-1000000000000000LL);
161 numbers.push_back(-100000000000000LL);
162 numbers.push_back(-10000000000000LL);
163 numbers.push_back(-1000000000000LL);
164 numbers.push_back(-100000000000LL);
165 numbers.push_back(-10000000000LL);
166 numbers.push_back(-2147483649LL);
167 for (auto i : numbers)
168 {
169 CAPTURE(i)
170
171 // create JSON value with integer number
172 json j = i;
173
174 // check type
175 CHECK(j.is_number_integer());
176
177 // create expected byte vector
178 std::vector<uint8_t> expected;
179 expected.push_back(static_cast<uint8_t>('L'));
180 expected.push_back(static_cast<uint8_t>((i >> 56) & 0xff));
181 expected.push_back(static_cast<uint8_t>((i >> 48) & 0xff));
182 expected.push_back(static_cast<uint8_t>((i >> 40) & 0xff));
183 expected.push_back(static_cast<uint8_t>((i >> 32) & 0xff));
184 expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
185 expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
186 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
187 expected.push_back(static_cast<uint8_t>(i & 0xff));
188
189 // compare result + size
190 const auto result = json::to_ubjson(j);
191 CHECK(result == expected);
192 CHECK(result.size() == 9);
193
194 // check individual bytes
195 CHECK(result[0] == 'L');
196 int64_t restored = (static_cast<int64_t>(result[1]) << 070) +
197 (static_cast<int64_t>(result[2]) << 060) +
198 (static_cast<int64_t>(result[3]) << 050) +
199 (static_cast<int64_t>(result[4]) << 040) +
200 (static_cast<int64_t>(result[5]) << 030) +
201 (static_cast<int64_t>(result[6]) << 020) +
202 (static_cast<int64_t>(result[7]) << 010) +
203 static_cast<int64_t>(result[8]);
204 CHECK(restored == i);
205
206 // roundtrip
207 CHECK(json::from_ubjson(result) == j);
208 CHECK(json::from_ubjson(result, true, false) == j);
209 }
210 }
211
212 SECTION("-2147483648..-32769 (int32)")
213 {
214 std::vector<int32_t> numbers;
215 numbers.push_back(-32769);
216 numbers.push_back(-100000);
217 numbers.push_back(-1000000);
218 numbers.push_back(-10000000);
219 numbers.push_back(-100000000);
220 numbers.push_back(-1000000000);
221 numbers.push_back(-2147483647 - 1); // https://stackoverflow.com/a/29356002/266378
222 for (auto i : numbers)
223 {
224 CAPTURE(i)
225
226 // create JSON value with integer number
227 json j = i;
228
229 // check type
230 CHECK(j.is_number_integer());
231
232 // create expected byte vector
233 std::vector<uint8_t> expected;
234 expected.push_back(static_cast<uint8_t>('l'));
235 expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
236 expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
237 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
238 expected.push_back(static_cast<uint8_t>(i & 0xff));
239
240 // compare result + size
241 const auto result = json::to_ubjson(j);
242 CHECK(result == expected);
243 CHECK(result.size() == 5);
244
245 // check individual bytes
246 CHECK(result[0] == 'l');
247 int32_t restored = (static_cast<int32_t>(result[1]) << 030) +
248 (static_cast<int32_t>(result[2]) << 020) +
249 (static_cast<int32_t>(result[3]) << 010) +
250 static_cast<int32_t>(result[4]);
251 CHECK(restored == i);
252
253 // roundtrip
254 CHECK(json::from_ubjson(result) == j);
255 CHECK(json::from_ubjson(result, true, false) == j);
256 }
257 }
258
259 SECTION("-32768..-129 (int16)")
260 {
261 for (int32_t i = -32768; i <= -129; ++i)
262 {
263 CAPTURE(i)
264
265 // create JSON value with integer number
266 json j = i;
267
268 // check type
269 CHECK(j.is_number_integer());
270
271 // create expected byte vector
272 std::vector<uint8_t> expected;
273 expected.push_back(static_cast<uint8_t>('I'));
274 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
275 expected.push_back(static_cast<uint8_t>(i & 0xff));
276
277 // compare result + size
278 const auto result = json::to_ubjson(j);
279 CHECK(result == expected);
280 CHECK(result.size() == 3);
281
282 // check individual bytes
283 CHECK(result[0] == 'I');
284 auto restored = static_cast<int16_t>(((result[1] << 8) + result[2]));
285 CHECK(restored == i);
286
287 // roundtrip
288 CHECK(json::from_ubjson(result) == j);
289 CHECK(json::from_ubjson(result, true, false) == j);
290 }
291 }
292
293 SECTION("-9263 (int16)")
294 {
295 json j = -9263;
296 std::vector<uint8_t> expected = {'I', 0xdb, 0xd1};
297
298 // compare result + size
299 const auto result = json::to_ubjson(j);
300 CHECK(result == expected);
301 CHECK(result.size() == 3);
302
303 // check individual bytes
304 CHECK(result[0] == 'I');
305 auto restored = static_cast<int16_t>(((result[1] << 8) + result[2]));
306 CHECK(restored == -9263);
307
308 // roundtrip
309 CHECK(json::from_ubjson(result) == j);
310 CHECK(json::from_ubjson(result, true, false) == j);
311 }
312
313 SECTION("-128..-1 (int8)")
314 {
315 for (auto i = -128; i <= -1; ++i)
316 {
317 CAPTURE(i)
318
319 // create JSON value with integer number
320 json j = i;
321
322 // check type
323 CHECK(j.is_number_integer());
324
325 // create expected byte vector
326 std::vector<uint8_t> expected;
327 expected.push_back('i');
328 expected.push_back(static_cast<uint8_t>(i));
329
330 // compare result + size
331 const auto result = json::to_ubjson(j);
332 CHECK(result == expected);
333 CHECK(result.size() == 2);
334
335 // check individual bytes
336 CHECK(result[0] == 'i');
337 CHECK(static_cast<int8_t>(result[1]) == i);
338
339 // roundtrip
340 CHECK(json::from_ubjson(result) == j);
341 CHECK(json::from_ubjson(result, true, false) == j);
342 }
343 }
344
345 SECTION("0..127 (int8)")
346 {
347 for (size_t i = 0; i <= 127; ++i)
348 {
349 CAPTURE(i)
350
351 // create JSON value with integer number
352 json j = -1;
353 j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
354
355 // check type
356 CHECK(j.is_number_integer());
357
358 // create expected byte vector
359 std::vector<uint8_t> expected;
360 expected.push_back(static_cast<uint8_t>('i'));
361 expected.push_back(static_cast<uint8_t>(i));
362
363 // compare result + size
364 const auto result = json::to_ubjson(j);
365 CHECK(result == expected);
366 CHECK(result.size() == 2);
367
368 // check individual bytes
369 CHECK(result[0] == 'i');
370 CHECK(result[1] == i);
371
372 // roundtrip
373 CHECK(json::from_ubjson(result) == j);
374 CHECK(json::from_ubjson(result, true, false) == j);
375 }
376 }
377
378 SECTION("128..255 (uint8)")
379 {
380 for (size_t i = 128; i <= 255; ++i)
381 {
382 CAPTURE(i)
383
384 // create JSON value with integer number
385 json j = -1;
386 j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
387
388 // check type
389 CHECK(j.is_number_integer());
390
391 // create expected byte vector
392 std::vector<uint8_t> expected;
393 expected.push_back(static_cast<uint8_t>('U'));
394 expected.push_back(static_cast<uint8_t>(i));
395
396 // compare result + size
397 const auto result = json::to_ubjson(j);
398 CHECK(result == expected);
399 CHECK(result.size() == 2);
400
401 // check individual bytes
402 CHECK(result[0] == 'U');
403 CHECK(result[1] == i);
404
405 // roundtrip
406 CHECK(json::from_ubjson(result) == j);
407 CHECK(json::from_ubjson(result, true, false) == j);
408 }
409 }
410
411 SECTION("256..32767 (int16)")
412 {
413 for (size_t i = 256; i <= 32767; ++i)
414 {
415 CAPTURE(i)
416
417 // create JSON value with integer number
418 json j = -1;
419 j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
420
421 // check type
422 CHECK(j.is_number_integer());
423
424 // create expected byte vector
425 std::vector<uint8_t> expected;
426 expected.push_back(static_cast<uint8_t>('I'));
427 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
428 expected.push_back(static_cast<uint8_t>(i & 0xff));
429
430 // compare result + size
431 const auto result = json::to_ubjson(j);
432 CHECK(result == expected);
433 CHECK(result.size() == 3);
434
435 // check individual bytes
436 CHECK(result[0] == 'I');
437 auto restored = static_cast<uint16_t>(static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]));
438 CHECK(restored == i);
439
440 // roundtrip
441 CHECK(json::from_ubjson(result) == j);
442 CHECK(json::from_ubjson(result, true, false) == j);
443 }
444 }
445
446 SECTION("65536..2147483647 (int32)")
447 {
448 for (uint32_t i :
449 {
450 65536u, 77777u, 1048576u
451 })
452 {
453 CAPTURE(i)
454
455 // create JSON value with integer number
456 json j = -1;
457 j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
458
459 // check type
460 CHECK(j.is_number_integer());
461
462 // create expected byte vector
463 std::vector<uint8_t> expected;
464 expected.push_back('l');
465 expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
466 expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
467 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
468 expected.push_back(static_cast<uint8_t>(i & 0xff));
469
470 // compare result + size
471 const auto result = json::to_ubjson(j);
472 CHECK(result == expected);
473 CHECK(result.size() == 5);
474
475 // check individual bytes
476 CHECK(result[0] == 'l');
477 uint32_t restored = (static_cast<uint32_t>(result[1]) << 030) +
478 (static_cast<uint32_t>(result[2]) << 020) +
479 (static_cast<uint32_t>(result[3]) << 010) +
480 static_cast<uint32_t>(result[4]);
481 CHECK(restored == i);
482
483 // roundtrip
484 CHECK(json::from_ubjson(result) == j);
485 CHECK(json::from_ubjson(result, true, false) == j);
486 }
487 }
488
489 SECTION("2147483648..9223372036854775807 (int64)")
490 {
491 std::vector<uint64_t> v = {2147483648ul, 9223372036854775807ul};
492 for (uint64_t i : v)
493 {
494 CAPTURE(i)
495
496 // create JSON value with integer number
497 json j = -1;
498 j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
499
500 // check type
501 CHECK(j.is_number_integer());
502
503 // create expected byte vector
504 std::vector<uint8_t> expected;
505 expected.push_back('L');
506 expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff));
507 expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff));
508 expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff));
509 expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff));
510 expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff));
511 expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff));
512 expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff));
513 expected.push_back(static_cast<uint8_t>(i & 0xff));
514
515 // compare result + size
516 const auto result = json::to_ubjson(j);
517 CHECK(result == expected);
518 CHECK(result.size() == 9);
519
520 // check individual bytes
521 CHECK(result[0] == 'L');
522 uint64_t restored = (static_cast<uint64_t>(result[1]) << 070) +
523 (static_cast<uint64_t>(result[2]) << 060) +
524 (static_cast<uint64_t>(result[3]) << 050) +
525 (static_cast<uint64_t>(result[4]) << 040) +
526 (static_cast<uint64_t>(result[5]) << 030) +
527 (static_cast<uint64_t>(result[6]) << 020) +
528 (static_cast<uint64_t>(result[7]) << 010) +
529 static_cast<uint64_t>(result[8]);
530 CHECK(restored == i);
531
532 // roundtrip
533 CHECK(json::from_ubjson(result) == j);
534 CHECK(json::from_ubjson(result, true, false) == j);
535 }
536 }
537 }
538
539 SECTION("unsigned")
540 {
541 SECTION("0..127 (int8)")
542 {
543 for (size_t i = 0; i <= 127; ++i)
544 {
545 CAPTURE(i)
546
547 // create JSON value with unsigned integer number
548 json j = i;
549
550 // check type
551 CHECK(j.is_number_unsigned());
552
553 // create expected byte vector
554 std::vector<uint8_t> expected;
555 expected.push_back('i');
556 expected.push_back(static_cast<uint8_t>(i));
557
558 // compare result + size
559 const auto result = json::to_ubjson(j);
560 CHECK(result == expected);
561 CHECK(result.size() == 2);
562
563 // check individual bytes
564 CHECK(result[0] == 'i');
565 auto restored = static_cast<uint8_t>(result[1]);
566 CHECK(restored == i);
567
568 // roundtrip
569 CHECK(json::from_ubjson(result) == j);
570 CHECK(json::from_ubjson(result, true, false) == j);
571 }
572 }
573
574 SECTION("128..255 (uint8)")
575 {
576 for (size_t i = 128; i <= 255; ++i)
577 {
578 CAPTURE(i)
579
580 // create JSON value with unsigned integer number
581 json j = i;
582
583 // check type
584 CHECK(j.is_number_unsigned());
585
586 // create expected byte vector
587 std::vector<uint8_t> expected;
588 expected.push_back('U');
589 expected.push_back(static_cast<uint8_t>(i));
590
591 // compare result + size
592 const auto result = json::to_ubjson(j);
593 CHECK(result == expected);
594 CHECK(result.size() == 2);
595
596 // check individual bytes
597 CHECK(result[0] == 'U');
598 auto restored = static_cast<uint8_t>(result[1]);
599 CHECK(restored == i);
600
601 // roundtrip
602 CHECK(json::from_ubjson(result) == j);
603 CHECK(json::from_ubjson(result, true, false) == j);
604 }
605 }
606
607 SECTION("256..32767 (int16)")
608 {
609 for (size_t i = 256; i <= 32767; ++i)
610 {
611 CAPTURE(i)
612
613 // create JSON value with unsigned integer number
614 json j = i;
615
616 // check type
617 CHECK(j.is_number_unsigned());
618
619 // create expected byte vector
620 std::vector<uint8_t> expected;
621 expected.push_back('I');
622 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
623 expected.push_back(static_cast<uint8_t>(i & 0xff));
624
625 // compare result + size
626 const auto result = json::to_ubjson(j);
627 CHECK(result == expected);
628 CHECK(result.size() == 3);
629
630 // check individual bytes
631 CHECK(result[0] == 'I');
632 auto restored = static_cast<uint16_t>(static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]));
633 CHECK(restored == i);
634
635 // roundtrip
636 CHECK(json::from_ubjson(result) == j);
637 CHECK(json::from_ubjson(result, true, false) == j);
638 }
639 }
640
641 SECTION("65536..2147483647 (int32)")
642 {
643 for (uint32_t i :
644 {
645 65536u, 77777u, 1048576u
646 })
647 {
648 CAPTURE(i)
649
650 // create JSON value with unsigned integer number
651 json j = i;
652
653 // check type
654 CHECK(j.is_number_unsigned());
655
656 // create expected byte vector
657 std::vector<uint8_t> expected;
658 expected.push_back('l');
659 expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
660 expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
661 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
662 expected.push_back(static_cast<uint8_t>(i & 0xff));
663
664 // compare result + size
665 const auto result = json::to_ubjson(j);
666 CHECK(result == expected);
667 CHECK(result.size() == 5);
668
669 // check individual bytes
670 CHECK(result[0] == 'l');
671 uint32_t restored = (static_cast<uint32_t>(result[1]) << 030) +
672 (static_cast<uint32_t>(result[2]) << 020) +
673 (static_cast<uint32_t>(result[3]) << 010) +
674 static_cast<uint32_t>(result[4]);
675 CHECK(restored == i);
676
677 // roundtrip
678 CHECK(json::from_ubjson(result) == j);
679 CHECK(json::from_ubjson(result, true, false) == j);
680 }
681 }
682
683 SECTION("2147483648..9223372036854775807 (int64)")
684 {
685 std::vector<uint64_t> v = {2147483648ul, 9223372036854775807ul};
686 for (uint64_t i : v)
687 {
688 CAPTURE(i)
689
690 // create JSON value with integer number
691 json j = i;
692
693 // check type
694 CHECK(j.is_number_unsigned());
695
696 // create expected byte vector
697 std::vector<uint8_t> expected;
698 expected.push_back('L');
699 expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff));
700 expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff));
701 expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff));
702 expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff));
703 expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff));
704 expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff));
705 expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff));
706 expected.push_back(static_cast<uint8_t>(i & 0xff));
707
708 // compare result + size
709 const auto result = json::to_ubjson(j);
710 CHECK(result == expected);
711 CHECK(result.size() == 9);
712
713 // check individual bytes
714 CHECK(result[0] == 'L');
715 uint64_t restored = (static_cast<uint64_t>(result[1]) << 070) +
716 (static_cast<uint64_t>(result[2]) << 060) +
717 (static_cast<uint64_t>(result[3]) << 050) +
718 (static_cast<uint64_t>(result[4]) << 040) +
719 (static_cast<uint64_t>(result[5]) << 030) +
720 (static_cast<uint64_t>(result[6]) << 020) +
721 (static_cast<uint64_t>(result[7]) << 010) +
722 static_cast<uint64_t>(result[8]);
723 CHECK(restored == i);
724
725 // roundtrip
726 CHECK(json::from_ubjson(result) == j);
727 CHECK(json::from_ubjson(result, true, false) == j);
728 }
729 }
730 }
731
732 SECTION("float64")
733 {
734 SECTION("3.1415925")
735 {
736 double v = 3.1415925;
737 json j = v;
738 std::vector<uint8_t> expected =
739 {
740 'D', 0x40, 0x09, 0x21, 0xfb, 0x3f, 0xa6, 0xde, 0xfc
741 };
742 const auto result = json::to_ubjson(j);
743 CHECK(result == expected);
744
745 // roundtrip
746 CHECK(json::from_ubjson(result) == j);
747 CHECK(json::from_ubjson(result) == v);
748 CHECK(json::from_ubjson(result, true, false) == j);
749 }
750 }
751
752 SECTION("high-precision number")
753 {
754 SECTION("unsigned integer number")
755 {
756 std::vector<uint8_t> vec = {'H', 'i', 0x14, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
757 const auto j = json::from_ubjson(vec);
758 CHECK(j.is_number_unsigned());
759 CHECK(j.dump() == "12345678901234567890");
760 }
761
762 SECTION("signed integer number")
763 {
764 std::vector<uint8_t> vec = {'H', 'i', 0x13, '-', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8'};
765 const auto j = json::from_ubjson(vec);
766 CHECK(j.is_number_integer());
767 CHECK(j.dump() == "-123456789012345678");
768 }
769
770 SECTION("floating-point number")
771 {
772 std::vector<uint8_t> vec = {'H', 'i', 0x16, '3', '.', '1', '4', '1', '5', '9', '2', '6', '5', '3', '5', '8', '9', '7', '9', '3', '2', '3', '8', '4', '6'};
773 const auto j = json::from_ubjson(vec);
774 CHECK(j.is_number_float());
775 CHECK(j.dump() == "3.141592653589793");
776 }
777
778 SECTION("errors")
779 {
780 // error while parsing length
781 std::vector<uint8_t> vec0 = {'H', 'i'};
782 CHECK(json::from_ubjson(vec0, true, false).is_discarded());
783 // error while parsing string
784 std::vector<uint8_t> vec1 = {'H', 'i', '1'};
785 CHECK(json::from_ubjson(vec1, true, false).is_discarded());
786
787 json _;
788 std::vector<uint8_t> vec2 = {'H', 'i', 2, '1', 'A', '3'};
789 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vec2), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A", json::parse_error);
790 std::vector<uint8_t> vec3 = {'H', 'i', 2, '1', '.'};
791 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vec3), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1.", json::parse_error);
792 std::vector<uint8_t> vec4 = {'H', 2, '1', '0'};
793 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vec4), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing UBJSON size: expected length type specification (U, i, I, l, L) after '#'; last byte: 0x02", json::parse_error);
794 }
795
796 SECTION("serialization")
797 {
798 // number that does not fit int64
799 json j = 11111111111111111111ULL;
800 CHECK(j.is_number_unsigned());
801
802 // number will be serialized to high-precision number
803 const auto vec = json::to_ubjson(j);
804 std::vector<uint8_t> expected = {'H', 'i', 0x14, '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1'};
805 CHECK(vec == expected);
806
807 // roundtrip
808 CHECK(json::from_ubjson(vec) == j);
809 }
810 }
811 }
812
813 SECTION("string")
814 {
815 SECTION("N = 0..127")
816 {
817 for (size_t N = 0; N <= 127; ++N)
818 {
819 CAPTURE(N)
820
821 // create JSON value with string containing of N * 'x'
822 const auto s = std::string(N, 'x');
823 json j = s;
824
825 // create expected byte vector
826 std::vector<uint8_t> expected;
827 expected.push_back('S');
828 expected.push_back('i');
829 expected.push_back(static_cast<uint8_t>(N));
830 for (size_t i = 0; i < N; ++i)
831 {
832 expected.push_back('x');
833 }
834
835 // compare result + size
836 const auto result = json::to_ubjson(j);
837 CHECK(result == expected);
838 CHECK(result.size() == N + 3);
839 // check that no null byte is appended
840 if (N > 0)
841 {
842 CHECK(result.back() != '\x00');
843 }
844
845 // roundtrip
846 CHECK(json::from_ubjson(result) == j);
847 CHECK(json::from_ubjson(result, true, false) == j);
848 }
849 }
850
851 SECTION("N = 128..255")
852 {
853 for (size_t N = 128; N <= 255; ++N)
854 {
855 CAPTURE(N)
856
857 // create JSON value with string containing of N * 'x'
858 const auto s = std::string(N, 'x');
859 json j = s;
860
861 // create expected byte vector
862 std::vector<uint8_t> expected;
863 expected.push_back('S');
864 expected.push_back('U');
865 expected.push_back(static_cast<uint8_t>(N));
866 for (size_t i = 0; i < N; ++i)
867 {
868 expected.push_back('x');
869 }
870
871 // compare result + size
872 const auto result = json::to_ubjson(j);
873 CHECK(result == expected);
874 CHECK(result.size() == N + 3);
875 // check that no null byte is appended
876 CHECK(result.back() != '\x00');
877
878 // roundtrip
879 CHECK(json::from_ubjson(result) == j);
880 CHECK(json::from_ubjson(result, true, false) == j);
881 }
882 }
883
884 SECTION("N = 256..32767")
885 {
886 for (size_t N :
887 {
888 256u, 999u, 1025u, 3333u, 2048u, 32767u
889 })
890 {
891 CAPTURE(N)
892
893 // create JSON value with string containing of N * 'x'
894 const auto s = std::string(N, 'x');
895 json j = s;
896
897 // create expected byte vector (hack: create string first)
898 std::vector<uint8_t> expected(N, 'x');
899 // reverse order of commands, because we insert at begin()
900 expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
901 expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
902 expected.insert(expected.begin(), 'I');
903 expected.insert(expected.begin(), 'S');
904
905 // compare result + size
906 const auto result = json::to_ubjson(j);
907 CHECK(result == expected);
908 CHECK(result.size() == N + 4);
909 // check that no null byte is appended
910 CHECK(result.back() != '\x00');
911
912 // roundtrip
913 CHECK(json::from_ubjson(result) == j);
914 CHECK(json::from_ubjson(result, true, false) == j);
915 }
916 }
917
918 SECTION("N = 65536..2147483647")
919 {
920 for (size_t N :
921 {
922 65536u, 77777u, 1048576u
923 })
924 {
925 CAPTURE(N)
926
927 // create JSON value with string containing of N * 'x'
928 const auto s = std::string(N, 'x');
929 json j = s;
930
931 // create expected byte vector (hack: create string first)
932 std::vector<uint8_t> expected(N, 'x');
933 // reverse order of commands, because we insert at begin()
934 expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
935 expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
936 expected.insert(expected.begin(), static_cast<uint8_t>((N >> 16) & 0xff));
937 expected.insert(expected.begin(), static_cast<uint8_t>((N >> 24) & 0xff));
938 expected.insert(expected.begin(), 'l');
939 expected.insert(expected.begin(), 'S');
940
941 // compare result + size
942 const auto result = json::to_ubjson(j);
943 CHECK(result == expected);
944 CHECK(result.size() == N + 6);
945 // check that no null byte is appended
946 CHECK(result.back() != '\x00');
947
948 // roundtrip
949 CHECK(json::from_ubjson(result) == j);
950 CHECK(json::from_ubjson(result, true, false) == j);
951 }
952 }
953 }
954
955 SECTION("binary")
956 {
957 SECTION("N = 0..127")
958 {
959 for (std::size_t N = 0; N <= 127; ++N)
960 {
961 CAPTURE(N)
962
963 // create JSON value with byte array containing of N * 'x'
964 const auto s = std::vector<std::uint8_t>(N, 'x');
965 json j = json::binary(s);
966
967 // create expected byte vector
968 std::vector<std::uint8_t> expected;
969 expected.push_back(static_cast<std::uint8_t>('['));
970 if (N != 0)
971 {
972 expected.push_back(static_cast<std::uint8_t>('$'));
973 expected.push_back(static_cast<std::uint8_t>('U'));
974 }
975 expected.push_back(static_cast<std::uint8_t>('#'));
976 expected.push_back(static_cast<std::uint8_t>('i'));
977 expected.push_back(static_cast<std::uint8_t>(N));
978 for (size_t i = 0; i < N; ++i)
979 {
980 expected.push_back(0x78);
981 }
982
983 // compare result + size
984 const auto result = json::to_ubjson(j, true, true);
985 CHECK(result == expected);
986 if (N == 0)
987 {
988 CHECK(result.size() == N + 4);
989 }
990 else
991 {
992 CHECK(result.size() == N + 6);
993 }
994
995 // check that no null byte is appended
996 if (N > 0)
997 {
998 CHECK(result.back() != '\x00');
999 }
1000
1001 // roundtrip only works to an array of numbers
1002 json j_out = s;
1003 CHECK(json::from_ubjson(result) == j_out);
1004 CHECK(json::from_ubjson(result, true, false) == j_out);
1005 }
1006 }
1007
1008 SECTION("N = 128..255")
1009 {
1010 for (std::size_t N = 128; N <= 255; ++N)
1011 {
1012 CAPTURE(N)
1013
1014 // create JSON value with byte array containing of N * 'x'
1015 const auto s = std::vector<std::uint8_t>(N, 'x');
1016 json j = json::binary(s);
1017
1018 // create expected byte vector
1019 std::vector<uint8_t> expected;
1020 expected.push_back(static_cast<std::uint8_t>('['));
1021 expected.push_back(static_cast<std::uint8_t>('$'));
1022 expected.push_back(static_cast<std::uint8_t>('U'));
1023 expected.push_back(static_cast<std::uint8_t>('#'));
1024 expected.push_back(static_cast<std::uint8_t>('U'));
1025 expected.push_back(static_cast<std::uint8_t>(N));
1026 for (size_t i = 0; i < N; ++i)
1027 {
1028 expected.push_back(0x78);
1029 }
1030
1031 // compare result + size
1032 const auto result = json::to_ubjson(j, true, true);
1033 CHECK(result == expected);
1034 CHECK(result.size() == N + 6);
1035 // check that no null byte is appended
1036 CHECK(result.back() != '\x00');
1037
1038 // roundtrip only works to an array of numbers
1039 json j_out = s;
1040 CHECK(json::from_ubjson(result) == j_out);
1041 CHECK(json::from_ubjson(result, true, false) == j_out);
1042 }
1043 }
1044
1045 SECTION("N = 256..32767")
1046 {
1047 for (std::size_t N :
1048 {
1049 256u, 999u, 1025u, 3333u, 2048u, 32767u
1050 })
1051 {
1052 CAPTURE(N)
1053
1054 // create JSON value with byte array containing of N * 'x'
1055 const auto s = std::vector<std::uint8_t>(N, 'x');
1056 json j = json::binary(s);
1057
1058 // create expected byte vector
1059 std::vector<std::uint8_t> expected(N + 7, 'x');
1060 expected[0] = '[';
1061 expected[1] = '$';
1062 expected[2] = 'U';
1063 expected[3] = '#';
1064 expected[4] = 'I';
1065 expected[5] = static_cast<std::uint8_t>((N >> 8) & 0xFF);
1066 expected[6] = static_cast<std::uint8_t>(N & 0xFF);
1067
1068 // compare result + size
1069 const auto result = json::to_ubjson(j, true, true);
1070 CHECK(result == expected);
1071 CHECK(result.size() == N + 7);
1072 // check that no null byte is appended
1073 CHECK(result.back() != '\x00');
1074
1075 // roundtrip only works to an array of numbers
1076 json j_out = s;
1077 CHECK(json::from_ubjson(result) == j_out);
1078 CHECK(json::from_ubjson(result, true, false) == j_out);
1079 }
1080 }
1081
1082 SECTION("N = 32768..2147483647")
1083 {
1084 for (std::size_t N :
1085 {
1086 32768u, 77777u, 1048576u
1087 })
1088 {
1089 CAPTURE(N)
1090
1091 // create JSON value with byte array containing of N * 'x'
1092 const auto s = std::vector<std::uint8_t>(N, 'x');
1093 json j = json::binary(s);
1094
1095 // create expected byte vector
1096 std::vector<std::uint8_t> expected(N + 9, 'x');
1097 expected[0] = '[';
1098 expected[1] = '$';
1099 expected[2] = 'U';
1100 expected[3] = '#';
1101 expected[4] = 'l';
1102 expected[5] = static_cast<std::uint8_t>((N >> 24) & 0xFF);
1103 expected[6] = static_cast<std::uint8_t>((N >> 16) & 0xFF);
1104 expected[7] = static_cast<std::uint8_t>((N >> 8) & 0xFF);
1105 expected[8] = static_cast<std::uint8_t>(N & 0xFF);
1106
1107 // compare result + size
1108 const auto result = json::to_ubjson(j, true, true);
1109 CHECK(result == expected);
1110 CHECK(result.size() == N + 9);
1111 // check that no null byte is appended
1112 CHECK(result.back() != '\x00');
1113
1114 // roundtrip only works to an array of numbers
1115 json j_out = s;
1116 CHECK(json::from_ubjson(result) == j_out);
1117 CHECK(json::from_ubjson(result, true, false) == j_out);
1118 }
1119 }
1120
1121 SECTION("Other Serializations")
1122 {
1123 const std::size_t N = 10;
1124 const auto s = std::vector<std::uint8_t>(N, 'x');
1125 json j = json::binary(s);
1126
1127 SECTION("No Count No Type")
1128 {
1129 std::vector<uint8_t> expected;
1130 expected.push_back(static_cast<std::uint8_t>('['));
1131 for (std::size_t i = 0; i < N; ++i)
1132 {
1133 expected.push_back(static_cast<std::uint8_t>('U'));
1134 expected.push_back(static_cast<std::uint8_t>(0x78));
1135 }
1136 expected.push_back(static_cast<std::uint8_t>(']'));
1137
1138 // compare result + size
1139 const auto result = json::to_ubjson(j, false, false);
1140 CHECK(result == expected);
1141 CHECK(result.size() == N + 12);
1142 // check that no null byte is appended
1143 CHECK(result.back() != '\x00');
1144
1145 // roundtrip only works to an array of numbers
1146 json j_out = s;
1147 CHECK(json::from_ubjson(result) == j_out);
1148 CHECK(json::from_ubjson(result, true, false) == j_out);
1149 }
1150
1151 SECTION("Yes Count No Type")
1152 {
1153 std::vector<std::uint8_t> expected;
1154 expected.push_back(static_cast<std::uint8_t>('['));
1155 expected.push_back(static_cast<std::uint8_t>('#'));
1156 expected.push_back(static_cast<std::uint8_t>('i'));
1157 expected.push_back(static_cast<std::uint8_t>(N));
1158
1159 for (size_t i = 0; i < N; ++i)
1160 {
1161 expected.push_back(static_cast<std::uint8_t>('U'));
1162 expected.push_back(static_cast<std::uint8_t>(0x78));
1163 }
1164
1165 // compare result + size
1166 const auto result = json::to_ubjson(j, true, false);
1167 CHECK(result == expected);
1168 CHECK(result.size() == N + 14);
1169 // check that no null byte is appended
1170 CHECK(result.back() != '\x00');
1171
1172 // roundtrip only works to an array of numbers
1173 json j_out = s;
1174 CHECK(json::from_ubjson(result) == j_out);
1175 CHECK(json::from_ubjson(result, true, false) == j_out);
1176 }
1177 }
1178 }
1179
1180 SECTION("array")
1181 {
1182 SECTION("empty")
1183 {
1184 SECTION("size=false type=false")
1185 {
1186 json j = json::array();
1187 std::vector<uint8_t> expected = {'[', ']'};
1188 const auto result = json::to_ubjson(j);
1189 CHECK(result == expected);
1190
1191 // roundtrip
1192 CHECK(json::from_ubjson(result) == j);
1193 CHECK(json::from_ubjson(result, true, false) == j);
1194 }
1195
1196 SECTION("size=true type=false")
1197 {
1198 json j = json::array();
1199 std::vector<uint8_t> expected = {'[', '#', 'i', 0};
1200 const auto result = json::to_ubjson(j, true);
1201 CHECK(result == expected);
1202
1203 // roundtrip
1204 CHECK(json::from_ubjson(result) == j);
1205 CHECK(json::from_ubjson(result, true, false) == j);
1206 }
1207
1208 SECTION("size=true type=true")
1209 {
1210 json j = json::array();
1211 std::vector<uint8_t> expected = {'[', '#', 'i', 0};
1212 const auto result = json::to_ubjson(j, true, true);
1213 CHECK(result == expected);
1214
1215 // roundtrip
1216 CHECK(json::from_ubjson(result) == j);
1217 CHECK(json::from_ubjson(result, true, false) == j);
1218 }
1219 }
1220
1221 SECTION("[null]")
1222 {
1223 SECTION("size=false type=false")
1224 {
1225 json j = {nullptr};
1226 std::vector<uint8_t> expected = {'[', 'Z', ']'};
1227 const auto result = json::to_ubjson(j);
1228 CHECK(result == expected);
1229
1230 // roundtrip
1231 CHECK(json::from_ubjson(result) == j);
1232 CHECK(json::from_ubjson(result, true, false) == j);
1233 }
1234
1235 SECTION("size=true type=false")
1236 {
1237 json j = {nullptr};
1238 std::vector<uint8_t> expected = {'[', '#', 'i', 1, 'Z'};
1239 const auto result = json::to_ubjson(j, true);
1240 CHECK(result == expected);
1241
1242 // roundtrip
1243 CHECK(json::from_ubjson(result) == j);
1244 CHECK(json::from_ubjson(result, true, false) == j);
1245 }
1246
1247 SECTION("size=true type=true")
1248 {
1249 json j = {nullptr};
1250 std::vector<uint8_t> expected = {'[', '$', 'Z', '#', 'i', 1};
1251 const auto result = json::to_ubjson(j, true, true);
1252 CHECK(result == expected);
1253
1254 // roundtrip
1255 CHECK(json::from_ubjson(result) == j);
1256 CHECK(json::from_ubjson(result, true, false) == j);
1257 }
1258 }
1259
1260 SECTION("[1,2,3,4,5]")
1261 {
1262 SECTION("size=false type=false")
1263 {
1264 json j = json::parse("[1,2,3,4,5]");
1265 std::vector<uint8_t> expected = {'[', 'i', 1, 'i', 2, 'i', 3, 'i', 4, 'i', 5, ']'};
1266 const auto result = json::to_ubjson(j);
1267 CHECK(result == expected);
1268
1269 // roundtrip
1270 CHECK(json::from_ubjson(result) == j);
1271 CHECK(json::from_ubjson(result, true, false) == j);
1272 }
1273
1274 SECTION("size=true type=false")
1275 {
1276 json j = json::parse("[1,2,3,4,5]");
1277 std::vector<uint8_t> expected = {'[', '#', 'i', 5, 'i', 1, 'i', 2, 'i', 3, 'i', 4, 'i', 5};
1278 const auto result = json::to_ubjson(j, true);
1279 CHECK(result == expected);
1280
1281 // roundtrip
1282 CHECK(json::from_ubjson(result) == j);
1283 CHECK(json::from_ubjson(result, true, false) == j);
1284 }
1285
1286 SECTION("size=true type=true")
1287 {
1288 json j = json::parse("[1,2,3,4,5]");
1289 std::vector<uint8_t> expected = {'[', '$', 'i', '#', 'i', 5, 1, 2, 3, 4, 5};
1290 const auto result = json::to_ubjson(j, true, true);
1291 CHECK(result == expected);
1292
1293 // roundtrip
1294 CHECK(json::from_ubjson(result) == j);
1295 CHECK(json::from_ubjson(result, true, false) == j);
1296 }
1297 }
1298
1299 SECTION("[[[[]]]]")
1300 {
1301 SECTION("size=false type=false")
1302 {
1303 json j = json::parse("[[[[]]]]");
1304 std::vector<uint8_t> expected = {'[', '[', '[', '[', ']', ']', ']', ']'};
1305 const auto result = json::to_ubjson(j);
1306 CHECK(result == expected);
1307
1308 // roundtrip
1309 CHECK(json::from_ubjson(result) == j);
1310 CHECK(json::from_ubjson(result, true, false) == j);
1311 }
1312
1313 SECTION("size=true type=false")
1314 {
1315 json j = json::parse("[[[[]]]]");
1316 std::vector<uint8_t> expected = {'[', '#', 'i', 1, '[', '#', 'i', 1, '[', '#', 'i', 1, '[', '#', 'i', 0};
1317 const auto result = json::to_ubjson(j, true);
1318 CHECK(result == expected);
1319
1320 // roundtrip
1321 CHECK(json::from_ubjson(result) == j);
1322 CHECK(json::from_ubjson(result, true, false) == j);
1323 }
1324
1325 SECTION("size=true type=true")
1326 {
1327 json j = json::parse("[[[[]]]]");
1328 std::vector<uint8_t> expected = {'[', '$', '[', '#', 'i', 1, '$', '[', '#', 'i', 1, '$', '[', '#', 'i', 1, '#', 'i', 0};
1329 const auto result = json::to_ubjson(j, true, true);
1330 CHECK(result == expected);
1331
1332 // roundtrip
1333 CHECK(json::from_ubjson(result) == j);
1334 CHECK(json::from_ubjson(result, true, false) == j);
1335 }
1336 }
1337
1338 SECTION("array with uint16_t elements")
1339 {
1340 SECTION("size=false type=false")
1341 {
1342 json j(257, nullptr);
1343 std::vector<uint8_t> expected(j.size() + 2, 'Z'); // all null
1344 expected[0] = '['; // opening array
1345 expected[258] = ']'; // closing array
1346 const auto result = json::to_ubjson(j);
1347 CHECK(result == expected);
1348
1349 // roundtrip
1350 CHECK(json::from_ubjson(result) == j);
1351 CHECK(json::from_ubjson(result, true, false) == j);
1352 }
1353
1354 SECTION("size=true type=false")
1355 {
1356 json j(257, nullptr);
1357 std::vector<uint8_t> expected(j.size() + 5, 'Z'); // all null
1358 expected[0] = '['; // opening array
1359 expected[1] = '#'; // array size
1360 expected[2] = 'I'; // int16
1361 expected[3] = 0x01; // 0x0101, first byte
1362 expected[4] = 0x01; // 0x0101, second byte
1363 const auto result = json::to_ubjson(j, true);
1364 CHECK(result == expected);
1365
1366 // roundtrip
1367 CHECK(json::from_ubjson(result) == j);
1368 CHECK(json::from_ubjson(result, true, false) == j);
1369 }
1370
1371 SECTION("size=true type=true")
1372 {
1373 json j(257, nullptr);
1374 std::vector<uint8_t> expected = {'[', '$', 'Z', '#', 'I', 0x01, 0x01};
1375 const auto result = json::to_ubjson(j, true, true);
1376 CHECK(result == expected);
1377
1378 // roundtrip
1379 CHECK(json::from_ubjson(result) == j);
1380 CHECK(json::from_ubjson(result, true, false) == j);
1381 }
1382 }
1383
1384 SECTION("array with uint32_t elements")
1385 {
1386 SECTION("size=false type=false")
1387 {
1388 json j(65793, nullptr);
1389 std::vector<uint8_t> expected(j.size() + 2, 'Z'); // all null
1390 expected[0] = '['; // opening array
1391 expected[65794] = ']'; // closing array
1392 const auto result = json::to_ubjson(j);
1393 CHECK(result == expected);
1394
1395 // roundtrip
1396 CHECK(json::from_ubjson(result) == j);
1397 CHECK(json::from_ubjson(result, true, false) == j);
1398 }
1399
1400 SECTION("size=true type=false")
1401 {
1402 json j(65793, nullptr);
1403 std::vector<uint8_t> expected(j.size() + 7, 'Z'); // all null
1404 expected[0] = '['; // opening array
1405 expected[1] = '#'; // array size
1406 expected[2] = 'l'; // int32
1407 expected[3] = 0x00; // 0x00010101, first byte
1408 expected[4] = 0x01; // 0x00010101, second byte
1409 expected[5] = 0x01; // 0x00010101, third byte
1410 expected[6] = 0x01; // 0x00010101, fourth byte
1411 const auto result = json::to_ubjson(j, true);
1412 CHECK(result == expected);
1413
1414 // roundtrip
1415 CHECK(json::from_ubjson(result) == j);
1416 CHECK(json::from_ubjson(result, true, false) == j);
1417 }
1418
1419 SECTION("size=true type=true")
1420 {
1421 json j(65793, nullptr);
1422 std::vector<uint8_t> expected = {'[', '$', 'Z', '#', 'l', 0x00, 0x01, 0x01, 0x01};
1423 const auto result = json::to_ubjson(j, true, true);
1424 CHECK(result == expected);
1425
1426 // roundtrip
1427 CHECK(json::from_ubjson(result) == j);
1428 CHECK(json::from_ubjson(result, true, false) == j);
1429 }
1430 }
1431 }
1432
1433 SECTION("object")
1434 {
1435 SECTION("empty")
1436 {
1437 SECTION("size=false type=false")
1438 {
1439 json j = json::object();
1440 std::vector<uint8_t> expected = {'{', '}'};
1441 const auto result = json::to_ubjson(j);
1442 CHECK(result == expected);
1443
1444 // roundtrip
1445 CHECK(json::from_ubjson(result) == j);
1446 CHECK(json::from_ubjson(result, true, false) == j);
1447 }
1448
1449 SECTION("size=true type=false")
1450 {
1451 json j = json::object();
1452 std::vector<uint8_t> expected = {'{', '#', 'i', 0};
1453 const auto result = json::to_ubjson(j, true);
1454 CHECK(result == expected);
1455
1456 // roundtrip
1457 CHECK(json::from_ubjson(result) == j);
1458 CHECK(json::from_ubjson(result, true, false) == j);
1459 }
1460
1461 SECTION("size=true type=true")
1462 {
1463 json j = json::object();
1464 std::vector<uint8_t> expected = {'{', '#', 'i', 0};
1465 const auto result = json::to_ubjson(j, true, true);
1466 CHECK(result == expected);
1467
1468 // roundtrip
1469 CHECK(json::from_ubjson(result) == j);
1470 CHECK(json::from_ubjson(result, true, false) == j);
1471 }
1472 }
1473
1474 SECTION("{\"\":null}")
1475 {
1476 SECTION("size=false type=false")
1477 {
1478 json j = {{"", nullptr}};
1479 std::vector<uint8_t> expected = {'{', 'i', 0, 'Z', '}'};
1480 const auto result = json::to_ubjson(j);
1481 CHECK(result == expected);
1482
1483 // roundtrip
1484 CHECK(json::from_ubjson(result) == j);
1485 CHECK(json::from_ubjson(result, true, false) == j);
1486 }
1487
1488 SECTION("size=true type=false")
1489 {
1490 json j = {{"", nullptr}};
1491 std::vector<uint8_t> expected = {'{', '#', 'i', 1, 'i', 0, 'Z'};
1492 const auto result = json::to_ubjson(j, true);
1493 CHECK(result == expected);
1494
1495 // roundtrip
1496 CHECK(json::from_ubjson(result) == j);
1497 CHECK(json::from_ubjson(result, true, false) == j);
1498 }
1499
1500 SECTION("size=true type=true")
1501 {
1502 json j = {{"", nullptr}};
1503 std::vector<uint8_t> expected = {'{', '$', 'Z', '#', 'i', 1, 'i', 0};
1504 const auto result = json::to_ubjson(j, true, true);
1505 CHECK(result == expected);
1506
1507 // roundtrip
1508 CHECK(json::from_ubjson(result) == j);
1509 CHECK(json::from_ubjson(result, true, false) == j);
1510 }
1511 }
1512
1513 SECTION("{\"a\": {\"b\": {\"c\": {}}}}")
1514 {
1515 SECTION("size=false type=false")
1516 {
1517 json j = json::parse(R"({"a": {"b": {"c": {}}}})");
1518 std::vector<uint8_t> expected =
1519 {
1520 '{', 'i', 1, 'a', '{', 'i', 1, 'b', '{', 'i', 1, 'c', '{', '}', '}', '}', '}'
1521 };
1522 const auto result = json::to_ubjson(j);
1523 CHECK(result == expected);
1524
1525 // roundtrip
1526 CHECK(json::from_ubjson(result) == j);
1527 CHECK(json::from_ubjson(result, true, false) == j);
1528 }
1529
1530 SECTION("size=true type=false")
1531 {
1532 json j = json::parse(R"({"a": {"b": {"c": {}}}})");
1533 std::vector<uint8_t> expected =
1534 {
1535 '{', '#', 'i', 1, 'i', 1, 'a', '{', '#', 'i', 1, 'i', 1, 'b', '{', '#', 'i', 1, 'i', 1, 'c', '{', '#', 'i', 0
1536 };
1537 const auto result = json::to_ubjson(j, true);
1538 CHECK(result == expected);
1539
1540 // roundtrip
1541 CHECK(json::from_ubjson(result) == j);
1542 CHECK(json::from_ubjson(result, true, false) == j);
1543 }
1544
1545 SECTION("size=true type=true")
1546 {
1547 json j = json::parse(R"({"a": {"b": {"c": {}}}})");
1548 std::vector<uint8_t> expected =
1549 {
1550 '{', '$', '{', '#', 'i', 1, 'i', 1, 'a', '$', '{', '#', 'i', 1, 'i', 1, 'b', '$', '{', '#', 'i', 1, 'i', 1, 'c', '#', 'i', 0
1551 };
1552 const auto result = json::to_ubjson(j, true, true);
1553 CHECK(result == expected);
1554
1555 // roundtrip
1556 CHECK(json::from_ubjson(result) == j);
1557 CHECK(json::from_ubjson(result, true, false) == j);
1558 }
1559 }
1560 }
1561 }
1562
1563 SECTION("errors")
1564 {
1565 SECTION("strict mode")
1566 {
1567 std::vector<uint8_t> vec = {'Z', 'Z'};
1568 SECTION("non-strict mode")
1569 {
1570 const auto result = json::from_ubjson(vec, false);
1571 CHECK(result == json());
1572 }
1573
1574 SECTION("strict mode")
1575 {
1576 json _;
1577 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vec), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing UBJSON value: expected end of input; last byte: 0x5A", json::parse_error&);
1578 }
1579 }
1580
1581 SECTION("excessive size")
1582 {
1583 SECTION("array")
1584 {
1585 std::vector<uint8_t> v_ubjson = {'[', '$', 'Z', '#', 'L', 0x78, 0x28, 0x00, 0x68, 0x28, 0x69, 0x69, 0x17};
1586 json _;
1587 CHECK_THROWS_AS(_ = json::from_ubjson(v_ubjson), json::out_of_range&);
1588
1589 json j;
1590 nlohmann::detail::json_sax_dom_callback_parser<json> scp(j, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) noexcept
__anon929085140202(int , json::parse_event_t , const json& ) 1591 {
1592 return true;
1593 });
1594 CHECK_THROWS_AS(_ = json::sax_parse(v_ubjson, &scp, json::input_format_t::ubjson), json::out_of_range&);
1595 }
1596
1597 SECTION("object")
1598 {
1599 std::vector<uint8_t> v_ubjson = {'{', '$', 'Z', '#', 'L', 0x78, 0x28, 0x00, 0x68, 0x28, 0x69, 0x69, 0x17};
1600 json _;
1601 CHECK_THROWS_AS(_ = json::from_ubjson(v_ubjson), json::out_of_range&);
1602
1603 json j;
1604 nlohmann::detail::json_sax_dom_callback_parser<json> scp(j, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) noexcept
__anon929085140302(int , json::parse_event_t , const json& ) 1605 {
1606 return true;
1607 });
1608 CHECK_THROWS_AS(_ = json::sax_parse(v_ubjson, &scp, json::input_format_t::ubjson), json::out_of_range&);
1609 }
1610 }
1611 }
1612
1613 SECTION("SAX aborts")
1614 {
1615 SECTION("start_array()")
1616 {
1617 std::vector<uint8_t> v = {'[', 'T', 'F', ']'};
1618 SaxCountdown scp(0);
1619 CHECK(!json::sax_parse(v, &scp, json::input_format_t::ubjson));
1620 }
1621
1622 SECTION("start_object()")
1623 {
1624 std::vector<uint8_t> v = {'{', 'i', 3, 'f', 'o', 'o', 'F', '}'};
1625 SaxCountdown scp(0);
1626 CHECK(!json::sax_parse(v, &scp, json::input_format_t::ubjson));
1627 }
1628
1629 SECTION("key() in object")
1630 {
1631 std::vector<uint8_t> v = {'{', 'i', 3, 'f', 'o', 'o', 'F', '}'};
1632 SaxCountdown scp(1);
1633 CHECK(!json::sax_parse(v, &scp, json::input_format_t::ubjson));
1634 }
1635
1636 SECTION("start_array(len)")
1637 {
1638 std::vector<uint8_t> v = {'[', '#', 'i', '2', 'T', 'F'};
1639 SaxCountdown scp(0);
1640 CHECK(!json::sax_parse(v, &scp, json::input_format_t::ubjson));
1641 }
1642
1643 SECTION("start_object(len)")
1644 {
1645 std::vector<uint8_t> v = {'{', '#', 'i', '1', 3, 'f', 'o', 'o', 'F'};
1646 SaxCountdown scp(0);
1647 CHECK(!json::sax_parse(v, &scp, json::input_format_t::ubjson));
1648 }
1649
1650 SECTION("key() in object with length")
1651 {
1652 std::vector<uint8_t> v = {'{', 'i', 3, 'f', 'o', 'o', 'F', '}'};
1653 SaxCountdown scp(1);
1654 CHECK(!json::sax_parse(v, &scp, json::input_format_t::ubjson));
1655 }
1656 }
1657
1658 SECTION("parsing values")
1659 {
1660 SECTION("strings")
1661 {
1662 // create a single-character string for all number types
1663 std::vector<uint8_t> s_i = {'S', 'i', 1, 'a'};
1664 std::vector<uint8_t> s_U = {'S', 'U', 1, 'a'};
1665 std::vector<uint8_t> s_I = {'S', 'I', 0, 1, 'a'};
1666 std::vector<uint8_t> s_l = {'S', 'l', 0, 0, 0, 1, 'a'};
1667 std::vector<uint8_t> s_L = {'S', 'L', 0, 0, 0, 0, 0, 0, 0, 1, 'a'};
1668
1669 // check if string is parsed correctly to "a"
1670 CHECK(json::from_ubjson(s_i) == "a");
1671 CHECK(json::from_ubjson(s_U) == "a");
1672 CHECK(json::from_ubjson(s_I) == "a");
1673 CHECK(json::from_ubjson(s_l) == "a");
1674 CHECK(json::from_ubjson(s_L) == "a");
1675
1676 // roundtrip: output should be optimized
1677 CHECK(json::to_ubjson(json::from_ubjson(s_i)) == s_i);
1678 CHECK(json::to_ubjson(json::from_ubjson(s_U)) == s_i);
1679 CHECK(json::to_ubjson(json::from_ubjson(s_I)) == s_i);
1680 CHECK(json::to_ubjson(json::from_ubjson(s_l)) == s_i);
1681 CHECK(json::to_ubjson(json::from_ubjson(s_L)) == s_i);
1682 }
1683
1684 SECTION("number")
1685 {
1686 SECTION("float")
1687 {
1688 // float32
1689 std::vector<uint8_t> v_d = {'d', 0x40, 0x49, 0x0f, 0xd0};
1690 CHECK(json::from_ubjson(v_d) == 3.14159f);
1691
1692 // float64
1693 std::vector<uint8_t> v_D = {'D', 0x40, 0x09, 0x21, 0xf9, 0xf0, 0x1b, 0x86, 0x6e};
1694 CHECK(json::from_ubjson(v_D) == 3.14159);
1695
1696 // float32 is serialized as float64 as the library does not support float32
1697 CHECK(json::to_ubjson(json::from_ubjson(v_d)) == json::to_ubjson(3.14159f));
1698 }
1699 }
1700
1701 SECTION("array")
1702 {
1703 SECTION("optimized version (length only)")
1704 {
1705 // create vector with two elements of the same type
1706 std::vector<uint8_t> v_TU = {'[', '#', 'U', 2, 'T', 'T'};
1707 std::vector<uint8_t> v_T = {'[', '#', 'i', 2, 'T', 'T'};
1708 std::vector<uint8_t> v_F = {'[', '#', 'i', 2, 'F', 'F'};
1709 std::vector<uint8_t> v_Z = {'[', '#', 'i', 2, 'Z', 'Z'};
1710 std::vector<uint8_t> v_i = {'[', '#', 'i', 2, 'i', 0x7F, 'i', 0x7F};
1711 std::vector<uint8_t> v_U = {'[', '#', 'i', 2, 'U', 0xFF, 'U', 0xFF};
1712 std::vector<uint8_t> v_I = {'[', '#', 'i', 2, 'I', 0x7F, 0xFF, 'I', 0x7F, 0xFF};
1713 std::vector<uint8_t> v_l = {'[', '#', 'i', 2, 'l', 0x7F, 0xFF, 0xFF, 0xFF, 'l', 0x7F, 0xFF, 0xFF, 0xFF};
1714 std::vector<uint8_t> v_L = {'[', '#', 'i', 2, 'L', 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 'L', 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
1715 std::vector<uint8_t> v_D = {'[', '#', 'i', 2, 'D', 0x40, 0x09, 0x21, 0xfb, 0x4d, 0x12, 0xd8, 0x4a, 'D', 0x40, 0x09, 0x21, 0xfb, 0x4d, 0x12, 0xd8, 0x4a};
1716 std::vector<uint8_t> v_S = {'[', '#', 'i', 2, 'S', 'i', 1, 'a', 'S', 'i', 1, 'a'};
1717 std::vector<uint8_t> v_C = {'[', '#', 'i', 2, 'C', 'a', 'C', 'a'};
1718
1719 // check if vector is parsed correctly
1720 CHECK(json::from_ubjson(v_TU) == json({true, true}));
1721 CHECK(json::from_ubjson(v_T) == json({true, true}));
1722 CHECK(json::from_ubjson(v_F) == json({false, false}));
1723 CHECK(json::from_ubjson(v_Z) == json({nullptr, nullptr}));
1724 CHECK(json::from_ubjson(v_i) == json({127, 127}));
1725 CHECK(json::from_ubjson(v_U) == json({255, 255}));
1726 CHECK(json::from_ubjson(v_I) == json({32767, 32767}));
1727 CHECK(json::from_ubjson(v_l) == json({2147483647, 2147483647}));
1728 CHECK(json::from_ubjson(v_L) == json({9223372036854775807, 9223372036854775807}));
1729 CHECK(json::from_ubjson(v_D) == json({3.1415926, 3.1415926}));
1730 CHECK(json::from_ubjson(v_S) == json({"a", "a"}));
1731 CHECK(json::from_ubjson(v_C) == json({"a", "a"}));
1732
1733 // roundtrip: output should be optimized
1734 CHECK(json::to_ubjson(json::from_ubjson(v_T), true) == v_T);
1735 CHECK(json::to_ubjson(json::from_ubjson(v_F), true) == v_F);
1736 CHECK(json::to_ubjson(json::from_ubjson(v_Z), true) == v_Z);
1737 CHECK(json::to_ubjson(json::from_ubjson(v_i), true) == v_i);
1738 CHECK(json::to_ubjson(json::from_ubjson(v_U), true) == v_U);
1739 CHECK(json::to_ubjson(json::from_ubjson(v_I), true) == v_I);
1740 CHECK(json::to_ubjson(json::from_ubjson(v_l), true) == v_l);
1741 CHECK(json::to_ubjson(json::from_ubjson(v_L), true) == v_L);
1742 CHECK(json::to_ubjson(json::from_ubjson(v_D), true) == v_D);
1743 CHECK(json::to_ubjson(json::from_ubjson(v_S), true) == v_S);
1744 CHECK(json::to_ubjson(json::from_ubjson(v_C), true) == v_S); // char is serialized to string
1745 }
1746
1747 SECTION("optimized version (type and length)")
1748 {
1749 // create vector with two elements of the same type
1750 std::vector<uint8_t> v_N = {'[', '$', 'N', '#', 'i', 2};
1751 std::vector<uint8_t> v_T = {'[', '$', 'T', '#', 'i', 2};
1752 std::vector<uint8_t> v_F = {'[', '$', 'F', '#', 'i', 2};
1753 std::vector<uint8_t> v_Z = {'[', '$', 'Z', '#', 'i', 2};
1754 std::vector<uint8_t> v_i = {'[', '$', 'i', '#', 'i', 2, 0x7F, 0x7F};
1755 std::vector<uint8_t> v_U = {'[', '$', 'U', '#', 'i', 2, 0xFF, 0xFF};
1756 std::vector<uint8_t> v_I = {'[', '$', 'I', '#', 'i', 2, 0x7F, 0xFF, 0x7F, 0xFF};
1757 std::vector<uint8_t> v_l = {'[', '$', 'l', '#', 'i', 2, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF};
1758 std::vector<uint8_t> v_L = {'[', '$', 'L', '#', 'i', 2, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
1759 std::vector<uint8_t> v_D = {'[', '$', 'D', '#', 'i', 2, 0x40, 0x09, 0x21, 0xfb, 0x4d, 0x12, 0xd8, 0x4a, 0x40, 0x09, 0x21, 0xfb, 0x4d, 0x12, 0xd8, 0x4a};
1760 std::vector<uint8_t> v_S = {'[', '$', 'S', '#', 'i', 2, 'i', 1, 'a', 'i', 1, 'a'};
1761 std::vector<uint8_t> v_C = {'[', '$', 'C', '#', 'i', 2, 'a', 'a'};
1762
1763 // check if vector is parsed correctly
1764 CHECK(json::from_ubjson(v_N) == json::array());
1765 CHECK(json::from_ubjson(v_T) == json({true, true}));
1766 CHECK(json::from_ubjson(v_F) == json({false, false}));
1767 CHECK(json::from_ubjson(v_Z) == json({nullptr, nullptr}));
1768 CHECK(json::from_ubjson(v_i) == json({127, 127}));
1769 CHECK(json::from_ubjson(v_U) == json({255, 255}));
1770 CHECK(json::from_ubjson(v_I) == json({32767, 32767}));
1771 CHECK(json::from_ubjson(v_l) == json({2147483647, 2147483647}));
1772 CHECK(json::from_ubjson(v_L) == json({9223372036854775807, 9223372036854775807}));
1773 CHECK(json::from_ubjson(v_D) == json({3.1415926, 3.1415926}));
1774 CHECK(json::from_ubjson(v_S) == json({"a", "a"}));
1775 CHECK(json::from_ubjson(v_C) == json({"a", "a"}));
1776
1777 // roundtrip: output should be optimized
1778 std::vector<uint8_t> v_empty = {'[', '#', 'i', 0};
1779 CHECK(json::to_ubjson(json::from_ubjson(v_N), true, true) == v_empty);
1780 CHECK(json::to_ubjson(json::from_ubjson(v_T), true, true) == v_T);
1781 CHECK(json::to_ubjson(json::from_ubjson(v_F), true, true) == v_F);
1782 CHECK(json::to_ubjson(json::from_ubjson(v_Z), true, true) == v_Z);
1783 CHECK(json::to_ubjson(json::from_ubjson(v_i), true, true) == v_i);
1784 CHECK(json::to_ubjson(json::from_ubjson(v_U), true, true) == v_U);
1785 CHECK(json::to_ubjson(json::from_ubjson(v_I), true, true) == v_I);
1786 CHECK(json::to_ubjson(json::from_ubjson(v_l), true, true) == v_l);
1787 CHECK(json::to_ubjson(json::from_ubjson(v_L), true, true) == v_L);
1788 CHECK(json::to_ubjson(json::from_ubjson(v_D), true, true) == v_D);
1789 CHECK(json::to_ubjson(json::from_ubjson(v_S), true, true) == v_S);
1790 CHECK(json::to_ubjson(json::from_ubjson(v_C), true, true) == v_S); // char is serialized to string
1791 }
1792 }
1793 }
1794
1795 SECTION("parse errors")
1796 {
1797 SECTION("empty byte vector")
1798 {
1799 json _;
1800 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(std::vector<uint8_t>()), "[json.exception.parse_error.110] parse error at byte 1: syntax error while parsing UBJSON value: unexpected end of input", json::parse_error&);
1801 }
1802
1803 SECTION("char")
1804 {
1805 SECTION("eof after C byte")
1806 {
1807 std::vector<uint8_t> v = {'C'};
1808 json _;
1809 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(v), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing UBJSON char: unexpected end of input", json::parse_error&);
1810 }
1811
1812 SECTION("byte out of range")
1813 {
1814 std::vector<uint8_t> v = {'C', 130};
1815 json _;
1816 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(v), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing UBJSON char: byte after 'C' must be in range 0x00..0x7F; last byte: 0x82", json::parse_error&);
1817 }
1818 }
1819
1820 SECTION("strings")
1821 {
1822 SECTION("eof after S byte")
1823 {
1824 std::vector<uint8_t> v = {'S'};
1825 json _;
1826 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(v), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing UBJSON value: unexpected end of input", json::parse_error&);
1827 }
1828
1829 SECTION("invalid byte")
1830 {
1831 std::vector<uint8_t> v = {'S', '1', 'a'};
1832 json _;
1833 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(v), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing UBJSON string: expected length type specification (U, i, I, l, L); last byte: 0x31", json::parse_error&);
1834 }
1835 }
1836
1837 SECTION("array")
1838 {
1839 SECTION("optimized array: no size following type")
1840 {
1841 std::vector<uint8_t> v = {'[', '$', 'i', 2};
1842 json _;
1843 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(v), "[json.exception.parse_error.112] parse error at byte 4: syntax error while parsing UBJSON size: expected '#' after type information; last byte: 0x02", json::parse_error&);
1844 }
1845 }
1846
1847 SECTION("strings")
1848 {
1849 std::vector<uint8_t> vS = {'S'};
1850 json _;
1851 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vS), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing UBJSON value: unexpected end of input", json::parse_error&);
1852 CHECK(json::from_ubjson(vS, true, false).is_discarded());
1853
1854 std::vector<uint8_t> v = {'S', 'i', '2', 'a'};
1855 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(v), "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing UBJSON string: unexpected end of input", json::parse_error&);
1856 CHECK(json::from_ubjson(v, true, false).is_discarded());
1857
1858 std::vector<uint8_t> vC = {'C'};
1859 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vC), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing UBJSON char: unexpected end of input", json::parse_error&);
1860 CHECK(json::from_ubjson(vC, true, false).is_discarded());
1861 }
1862
1863 SECTION("sizes")
1864 {
1865 std::vector<uint8_t> vU = {'[', '#', 'U'};
1866 json _;
1867 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vU), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON number: unexpected end of input", json::parse_error&);
1868 CHECK(json::from_ubjson(vU, true, false).is_discarded());
1869
1870 std::vector<uint8_t> vi = {'[', '#', 'i'};
1871 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vi), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON number: unexpected end of input", json::parse_error&);
1872 CHECK(json::from_ubjson(vi, true, false).is_discarded());
1873
1874 std::vector<uint8_t> vI = {'[', '#', 'I'};
1875 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vI), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON number: unexpected end of input", json::parse_error&);
1876 CHECK(json::from_ubjson(vI, true, false).is_discarded());
1877
1878 std::vector<uint8_t> vl = {'[', '#', 'l'};
1879 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vl), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON number: unexpected end of input", json::parse_error&);
1880 CHECK(json::from_ubjson(vl, true, false).is_discarded());
1881
1882 std::vector<uint8_t> vL = {'[', '#', 'L'};
1883 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vL), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON number: unexpected end of input", json::parse_error&);
1884 CHECK(json::from_ubjson(vL, true, false).is_discarded());
1885
1886 std::vector<uint8_t> v0 = {'[', '#', 'T', ']'};
1887 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(v0), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing UBJSON size: expected length type specification (U, i, I, l, L) after '#'; last byte: 0x54", json::parse_error&);
1888 CHECK(json::from_ubjson(v0, true, false).is_discarded());
1889 }
1890
1891 SECTION("types")
1892 {
1893 std::vector<uint8_t> v0 = {'[', '$'};
1894 json _;
1895 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(v0), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing UBJSON type: unexpected end of input", json::parse_error&);
1896 CHECK(json::from_ubjson(v0, true, false).is_discarded());
1897
1898 std::vector<uint8_t> vi = {'[', '$', '#'};
1899 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vi), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON value: unexpected end of input", json::parse_error&);
1900 CHECK(json::from_ubjson(vi, true, false).is_discarded());
1901
1902 std::vector<uint8_t> vT = {'[', '$', 'T'};
1903 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vT), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON value: unexpected end of input", json::parse_error&);
1904 CHECK(json::from_ubjson(vT, true, false).is_discarded());
1905 }
1906
1907 SECTION("arrays")
1908 {
1909 std::vector<uint8_t> vST = {'[', '$', 'i', '#', 'i', 2, 1};
1910 json _;
1911 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vST), "[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing UBJSON number: unexpected end of input", json::parse_error&);
1912 CHECK(json::from_ubjson(vST, true, false).is_discarded());
1913
1914 std::vector<uint8_t> vS = {'[', '#', 'i', 2, 'i', 1};
1915 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vS), "[json.exception.parse_error.110] parse error at byte 7: syntax error while parsing UBJSON value: unexpected end of input", json::parse_error&);
1916 CHECK(json::from_ubjson(vS, true, false).is_discarded());
1917
1918 std::vector<uint8_t> v = {'[', 'i', 2, 'i', 1};
1919 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(v), "[json.exception.parse_error.110] parse error at byte 6: syntax error while parsing UBJSON value: unexpected end of input", json::parse_error&);
1920 CHECK(json::from_ubjson(v, true, false).is_discarded());
1921 }
1922
1923 SECTION("objects")
1924 {
1925 std::vector<uint8_t> vST = {'{', '$', 'i', '#', 'i', 2, 'i', 1, 'a', 1};
1926 json _;
1927 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vST), "[json.exception.parse_error.110] parse error at byte 11: syntax error while parsing UBJSON value: unexpected end of input", json::parse_error&);
1928 CHECK(json::from_ubjson(vST, true, false).is_discarded());
1929
1930 std::vector<uint8_t> vT = {'{', '$', 'i', 'i', 1, 'a', 1};
1931 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vT), "[json.exception.parse_error.112] parse error at byte 4: syntax error while parsing UBJSON size: expected '#' after type information; last byte: 0x69", json::parse_error&);
1932 CHECK(json::from_ubjson(vT, true, false).is_discarded());
1933
1934 std::vector<uint8_t> vS = {'{', '#', 'i', 2, 'i', 1, 'a', 'i', 1};
1935 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vS), "[json.exception.parse_error.110] parse error at byte 10: syntax error while parsing UBJSON value: unexpected end of input", json::parse_error&);
1936 CHECK(json::from_ubjson(vS, true, false).is_discarded());
1937
1938 std::vector<uint8_t> v = {'{', 'i', 1, 'a', 'i', 1};
1939 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(v), "[json.exception.parse_error.110] parse error at byte 7: syntax error while parsing UBJSON value: unexpected end of input", json::parse_error&);
1940 CHECK(json::from_ubjson(v, true, false).is_discarded());
1941
1942 std::vector<uint8_t> v2 = {'{', 'i', 1, 'a', 'i', 1, 'i'};
1943 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(v2), "[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing UBJSON number: unexpected end of input", json::parse_error&);
1944 CHECK(json::from_ubjson(v2, true, false).is_discarded());
1945
1946 std::vector<uint8_t> v3 = {'{', 'i', 1, 'a'};
1947 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(v3), "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing UBJSON value: unexpected end of input", json::parse_error&);
1948 CHECK(json::from_ubjson(v3, true, false).is_discarded());
1949
1950 std::vector<uint8_t> vST1 = {'{', '$', 'd', '#', 'i', 2, 'i', 1, 'a'};
1951 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vST1), "[json.exception.parse_error.110] parse error at byte 10: syntax error while parsing UBJSON number: unexpected end of input", json::parse_error&);
1952 CHECK(json::from_ubjson(vST1, true, false).is_discarded());
1953
1954 std::vector<uint8_t> vST2 = {'{', '#', 'i', 2, 'i', 1, 'a'};
1955 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vST2), "[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing UBJSON value: unexpected end of input", json::parse_error&);
1956 CHECK(json::from_ubjson(vST2, true, false).is_discarded());
1957 }
1958 }
1959
1960 SECTION("writing optimized values")
1961 {
1962 SECTION("integer")
1963 {
1964 SECTION("array of i")
1965 {
1966 json j = {1, -1};
1967 std::vector<uint8_t> expected = {'[', '$', 'i', '#', 'i', 2, 1, 0xff};
1968 CHECK(json::to_ubjson(j, true, true) == expected);
1969 }
1970
1971 SECTION("array of U")
1972 {
1973 json j = {200, 201};
1974 std::vector<uint8_t> expected = {'[', '$', 'U', '#', 'i', 2, 0xC8, 0xC9};
1975 CHECK(json::to_ubjson(j, true, true) == expected);
1976 }
1977
1978 SECTION("array of I")
1979 {
1980 json j = {30000, -30000};
1981 std::vector<uint8_t> expected = {'[', '$', 'I', '#', 'i', 2, 0x75, 0x30, 0x8a, 0xd0};
1982 CHECK(json::to_ubjson(j, true, true) == expected);
1983 }
1984
1985 SECTION("array of l")
1986 {
1987 json j = {70000, -70000};
1988 std::vector<uint8_t> expected = {'[', '$', 'l', '#', 'i', 2, 0x00, 0x01, 0x11, 0x70, 0xFF, 0xFE, 0xEE, 0x90};
1989 CHECK(json::to_ubjson(j, true, true) == expected);
1990 }
1991
1992 SECTION("array of L")
1993 {
1994 json j = {5000000000, -5000000000};
1995 std::vector<uint8_t> expected = {'[', '$', 'L', '#', 'i', 2, 0x00, 0x00, 0x00, 0x01, 0x2A, 0x05, 0xF2, 0x00, 0xFF, 0xFF, 0xFF, 0xFE, 0xD5, 0xFA, 0x0E, 0x00};
1996 CHECK(json::to_ubjson(j, true, true) == expected);
1997 }
1998 }
1999
2000 SECTION("unsigned integer")
2001 {
2002 SECTION("array of i")
2003 {
2004 json j = {1u, 2u};
2005 std::vector<uint8_t> expected = {'[', '$', 'i', '#', 'i', 2, 1, 2};
2006 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'i', 1, 'i', 2};
2007 CHECK(json::to_ubjson(j, true, true) == expected);
2008 CHECK(json::to_ubjson(j, true) == expected_size);
2009 }
2010
2011 SECTION("array of U")
2012 {
2013 json j = {200u, 201u};
2014 std::vector<uint8_t> expected = {'[', '$', 'U', '#', 'i', 2, 0xC8, 0xC9};
2015 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'U', 0xC8, 'U', 0xC9};
2016 CHECK(json::to_ubjson(j, true, true) == expected);
2017 CHECK(json::to_ubjson(j, true) == expected_size);
2018 }
2019
2020 SECTION("array of I")
2021 {
2022 json j = {30000u, 30001u};
2023 std::vector<uint8_t> expected = {'[', '$', 'I', '#', 'i', 2, 0x75, 0x30, 0x75, 0x31};
2024 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'I', 0x75, 0x30, 'I', 0x75, 0x31};
2025 CHECK(json::to_ubjson(j, true, true) == expected);
2026 CHECK(json::to_ubjson(j, true) == expected_size);
2027 }
2028
2029 SECTION("array of l")
2030 {
2031 json j = {70000u, 70001u};
2032 std::vector<uint8_t> expected = {'[', '$', 'l', '#', 'i', 2, 0x00, 0x01, 0x11, 0x70, 0x00, 0x01, 0x11, 0x71};
2033 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'l', 0x00, 0x01, 0x11, 0x70, 'l', 0x00, 0x01, 0x11, 0x71};
2034 CHECK(json::to_ubjson(j, true, true) == expected);
2035 CHECK(json::to_ubjson(j, true) == expected_size);
2036 }
2037
2038 SECTION("array of L")
2039 {
2040 json j = {5000000000u, 5000000001u};
2041 std::vector<uint8_t> expected = {'[', '$', 'L', '#', 'i', 2, 0x00, 0x00, 0x00, 0x01, 0x2A, 0x05, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2A, 0x05, 0xF2, 0x01};
2042 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'L', 0x00, 0x00, 0x00, 0x01, 0x2A, 0x05, 0xF2, 0x00, 'L', 0x00, 0x00, 0x00, 0x01, 0x2A, 0x05, 0xF2, 0x01};
2043 CHECK(json::to_ubjson(j, true, true) == expected);
2044 CHECK(json::to_ubjson(j, true) == expected_size);
2045 }
2046 }
2047
2048 SECTION("discarded")
2049 {
2050 json j = {json::value_t::discarded, json::value_t::discarded};
2051 std::vector<uint8_t> expected = {'[', '$', 'N', '#', 'i', 2};
2052 CHECK(json::to_ubjson(j, true, true) == expected);
2053 }
2054 }
2055 }
2056
2057 TEST_CASE("Universal Binary JSON Specification Examples 1")
2058 {
2059 SECTION("Null Value")
2060 {
2061 json j = {{"passcode", nullptr}};
2062 std::vector<uint8_t> v = {'{', 'i', 8, 'p', 'a', 's', 's', 'c', 'o', 'd', 'e', 'Z', '}'};
2063 CHECK(json::to_ubjson(j) == v);
2064 CHECK(json::from_ubjson(v) == j);
2065 }
2066
2067 SECTION("No-Op Value")
2068 {
2069 json j = {"foo", "bar", "baz"};
2070 std::vector<uint8_t> v = {'[', 'S', 'i', 3, 'f', 'o', 'o',
2071 'S', 'i', 3, 'b', 'a', 'r',
2072 'S', 'i', 3, 'b', 'a', 'z', ']'
2073 };
2074 std::vector<uint8_t> v2 = {'[', 'S', 'i', 3, 'f', 'o', 'o', 'N',
2075 'S', 'i', 3, 'b', 'a', 'r', 'N', 'N', 'N',
2076 'S', 'i', 3, 'b', 'a', 'z', 'N', 'N', ']'
2077 };
2078 CHECK(json::to_ubjson(j) == v);
2079 CHECK(json::from_ubjson(v) == j);
2080 CHECK(json::from_ubjson(v2) == j);
2081 }
2082
2083 SECTION("Boolean Types")
2084 {
2085 json j = {{"authorized", true}, {"verified", false}};
2086 std::vector<uint8_t> v = {'{', 'i', 10, 'a', 'u', 't', 'h', 'o', 'r', 'i', 'z', 'e', 'd', 'T',
2087 'i', 8, 'v', 'e', 'r', 'i', 'f', 'i', 'e', 'd', 'F', '}'
2088 };
2089 CHECK(json::to_ubjson(j) == v);
2090 CHECK(json::from_ubjson(v) == j);
2091 }
2092
2093 SECTION("Numeric Types")
2094 {
2095 json j =
2096 {
2097 {"int8", 16},
2098 {"uint8", 255},
2099 {"int16", 32767},
2100 {"int32", 2147483647},
2101 {"int64", 9223372036854775807},
2102 {"float64", 113243.7863123}
2103 };
2104 std::vector<uint8_t> v = {'{',
2105 'i', 7, 'f', 'l', 'o', 'a', 't', '6', '4', 'D', 0x40, 0xfb, 0xa5, 0xbc, 0x94, 0xbc, 0x34, 0xcf,
2106 'i', 5, 'i', 'n', 't', '1', '6', 'I', 0x7f, 0xff,
2107 'i', 5, 'i', 'n', 't', '3', '2', 'l', 0x7f, 0xff, 0xff, 0xff,
2108 'i', 5, 'i', 'n', 't', '6', '4', 'L', 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2109 'i', 4, 'i', 'n', 't', '8', 'i', 16,
2110 'i', 5, 'u', 'i', 'n', 't', '8', 'U', 0xff,
2111 '}'
2112 };
2113 CHECK(json::to_ubjson(j) == v);
2114 CHECK(json::from_ubjson(v) == j);
2115 }
2116
2117 SECTION("Char Type")
2118 {
2119 json j = {{"rolecode", "a"}, {"delim", ";"}};
2120 std::vector<uint8_t> v = {'{', 'i', 5, 'd', 'e', 'l', 'i', 'm', 'C', ';', 'i', 8, 'r', 'o', 'l', 'e', 'c', 'o', 'd', 'e', 'C', 'a', '}'};
2121 //CHECK(json::to_ubjson(j) == v);
2122 CHECK(json::from_ubjson(v) == j);
2123 }
2124
2125 SECTION("String Type")
2126 {
2127 SECTION("English")
2128 {
2129 json j = "hello";
2130 std::vector<uint8_t> v = {'S', 'i', 5, 'h', 'e', 'l', 'l', 'o'};
2131 CHECK(json::to_ubjson(j) == v);
2132 CHECK(json::from_ubjson(v) == j);
2133 }
2134
2135 SECTION("Russian")
2136 {
2137 json j = "привет";
2138 std::vector<uint8_t> v = {'S', 'i', 12, 0xD0, 0xBF, 0xD1, 0x80, 0xD0, 0xB8, 0xD0, 0xB2, 0xD0, 0xB5, 0xD1, 0x82};
2139 CHECK(json::to_ubjson(j) == v);
2140 CHECK(json::from_ubjson(v) == j);
2141 }
2142
2143 SECTION("Russian")
2144 {
2145 json j = "مرحبا";
2146 std::vector<uint8_t> v = {'S', 'i', 10, 0xD9, 0x85, 0xD8, 0xB1, 0xD8, 0xAD, 0xD8, 0xA8, 0xD8, 0xA7};
2147 CHECK(json::to_ubjson(j) == v);
2148 CHECK(json::from_ubjson(v) == j);
2149 }
2150 }
2151
2152 SECTION("Array Type")
2153 {
2154 SECTION("size=false type=false")
2155 {
2156 // note the float has been replaced by a double
2157 json j = {nullptr, true, false, 4782345193, 153.132, "ham"};
2158 std::vector<uint8_t> v = {'[', 'Z', 'T', 'F', 'L', 0x00, 0x00, 0x00, 0x01, 0x1D, 0x0C, 0xCB, 0xE9, 'D', 0x40, 0x63, 0x24, 0x39, 0x58, 0x10, 0x62, 0x4e, 'S', 'i', 3, 'h', 'a', 'm', ']'};
2159 CHECK(json::to_ubjson(j) == v);
2160 CHECK(json::from_ubjson(v) == j);
2161 }
2162
2163 SECTION("size=true type=false")
2164 {
2165 // note the float has been replaced by a double
2166 json j = {nullptr, true, false, 4782345193, 153.132, "ham"};
2167 std::vector<uint8_t> v = {'[', '#', 'i', 6, 'Z', 'T', 'F', 'L', 0x00, 0x00, 0x00, 0x01, 0x1D, 0x0C, 0xCB, 0xE9, 'D', 0x40, 0x63, 0x24, 0x39, 0x58, 0x10, 0x62, 0x4e, 'S', 'i', 3, 'h', 'a', 'm'};
2168 CHECK(json::to_ubjson(j, true) == v);
2169 CHECK(json::from_ubjson(v) == j);
2170 }
2171
2172 SECTION("size=true type=true")
2173 {
2174 // note the float has been replaced by a double
2175 json j = {nullptr, true, false, 4782345193, 153.132, "ham"};
2176 std::vector<uint8_t> v = {'[', '#', 'i', 6, 'Z', 'T', 'F', 'L', 0x00, 0x00, 0x00, 0x01, 0x1D, 0x0C, 0xCB, 0xE9, 'D', 0x40, 0x63, 0x24, 0x39, 0x58, 0x10, 0x62, 0x4e, 'S', 'i', 3, 'h', 'a', 'm'};
2177 CHECK(json::to_ubjson(j, true, true) == v);
2178 CHECK(json::from_ubjson(v) == j);
2179 }
2180 }
2181
2182 SECTION("Object Type")
2183 {
2184 SECTION("size=false type=false")
2185 {
2186 json j =
2187 {
2188 {
2189 "post", {
2190 {"id", 1137},
2191 {"author", "rkalla"},
2192 {"timestamp", 1364482090592},
2193 {"body", "I totally agree!"}
2194 }
2195 }
2196 };
2197 std::vector<uint8_t> v = {'{', 'i', 4, 'p', 'o', 's', 't', '{',
2198 'i', 6, 'a', 'u', 't', 'h', 'o', 'r', 'S', 'i', 6, 'r', 'k', 'a', 'l', 'l', 'a',
2199 'i', 4, 'b', 'o', 'd', 'y', 'S', 'i', 16, 'I', ' ', 't', 'o', 't', 'a', 'l', 'l', 'y', ' ', 'a', 'g', 'r', 'e', 'e', '!',
2200 'i', 2, 'i', 'd', 'I', 0x04, 0x71,
2201 'i', 9, 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'L', 0x00, 0x00, 0x01, 0x3D, 0xB1, 0x78, 0x66, 0x60,
2202 '}', '}'
2203 };
2204 CHECK(json::to_ubjson(j) == v);
2205 CHECK(json::from_ubjson(v) == j);
2206 }
2207
2208 SECTION("size=true type=false")
2209 {
2210 json j =
2211 {
2212 {
2213 "post", {
2214 {"id", 1137},
2215 {"author", "rkalla"},
2216 {"timestamp", 1364482090592},
2217 {"body", "I totally agree!"}
2218 }
2219 }
2220 };
2221 std::vector<uint8_t> v = {'{', '#', 'i', 1, 'i', 4, 'p', 'o', 's', 't', '{', '#', 'i', 4,
2222 'i', 6, 'a', 'u', 't', 'h', 'o', 'r', 'S', 'i', 6, 'r', 'k', 'a', 'l', 'l', 'a',
2223 'i', 4, 'b', 'o', 'd', 'y', 'S', 'i', 16, 'I', ' ', 't', 'o', 't', 'a', 'l', 'l', 'y', ' ', 'a', 'g', 'r', 'e', 'e', '!',
2224 'i', 2, 'i', 'd', 'I', 0x04, 0x71,
2225 'i', 9, 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'L', 0x00, 0x00, 0x01, 0x3D, 0xB1, 0x78, 0x66, 0x60
2226 };
2227 CHECK(json::to_ubjson(j, true) == v);
2228 CHECK(json::from_ubjson(v) == j);
2229 }
2230
2231 SECTION("size=true type=true")
2232 {
2233 json j =
2234 {
2235 {
2236 "post", {
2237 {"id", 1137},
2238 {"author", "rkalla"},
2239 {"timestamp", 1364482090592},
2240 {"body", "I totally agree!"}
2241 }
2242 }
2243 };
2244 std::vector<uint8_t> v = {'{', '$', '{', '#', 'i', 1, 'i', 4, 'p', 'o', 's', 't', '#', 'i', 4,
2245 'i', 6, 'a', 'u', 't', 'h', 'o', 'r', 'S', 'i', 6, 'r', 'k', 'a', 'l', 'l', 'a',
2246 'i', 4, 'b', 'o', 'd', 'y', 'S', 'i', 16, 'I', ' ', 't', 'o', 't', 'a', 'l', 'l', 'y', ' ', 'a', 'g', 'r', 'e', 'e', '!',
2247 'i', 2, 'i', 'd', 'I', 0x04, 0x71,
2248 'i', 9, 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'L', 0x00, 0x00, 0x01, 0x3D, 0xB1, 0x78, 0x66, 0x60
2249 };
2250 CHECK(json::to_ubjson(j, true, true) == v);
2251 CHECK(json::from_ubjson(v) == j);
2252 }
2253 }
2254
2255 SECTION("Optimized Format")
2256 {
2257 SECTION("Array Example")
2258 {
2259 SECTION("No Optimization")
2260 {
2261 // note the floats have been replaced by doubles
2262 json j = {29.97, 31.13, 67.0, 2.113, 23.888};
2263 std::vector<uint8_t> v = {'[',
2264 'D', 0x40, 0x3d, 0xf8, 0x51, 0xeb, 0x85, 0x1e, 0xb8,
2265 'D', 0x40, 0x3f, 0x21, 0x47, 0xae, 0x14, 0x7a, 0xe1,
2266 'D', 0x40, 0x50, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
2267 'D', 0x40, 0x00, 0xe7, 0x6c, 0x8b, 0x43, 0x95, 0x81,
2268 'D', 0x40, 0x37, 0xe3, 0x53, 0xf7, 0xce, 0xd9, 0x17,
2269 ']'
2270 };
2271 CHECK(json::to_ubjson(j) == v);
2272 CHECK(json::from_ubjson(v) == j);
2273 }
2274
2275 SECTION("Optimized with count")
2276 {
2277 // note the floats have been replaced by doubles
2278 json j = {29.97, 31.13, 67.0, 2.113, 23.888};
2279 std::vector<uint8_t> v = {'[', '#', 'i', 5,
2280 'D', 0x40, 0x3d, 0xf8, 0x51, 0xeb, 0x85, 0x1e, 0xb8,
2281 'D', 0x40, 0x3f, 0x21, 0x47, 0xae, 0x14, 0x7a, 0xe1,
2282 'D', 0x40, 0x50, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
2283 'D', 0x40, 0x00, 0xe7, 0x6c, 0x8b, 0x43, 0x95, 0x81,
2284 'D', 0x40, 0x37, 0xe3, 0x53, 0xf7, 0xce, 0xd9, 0x17
2285 };
2286 CHECK(json::to_ubjson(j, true) == v);
2287 CHECK(json::from_ubjson(v) == j);
2288 }
2289
2290 SECTION("Optimized with type & count")
2291 {
2292 // note the floats have been replaced by doubles
2293 json j = {29.97, 31.13, 67.0, 2.113, 23.888};
2294 std::vector<uint8_t> v = {'[', '$', 'D', '#', 'i', 5,
2295 0x40, 0x3d, 0xf8, 0x51, 0xeb, 0x85, 0x1e, 0xb8,
2296 0x40, 0x3f, 0x21, 0x47, 0xae, 0x14, 0x7a, 0xe1,
2297 0x40, 0x50, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
2298 0x40, 0x00, 0xe7, 0x6c, 0x8b, 0x43, 0x95, 0x81,
2299 0x40, 0x37, 0xe3, 0x53, 0xf7, 0xce, 0xd9, 0x17
2300 };
2301 CHECK(json::to_ubjson(j, true, true) == v);
2302 CHECK(json::from_ubjson(v) == j);
2303 }
2304 }
2305
2306 SECTION("Object Example")
2307 {
2308 SECTION("No Optimization")
2309 {
2310 // note the floats have been replaced by doubles
2311 json j = { {"lat", 29.976}, {"long", 31.131}, {"alt", 67.0} };
2312 std::vector<uint8_t> v = {'{',
2313 'i', 3, 'a', 'l', 't', 'D', 0x40, 0x50, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
2314 'i', 3, 'l', 'a', 't', 'D', 0x40, 0x3d, 0xf9, 0xdb, 0x22, 0xd0, 0xe5, 0x60,
2315 'i', 4, 'l', 'o', 'n', 'g', 'D', 0x40, 0x3f, 0x21, 0x89, 0x37, 0x4b, 0xc6, 0xa8,
2316 '}'
2317 };
2318 CHECK(json::to_ubjson(j) == v);
2319 CHECK(json::from_ubjson(v) == j);
2320 }
2321
2322 SECTION("Optimized with count")
2323 {
2324 // note the floats have been replaced by doubles
2325 json j = { {"lat", 29.976}, {"long", 31.131}, {"alt", 67.0} };
2326 std::vector<uint8_t> v = {'{', '#', 'i', 3,
2327 'i', 3, 'a', 'l', 't', 'D', 0x40, 0x50, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
2328 'i', 3, 'l', 'a', 't', 'D', 0x40, 0x3d, 0xf9, 0xdb, 0x22, 0xd0, 0xe5, 0x60,
2329 'i', 4, 'l', 'o', 'n', 'g', 'D', 0x40, 0x3f, 0x21, 0x89, 0x37, 0x4b, 0xc6, 0xa8
2330 };
2331 CHECK(json::to_ubjson(j, true) == v);
2332 CHECK(json::from_ubjson(v) == j);
2333 }
2334
2335 SECTION("Optimized with type & count")
2336 {
2337 // note the floats have been replaced by doubles
2338 json j = { {"lat", 29.976}, {"long", 31.131}, {"alt", 67.0} };
2339 std::vector<uint8_t> v = {'{', '$', 'D', '#', 'i', 3,
2340 'i', 3, 'a', 'l', 't', 0x40, 0x50, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
2341 'i', 3, 'l', 'a', 't', 0x40, 0x3d, 0xf9, 0xdb, 0x22, 0xd0, 0xe5, 0x60,
2342 'i', 4, 'l', 'o', 'n', 'g', 0x40, 0x3f, 0x21, 0x89, 0x37, 0x4b, 0xc6, 0xa8
2343 };
2344 CHECK(json::to_ubjson(j, true, true) == v);
2345 CHECK(json::from_ubjson(v) == j);
2346 }
2347 }
2348
2349 SECTION("Special Cases (Null, No-Op and Boolean)")
2350 {
2351 SECTION("Array")
2352 {
2353 std::vector<uint8_t> v = {'[', '$', 'N', '#', 'I', 0x02, 0x00};
2354 CHECK(json::from_ubjson(v) == json::array());
2355 }
2356
2357 SECTION("Object")
2358 {
2359 std::vector<uint8_t> v = {'{', '$', 'Z', '#', 'i', 3, 'i', 4, 'n', 'a', 'm', 'e', 'i', 8, 'p', 'a', 's', 's', 'w', 'o', 'r', 'd', 'i', 5, 'e', 'm', 'a', 'i', 'l'};
2360 CHECK(json::from_ubjson(v) == json({ {"name", nullptr}, {"password", nullptr}, {"email", nullptr} }));
2361 }
2362 }
2363 }
2364 }
2365
2366 #if !defined(JSON_NOEXCEPTION)
2367 TEST_CASE("all UBJSON first bytes")
2368 {
2369 // these bytes will fail immediately with exception parse_error.112
2370 std::set<uint8_t> supported =
2371 {
2372 'T', 'F', 'Z', 'U', 'i', 'I', 'l', 'L', 'd', 'D', 'C', 'S', '[', '{', 'N', 'H'
2373 };
2374
2375 for (auto i = 0; i < 256; ++i)
2376 {
2377 const auto byte = static_cast<uint8_t>(i);
CAPTURE(byte)2378 CAPTURE(byte)
2379
2380 try
2381 {
2382 auto res = json::from_ubjson(std::vector<uint8_t>(1, byte));
2383 }
2384 catch (const json::parse_error& e)
2385 {
2386 // check that parse_error.112 is only thrown if the
2387 // first byte is not in the supported set
2388 INFO_WITH_TEMP(e.what());
2389 if (supported.find(byte) == supported.end())
2390 {
2391 CHECK(e.id == 112);
2392 }
2393 else
2394 {
2395 CHECK(e.id != 112);
2396 }
2397 }
2398 }
2399 }
2400 #endif
2401
skip()2402 TEST_CASE("UBJSON roundtrips" * doctest::skip())
2403 {
2404 SECTION("input from self-generated UBJSON files")
2405 {
2406 for (std::string filename :
2407 {
2408 TEST_DATA_DIRECTORY "/json_nlohmann_tests/all_unicode.json",
2409 TEST_DATA_DIRECTORY "/json.org/1.json",
2410 TEST_DATA_DIRECTORY "/json.org/2.json",
2411 TEST_DATA_DIRECTORY "/json.org/3.json",
2412 TEST_DATA_DIRECTORY "/json.org/4.json",
2413 TEST_DATA_DIRECTORY "/json.org/5.json",
2414 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip01.json",
2415 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip02.json",
2416 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip03.json",
2417 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip04.json",
2418 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip05.json",
2419 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip06.json",
2420 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip07.json",
2421 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip08.json",
2422 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip09.json",
2423 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip10.json",
2424 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip11.json",
2425 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip12.json",
2426 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip13.json",
2427 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip14.json",
2428 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip15.json",
2429 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip16.json",
2430 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip17.json",
2431 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip18.json",
2432 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip19.json",
2433 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip20.json",
2434 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip21.json",
2435 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip22.json",
2436 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip23.json",
2437 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip24.json",
2438 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip25.json",
2439 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip26.json",
2440 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip27.json",
2441 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip28.json",
2442 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip29.json",
2443 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip30.json",
2444 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip31.json",
2445 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip32.json",
2446 TEST_DATA_DIRECTORY "/json_testsuite/sample.json",
2447 TEST_DATA_DIRECTORY "/json_tests/pass1.json",
2448 TEST_DATA_DIRECTORY "/json_tests/pass2.json",
2449 TEST_DATA_DIRECTORY "/json_tests/pass3.json"
2450 })
2451 {
2452 CAPTURE(filename)
2453
2454 {
2455 INFO_WITH_TEMP(filename + ": std::vector<uint8_t>");
2456 // parse JSON file
2457 std::ifstream f_json(filename);
2458 json j1 = json::parse(f_json);
2459
2460 // parse UBJSON file
2461 auto packed = utils::read_binary_file(filename + ".ubjson");
2462 json j2;
2463 CHECK_NOTHROW(j2 = json::from_ubjson(packed));
2464
2465 // compare parsed JSON values
2466 CHECK(j1 == j2);
2467 }
2468
2469 {
2470 INFO_WITH_TEMP(filename + ": std::ifstream");
2471 // parse JSON file
2472 std::ifstream f_json(filename);
2473 json j1 = json::parse(f_json);
2474
2475 // parse UBJSON file
2476 std::ifstream f_ubjson(filename + ".ubjson", std::ios::binary);
2477 json j2;
2478 CHECK_NOTHROW(j2 = json::from_ubjson(f_ubjson));
2479
2480 // compare parsed JSON values
2481 CHECK(j1 == j2);
2482 }
2483
2484 {
2485 INFO_WITH_TEMP(filename + ": uint8_t* and size");
2486 // parse JSON file
2487 std::ifstream f_json(filename);
2488 json j1 = json::parse(f_json);
2489
2490 // parse UBJSON file
2491 auto packed = utils::read_binary_file(filename + ".ubjson");
2492 json j2;
2493 CHECK_NOTHROW(j2 = json::from_ubjson({packed.data(), packed.size()}));
2494
2495 // compare parsed JSON values
2496 CHECK(j1 == j2);
2497 }
2498
2499 {
2500 INFO_WITH_TEMP(filename + ": output to output adapters");
2501 // parse JSON file
2502 std::ifstream f_json(filename);
2503 json j1 = json::parse(f_json);
2504
2505 // parse UBJSON file
2506 auto packed = utils::read_binary_file(filename + ".ubjson");
2507
2508 {
2509 INFO_WITH_TEMP(filename + ": output adapters: std::vector<uint8_t>");
2510 std::vector<uint8_t> vec;
2511 json::to_ubjson(j1, vec);
2512 CHECK(vec == packed);
2513 }
2514 }
2515 }
2516 }
2517 }
2518