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