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