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