• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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