• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //     __ _____ _____ _____
2 //  __|  |   __|     |   | |  JSON for Modern C++ (supporting code)
3 // |  |  |__   |  |  | | | |  version 3.11.3
4 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5 //
6 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
7 // SPDX-License-Identifier: MIT
8 
9 #include "doctest_compatibility.h"
10 
11 #define JSON_TESTS_PRIVATE
12 #include <nlohmann/json.hpp>
13 using nlohmann::json;
14 
15 #include <algorithm>
16 #include <climits>
17 #include <limits>
18 #include <iostream>
19 #include <fstream>
20 #include <set>
21 #include "make_test_data_available.hpp"
22 #include "test_utils.hpp"
23 
24 namespace
25 {
26 class SaxCountdown
27 {
28   public:
SaxCountdown(const int count)29     explicit SaxCountdown(const int count) : events_left(count)
30     {}
31 
null()32     bool null()
33     {
34         return events_left-- > 0;
35     }
36 
boolean(bool)37     bool boolean(bool /*unused*/)
38     {
39         return events_left-- > 0;
40     }
41 
number_integer(json::number_integer_t)42     bool number_integer(json::number_integer_t /*unused*/)
43     {
44         return events_left-- > 0;
45     }
46 
number_unsigned(json::number_unsigned_t)47     bool number_unsigned(json::number_unsigned_t /*unused*/)
48     {
49         return events_left-- > 0;
50     }
51 
number_float(json::number_float_t,const std::string &)52     bool number_float(json::number_float_t /*unused*/, const std::string& /*unused*/)
53     {
54         return events_left-- > 0;
55     }
56 
string(std::string &)57     bool string(std::string& /*unused*/)
58     {
59         return events_left-- > 0;
60     }
61 
binary(std::vector<std::uint8_t> &)62     bool binary(std::vector<std::uint8_t>& /*unused*/)
63     {
64         return events_left-- > 0;
65     }
66 
start_object(std::size_t)67     bool start_object(std::size_t /*unused*/)
68     {
69         return events_left-- > 0;
70     }
71 
key(std::string &)72     bool key(std::string& /*unused*/)
73     {
74         return events_left-- > 0;
75     }
76 
end_object()77     bool end_object()
78     {
79         return events_left-- > 0;
80     }
81 
start_array(std::size_t)82     bool start_array(std::size_t /*unused*/)
83     {
84         return events_left-- > 0;
85     }
86 
end_array()87     bool end_array()
88     {
89         return events_left-- > 0;
90     }
91 
parse_error(std::size_t,const std::string &,const json::exception &)92     bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const json::exception& /*unused*/) // NOLINT(readability-convert-member-functions-to-static)
93     {
94         return false;
95     }
96 
97   private:
98     int events_left = 0;
99 };
100 } // namespace
101 
102 // at some point in the future, a unit test dedicated to type traits might be a good idea
103 template <typename OfType, typename T, bool MinInRange, bool MaxInRange>
104 struct trait_test_arg
105 {
106     using of_type = OfType;
107     using type = T;
108     static constexpr bool min_in_range = MinInRange;
109     static constexpr bool max_in_range = MaxInRange;
110 };
111 
112 TEST_CASE_TEMPLATE_DEFINE("value_in_range_of trait", T, value_in_range_of_test)
113 {
114     using nlohmann::detail::value_in_range_of;
115 
116     using of_type = typename T::of_type;
117     using type = typename T::type;
118     constexpr bool min_in_range = T::min_in_range;
119     constexpr bool max_in_range = T::max_in_range;
120 
121     type const val_min = std::numeric_limits<type>::min();
122     type const val_min2 = val_min + 1;
123     type const val_max = std::numeric_limits<type>::max();
124     type const val_max2 = val_max - 1;
125 
126     REQUIRE(CHAR_BIT == 8);
127 
128     std::string of_type_str;
129     if (std::is_unsigned<of_type>::value)
130     {
131         of_type_str += "u";
132     }
133     of_type_str += "int";
134     of_type_str += std::to_string(sizeof(of_type) * 8);
135 
136     INFO("of_type := ", of_type_str);
137 
138     std::string type_str;
139     if (std::is_unsigned<type>::value)
140     {
141         type_str += "u";
142     }
143     type_str += "int";
144     type_str += std::to_string(sizeof(type) * 8);
145 
146     INFO("type := ", type_str);
147 
148     CAPTURE(val_min);
149     CAPTURE(min_in_range);
150     CAPTURE(val_max);
151     CAPTURE(max_in_range);
152 
153     if (min_in_range)
154     {
155         CHECK(value_in_range_of<of_type>(val_min));
156         CHECK(value_in_range_of<of_type>(val_min2));
157     }
158     else
159     {
160         CHECK_FALSE(value_in_range_of<of_type>(val_min));
161         CHECK_FALSE(value_in_range_of<of_type>(val_min2));
162     }
163 
164     if (max_in_range)
165     {
166         CHECK(value_in_range_of<of_type>(val_max));
167         CHECK(value_in_range_of<of_type>(val_max2));
168     }
169     else
170     {
171         CHECK_FALSE(value_in_range_of<of_type>(val_max));
172         CHECK_FALSE(value_in_range_of<of_type>(val_max2));
173     }
174 }
175 
176 TEST_CASE_TEMPLATE_INVOKE(value_in_range_of_test, \
177                           trait_test_arg<std::int32_t, std::int32_t, true, true>, \
178                           trait_test_arg<std::int32_t, std::uint32_t, true, false>, \
179                           trait_test_arg<std::uint32_t, std::int32_t, false, true>, \
180                           trait_test_arg<std::uint32_t, std::uint32_t, true, true>, \
181                           trait_test_arg<std::int32_t, std::int64_t, false, false>, \
182                           trait_test_arg<std::int32_t, std::uint64_t, true, false>, \
183                           trait_test_arg<std::uint32_t, std::int64_t, false, false>, \
184                           trait_test_arg<std::uint32_t, std::uint64_t, true, false>, \
185                           trait_test_arg<std::int64_t, std::int32_t, true, true>, \
186                           trait_test_arg<std::int64_t, std::uint32_t, true, true>, \
187                           trait_test_arg<std::uint64_t, std::int32_t, false, true>, \
188                           trait_test_arg<std::uint64_t, std::uint32_t, true, true>, \
189                           trait_test_arg<std::int64_t, std::int64_t, true, true>, \
190                           trait_test_arg<std::int64_t, std::uint64_t, true, false>, \
191                           trait_test_arg<std::uint64_t, std::int64_t, false, true>, \
192                           trait_test_arg<std::uint64_t, std::uint64_t, true, true>);
193 
194 #if SIZE_MAX == 0xffffffff
195 TEST_CASE_TEMPLATE_INVOKE(value_in_range_of_test, \
196                           trait_test_arg<std::size_t, std::int32_t, false, true>, \
197                           trait_test_arg<std::size_t, std::uint32_t, true, true>, \
198                           trait_test_arg<std::size_t, std::int64_t, false, false>, \
199                           trait_test_arg<std::size_t, std::uint64_t, true, false>);
200 #else
201 TEST_CASE_TEMPLATE_INVOKE(value_in_range_of_test, \
202                           trait_test_arg<std::size_t, std::int32_t, false, true>, \
203                           trait_test_arg<std::size_t, std::uint32_t, true, true>, \
204                           trait_test_arg<std::size_t, std::int64_t, false, true>, \
205                           trait_test_arg<std::size_t, std::uint64_t, true, true>);
206 #endif
207 
208 TEST_CASE("BJData")
209 {
210     SECTION("binary_reader BJData LUT arrays are sorted")
211     {
212         std::vector<std::uint8_t> const data;
213         auto ia = nlohmann::detail::input_adapter(data);
214         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
215         nlohmann::detail::binary_reader<json, decltype(ia)> const br{std::move(ia), json::input_format_t::bjdata};
216 
217         CHECK(std::is_sorted(br.bjd_optimized_type_markers.begin(), br.bjd_optimized_type_markers.end()));
218         CHECK(std::is_sorted(br.bjd_types_map.begin(), br.bjd_types_map.end()));
219     }
220 
221     SECTION("individual values")
222     {
223         SECTION("discarded")
224         {
225             // discarded values are not serialized
226             json const j = json::value_t::discarded;
227             const auto result = json::to_bjdata(j);
228             CHECK(result.empty());
229         }
230 
231         SECTION("null")
232         {
233             json const j = nullptr;
234             std::vector<uint8_t> const expected = {'Z'};
235             const auto result = json::to_bjdata(j);
236             CHECK(result == expected);
237 
238             // roundtrip
239             CHECK(json::from_bjdata(result) == j);
240             CHECK(json::from_bjdata(result, true, false) == j);
241         }
242 
243         SECTION("boolean")
244         {
245             SECTION("true")
246             {
247                 json const j = true;
248                 std::vector<uint8_t> const expected = {'T'};
249                 const auto result = json::to_bjdata(j);
250                 CHECK(result == expected);
251 
252                 // roundtrip
253                 CHECK(json::from_bjdata(result) == j);
254                 CHECK(json::from_bjdata(result, true, false) == j);
255             }
256 
257             SECTION("false")
258             {
259                 json const j = false;
260                 std::vector<uint8_t> const expected = {'F'};
261                 const auto result = json::to_bjdata(j);
262                 CHECK(result == expected);
263 
264                 // roundtrip
265                 CHECK(json::from_bjdata(result) == j);
266                 CHECK(json::from_bjdata(result, true, false) == j);
267             }
268         }
269 
270         SECTION("number")
271         {
272             SECTION("signed")
273             {
274                 SECTION("-9223372036854775808..-2147483649 (int64)")
275                 {
276                     std::vector<int64_t> const numbers
277                     {
278                         (std::numeric_limits<int64_t>::min)(),
279                         -1000000000000000000LL,
280                         -100000000000000000LL,
281                         -10000000000000000LL,
282                         -1000000000000000LL,
283                         -100000000000000LL,
284                         -10000000000000LL,
285                         -1000000000000LL,
286                         -100000000000LL,
287                         -10000000000LL,
288                         -2147483649LL,
289                     };
290                     for (const auto i : numbers)
291                     {
292                         CAPTURE(i)
293 
294                         // create JSON value with integer number
295                         json const j = i;
296 
297                         // check type
298                         CHECK(j.is_number_integer());
299 
300                         // create expected byte vector
301                         std::vector<uint8_t> const expected
302                         {
303                             static_cast<uint8_t>('L'),
304                             static_cast<uint8_t>(i & 0xff),
305                             static_cast<uint8_t>((i >> 8) & 0xff),
306                             static_cast<uint8_t>((i >> 16) & 0xff),
307                             static_cast<uint8_t>((i >> 24) & 0xff),
308                             static_cast<uint8_t>((i >> 32) & 0xff),
309                             static_cast<uint8_t>((i >> 40) & 0xff),
310                             static_cast<uint8_t>((i >> 48) & 0xff),
311                             static_cast<uint8_t>((i >> 56) & 0xff),
312                         };
313 
314                         // compare result + size
315                         const auto result = json::to_bjdata(j);
316                         CHECK(result == expected);
317                         CHECK(result.size() == 9);
318 
319                         // check individual bytes
320                         CHECK(result[0] == 'L');
321                         int64_t const restored = (static_cast<int64_t>(result[8]) << 070) +
322                                                  (static_cast<int64_t>(result[7]) << 060) +
323                                                  (static_cast<int64_t>(result[6]) << 050) +
324                                                  (static_cast<int64_t>(result[5]) << 040) +
325                                                  (static_cast<int64_t>(result[4]) << 030) +
326                                                  (static_cast<int64_t>(result[3]) << 020) +
327                                                  (static_cast<int64_t>(result[2]) << 010) +
328                                                  static_cast<int64_t>(result[1]);
329                         CHECK(restored == i);
330 
331                         // roundtrip
332                         CHECK(json::from_bjdata(result) == j);
333                         CHECK(json::from_bjdata(result, true, false) == j);
334                     }
335                 }
336 
337                 SECTION("-2147483648..-32769 (int32)")
338                 {
339                     std::vector<int32_t> const numbers
340                     {
341                         -32769,
342                             -100000,
343                             -1000000,
344                             -10000000,
345                             -100000000,
346                             -1000000000,
347                             -2147483647 - 1, // https://stackoverflow.com/a/29356002/266378
348                         };
349                     for (const auto i : numbers)
350                     {
351                         CAPTURE(i)
352 
353                         // create JSON value with integer number
354                         json const j = i;
355 
356                         // check type
357                         CHECK(j.is_number_integer());
358 
359                         // create expected byte vector
360                         std::vector<uint8_t> const expected
361                         {
362                             static_cast<uint8_t>('l'),
363                             static_cast<uint8_t>(i & 0xff),
364                             static_cast<uint8_t>((i >> 8) & 0xff),
365                             static_cast<uint8_t>((i >> 16) & 0xff),
366                             static_cast<uint8_t>((i >> 24) & 0xff),
367                         };
368 
369                         // compare result + size
370                         const auto result = json::to_bjdata(j);
371                         CHECK(result == expected);
372                         CHECK(result.size() == 5);
373 
374                         // check individual bytes
375                         CHECK(result[0] == 'l');
376                         int32_t const restored = (static_cast<int32_t>(result[4]) << 030) +
377                                                  (static_cast<int32_t>(result[3]) << 020) +
378                                                  (static_cast<int32_t>(result[2]) << 010) +
379                                                  static_cast<int32_t>(result[1]);
380                         CHECK(restored == i);
381 
382                         // roundtrip
383                         CHECK(json::from_bjdata(result) == j);
384                         CHECK(json::from_bjdata(result, true, false) == j);
385                     }
386                 }
387 
388                 SECTION("-32768..-129 (int16)")
389                 {
390                     for (int32_t i = -32768; i <= -129; ++i)
391                     {
392                         CAPTURE(i)
393 
394                         // create JSON value with integer number
395                         json const j = i;
396 
397                         // check type
398                         CHECK(j.is_number_integer());
399 
400                         // create expected byte vector
401                         std::vector<uint8_t> const expected
402                         {
403                             static_cast<uint8_t>('I'),
404                             static_cast<uint8_t>(i & 0xff),
405                             static_cast<uint8_t>((i >> 8) & 0xff),
406                         };
407 
408                         // compare result + size
409                         const auto result = json::to_bjdata(j);
410                         CHECK(result == expected);
411                         CHECK(result.size() == 3);
412 
413                         // check individual bytes
414                         CHECK(result[0] == 'I');
415                         auto const restored = static_cast<int16_t>(((result[2] << 8) + result[1]));
416                         CHECK(restored == i);
417 
418                         // roundtrip
419                         CHECK(json::from_bjdata(result) == j);
420                         CHECK(json::from_bjdata(result, true, false) == j);
421                     }
422                 }
423 
424                 SECTION("-9263 (int16)")
425                 {
426                     json const j = -9263;
427                     std::vector<uint8_t> const expected = {'I', 0xd1, 0xdb};
428 
429                     // compare result + size
430                     const auto result = json::to_bjdata(j);
431                     CHECK(result == expected);
432                     CHECK(result.size() == 3);
433 
434                     // check individual bytes
435                     CHECK(result[0] == 'I');
436                     auto const restored = static_cast<int16_t>(((result[2] << 8) + result[1]));
437                     CHECK(restored == -9263);
438 
439                     // roundtrip
440                     CHECK(json::from_bjdata(result) == j);
441                     CHECK(json::from_bjdata(result, true, false) == j);
442                 }
443 
444                 SECTION("-128..-1 (int8)")
445                 {
446                     for (auto i = -128; i <= -1; ++i)
447                     {
448                         CAPTURE(i)
449 
450                         // create JSON value with integer number
451                         json const j = i;
452 
453                         // check type
454                         CHECK(j.is_number_integer());
455 
456                         // create expected byte vector
457                         std::vector<uint8_t> const expected
458                         {
459                             'i',
460                             static_cast<uint8_t>(i),
461                         };
462 
463                         // compare result + size
464                         const auto result = json::to_bjdata(j);
465                         CHECK(result == expected);
466                         CHECK(result.size() == 2);
467 
468                         // check individual bytes
469                         CHECK(result[0] == 'i');
470                         CHECK(static_cast<int8_t>(result[1]) == i);
471 
472                         // roundtrip
473                         CHECK(json::from_bjdata(result) == j);
474                         CHECK(json::from_bjdata(result, true, false) == j);
475                     }
476                 }
477 
478                 SECTION("0..127 (int8)")
479                 {
480                     for (size_t i = 0; i <= 127; ++i)
481                     {
482                         CAPTURE(i)
483 
484                         // create JSON value with integer number
485                         json j = -1;
486                         j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
487 
488                         // check type
489                         CHECK(j.is_number_integer());
490 
491                         // create expected byte vector
492                         std::vector<uint8_t> const expected
493                         {
494                             static_cast<uint8_t>('i'),
495                             static_cast<uint8_t>(i),
496                         };
497 
498                         // compare result + size
499                         const auto result = json::to_bjdata(j);
500                         CHECK(result == expected);
501                         CHECK(result.size() == 2);
502 
503                         // check individual bytes
504                         CHECK(result[0] == 'i');
505                         CHECK(result[1] == i);
506 
507                         // roundtrip
508                         CHECK(json::from_bjdata(result) == j);
509                         CHECK(json::from_bjdata(result, true, false) == j);
510                     }
511                 }
512 
513                 SECTION("128..255 (uint8)")
514                 {
515                     for (size_t i = 128; i <= 255; ++i)
516                     {
517                         CAPTURE(i)
518 
519                         // create JSON value with integer number
520                         json j = -1;
521                         j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
522 
523                         // check type
524                         CHECK(j.is_number_integer());
525 
526                         // create expected byte vector
527                         std::vector<uint8_t> const expected
528                         {
529                             static_cast<uint8_t>('U'),
530                             static_cast<uint8_t>(i),
531                         };
532 
533                         // compare result + size
534                         const auto result = json::to_bjdata(j);
535                         CHECK(result == expected);
536                         CHECK(result.size() == 2);
537 
538                         // check individual bytes
539                         CHECK(result[0] == 'U');
540                         CHECK(result[1] == i);
541 
542                         // roundtrip
543                         CHECK(json::from_bjdata(result) == j);
544                         CHECK(json::from_bjdata(result, true, false) == j);
545                     }
546                 }
547 
548                 SECTION("256..32767 (int16)")
549                 {
550                     for (size_t i = 256; i <= 32767; ++i)
551                     {
552                         CAPTURE(i)
553 
554                         // create JSON value with integer number
555                         json j = -1;
556                         j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
557 
558                         // check type
559                         CHECK(j.is_number_integer());
560 
561                         // create expected byte vector
562                         std::vector<uint8_t> const expected
563                         {
564                             static_cast<uint8_t>('I'),
565                             static_cast<uint8_t>(i & 0xff),
566                             static_cast<uint8_t>((i >> 8) & 0xff),
567                         };
568 
569                         // compare result + size
570                         const auto result = json::to_bjdata(j);
571                         CHECK(result == expected);
572                         CHECK(result.size() == 3);
573 
574                         // check individual bytes
575                         CHECK(result[0] == 'I');
576                         auto const restored = static_cast<uint16_t>(static_cast<uint8_t>(result[2]) * 256 + static_cast<uint8_t>(result[1]));
577                         CHECK(restored == i);
578 
579                         // roundtrip
580                         CHECK(json::from_bjdata(result) == j);
581                         CHECK(json::from_bjdata(result, true, false) == j);
582                     }
583                 }
584 
585                 SECTION("32768..65535 (uint16)")
586                 {
587                     for (const uint32_t i :
588                             {
589                                 32768u, 55555u, 65535u
590                             })
591                     {
592                         CAPTURE(i)
593 
594                         // create JSON value with integer number
595                         json j = -1;
596                         j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
597 
598                         // check type
599                         CHECK(j.is_number_integer());
600 
601                         // create expected byte vector
602                         std::vector<uint8_t> const expected
603                         {
604                             static_cast<uint8_t>('u'),
605                             static_cast<uint8_t>(i & 0xff),
606                             static_cast<uint8_t>((i >> 8) & 0xff),
607                         };
608 
609                         // compare result + size
610                         const auto result = json::to_bjdata(j);
611                         CHECK(result == expected);
612                         CHECK(result.size() == 3);
613 
614                         // check individual bytes
615                         CHECK(result[0] == 'u');
616                         auto const restored = static_cast<uint16_t>(static_cast<uint8_t>(result[2]) * 256 + static_cast<uint8_t>(result[1]));
617                         CHECK(restored == i);
618 
619                         // roundtrip
620                         CHECK(json::from_bjdata(result) == j);
621                         CHECK(json::from_bjdata(result, true, false) == j);
622                     }
623                 }
624 
625                 SECTION("65536..2147483647 (int32)")
626                 {
627                     for (const uint32_t i :
628                             {
629                                 65536u, 77777u, 2147483647u
630                             })
631                     {
632                         CAPTURE(i)
633 
634                         // create JSON value with integer number
635                         json j = -1;
636                         j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
637 
638                         // check type
639                         CHECK(j.is_number_integer());
640 
641                         // create expected byte vector
642                         std::vector<uint8_t> const expected
643                         {
644                             'l',
645                             static_cast<uint8_t>(i & 0xff),
646                             static_cast<uint8_t>((i >> 8) & 0xff),
647                             static_cast<uint8_t>((i >> 16) & 0xff),
648                             static_cast<uint8_t>((i >> 24) & 0xff),
649                         };
650 
651                         // compare result + size
652                         const auto result = json::to_bjdata(j);
653                         CHECK(result == expected);
654                         CHECK(result.size() == 5);
655 
656                         // check individual bytes
657                         CHECK(result[0] == 'l');
658                         uint32_t const restored = (static_cast<uint32_t>(result[4]) << 030) +
659                                                   (static_cast<uint32_t>(result[3]) << 020) +
660                                                   (static_cast<uint32_t>(result[2]) << 010) +
661                                                   static_cast<uint32_t>(result[1]);
662                         CHECK(restored == i);
663 
664                         // roundtrip
665                         CHECK(json::from_bjdata(result) == j);
666                         CHECK(json::from_bjdata(result, true, false) == j);
667                     }
668                 }
669 
670                 SECTION("2147483648..4294967295 (uint32)")
671                 {
672                     for (const uint32_t i :
673                             {
674                                 2147483648u, 3333333333u, 4294967295u
675                             })
676                     {
677                         CAPTURE(i)
678 
679                         // create JSON value with integer number
680                         json j = -1;
681                         j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
682 
683                         // check type
684                         CHECK(j.is_number_integer());
685 
686                         // create expected byte vector
687                         std::vector<uint8_t> const expected
688                         {
689                             'm',
690                             static_cast<uint8_t>(i & 0xff),
691                             static_cast<uint8_t>((i >> 8) & 0xff),
692                             static_cast<uint8_t>((i >> 16) & 0xff),
693                             static_cast<uint8_t>((i >> 24) & 0xff),
694                         };
695 
696                         // compare result + size
697                         const auto result = json::to_bjdata(j);
698                         CHECK(result == expected);
699                         CHECK(result.size() == 5);
700 
701                         // check individual bytes
702                         CHECK(result[0] == 'm');
703                         uint32_t const restored = (static_cast<uint32_t>(result[4]) << 030) +
704                                                   (static_cast<uint32_t>(result[3]) << 020) +
705                                                   (static_cast<uint32_t>(result[2]) << 010) +
706                                                   static_cast<uint32_t>(result[1]);
707                         CHECK(restored == i);
708 
709                         // roundtrip
710                         CHECK(json::from_bjdata(result) == j);
711                         CHECK(json::from_bjdata(result, true, false) == j);
712                     }
713                 }
714 
715                 SECTION("4294967296..9223372036854775807 (int64)")
716                 {
717                     std::vector<uint64_t> const v = {4294967296LU, 9223372036854775807LU};
718                     for (const uint64_t i : v)
719                     {
720                         CAPTURE(i)
721 
722                         // create JSON value with integer number
723                         json j = -1;
724                         j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
725 
726                         // check type
727                         CHECK(j.is_number_integer());
728 
729                         // create expected byte vector
730                         std::vector<uint8_t> const expected
731                         {
732                             'L',
733                             static_cast<uint8_t>(i & 0xff),
734                             static_cast<uint8_t>((i >> 010) & 0xff),
735                             static_cast<uint8_t>((i >> 020) & 0xff),
736                             static_cast<uint8_t>((i >> 030) & 0xff),
737                             static_cast<uint8_t>((i >> 040) & 0xff),
738                             static_cast<uint8_t>((i >> 050) & 0xff),
739                             static_cast<uint8_t>((i >> 060) & 0xff),
740                             static_cast<uint8_t>((i >> 070) & 0xff),
741                         };
742 
743                         // compare result + size
744                         const auto result = json::to_bjdata(j);
745                         CHECK(result == expected);
746                         CHECK(result.size() == 9);
747 
748                         // check individual bytes
749                         CHECK(result[0] == 'L');
750                         uint64_t const restored = (static_cast<uint64_t>(result[8]) << 070) +
751                                                   (static_cast<uint64_t>(result[7]) << 060) +
752                                                   (static_cast<uint64_t>(result[6]) << 050) +
753                                                   (static_cast<uint64_t>(result[5]) << 040) +
754                                                   (static_cast<uint64_t>(result[4]) << 030) +
755                                                   (static_cast<uint64_t>(result[3]) << 020) +
756                                                   (static_cast<uint64_t>(result[2]) << 010) +
757                                                   static_cast<uint64_t>(result[1]);
758                         CHECK(restored == i);
759 
760                         // roundtrip
761                         CHECK(json::from_bjdata(result) == j);
762                         CHECK(json::from_bjdata(result, true, false) == j);
763                     }
764                 }
765 
766                 SECTION("9223372036854775808..18446744073709551615 (uint64)")
767                 {
768                     std::vector<uint64_t> const v = {9223372036854775808ull, 18446744073709551615ull};
769                     for (const uint64_t i : v)
770                     {
771                         CAPTURE(i)
772 
773                         // create JSON value with integer number
774                         json const j = i;
775 
776                         // check type
777                         CHECK(j.is_number_unsigned());
778 
779                         // create expected byte vector
780                         std::vector<uint8_t> const expected
781                         {
782                             'M',
783                             static_cast<uint8_t>(i & 0xff),
784                             static_cast<uint8_t>((i >> 010) & 0xff),
785                             static_cast<uint8_t>((i >> 020) & 0xff),
786                             static_cast<uint8_t>((i >> 030) & 0xff),
787                             static_cast<uint8_t>((i >> 040) & 0xff),
788                             static_cast<uint8_t>((i >> 050) & 0xff),
789                             static_cast<uint8_t>((i >> 060) & 0xff),
790                             static_cast<uint8_t>((i >> 070) & 0xff),
791                         };
792 
793                         // compare result + size
794                         const auto result = json::to_bjdata(j);
795                         CHECK(result == expected);
796                         CHECK(result.size() == 9);
797 
798                         // check individual bytes
799                         CHECK(result[0] == 'M');
800                         uint64_t const restored = (static_cast<uint64_t>(result[8]) << 070) +
801                                                   (static_cast<uint64_t>(result[7]) << 060) +
802                                                   (static_cast<uint64_t>(result[6]) << 050) +
803                                                   (static_cast<uint64_t>(result[5]) << 040) +
804                                                   (static_cast<uint64_t>(result[4]) << 030) +
805                                                   (static_cast<uint64_t>(result[3]) << 020) +
806                                                   (static_cast<uint64_t>(result[2]) << 010) +
807                                                   static_cast<uint64_t>(result[1]);
808                         CHECK(restored == i);
809 
810                         // roundtrip
811                         CHECK(json::from_bjdata(result) == j);
812                         CHECK(json::from_bjdata(result, true, false) == j);
813                     }
814                 }
815             }
816 
817             SECTION("unsigned")
818             {
819                 SECTION("0..127 (int8)")
820                 {
821                     for (size_t i = 0; i <= 127; ++i)
822                     {
823                         CAPTURE(i)
824 
825                         // create JSON value with unsigned integer number
826                         json const j = i;
827 
828                         // check type
829                         CHECK(j.is_number_unsigned());
830 
831                         // create expected byte vector
832                         std::vector<uint8_t> const expected{'i', static_cast<uint8_t>(i)};
833 
834                         // compare result + size
835                         const auto result = json::to_bjdata(j);
836                         CHECK(result == expected);
837                         CHECK(result.size() == 2);
838 
839                         // check individual bytes
840                         CHECK(result[0] == 'i');
841                         auto const restored = static_cast<uint8_t>(result[1]);
842                         CHECK(restored == i);
843 
844                         // roundtrip
845                         CHECK(json::from_bjdata(result) == j);
846                         CHECK(json::from_bjdata(result, true, false) == j);
847                     }
848                 }
849 
850                 SECTION("128..255 (uint8)")
851                 {
852                     for (size_t i = 128; i <= 255; ++i)
853                     {
854                         CAPTURE(i)
855 
856                         // create JSON value with unsigned integer number
857                         json const j = i;
858 
859                         // check type
860                         CHECK(j.is_number_unsigned());
861 
862                         // create expected byte vector
863                         std::vector<uint8_t> const expected{'U', static_cast<uint8_t>(i)};
864 
865                         // compare result + size
866                         const auto result = json::to_bjdata(j);
867                         CHECK(result == expected);
868                         CHECK(result.size() == 2);
869 
870                         // check individual bytes
871                         CHECK(result[0] == 'U');
872                         auto const restored = static_cast<uint8_t>(result[1]);
873                         CHECK(restored == i);
874 
875                         // roundtrip
876                         CHECK(json::from_bjdata(result) == j);
877                         CHECK(json::from_bjdata(result, true, false) == j);
878                     }
879                 }
880 
881                 SECTION("256..32767 (int16)")
882                 {
883                     for (size_t i = 256; i <= 32767; ++i)
884                     {
885                         CAPTURE(i)
886 
887                         // create JSON value with unsigned integer number
888                         json const j = i;
889 
890                         // check type
891                         CHECK(j.is_number_unsigned());
892 
893                         // create expected byte vector
894                         std::vector<uint8_t> const expected
895                         {
896                             'I',
897                             static_cast<uint8_t>(i & 0xff),
898                             static_cast<uint8_t>((i >> 8) & 0xff),
899                         };
900 
901                         // compare result + size
902                         const auto result = json::to_bjdata(j);
903                         CHECK(result == expected);
904                         CHECK(result.size() == 3);
905 
906                         // check individual bytes
907                         CHECK(result[0] == 'I');
908                         auto const restored = static_cast<uint16_t>(static_cast<uint8_t>(result[2]) * 256 + static_cast<uint8_t>(result[1]));
909                         CHECK(restored == i);
910 
911                         // roundtrip
912                         CHECK(json::from_bjdata(result) == j);
913                         CHECK(json::from_bjdata(result, true, false) == j);
914                     }
915                 }
916 
917                 SECTION("32768..65535 (uint16)")
918                 {
919                     for (const uint32_t i :
920                             {
921                                 32768u, 55555u, 65535u
922                             })
923                     {
924                         CAPTURE(i)
925 
926                         // create JSON value with unsigned integer number
927                         json const j = i;
928 
929                         // check type
930                         CHECK(j.is_number_unsigned());
931 
932                         // create expected byte vector
933                         std::vector<uint8_t> const expected
934                         {
935                             'u',
936                             static_cast<uint8_t>(i & 0xff),
937                             static_cast<uint8_t>((i >> 8) & 0xff),
938                         };
939 
940                         // compare result + size
941                         const auto result = json::to_bjdata(j);
942                         CHECK(result == expected);
943                         CHECK(result.size() == 3);
944 
945                         // check individual bytes
946                         CHECK(result[0] == 'u');
947                         auto const restored = static_cast<uint16_t>(static_cast<uint8_t>(result[2]) * 256 + static_cast<uint8_t>(result[1]));
948                         CHECK(restored == i);
949 
950                         // roundtrip
951                         CHECK(json::from_bjdata(result) == j);
952                         CHECK(json::from_bjdata(result, true, false) == j);
953                     }
954                 }
955                 SECTION("65536..2147483647 (int32)")
956                 {
957                     for (const uint32_t i :
958                             {
959                                 65536u, 77777u, 2147483647u
960                             })
961                     {
962                         CAPTURE(i)
963 
964                         // create JSON value with unsigned integer number
965                         json const j = i;
966 
967                         // check type
968                         CHECK(j.is_number_unsigned());
969 
970                         // create expected byte vector
971                         std::vector<uint8_t> const expected
972                         {
973                             'l',
974                             static_cast<uint8_t>(i & 0xff),
975                             static_cast<uint8_t>((i >> 8) & 0xff),
976                             static_cast<uint8_t>((i >> 16) & 0xff),
977                             static_cast<uint8_t>((i >> 24) & 0xff),
978                         };
979 
980                         // compare result + size
981                         const auto result = json::to_bjdata(j);
982                         CHECK(result == expected);
983                         CHECK(result.size() == 5);
984 
985                         // check individual bytes
986                         CHECK(result[0] == 'l');
987                         uint32_t const restored = (static_cast<uint32_t>(result[4]) << 030) +
988                                                   (static_cast<uint32_t>(result[3]) << 020) +
989                                                   (static_cast<uint32_t>(result[2]) << 010) +
990                                                   static_cast<uint32_t>(result[1]);
991                         CHECK(restored == i);
992 
993                         // roundtrip
994                         CHECK(json::from_bjdata(result) == j);
995                         CHECK(json::from_bjdata(result, true, false) == j);
996                     }
997                 }
998 
999                 SECTION("2147483648..4294967295 (uint32)")
1000                 {
1001                     for (const uint32_t i :
1002                             {
1003                                 2147483648u, 3333333333u, 4294967295u
1004                             })
1005                     {
1006                         CAPTURE(i)
1007 
1008                         // create JSON value with unsigned integer number
1009                         json const j = i;
1010 
1011                         // check type
1012                         CHECK(j.is_number_unsigned());
1013 
1014                         // create expected byte vector
1015                         std::vector<uint8_t> const expected
1016                         {
1017                             'm',
1018                             static_cast<uint8_t>(i & 0xff),
1019                             static_cast<uint8_t>((i >> 8) & 0xff),
1020                             static_cast<uint8_t>((i >> 16) & 0xff),
1021                             static_cast<uint8_t>((i >> 24) & 0xff),
1022                         };
1023 
1024                         // compare result + size
1025                         const auto result = json::to_bjdata(j);
1026                         CHECK(result == expected);
1027                         CHECK(result.size() == 5);
1028 
1029                         // check individual bytes
1030                         CHECK(result[0] == 'm');
1031                         uint32_t const restored = (static_cast<uint32_t>(result[4]) << 030) +
1032                                                   (static_cast<uint32_t>(result[3]) << 020) +
1033                                                   (static_cast<uint32_t>(result[2]) << 010) +
1034                                                   static_cast<uint32_t>(result[1]);
1035                         CHECK(restored == i);
1036 
1037                         // roundtrip
1038                         CHECK(json::from_bjdata(result) == j);
1039                         CHECK(json::from_bjdata(result, true, false) == j);
1040                     }
1041                 }
1042 
1043                 SECTION("4294967296..9223372036854775807 (int64)")
1044                 {
1045                     std::vector<uint64_t> const v = {4294967296ul, 9223372036854775807ul};
1046                     for (const uint64_t i : v)
1047                     {
1048                         CAPTURE(i)
1049 
1050                         // create JSON value with integer number
1051                         json const j = i;
1052 
1053                         // check type
1054                         CHECK(j.is_number_unsigned());
1055 
1056                         // create expected byte vector
1057                         std::vector<uint8_t> const expected
1058                         {
1059                             'L',
1060                             static_cast<uint8_t>(i & 0xff),
1061                             static_cast<uint8_t>((i >> 010) & 0xff),
1062                             static_cast<uint8_t>((i >> 020) & 0xff),
1063                             static_cast<uint8_t>((i >> 030) & 0xff),
1064                             static_cast<uint8_t>((i >> 040) & 0xff),
1065                             static_cast<uint8_t>((i >> 050) & 0xff),
1066                             static_cast<uint8_t>((i >> 060) & 0xff),
1067                             static_cast<uint8_t>((i >> 070) & 0xff),
1068                         };
1069 
1070                         // compare result + size
1071                         const auto result = json::to_bjdata(j);
1072                         CHECK(result == expected);
1073                         CHECK(result.size() == 9);
1074 
1075                         // check individual bytes
1076                         CHECK(result[0] == 'L');
1077                         uint64_t const restored = (static_cast<uint64_t>(result[8]) << 070) +
1078                                                   (static_cast<uint64_t>(result[7]) << 060) +
1079                                                   (static_cast<uint64_t>(result[6]) << 050) +
1080                                                   (static_cast<uint64_t>(result[5]) << 040) +
1081                                                   (static_cast<uint64_t>(result[4]) << 030) +
1082                                                   (static_cast<uint64_t>(result[3]) << 020) +
1083                                                   (static_cast<uint64_t>(result[2]) << 010) +
1084                                                   static_cast<uint64_t>(result[1]);
1085                         CHECK(restored == i);
1086 
1087                         // roundtrip
1088                         CHECK(json::from_bjdata(result) == j);
1089                         CHECK(json::from_bjdata(result, true, false) == j);
1090                     }
1091                 }
1092 
1093                 SECTION("9223372036854775808..18446744073709551615 (uint64)")
1094                 {
1095                     std::vector<uint64_t> const v = {9223372036854775808ull, 18446744073709551615ull};
1096                     for (const uint64_t i : v)
1097                     {
1098                         CAPTURE(i)
1099 
1100                         // create JSON value with integer number
1101                         json const j = i;
1102 
1103                         // check type
1104                         CHECK(j.is_number_unsigned());
1105 
1106                         // create expected byte vector
1107                         std::vector<uint8_t> const expected
1108                         {
1109                             'M',
1110                             static_cast<uint8_t>(i & 0xff),
1111                             static_cast<uint8_t>((i >> 010) & 0xff),
1112                             static_cast<uint8_t>((i >> 020) & 0xff),
1113                             static_cast<uint8_t>((i >> 030) & 0xff),
1114                             static_cast<uint8_t>((i >> 040) & 0xff),
1115                             static_cast<uint8_t>((i >> 050) & 0xff),
1116                             static_cast<uint8_t>((i >> 060) & 0xff),
1117                             static_cast<uint8_t>((i >> 070) & 0xff),
1118                         };
1119 
1120                         // compare result + size
1121                         const auto result = json::to_bjdata(j);
1122                         CHECK(result == expected);
1123                         CHECK(result.size() == 9);
1124 
1125                         // check individual bytes
1126                         CHECK(result[0] == 'M');
1127                         uint64_t const restored = (static_cast<uint64_t>(result[8]) << 070) +
1128                                                   (static_cast<uint64_t>(result[7]) << 060) +
1129                                                   (static_cast<uint64_t>(result[6]) << 050) +
1130                                                   (static_cast<uint64_t>(result[5]) << 040) +
1131                                                   (static_cast<uint64_t>(result[4]) << 030) +
1132                                                   (static_cast<uint64_t>(result[3]) << 020) +
1133                                                   (static_cast<uint64_t>(result[2]) << 010) +
1134                                                   static_cast<uint64_t>(result[1]);
1135                         CHECK(restored == i);
1136 
1137                         // roundtrip
1138                         CHECK(json::from_bjdata(result) == j);
1139                         CHECK(json::from_bjdata(result, true, false) == j);
1140                     }
1141                 }
1142             }
1143             SECTION("float64")
1144             {
1145                 SECTION("3.1415925")
1146                 {
1147                     double v = 3.1415925;
1148                     json const j = v;
1149                     std::vector<uint8_t> const expected =
1150                     {
1151                         'D', 0xfc, 0xde, 0xa6, 0x3f, 0xfb, 0x21, 0x09, 0x40
1152                     };
1153                     const auto result = json::to_bjdata(j);
1154                     CHECK(result == expected);
1155 
1156                     // roundtrip
1157                     CHECK(json::from_bjdata(result) == j);
1158                     CHECK(json::from_bjdata(result) == v);
1159                     CHECK(json::from_bjdata(result, true, false) == j);
1160                 }
1161             }
1162 
1163             SECTION("half-precision float")
1164             {
1165                 SECTION("simple half floats")
1166                 {
1167                     CHECK(json::parse("0.0") == json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x00})));
1168                     CHECK(json::parse("-0.0") == json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x80})));
1169                     CHECK(json::parse("1.0") == json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x3c})));
1170                     CHECK(json::parse("1.5") == json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x3e})));
1171                     CHECK(json::parse("65504.0") == json::from_bjdata(std::vector<uint8_t>({'h', 0xff, 0x7b})));
1172                 }
1173 
1174                 SECTION("errors")
1175                 {
1176                     SECTION("no byte follows")
1177                     {
1178                         json _;
1179                         std::vector<uint8_t> const vec0 = {'h'};
1180                         CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec0), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
1181                         CHECK(json::from_bjdata(vec0, true, false).is_discarded());
1182                     }
1183 
1184                     SECTION("only one byte follows")
1185                     {
1186                         json _;
1187                         std::vector<uint8_t> const vec1 = {'h', 0x00};
1188                         CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec1), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
1189                         CHECK(json::from_bjdata(vec1, true, false).is_discarded());
1190                     }
1191                 }
1192             }
1193 
1194             SECTION("half-precision float (edge cases)")
1195             {
1196                 SECTION("exp = 0b00000")
1197                 {
1198                     SECTION("0 (0 00000 0000000000)")
1199                     {
1200                         json const j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x00}));
1201                         json::number_float_t d{j};
1202                         CHECK(d == 0.0);
1203                     }
1204 
1205                     SECTION("-0 (1 00000 0000000000)")
1206                     {
1207                         json const j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x80}));
1208                         json::number_float_t d{j};
1209                         CHECK(d == -0.0);
1210                     }
1211 
1212                     SECTION("2**-24 (0 00000 0000000001)")
1213                     {
1214                         json const j = json::from_bjdata(std::vector<uint8_t>({'h', 0x01, 0x00}));
1215                         json::number_float_t d{j};
1216                         CHECK(d == std::pow(2.0, -24.0));
1217                     }
1218                 }
1219 
1220                 SECTION("exp = 0b11111")
1221                 {
1222                     SECTION("infinity (0 11111 0000000000)")
1223                     {
1224                         json const j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x7c}));
1225                         json::number_float_t d{j};
1226                         CHECK(d == std::numeric_limits<json::number_float_t>::infinity());
1227                         CHECK(j.dump() == "null");
1228                     }
1229 
1230                     SECTION("-infinity (1 11111 0000000000)")
1231                     {
1232                         json const j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0xfc}));
1233                         json::number_float_t d{j};
1234                         CHECK(d == -std::numeric_limits<json::number_float_t>::infinity());
1235                         CHECK(j.dump() == "null");
1236                     }
1237                 }
1238 
1239                 SECTION("other values from https://en.wikipedia.org/wiki/Half-precision_floating-point_format")
1240                 {
1241                     SECTION("1 (0 01111 0000000000)")
1242                     {
1243                         json const j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x3c}));
1244                         json::number_float_t d{j};
1245                         CHECK(d == 1);
1246                     }
1247 
1248                     SECTION("-2 (1 10000 0000000000)")
1249                     {
1250                         json const j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0xc0}));
1251                         json::number_float_t d{j};
1252                         CHECK(d == -2);
1253                     }
1254 
1255                     SECTION("65504 (0 11110 1111111111)")
1256                     {
1257                         json const j = json::from_bjdata(std::vector<uint8_t>({'h', 0xff, 0x7b}));
1258                         json::number_float_t d{j};
1259                         CHECK(d == 65504);
1260                     }
1261                 }
1262 
1263                 SECTION("infinity")
1264                 {
1265                     json const j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x7c}));
1266                     json::number_float_t const d{j};
1267                     CHECK_FALSE(std::isfinite(d));
1268                     CHECK(j.dump() == "null");
1269                 }
1270 
1271                 SECTION("NaN")
1272                 {
1273                     json const j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x7e }));
1274                     json::number_float_t const d{j};
1275                     CHECK(std::isnan(d));
1276                     CHECK(j.dump() == "null");
1277                 }
1278             }
1279 
1280             SECTION("high-precision number")
1281             {
1282                 SECTION("unsigned integer number")
1283                 {
1284                     std::vector<uint8_t> const vec = {'H', 'i', 0x14, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
1285                     const auto j = json::from_bjdata(vec);
1286                     CHECK(j.is_number_unsigned());
1287                     CHECK(j.dump() == "12345678901234567890");
1288                 }
1289 
1290                 SECTION("signed integer number")
1291                 {
1292                     std::vector<uint8_t> const vec = {'H', 'i', 0x13, '-', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8'};
1293                     const auto j = json::from_bjdata(vec);
1294                     CHECK(j.is_number_integer());
1295                     CHECK(j.dump() == "-123456789012345678");
1296                 }
1297 
1298                 SECTION("floating-point number")
1299                 {
1300                     std::vector<uint8_t> const vec = {'H', 'i', 0x16, '3', '.', '1', '4', '1', '5', '9',  '2', '6', '5', '3', '5', '8', '9',  '7', '9', '3', '2', '3', '8', '4',  '6'};
1301                     const auto j = json::from_bjdata(vec);
1302                     CHECK(j.is_number_float());
1303                     CHECK(j.dump() == "3.141592653589793");
1304                 }
1305 
1306                 SECTION("errors")
1307                 {
1308                     // error while parsing length
1309                     std::vector<uint8_t> const vec0 = {'H', 'i'};
1310                     CHECK(json::from_bjdata(vec0, true, false).is_discarded());
1311                     // error while parsing string
1312                     std::vector<uint8_t> const vec1 = {'H', 'i', '1'};
1313                     CHECK(json::from_bjdata(vec1, true, false).is_discarded());
1314 
1315                     json _;
1316                     std::vector<uint8_t> const vec2 = {'H', 'i', 2, '1', 'A', '3'};
1317                     CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec2), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing BJData high-precision number: invalid number text: 1A", json::parse_error);
1318                     std::vector<uint8_t> const vec3 = {'H', 'i', 2, '1', '.'};
1319                     CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec3), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing BJData high-precision number: invalid number text: 1.", json::parse_error);
1320                     std::vector<uint8_t> const vec4 = {'H', 2, '1', '0'};
1321                     CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec4), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing BJData size: expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x02", json::parse_error);
1322                 }
1323             }
1324         }
1325 
1326         SECTION("string")
1327         {
1328             SECTION("N = 0..127")
1329             {
1330                 for (size_t N = 0; N <= 127; ++N)
1331                 {
1332                     CAPTURE(N)
1333 
1334                     // create JSON value with string containing of N * 'x'
1335                     const auto s = std::string(N, 'x');
1336                     json const j = s;
1337 
1338                     // create expected byte vector
1339                     std::vector<uint8_t> expected;
1340                     expected.push_back('S');
1341                     expected.push_back('i');
1342                     expected.push_back(static_cast<uint8_t>(N));
1343                     for (size_t i = 0; i < N; ++i)
1344                     {
1345                         expected.push_back('x');
1346                     }
1347 
1348                     // compare result + size
1349                     const auto result = json::to_bjdata(j);
1350                     CHECK(result == expected);
1351                     CHECK(result.size() == N + 3);
1352                     // check that no null byte is appended
1353                     if (N > 0)
1354                     {
1355                         CHECK(result.back() != '\x00');
1356                     }
1357 
1358                     // roundtrip
1359                     CHECK(json::from_bjdata(result) == j);
1360                     CHECK(json::from_bjdata(result, true, false) == j);
1361                 }
1362             }
1363 
1364             SECTION("N = 128..255")
1365             {
1366                 for (size_t N = 128; N <= 255; ++N)
1367                 {
1368                     CAPTURE(N)
1369 
1370                     // create JSON value with string containing of N * 'x'
1371                     const auto s = std::string(N, 'x');
1372                     json const j = s;
1373 
1374                     // create expected byte vector
1375                     std::vector<uint8_t> expected;
1376                     expected.push_back('S');
1377                     expected.push_back('U');
1378                     expected.push_back(static_cast<uint8_t>(N));
1379                     for (size_t i = 0; i < N; ++i)
1380                     {
1381                         expected.push_back('x');
1382                     }
1383 
1384                     // compare result + size
1385                     const auto result = json::to_bjdata(j);
1386                     CHECK(result == expected);
1387                     CHECK(result.size() == N + 3);
1388                     // check that no null byte is appended
1389                     CHECK(result.back() != '\x00');
1390 
1391                     // roundtrip
1392                     CHECK(json::from_bjdata(result) == j);
1393                     CHECK(json::from_bjdata(result, true, false) == j);
1394                 }
1395             }
1396 
1397             SECTION("N = 256..32767")
1398             {
1399                 for (const size_t N :
1400                         {
1401                             256u, 999u, 1025u, 3333u, 2048u, 32767u
1402                         })
1403                 {
1404                     CAPTURE(N)
1405 
1406                     // create JSON value with string containing of N * 'x'
1407                     const auto s = std::string(N, 'x');
1408                     json const j = s;
1409 
1410                     // create expected byte vector (hack: create string first)
1411                     std::vector<uint8_t> expected(N, 'x');
1412                     // reverse order of commands, because we insert at begin()
1413                     expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
1414                     expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
1415                     expected.insert(expected.begin(), 'I');
1416                     expected.insert(expected.begin(), 'S');
1417 
1418                     // compare result + size
1419                     const auto result = json::to_bjdata(j);
1420                     CHECK(result == expected);
1421                     CHECK(result.size() == N + 4);
1422                     // check that no null byte is appended
1423                     CHECK(result.back() != '\x00');
1424 
1425                     // roundtrip
1426                     CHECK(json::from_bjdata(result) == j);
1427                     CHECK(json::from_bjdata(result, true, false) == j);
1428                 }
1429             }
1430 
1431             SECTION("N = 32768..65535")
1432             {
1433                 for (const size_t N :
1434                         {
1435                             32768u, 55555u, 65535u
1436                         })
1437                 {
1438                     CAPTURE(N)
1439 
1440                     // create JSON value with string containing of N * 'x'
1441                     const auto s = std::string(N, 'x');
1442                     json const j = s;
1443 
1444                     // create expected byte vector (hack: create string first)
1445                     std::vector<uint8_t> expected(N, 'x');
1446                     // reverse order of commands, because we insert at begin()
1447                     expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
1448                     expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
1449                     expected.insert(expected.begin(), 'u');
1450                     expected.insert(expected.begin(), 'S');
1451 
1452                     // compare result + size
1453                     const auto result = json::to_bjdata(j);
1454                     CHECK(result == expected);
1455                     CHECK(result.size() == N + 4);
1456                     // check that no null byte is appended
1457                     CHECK(result.back() != '\x00');
1458 
1459                     // roundtrip
1460                     CHECK(json::from_bjdata(result) == j);
1461                     CHECK(json::from_bjdata(result, true, false) == j);
1462                 }
1463             }
1464 
1465             SECTION("N = 65536..2147483647")
1466             {
1467                 for (const size_t N :
1468                         {
1469                             65536u, 77777u, 1048576u
1470                         })
1471                 {
1472                     CAPTURE(N)
1473 
1474                     // create JSON value with string containing of N * 'x'
1475                     const auto s = std::string(N, 'x');
1476                     json const j = s;
1477 
1478                     // create expected byte vector (hack: create string first)
1479                     std::vector<uint8_t> expected(N, 'x');
1480                     // reverse order of commands, because we insert at begin()
1481                     expected.insert(expected.begin(), static_cast<uint8_t>((N >> 24) & 0xff));
1482                     expected.insert(expected.begin(), static_cast<uint8_t>((N >> 16) & 0xff));
1483                     expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
1484                     expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
1485                     expected.insert(expected.begin(), 'l');
1486                     expected.insert(expected.begin(), 'S');
1487 
1488                     // compare result + size
1489                     const auto result = json::to_bjdata(j);
1490                     CHECK(result == expected);
1491                     CHECK(result.size() == N + 6);
1492                     // check that no null byte is appended
1493                     CHECK(result.back() != '\x00');
1494 
1495                     // roundtrip
1496                     CHECK(json::from_bjdata(result) == j);
1497                     CHECK(json::from_bjdata(result, true, false) == j);
1498                 }
1499             }
1500         }
1501 
1502         SECTION("binary")
1503         {
1504             SECTION("N = 0..127")
1505             {
1506                 for (std::size_t N = 0; N <= 127; ++N)
1507                 {
1508                     CAPTURE(N)
1509 
1510                     // create JSON value with byte array containing of N * 'x'
1511                     const auto s = std::vector<std::uint8_t>(N, 'x');
1512                     json const j = json::binary(s);
1513 
1514                     // create expected byte vector
1515                     std::vector<std::uint8_t> expected;
1516                     expected.push_back(static_cast<std::uint8_t>('['));
1517                     if (N != 0)
1518                     {
1519                         expected.push_back(static_cast<std::uint8_t>('$'));
1520                         expected.push_back(static_cast<std::uint8_t>('U'));
1521                     }
1522                     expected.push_back(static_cast<std::uint8_t>('#'));
1523                     expected.push_back(static_cast<std::uint8_t>('i'));
1524                     expected.push_back(static_cast<std::uint8_t>(N));
1525                     for (size_t i = 0; i < N; ++i)
1526                     {
1527                         expected.push_back(0x78);
1528                     }
1529 
1530                     // compare result + size
1531                     const auto result = json::to_bjdata(j, true, true);
1532                     CHECK(result == expected);
1533                     if (N == 0)
1534                     {
1535                         CHECK(result.size() == N + 4);
1536                     }
1537                     else
1538                     {
1539                         CHECK(result.size() == N + 6);
1540                     }
1541 
1542                     // check that no null byte is appended
1543                     if (N > 0)
1544                     {
1545                         CHECK(result.back() != '\x00');
1546                     }
1547 
1548                     // roundtrip only works to an array of numbers
1549                     json j_out = s;
1550                     CHECK(json::from_bjdata(result) == j_out);
1551                     CHECK(json::from_bjdata(result, true, false) == j_out);
1552                 }
1553             }
1554 
1555             SECTION("N = 128..255")
1556             {
1557                 for (std::size_t N = 128; N <= 255; ++N)
1558                 {
1559                     CAPTURE(N)
1560 
1561                     // create JSON value with byte array containing of N * 'x'
1562                     const auto s = std::vector<std::uint8_t>(N, 'x');
1563                     json const j = json::binary(s);
1564 
1565                     // create expected byte vector
1566                     std::vector<uint8_t> expected;
1567                     expected.push_back(static_cast<std::uint8_t>('['));
1568                     expected.push_back(static_cast<std::uint8_t>('$'));
1569                     expected.push_back(static_cast<std::uint8_t>('U'));
1570                     expected.push_back(static_cast<std::uint8_t>('#'));
1571                     expected.push_back(static_cast<std::uint8_t>('U'));
1572                     expected.push_back(static_cast<std::uint8_t>(N));
1573                     for (size_t i = 0; i < N; ++i)
1574                     {
1575                         expected.push_back(0x78);
1576                     }
1577 
1578                     // compare result + size
1579                     const auto result = json::to_bjdata(j, true, true);
1580                     CHECK(result == expected);
1581                     CHECK(result.size() == N + 6);
1582                     // check that no null byte is appended
1583                     CHECK(result.back() != '\x00');
1584 
1585                     // roundtrip only works to an array of numbers
1586                     json j_out = s;
1587                     CHECK(json::from_bjdata(result) == j_out);
1588                     CHECK(json::from_bjdata(result, true, false) == j_out);
1589                 }
1590             }
1591 
1592             SECTION("N = 256..32767")
1593             {
1594                 for (const std::size_t N :
1595                         {
1596                             256u, 999u, 1025u, 3333u, 2048u, 32767u
1597                         })
1598                 {
1599                     CAPTURE(N)
1600 
1601                     // create JSON value with byte array containing of N * 'x'
1602                     const auto s = std::vector<std::uint8_t>(N, 'x');
1603                     json const j = json::binary(s);
1604 
1605                     // create expected byte vector
1606                     std::vector<std::uint8_t> expected(N + 7, 'x');
1607                     expected[0] = '[';
1608                     expected[1] = '$';
1609                     expected[2] = 'U';
1610                     expected[3] = '#';
1611                     expected[4] = 'I';
1612                     expected[5] = static_cast<std::uint8_t>(N & 0xFF);
1613                     expected[6] = static_cast<std::uint8_t>((N >> 8) & 0xFF);
1614 
1615                     // compare result + size
1616                     const auto result = json::to_bjdata(j, true, true);
1617                     CHECK(result == expected);
1618                     CHECK(result.size() == N + 7);
1619                     // check that no null byte is appended
1620                     CHECK(result.back() != '\x00');
1621 
1622                     // roundtrip only works to an array of numbers
1623                     json j_out = s;
1624                     CHECK(json::from_bjdata(result) == j_out);
1625                     CHECK(json::from_bjdata(result, true, false) == j_out);
1626                 }
1627             }
1628 
1629             SECTION("N = 32768..65535")
1630             {
1631                 for (const std::size_t N :
1632                         {
1633                             32768u, 55555u, 65535u
1634                         })
1635                 {
1636                     CAPTURE(N)
1637 
1638                     // create JSON value with byte array containing of N * 'x'
1639                     const auto s = std::vector<std::uint8_t>(N, 'x');
1640                     json const j = json::binary(s);
1641 
1642                     // create expected byte vector
1643                     std::vector<std::uint8_t> expected(N + 7, 'x');
1644                     expected[0] = '[';
1645                     expected[1] = '$';
1646                     expected[2] = 'U';
1647                     expected[3] = '#';
1648                     expected[4] = 'u';
1649                     expected[5] = static_cast<std::uint8_t>(N & 0xFF);
1650                     expected[6] = static_cast<std::uint8_t>((N >> 8) & 0xFF);
1651 
1652                     // compare result + size
1653                     const auto result = json::to_bjdata(j, true, true);
1654                     CHECK(result == expected);
1655                     CHECK(result.size() == N + 7);
1656                     // check that no null byte is appended
1657                     CHECK(result.back() != '\x00');
1658 
1659                     // roundtrip only works to an array of numbers
1660                     json j_out = s;
1661                     CHECK(json::from_bjdata(result) == j_out);
1662                     CHECK(json::from_bjdata(result, true, false) == j_out);
1663                 }
1664             }
1665 
1666             SECTION("N = 65536..2147483647")
1667             {
1668                 for (const std::size_t N :
1669                         {
1670                             65536u, 77777u, 1048576u
1671                         })
1672                 {
1673                     CAPTURE(N)
1674 
1675                     // create JSON value with byte array containing of N * 'x'
1676                     const auto s = std::vector<std::uint8_t>(N, 'x');
1677                     json const j = json::binary(s);
1678 
1679                     // create expected byte vector
1680                     std::vector<std::uint8_t> expected(N + 9, 'x');
1681                     expected[0] = '[';
1682                     expected[1] = '$';
1683                     expected[2] = 'U';
1684                     expected[3] = '#';
1685                     expected[4] = 'l';
1686                     expected[5] = static_cast<std::uint8_t>(N & 0xFF);
1687                     expected[6] = static_cast<std::uint8_t>((N >> 8) & 0xFF);
1688                     expected[7] = static_cast<std::uint8_t>((N >> 16) & 0xFF);
1689                     expected[8] = static_cast<std::uint8_t>((N >> 24) & 0xFF);
1690 
1691                     // compare result + size
1692                     const auto result = json::to_bjdata(j, true, true);
1693                     CHECK(result == expected);
1694                     CHECK(result.size() == N + 9);
1695                     // check that no null byte is appended
1696                     CHECK(result.back() != '\x00');
1697 
1698                     // roundtrip only works to an array of numbers
1699                     json j_out = s;
1700                     CHECK(json::from_bjdata(result) == j_out);
1701                     CHECK(json::from_bjdata(result, true, false) == j_out);
1702                 }
1703             }
1704 
1705             SECTION("Other Serializations")
1706             {
1707                 const std::size_t N = 10;
1708                 const auto s = std::vector<std::uint8_t>(N, 'x');
1709                 json const j = json::binary(s);
1710 
1711                 SECTION("No Count No Type")
1712                 {
1713                     std::vector<uint8_t> expected;
1714                     expected.push_back(static_cast<std::uint8_t>('['));
1715                     for (std::size_t i = 0; i < N; ++i)
1716                     {
1717                         expected.push_back(static_cast<std::uint8_t>('U'));
1718                         expected.push_back(static_cast<std::uint8_t>(0x78));
1719                     }
1720                     expected.push_back(static_cast<std::uint8_t>(']'));
1721 
1722                     // compare result + size
1723                     const auto result = json::to_bjdata(j, false, false);
1724                     CHECK(result == expected);
1725                     CHECK(result.size() == N + 12);
1726                     // check that no null byte is appended
1727                     CHECK(result.back() != '\x00');
1728 
1729                     // roundtrip only works to an array of numbers
1730                     json j_out = s;
1731                     CHECK(json::from_bjdata(result) == j_out);
1732                     CHECK(json::from_bjdata(result, true, false) == j_out);
1733                 }
1734 
1735                 SECTION("Yes Count No Type")
1736                 {
1737                     std::vector<std::uint8_t> expected;
1738                     expected.push_back(static_cast<std::uint8_t>('['));
1739                     expected.push_back(static_cast<std::uint8_t>('#'));
1740                     expected.push_back(static_cast<std::uint8_t>('i'));
1741                     expected.push_back(static_cast<std::uint8_t>(N));
1742 
1743                     for (size_t i = 0; i < N; ++i)
1744                     {
1745                         expected.push_back(static_cast<std::uint8_t>('U'));
1746                         expected.push_back(static_cast<std::uint8_t>(0x78));
1747                     }
1748 
1749                     // compare result + size
1750                     const auto result = json::to_bjdata(j, true, false);
1751                     CHECK(result == expected);
1752                     CHECK(result.size() == N + 14);
1753                     // check that no null byte is appended
1754                     CHECK(result.back() != '\x00');
1755 
1756                     // roundtrip only works to an array of numbers
1757                     json j_out = s;
1758                     CHECK(json::from_bjdata(result) == j_out);
1759                     CHECK(json::from_bjdata(result, true, false) == j_out);
1760                 }
1761             }
1762         }
1763         SECTION("array")
1764         {
1765             SECTION("empty")
1766             {
1767                 SECTION("size=false type=false")
1768                 {
1769                     json const j = json::array();
1770                     std::vector<uint8_t> const expected = {'[', ']'};
1771                     const auto result = json::to_bjdata(j);
1772                     CHECK(result == expected);
1773 
1774                     // roundtrip
1775                     CHECK(json::from_bjdata(result) == j);
1776                     CHECK(json::from_bjdata(result, true, false) == j);
1777                 }
1778 
1779                 SECTION("size=true type=false")
1780                 {
1781                     json const j = json::array();
1782                     std::vector<uint8_t> const expected = {'[', '#', 'i', 0};
1783                     const auto result = json::to_bjdata(j, true);
1784                     CHECK(result == expected);
1785 
1786                     // roundtrip
1787                     CHECK(json::from_bjdata(result) == j);
1788                     CHECK(json::from_bjdata(result, true, false) == j);
1789                 }
1790 
1791                 SECTION("size=true type=true")
1792                 {
1793                     json const j = json::array();
1794                     std::vector<uint8_t> const expected = {'[', '#', 'i', 0};
1795                     const auto result = json::to_bjdata(j, true, true);
1796                     CHECK(result == expected);
1797 
1798                     // roundtrip
1799                     CHECK(json::from_bjdata(result) == j);
1800                     CHECK(json::from_bjdata(result, true, false) == j);
1801                 }
1802             }
1803 
1804             SECTION("[null]")
1805             {
1806                 SECTION("size=false type=false")
1807                 {
1808                     json const j = {nullptr};
1809                     std::vector<uint8_t> const expected = {'[', 'Z', ']'};
1810                     const auto result = json::to_bjdata(j);
1811                     CHECK(result == expected);
1812 
1813                     // roundtrip
1814                     CHECK(json::from_bjdata(result) == j);
1815                     CHECK(json::from_bjdata(result, true, false) == j);
1816                 }
1817 
1818                 SECTION("size=true type=false")
1819                 {
1820                     json const j = {nullptr};
1821                     std::vector<uint8_t> const expected = {'[', '#', 'i', 1, 'Z'};
1822                     const auto result = json::to_bjdata(j, true);
1823                     CHECK(result == expected);
1824 
1825                     // roundtrip
1826                     CHECK(json::from_bjdata(result) == j);
1827                     CHECK(json::from_bjdata(result, true, false) == j);
1828                 }
1829 
1830                 SECTION("size=true type=true")
1831                 {
1832                     json const j = {nullptr};
1833                     std::vector<uint8_t> const expected = {'[', '#', 'i', 1, 'Z'};
1834                     const auto result = json::to_bjdata(j, true, true);
1835                     CHECK(result == expected);
1836 
1837                     // roundtrip
1838                     CHECK(json::from_bjdata(result) == j);
1839                     CHECK(json::from_bjdata(result, true, false) == j);
1840                 }
1841             }
1842 
1843             SECTION("[1,2,3,4,5]")
1844             {
1845                 SECTION("size=false type=false")
1846                 {
1847                     json const j = json::parse("[1,2,3,4,5]");
1848                     std::vector<uint8_t> const expected = {'[', 'i', 1, 'i', 2, 'i', 3, 'i', 4, 'i', 5, ']'};
1849                     const auto result = json::to_bjdata(j);
1850                     CHECK(result == expected);
1851 
1852                     // roundtrip
1853                     CHECK(json::from_bjdata(result) == j);
1854                     CHECK(json::from_bjdata(result, true, false) == j);
1855                 }
1856 
1857                 SECTION("size=true type=false")
1858                 {
1859                     json const j = json::parse("[1,2,3,4,5]");
1860                     std::vector<uint8_t> const expected = {'[', '#', 'i', 5, 'i', 1, 'i', 2, 'i', 3, 'i', 4, 'i', 5};
1861                     const auto result = json::to_bjdata(j, true);
1862                     CHECK(result == expected);
1863 
1864                     // roundtrip
1865                     CHECK(json::from_bjdata(result) == j);
1866                     CHECK(json::from_bjdata(result, true, false) == j);
1867                 }
1868 
1869                 SECTION("size=true type=true")
1870                 {
1871                     json const j = json::parse("[1,2,3,4,5]");
1872                     std::vector<uint8_t> const expected = {'[', '$', 'i', '#', 'i', 5, 1, 2, 3, 4, 5};
1873                     const auto result = json::to_bjdata(j, true, true);
1874                     CHECK(result == expected);
1875 
1876                     // roundtrip
1877                     CHECK(json::from_bjdata(result) == j);
1878                     CHECK(json::from_bjdata(result, true, false) == j);
1879                 }
1880             }
1881 
1882             SECTION("[[[[]]]]")
1883             {
1884                 SECTION("size=false type=false")
1885                 {
1886                     json const j = json::parse("[[[[]]]]");
1887                     std::vector<uint8_t> const expected = {'[', '[', '[', '[', ']', ']', ']', ']'};
1888                     const auto result = json::to_bjdata(j);
1889                     CHECK(result == expected);
1890 
1891                     // roundtrip
1892                     CHECK(json::from_bjdata(result) == j);
1893                     CHECK(json::from_bjdata(result, true, false) == j);
1894                 }
1895 
1896                 SECTION("size=true type=false")
1897                 {
1898                     json const j = json::parse("[[[[]]]]");
1899                     std::vector<uint8_t> const expected = {'[', '#', 'i', 1, '[', '#', 'i', 1, '[', '#', 'i', 1, '[', '#', 'i', 0};
1900                     const auto result = json::to_bjdata(j, true);
1901                     CHECK(result == expected);
1902 
1903                     // roundtrip
1904                     CHECK(json::from_bjdata(result) == j);
1905                     CHECK(json::from_bjdata(result, true, false) == j);
1906                 }
1907 
1908                 SECTION("size=true type=true")
1909                 {
1910                     json const j = json::parse("[[[[]]]]");
1911                     std::vector<uint8_t> const expected = {'[', '#', 'i', 1, '[', '#', 'i', 1, '[', '#', 'i', 1, '[', '#', 'i', 0};
1912                     const auto result = json::to_bjdata(j, true, true);
1913                     CHECK(result == expected);
1914 
1915                     // roundtrip
1916                     CHECK(json::from_bjdata(result) == j);
1917                     CHECK(json::from_bjdata(result, true, false) == j);
1918                 }
1919             }
1920 
1921             SECTION("array with int16_t elements")
1922             {
1923                 SECTION("size=false type=false")
1924                 {
1925                     json j(257, nullptr);
1926                     std::vector<uint8_t> expected(j.size() + 2, 'Z'); // all null
1927                     expected[0] = '['; // opening array
1928                     expected[258] = ']'; // closing array
1929                     const auto result = json::to_bjdata(j);
1930                     CHECK(result == expected);
1931 
1932                     // roundtrip
1933                     CHECK(json::from_bjdata(result) == j);
1934                     CHECK(json::from_bjdata(result, true, false) == j);
1935                 }
1936 
1937                 SECTION("size=true type=false")
1938                 {
1939                     json j(257, nullptr);
1940                     std::vector<uint8_t> expected(j.size() + 5, 'Z'); // all null
1941                     expected[0] = '['; // opening array
1942                     expected[1] = '#'; // array size
1943                     expected[2] = 'I'; // int16
1944                     expected[3] = 0x01; // 0x0101, first byte
1945                     expected[4] = 0x01; // 0x0101, second byte
1946                     const auto result = json::to_bjdata(j, true);
1947                     CHECK(result == expected);
1948 
1949                     // roundtrip
1950                     CHECK(json::from_bjdata(result) == j);
1951                     CHECK(json::from_bjdata(result, true, false) == j);
1952                 }
1953             }
1954 
1955             SECTION("array with uint16_t elements")
1956             {
1957                 SECTION("size=false type=false")
1958                 {
1959                     json j(32768, nullptr);
1960                     std::vector<uint8_t> expected(j.size() + 2, 'Z'); // all null
1961                     expected[0] = '['; // opening array
1962                     expected[32769] = ']'; // closing array
1963                     const auto result = json::to_bjdata(j);
1964                     CHECK(result == expected);
1965 
1966                     // roundtrip
1967                     CHECK(json::from_bjdata(result) == j);
1968                     CHECK(json::from_bjdata(result, true, false) == j);
1969                 }
1970 
1971                 SECTION("size=true type=false")
1972                 {
1973                     json j(32768, nullptr);
1974                     std::vector<uint8_t> expected(j.size() + 5, 'Z'); // all null
1975                     expected[0] = '['; // opening array
1976                     expected[1] = '#'; // array size
1977                     expected[2] = 'u'; // int16
1978                     expected[3] = 0x00; // 0x0101, first byte
1979                     expected[4] = 0x80; // 0x0101, second byte
1980                     const auto result = json::to_bjdata(j, true);
1981                     CHECK(result == expected);
1982 
1983                     // roundtrip
1984                     CHECK(json::from_bjdata(result) == j);
1985                     CHECK(json::from_bjdata(result, true, false) == j);
1986                 }
1987             }
1988 
1989             SECTION("array with int32_t elements")
1990             {
1991                 SECTION("size=false type=false")
1992                 {
1993                     json j(65793, nullptr);
1994                     std::vector<uint8_t> expected(j.size() + 2, 'Z'); // all null
1995                     expected[0] = '['; // opening array
1996                     expected[65794] = ']'; // closing array
1997                     const auto result = json::to_bjdata(j);
1998                     CHECK(result == expected);
1999 
2000                     // roundtrip
2001                     CHECK(json::from_bjdata(result) == j);
2002                     CHECK(json::from_bjdata(result, true, false) == j);
2003                 }
2004 
2005                 SECTION("size=true type=false")
2006                 {
2007                     json j(65793, nullptr);
2008                     std::vector<uint8_t> expected(j.size() + 7, 'Z'); // all null
2009                     expected[0] = '['; // opening array
2010                     expected[1] = '#'; // array size
2011                     expected[2] = 'l'; // int32
2012                     expected[3] = 0x01; // 0x00010101, fourth byte
2013                     expected[4] = 0x01; // 0x00010101, third byte
2014                     expected[5] = 0x01; // 0x00010101, second byte
2015                     expected[6] = 0x00; // 0x00010101, first byte
2016                     const auto result = json::to_bjdata(j, true);
2017                     CHECK(result == expected);
2018 
2019                     // roundtrip
2020                     CHECK(json::from_bjdata(result) == j);
2021                     CHECK(json::from_bjdata(result, true, false) == j);
2022                 }
2023             }
2024         }
2025 
2026         SECTION("object")
2027         {
2028             SECTION("empty")
2029             {
2030                 SECTION("size=false type=false")
2031                 {
2032                     json const j = json::object();
2033                     std::vector<uint8_t> const expected = {'{', '}'};
2034                     const auto result = json::to_bjdata(j);
2035                     CHECK(result == expected);
2036 
2037                     // roundtrip
2038                     CHECK(json::from_bjdata(result) == j);
2039                     CHECK(json::from_bjdata(result, true, false) == j);
2040                 }
2041 
2042                 SECTION("size=true type=false")
2043                 {
2044                     json const j = json::object();
2045                     std::vector<uint8_t> const expected = {'{', '#', 'i', 0};
2046                     const auto result = json::to_bjdata(j, true);
2047                     CHECK(result == expected);
2048 
2049                     // roundtrip
2050                     CHECK(json::from_bjdata(result) == j);
2051                     CHECK(json::from_bjdata(result, true, false) == j);
2052                 }
2053 
2054                 SECTION("size=true type=true")
2055                 {
2056                     json const j = json::object();
2057                     std::vector<uint8_t> const expected = {'{', '#', 'i', 0};
2058                     const auto result = json::to_bjdata(j, true, true);
2059                     CHECK(result == expected);
2060 
2061                     // roundtrip
2062                     CHECK(json::from_bjdata(result) == j);
2063                     CHECK(json::from_bjdata(result, true, false) == j);
2064                 }
2065             }
2066 
2067             SECTION("{\"\":null}")
2068             {
2069                 SECTION("size=false type=false")
2070                 {
2071                     json const j = {{"", nullptr}};
2072                     std::vector<uint8_t> const expected = {'{', 'i', 0, 'Z', '}'};
2073                     const auto result = json::to_bjdata(j);
2074                     CHECK(result == expected);
2075 
2076                     // roundtrip
2077                     CHECK(json::from_bjdata(result) == j);
2078                     CHECK(json::from_bjdata(result, true, false) == j);
2079                 }
2080 
2081                 SECTION("size=true type=false")
2082                 {
2083                     json const j = {{"", nullptr}};
2084                     std::vector<uint8_t> const expected = {'{', '#', 'i', 1, 'i', 0, 'Z'};
2085                     const auto result = json::to_bjdata(j, true);
2086                     CHECK(result == expected);
2087 
2088                     // roundtrip
2089                     CHECK(json::from_bjdata(result) == j);
2090                     CHECK(json::from_bjdata(result, true, false) == j);
2091                 }
2092             }
2093 
2094             SECTION("{\"a\": {\"b\": {\"c\": {}}}}")
2095             {
2096                 SECTION("size=false type=false")
2097                 {
2098                     json const j = json::parse(R"({"a": {"b": {"c": {}}}})");
2099                     std::vector<uint8_t> const expected =
2100                     {
2101                         '{', 'i', 1, 'a', '{', 'i', 1, 'b', '{', 'i', 1, 'c', '{', '}', '}', '}', '}'
2102                     };
2103                     const auto result = json::to_bjdata(j);
2104                     CHECK(result == expected);
2105 
2106                     // roundtrip
2107                     CHECK(json::from_bjdata(result) == j);
2108                     CHECK(json::from_bjdata(result, true, false) == j);
2109                 }
2110 
2111                 SECTION("size=true type=false")
2112                 {
2113                     json const j = json::parse(R"({"a": {"b": {"c": {}}}})");
2114                     std::vector<uint8_t> const expected =
2115                     {
2116                         '{', '#', 'i', 1, 'i', 1, 'a', '{', '#', 'i', 1, 'i', 1, 'b', '{', '#', 'i', 1, 'i', 1, 'c', '{', '#', 'i', 0
2117                     };
2118                     const auto result = json::to_bjdata(j, true);
2119                     CHECK(result == expected);
2120 
2121                     // roundtrip
2122                     CHECK(json::from_bjdata(result) == j);
2123                     CHECK(json::from_bjdata(result, true, false) == j);
2124                 }
2125 
2126                 SECTION("size=true type=true ignore object type marker")
2127                 {
2128                     json const j = json::parse(R"({"a": {"b": {"c": {}}}})");
2129                     std::vector<uint8_t> const expected =
2130                     {
2131                         '{', '#', 'i', 1, 'i', 1, 'a', '{', '#', 'i', 1, 'i', 1, 'b', '{', '#', 'i', 1, 'i', 1, 'c', '{', '#', 'i', 0
2132                     };
2133                     const auto result = json::to_bjdata(j, true, true);
2134                     CHECK(result == expected);
2135 
2136                     // roundtrip
2137                     CHECK(json::from_bjdata(result) == j);
2138                     CHECK(json::from_bjdata(result, true, false) == j);
2139                 }
2140             }
2141         }
2142     }
2143 
2144     SECTION("errors")
2145     {
2146         SECTION("strict mode")
2147         {
2148             std::vector<uint8_t> const vec = {'Z', 'Z'};
2149             SECTION("non-strict mode")
2150             {
2151                 const auto result = json::from_bjdata(vec, false);
2152                 CHECK(result == json());
2153             }
2154 
2155             SECTION("strict mode")
2156             {
2157                 json _;
2158                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec),
2159                                      "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing BJData value: expected end of input; last byte: 0x5A", json::parse_error&);
2160             }
2161         }
2162     }
2163 
2164     SECTION("SAX aborts")
2165     {
2166         SECTION("start_array()")
2167         {
2168             std::vector<uint8_t> const v = {'[', 'T', 'F', ']'};
2169             SaxCountdown scp(0);
2170             CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2171         }
2172 
2173         SECTION("start_object()")
2174         {
2175             std::vector<uint8_t> const v = {'{', 'i', 3, 'f', 'o', 'o', 'F', '}'};
2176             SaxCountdown scp(0);
2177             CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2178         }
2179 
2180         SECTION("key() in object")
2181         {
2182             std::vector<uint8_t> const v = {'{', 'i', 3, 'f', 'o', 'o', 'F', '}'};
2183             SaxCountdown scp(1);
2184             CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2185         }
2186 
2187         SECTION("start_array(len)")
2188         {
2189             std::vector<uint8_t> const v = {'[', '#', 'i', '2', 'T', 'F'};
2190             SaxCountdown scp(0);
2191             CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2192         }
2193 
2194         SECTION("start_object(len)")
2195         {
2196             std::vector<uint8_t> const v = {'{', '#', 'i', '1', 3, 'f', 'o', 'o', 'F'};
2197             SaxCountdown scp(0);
2198             CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2199         }
2200 
2201         SECTION("key() in object with length")
2202         {
2203             std::vector<uint8_t> const v = {'{', 'i', 3, 'f', 'o', 'o', 'F', '}'};
2204             SaxCountdown scp(1);
2205             CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2206         }
2207 
2208         SECTION("start_array() in ndarray _ArraySize_")
2209         {
2210             std::vector<uint8_t> const v = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 2, 2, 1, 1, 2};
2211             SaxCountdown scp(2);
2212             CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2213         }
2214 
2215         SECTION("number_integer() in ndarray _ArraySize_")
2216         {
2217             std::vector<uint8_t> const v = {'[', '$', 'U', '#', '[', '$', 'i', '#', 'i', 2, 2, 1, 1, 2};
2218             SaxCountdown scp(3);
2219             CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2220         }
2221 
2222         SECTION("key() in ndarray _ArrayType_")
2223         {
2224             std::vector<uint8_t> const v = {'[', '$', 'U', '#', '[', '$', 'U', '#', 'i', 2, 2, 2, 1, 2, 3, 4};
2225             SaxCountdown scp(6);
2226             CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2227         }
2228 
2229         SECTION("string() in ndarray _ArrayType_")
2230         {
2231             std::vector<uint8_t> const v = {'[', '$', 'U', '#', '[', '$', 'U', '#', 'i', 2, 2, 2, 1, 2, 3, 4};
2232             SaxCountdown scp(7);
2233             CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2234         }
2235 
2236         SECTION("key() in ndarray _ArrayData_")
2237         {
2238             std::vector<uint8_t> const v = {'[', '$', 'U', '#', '[', '$', 'U', '#', 'i', 2, 2, 2, 1, 2, 3, 4};
2239             SaxCountdown scp(8);
2240             CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2241         }
2242 
2243         SECTION("string() in ndarray _ArrayData_")
2244         {
2245             std::vector<uint8_t> const v = {'[', '$', 'U', '#', '[', '$', 'U', '#', 'i', 2, 2, 2, 1, 2, 3, 4};
2246             SaxCountdown scp(9);
2247             CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2248         }
2249 
2250         SECTION("string() in ndarray _ArrayType_")
2251         {
2252             std::vector<uint8_t> const v = {'[', '$', 'U', '#', '[', '$', 'i', '#', 'i', 2, 3, 2, 6, 5, 4, 3, 2, 1};
2253             SaxCountdown scp(11);
2254             CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2255         }
2256 
2257         SECTION("start_array() in ndarray _ArrayData_")
2258         {
2259             std::vector<uint8_t> const v = {'[', '$', 'U', '#', '[', 'i', 2, 'i', 3, ']', 6, 5, 4, 3, 2, 1};
2260             SaxCountdown scp(13);
2261             CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2262         }
2263     }
2264 
2265     SECTION("parsing values")
2266     {
2267         SECTION("strings")
2268         {
2269             // create a single-character string for all number types
2270             std::vector<uint8_t> s_i = {'S', 'i', 1, 'a'};
2271             std::vector<uint8_t> const s_U = {'S', 'U', 1, 'a'};
2272             std::vector<uint8_t> const s_I = {'S', 'I', 1, 0, 'a'};
2273             std::vector<uint8_t> const s_u = {'S', 'u', 1, 0, 'a'};
2274             std::vector<uint8_t> const s_l = {'S', 'l', 1, 0, 0, 0, 'a'};
2275             std::vector<uint8_t> const s_m = {'S', 'm', 1, 0, 0, 0, 'a'};
2276             std::vector<uint8_t> const s_L = {'S', 'L', 1, 0, 0, 0, 0, 0, 0, 0, 'a'};
2277             std::vector<uint8_t> const s_M = {'S', 'M', 1, 0, 0, 0, 0, 0, 0, 0, 'a'};
2278 
2279             // check if string is parsed correctly to "a"
2280             CHECK(json::from_bjdata(s_i) == "a");
2281             CHECK(json::from_bjdata(s_U) == "a");
2282             CHECK(json::from_bjdata(s_I) == "a");
2283             CHECK(json::from_bjdata(s_u) == "a");
2284             CHECK(json::from_bjdata(s_l) == "a");
2285             CHECK(json::from_bjdata(s_m) == "a");
2286             CHECK(json::from_bjdata(s_L) == "a");
2287             CHECK(json::from_bjdata(s_M) == "a");
2288 
2289             // roundtrip: output should be optimized
2290             CHECK(json::to_bjdata(json::from_bjdata(s_i)) == s_i);
2291             CHECK(json::to_bjdata(json::from_bjdata(s_U)) == s_i);
2292             CHECK(json::to_bjdata(json::from_bjdata(s_I)) == s_i);
2293             CHECK(json::to_bjdata(json::from_bjdata(s_u)) == s_i);
2294             CHECK(json::to_bjdata(json::from_bjdata(s_l)) == s_i);
2295             CHECK(json::to_bjdata(json::from_bjdata(s_m)) == s_i);
2296             CHECK(json::to_bjdata(json::from_bjdata(s_L)) == s_i);
2297             CHECK(json::to_bjdata(json::from_bjdata(s_M)) == s_i);
2298         }
2299 
2300         SECTION("number")
2301         {
2302             SECTION("float")
2303             {
2304                 // float32
2305                 std::vector<uint8_t> const v_d = {'d', 0xd0, 0x0f, 0x49, 0x40};
2306                 CHECK(json::from_bjdata(v_d) == 3.14159f);
2307 
2308                 // float64
2309                 std::vector<uint8_t> const v_D = {'D', 0x6e, 0x86, 0x1b, 0xf0, 0xf9, 0x21, 0x09, 0x40};
2310                 CHECK(json::from_bjdata(v_D) == 3.14159);
2311 
2312                 // float32 is serialized as float64 as the library does not support float32
2313                 CHECK(json::to_bjdata(json::from_bjdata(v_d)) == json::to_bjdata(3.14159f));
2314             }
2315         }
2316 
2317         SECTION("array")
2318         {
2319             SECTION("optimized version (length only)")
2320             {
2321                 // create vector with two elements of the same type
2322                 std::vector<uint8_t> const v_TU = {'[', '#', 'U', 2, 'T', 'T'};
2323                 std::vector<uint8_t> const v_T = {'[', '#', 'i', 2, 'T', 'T'};
2324                 std::vector<uint8_t> const v_F = {'[', '#', 'i', 2, 'F', 'F'};
2325                 std::vector<uint8_t> const v_Z = {'[', '#', 'i', 2, 'Z', 'Z'};
2326                 std::vector<uint8_t> const v_i = {'[', '#', 'i', 2, 'i', 0x7F, 'i', 0x7F};
2327                 std::vector<uint8_t> const v_U = {'[', '#', 'i', 2, 'U', 0xFF, 'U', 0xFF};
2328                 std::vector<uint8_t> const v_I = {'[', '#', 'i', 2, 'I', 0xFF, 0x7F, 'I', 0xFF, 0x7F};
2329                 std::vector<uint8_t> const v_u = {'[', '#', 'i', 2, 'u', 0x0F, 0xA7, 'u', 0x0F, 0xA7};
2330                 std::vector<uint8_t> const v_l = {'[', '#', 'i', 2, 'l', 0xFF, 0xFF, 0xFF, 0x7F, 'l', 0xFF, 0xFF, 0xFF, 0x7F};
2331                 std::vector<uint8_t> const v_m = {'[', '#', 'i', 2, 'm', 0xFF, 0xC9, 0x9A, 0xBB, 'm', 0xFF, 0xC9, 0x9A, 0xBB};
2332                 std::vector<uint8_t> const v_L = {'[', '#', 'i', 2, 'L', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 'L', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F};
2333                 std::vector<uint8_t> const v_M = {'[', '#', 'i', 2, 'M', 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 'M', 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D};
2334                 std::vector<uint8_t> const v_D = {'[', '#', 'i', 2, 'D', 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40, 'D', 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40};
2335                 std::vector<uint8_t> const v_S = {'[', '#', 'i', 2, 'S', 'i', 1, 'a', 'S', 'i', 1, 'a'};
2336                 std::vector<uint8_t> const v_C = {'[', '#', 'i', 2, 'C', 'a', 'C', 'a'};
2337 
2338                 // check if vector is parsed correctly
2339                 CHECK(json::from_bjdata(v_TU) == json({true, true}));
2340                 CHECK(json::from_bjdata(v_T) == json({true, true}));
2341                 CHECK(json::from_bjdata(v_F) == json({false, false}));
2342                 CHECK(json::from_bjdata(v_Z) == json({nullptr, nullptr}));
2343                 CHECK(json::from_bjdata(v_i) == json({127, 127}));
2344                 CHECK(json::from_bjdata(v_U) == json({255, 255}));
2345                 CHECK(json::from_bjdata(v_I) == json({32767, 32767}));
2346                 CHECK(json::from_bjdata(v_u) == json({42767, 42767}));
2347                 CHECK(json::from_bjdata(v_l) == json({2147483647, 2147483647}));
2348                 CHECK(json::from_bjdata(v_m) == json({3147483647, 3147483647}));
2349                 CHECK(json::from_bjdata(v_L) == json({9223372036854775807, 9223372036854775807}));
2350                 CHECK(json::from_bjdata(v_M) == json({10223372036854775807ull, 10223372036854775807ull}));
2351                 CHECK(json::from_bjdata(v_D) == json({3.1415926, 3.1415926}));
2352                 CHECK(json::from_bjdata(v_S) == json({"a", "a"}));
2353                 CHECK(json::from_bjdata(v_C) == json({"a", "a"}));
2354 
2355                 // roundtrip: output should be optimized
2356                 CHECK(json::to_bjdata(json::from_bjdata(v_T), true) == v_T);
2357                 CHECK(json::to_bjdata(json::from_bjdata(v_F), true) == v_F);
2358                 CHECK(json::to_bjdata(json::from_bjdata(v_Z), true) == v_Z);
2359                 CHECK(json::to_bjdata(json::from_bjdata(v_i), true) == v_i);
2360                 CHECK(json::to_bjdata(json::from_bjdata(v_U), true) == v_U);
2361                 CHECK(json::to_bjdata(json::from_bjdata(v_I), true) == v_I);
2362                 CHECK(json::to_bjdata(json::from_bjdata(v_u), true) == v_u);
2363                 CHECK(json::to_bjdata(json::from_bjdata(v_l), true) == v_l);
2364                 CHECK(json::to_bjdata(json::from_bjdata(v_m), true) == v_m);
2365                 CHECK(json::to_bjdata(json::from_bjdata(v_L), true) == v_L);
2366                 CHECK(json::to_bjdata(json::from_bjdata(v_M), true) == v_M);
2367                 CHECK(json::to_bjdata(json::from_bjdata(v_D), true) == v_D);
2368                 CHECK(json::to_bjdata(json::from_bjdata(v_S), true) == v_S);
2369                 CHECK(json::to_bjdata(json::from_bjdata(v_C), true) == v_S); // char is serialized to string
2370             }
2371 
2372             SECTION("optimized version (type and length)")
2373             {
2374                 // create vector with two elements of the same type
2375                 std::vector<uint8_t> const v_i = {'[', '$', 'i', '#', 'i', 2, 0x7F, 0x7F};
2376                 std::vector<uint8_t> const v_U = {'[', '$', 'U', '#', 'i', 2, 0xFF, 0xFF};
2377                 std::vector<uint8_t> const v_I = {'[', '$', 'I', '#', 'i', 2, 0xFF, 0x7F, 0xFF, 0x7F};
2378                 std::vector<uint8_t> const v_u = {'[', '$', 'u', '#', 'i', 2, 0x0F, 0xA7, 0x0F, 0xA7};
2379                 std::vector<uint8_t> const v_l = {'[', '$', 'l', '#', 'i', 2, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F};
2380                 std::vector<uint8_t> const v_m = {'[', '$', 'm', '#', 'i', 2, 0xFF, 0xC9, 0x9A, 0xBB, 0xFF, 0xC9, 0x9A, 0xBB};
2381                 std::vector<uint8_t> const v_L = {'[', '$', 'L', '#', 'i', 2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F};
2382                 std::vector<uint8_t> const v_M = {'[', '$', 'M', '#', 'i', 2, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D};
2383                 std::vector<uint8_t> const v_D = {'[', '$', 'D', '#', 'i', 2, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40};
2384                 std::vector<uint8_t> const v_S = {'[', '#', 'i', 2, 'S', 'i', 1, 'a', 'S', 'i', 1, 'a'};
2385                 std::vector<uint8_t> const v_C = {'[', '$', 'C', '#', 'i', 2, 'a', 'a'};
2386 
2387                 // check if vector is parsed correctly
2388                 CHECK(json::from_bjdata(v_i) == json({127, 127}));
2389                 CHECK(json::from_bjdata(v_U) == json({255, 255}));
2390                 CHECK(json::from_bjdata(v_I) == json({32767, 32767}));
2391                 CHECK(json::from_bjdata(v_u) == json({42767, 42767}));
2392                 CHECK(json::from_bjdata(v_l) == json({2147483647, 2147483647}));
2393                 CHECK(json::from_bjdata(v_m) == json({3147483647, 3147483647}));
2394                 CHECK(json::from_bjdata(v_L) == json({9223372036854775807, 9223372036854775807}));
2395                 CHECK(json::from_bjdata(v_M) == json({10223372036854775807ull, 10223372036854775807ull}));
2396                 CHECK(json::from_bjdata(v_D) == json({3.1415926, 3.1415926}));
2397                 CHECK(json::from_bjdata(v_S) == json({"a", "a"}));
2398                 CHECK(json::from_bjdata(v_C) == json({"a", "a"}));
2399 
2400                 // roundtrip: output should be optimized
2401                 std::vector<uint8_t> const v_empty = {'[', '#', 'i', 0};
2402                 CHECK(json::to_bjdata(json::from_bjdata(v_i), true, true) == v_i);
2403                 CHECK(json::to_bjdata(json::from_bjdata(v_U), true, true) == v_U);
2404                 CHECK(json::to_bjdata(json::from_bjdata(v_I), true, true) == v_I);
2405                 CHECK(json::to_bjdata(json::from_bjdata(v_u), true, true) == v_u);
2406                 CHECK(json::to_bjdata(json::from_bjdata(v_l), true, true) == v_l);
2407                 CHECK(json::to_bjdata(json::from_bjdata(v_m), true, true) == v_m);
2408                 CHECK(json::to_bjdata(json::from_bjdata(v_L), true, true) == v_L);
2409                 CHECK(json::to_bjdata(json::from_bjdata(v_M), true, true) == v_M);
2410                 CHECK(json::to_bjdata(json::from_bjdata(v_D), true, true) == v_D);
2411                 CHECK(json::to_bjdata(json::from_bjdata(v_S), true, true) == v_S);
2412                 CHECK(json::to_bjdata(json::from_bjdata(v_C), true, true) == v_S); // char is serialized to string
2413             }
2414 
2415             SECTION("optimized ndarray (type and vector-size as optimized 1D array)")
2416             {
2417                 // create vector with two elements of the same type
2418                 std::vector<uint8_t> const v_0 = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 1, 0};
2419                 std::vector<uint8_t> const v_1 = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 1, 2, 0x7F, 0x7F};
2420                 std::vector<uint8_t> const v_i = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0x7F, 0x7F};
2421                 std::vector<uint8_t> const v_U = {'[', '$', 'U', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0xFF, 0xFF};
2422                 std::vector<uint8_t> const v_I = {'[', '$', 'I', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0xFF, 0x7F, 0xFF, 0x7F};
2423                 std::vector<uint8_t> const v_u = {'[', '$', 'u', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0x0F, 0xA7, 0x0F, 0xA7};
2424                 std::vector<uint8_t> const v_l = {'[', '$', 'l', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F};
2425                 std::vector<uint8_t> const v_m = {'[', '$', 'm', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0xFF, 0xC9, 0x9A, 0xBB, 0xFF, 0xC9, 0x9A, 0xBB};
2426                 std::vector<uint8_t> const v_L = {'[', '$', 'L', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F};
2427                 std::vector<uint8_t> const v_M = {'[', '$', 'M', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D};
2428                 std::vector<uint8_t> const v_D = {'[', '$', 'D', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40};
2429                 std::vector<uint8_t> const v_S = {'[', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 'S', 'i', 1, 'a', 'S', 'i', 1, 'a'};
2430                 std::vector<uint8_t> const v_C = {'[', '$', 'C', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 'a', 'a'};
2431 
2432                 // check if vector is parsed correctly
2433                 CHECK(json::from_bjdata(v_0) == json::array());
2434                 CHECK(json::from_bjdata(v_1) == json({127, 127}));
2435                 CHECK(json::from_bjdata(v_i) == json({127, 127}));
2436                 CHECK(json::from_bjdata(v_U) == json({255, 255}));
2437                 CHECK(json::from_bjdata(v_I) == json({32767, 32767}));
2438                 CHECK(json::from_bjdata(v_u) == json({42767, 42767}));
2439                 CHECK(json::from_bjdata(v_l) == json({2147483647, 2147483647}));
2440                 CHECK(json::from_bjdata(v_m) == json({3147483647, 3147483647}));
2441                 CHECK(json::from_bjdata(v_L) == json({9223372036854775807, 9223372036854775807}));
2442                 CHECK(json::from_bjdata(v_M) == json({10223372036854775807ull, 10223372036854775807ull}));
2443                 CHECK(json::from_bjdata(v_D) == json({3.1415926, 3.1415926}));
2444                 CHECK(json::from_bjdata(v_S) == json({"a", "a"}));
2445                 CHECK(json::from_bjdata(v_C) == json({"a", "a"}));
2446             }
2447 
2448             SECTION("optimized ndarray (type and vector-size ndarray with JData annotations)")
2449             {
2450                 // create vector with 0, 1, 2 elements of the same type
2451                 std::vector<uint8_t> const v_e = {'[', '$', 'U', '#', '[', '$', 'i', '#', 'i', 2, 2, 1, 0xFE, 0xFF};
2452                 std::vector<uint8_t> const v_U = {'[', '$', 'U', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
2453                 std::vector<uint8_t> const v_i = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
2454                 std::vector<uint8_t> const v_u = {'[', '$', 'u', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00};
2455                 std::vector<uint8_t> const v_I = {'[', '$', 'I', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00};
2456                 std::vector<uint8_t> const v_m = {'[', '$', 'm', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00};
2457                 std::vector<uint8_t> const v_l = {'[', '$', 'l', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00};
2458                 std::vector<uint8_t> const v_M = {'[', '$', 'M', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
2459                 std::vector<uint8_t> const v_L = {'[', '$', 'L', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
2460                 std::vector<uint8_t> const v_d = {'[', '$', 'd', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0xA0, 0x40, 0x00, 0x00, 0xC0, 0x40};
2461                 std::vector<uint8_t> const v_D = {'[', '$', 'D', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40};
2462                 std::vector<uint8_t> const v_C = {'[', '$', 'C', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 'a', 'b', 'c', 'd', 'e', 'f'};
2463 
2464                 // check if vector is parsed correctly
2465                 CHECK(json::from_bjdata(v_e) == json({{"_ArrayData_", {254, 255}}, {"_ArraySize_", {2, 1}}, {"_ArrayType_", "uint8"}}));
2466                 CHECK(json::from_bjdata(v_U) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "uint8"}}));
2467                 CHECK(json::from_bjdata(v_i) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "int8"}}));
2468                 CHECK(json::from_bjdata(v_i) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "int8"}}));
2469                 CHECK(json::from_bjdata(v_u) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "uint16"}}));
2470                 CHECK(json::from_bjdata(v_I) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "int16"}}));
2471                 CHECK(json::from_bjdata(v_m) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "uint32"}}));
2472                 CHECK(json::from_bjdata(v_l) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "int32"}}));
2473                 CHECK(json::from_bjdata(v_M) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "uint64"}}));
2474                 CHECK(json::from_bjdata(v_L) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "int64"}}));
2475                 CHECK(json::from_bjdata(v_d) == json({{"_ArrayData_", {1.f, 2.f, 3.f, 4.f, 5.f, 6.f}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "single"}}));
2476                 CHECK(json::from_bjdata(v_D) == json({{"_ArrayData_", {1., 2., 3., 4., 5., 6.}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "double"}}));
2477                 CHECK(json::from_bjdata(v_C) == json({{"_ArrayData_", {'a', 'b', 'c', 'd', 'e', 'f'}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "char"}}));
2478 
2479                 // roundtrip: output should be optimized
2480                 CHECK(json::to_bjdata(json::from_bjdata(v_e), true, true) == v_e);
2481                 CHECK(json::to_bjdata(json::from_bjdata(v_U), true, true) == v_U);
2482                 CHECK(json::to_bjdata(json::from_bjdata(v_i), true, true) == v_i);
2483                 CHECK(json::to_bjdata(json::from_bjdata(v_u), true, true) == v_u);
2484                 CHECK(json::to_bjdata(json::from_bjdata(v_I), true, true) == v_I);
2485                 CHECK(json::to_bjdata(json::from_bjdata(v_m), true, true) == v_m);
2486                 CHECK(json::to_bjdata(json::from_bjdata(v_l), true, true) == v_l);
2487                 CHECK(json::to_bjdata(json::from_bjdata(v_M), true, true) == v_M);
2488                 CHECK(json::to_bjdata(json::from_bjdata(v_L), true, true) == v_L);
2489                 CHECK(json::to_bjdata(json::from_bjdata(v_d), true, true) == v_d);
2490                 CHECK(json::to_bjdata(json::from_bjdata(v_D), true, true) == v_D);
2491                 CHECK(json::to_bjdata(json::from_bjdata(v_C), true, true) == v_C);
2492             }
2493 
2494             SECTION("optimized ndarray (type and vector-size as 1D array)")
2495             {
2496                 // create vector with two elements of the same type
2497                 std::vector<uint8_t> const v_0 = {'[', '$', 'i', '#', '[', ']'};
2498                 std::vector<uint8_t> const v_E = {'[', '$', 'i', '#', '[', 'i', 2, 'i', 0, ']'};
2499                 std::vector<uint8_t> const v_i = {'[', '$', 'i', '#', '[', 'i', 1, 'i', 2, ']', 0x7F, 0x7F};
2500                 std::vector<uint8_t> const v_U = {'[', '$', 'U', '#', '[', 'i', 1, 'i', 2, ']', 0xFF, 0xFF};
2501                 std::vector<uint8_t> const v_I = {'[', '$', 'I', '#', '[', 'i', 1, 'i', 2, ']', 0xFF, 0x7F, 0xFF, 0x7F};
2502                 std::vector<uint8_t> const v_u = {'[', '$', 'u', '#', '[', 'i', 1, 'i', 2, ']', 0x0F, 0xA7, 0x0F, 0xA7};
2503                 std::vector<uint8_t> const v_l = {'[', '$', 'l', '#', '[', 'i', 1, 'i', 2, ']', 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F};
2504                 std::vector<uint8_t> const v_m = {'[', '$', 'm', '#', '[', 'i', 1, 'i', 2, ']', 0xFF, 0xC9, 0x9A, 0xBB, 0xFF, 0xC9, 0x9A, 0xBB};
2505                 std::vector<uint8_t> const v_L = {'[', '$', 'L', '#', '[', 'i', 1, 'i', 2, ']', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F};
2506                 std::vector<uint8_t> const v_M = {'[', '$', 'M', '#', '[', 'i', 1, 'i', 2, ']', 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D};
2507                 std::vector<uint8_t> const v_D = {'[', '$', 'D', '#', '[', 'i', 1, 'i', 2, ']', 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40};
2508                 std::vector<uint8_t> const v_S = {'[', '#', '[', 'i', 1, 'i', 2, ']', 'S', 'i', 1, 'a', 'S', 'i', 1, 'a'};
2509                 std::vector<uint8_t> const v_C = {'[', '$', 'C', '#', '[', 'i', 1, 'i', 2, ']', 'a', 'a'};
2510                 std::vector<uint8_t> const v_R = {'[', '#', '[', 'i', 2, ']', 'i', 6, 'U', 7};
2511 
2512                 // check if vector is parsed correctly
2513                 CHECK(json::from_bjdata(v_0) == json::array());
2514                 CHECK(json::from_bjdata(v_E) == json::array());
2515                 CHECK(json::from_bjdata(v_i) == json({127, 127}));
2516                 CHECK(json::from_bjdata(v_U) == json({255, 255}));
2517                 CHECK(json::from_bjdata(v_I) == json({32767, 32767}));
2518                 CHECK(json::from_bjdata(v_u) == json({42767, 42767}));
2519                 CHECK(json::from_bjdata(v_l) == json({2147483647, 2147483647}));
2520                 CHECK(json::from_bjdata(v_m) == json({3147483647, 3147483647}));
2521                 CHECK(json::from_bjdata(v_L) == json({9223372036854775807, 9223372036854775807}));
2522                 CHECK(json::from_bjdata(v_M) == json({10223372036854775807ull, 10223372036854775807ull}));
2523                 CHECK(json::from_bjdata(v_D) == json({3.1415926, 3.1415926}));
2524                 CHECK(json::from_bjdata(v_S) == json({"a", "a"}));
2525                 CHECK(json::from_bjdata(v_C) == json({"a", "a"}));
2526                 CHECK(json::from_bjdata(v_R) == json({6, 7}));
2527             }
2528 
2529             SECTION("optimized ndarray (type and vector-size as size-optimized array)")
2530             {
2531                 // create vector with two elements of the same type
2532                 std::vector<uint8_t> const v_i = {'[', '$', 'i', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0x7F, 0x7F};
2533                 std::vector<uint8_t> const v_U = {'[', '$', 'U', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0xFF, 0xFF};
2534                 std::vector<uint8_t> const v_I = {'[', '$', 'I', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0xFF, 0x7F, 0xFF, 0x7F};
2535                 std::vector<uint8_t> const v_u = {'[', '$', 'u', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0x0F, 0xA7, 0x0F, 0xA7};
2536                 std::vector<uint8_t> const v_l = {'[', '$', 'l', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F};
2537                 std::vector<uint8_t> const v_m = {'[', '$', 'm', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0xFF, 0xC9, 0x9A, 0xBB, 0xFF, 0xC9, 0x9A, 0xBB};
2538                 std::vector<uint8_t> const v_L = {'[', '$', 'L', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F};
2539                 std::vector<uint8_t> const v_M = {'[', '$', 'M', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D};
2540                 std::vector<uint8_t> const v_D = {'[', '$', 'D', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40};
2541                 std::vector<uint8_t> const v_S = {'[', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 'S', 'i', 1, 'a', 'S', 'i', 1, 'a'};
2542                 std::vector<uint8_t> const v_C = {'[', '$', 'C', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 'a', 'a'};
2543 
2544                 // check if vector is parsed correctly
2545                 CHECK(json::from_bjdata(v_i) == json({127, 127}));
2546                 CHECK(json::from_bjdata(v_U) == json({255, 255}));
2547                 CHECK(json::from_bjdata(v_I) == json({32767, 32767}));
2548                 CHECK(json::from_bjdata(v_u) == json({42767, 42767}));
2549                 CHECK(json::from_bjdata(v_l) == json({2147483647, 2147483647}));
2550                 CHECK(json::from_bjdata(v_m) == json({3147483647, 3147483647}));
2551                 CHECK(json::from_bjdata(v_L) == json({9223372036854775807, 9223372036854775807}));
2552                 CHECK(json::from_bjdata(v_M) == json({10223372036854775807ull, 10223372036854775807ull}));
2553                 CHECK(json::from_bjdata(v_D) == json({3.1415926, 3.1415926}));
2554                 CHECK(json::from_bjdata(v_S) == json({"a", "a"}));
2555                 CHECK(json::from_bjdata(v_C) == json({"a", "a"}));
2556             }
2557 
2558             SECTION("invalid ndarray annotations remains as object")
2559             {
2560                 // check if invalid ND array annotations stay as object
2561                 json j_type = json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "invalidtype"}});
2562                 json j_size = json({{"_ArrayData_", {1, 2, 3, 4, 5}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "uint8"}});
2563 
2564                 // roundtrip: output should stay as object
2565                 CHECK(json::from_bjdata(json::to_bjdata(j_type), true, true) == j_type);
2566                 CHECK(json::from_bjdata(json::to_bjdata(j_size), true, true) == j_size);
2567             }
2568         }
2569     }
2570 
2571     SECTION("parse errors")
2572     {
2573         SECTION("empty byte vector")
2574         {
2575             json _;
2576             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(std::vector<uint8_t>()),
2577                                  "[json.exception.parse_error.110] parse error at byte 1: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2578         }
2579 
2580         SECTION("char")
2581         {
2582             SECTION("eof after C byte")
2583             {
2584                 std::vector<uint8_t> const v = {'C'};
2585                 json _;
2586                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing BJData char: unexpected end of input", json::parse_error&);
2587             }
2588 
2589             SECTION("byte out of range")
2590             {
2591                 std::vector<uint8_t> const v = {'C', 130};
2592                 json _;
2593                 CHECK_THROWS_WITH(_ = json::from_bjdata(v), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing BJData char: byte after 'C' must be in range 0x00..0x7F; last byte: 0x82");
2594             }
2595         }
2596 
2597         SECTION("strings")
2598         {
2599             SECTION("eof after S byte")
2600             {
2601                 std::vector<uint8_t> const v = {'S'};
2602                 json _;
2603                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2604             }
2605 
2606             SECTION("invalid byte")
2607             {
2608                 std::vector<uint8_t> const v = {'S', '1', 'a'};
2609                 json _;
2610                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing BJData string: expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x31", json::parse_error&);
2611             }
2612 
2613             SECTION("parse bjdata markers in ubjson")
2614             {
2615                 // create a single-character string for all number types
2616                 std::vector<uint8_t> const s_u = {'S', 'u', 1, 0, 'a'};
2617                 std::vector<uint8_t> const s_m = {'S', 'm', 1, 0, 0, 0, 'a'};
2618                 std::vector<uint8_t> const s_M = {'S', 'M', 1, 0, 0, 0, 0, 0, 0, 0, 'a'};
2619 
2620                 json _;
2621                 // check if string is parsed correctly to "a"
2622                 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(s_u), "[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: 0x75", json::parse_error&);
2623                 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(s_m), "[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: 0x6D", json::parse_error&);
2624                 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(s_M), "[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: 0x4D", json::parse_error&);
2625             }
2626         }
2627 
2628         SECTION("array")
2629         {
2630             SECTION("optimized array: no size following type")
2631             {
2632                 std::vector<uint8_t> const v = {'[', '$', 'i', 2};
2633                 json _;
2634                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.112] parse error at byte 4: syntax error while parsing BJData size: expected '#' after type information; last byte: 0x02", json::parse_error&);
2635             }
2636 
2637             SECTION("optimized array: negative size")
2638             {
2639                 std::vector<uint8_t> const v1 = {'[', '#', 'i', 0xF1};
2640                 std::vector<uint8_t> const v2 = {'[', '$', 'I', '#', 'i', 0xF2};
2641                 std::vector<uint8_t> const v3 = {'[', '$', 'I', '#', '[', 'i', 0xF4, 'i', 0x02, ']'};
2642                 std::vector<uint8_t> const v4 = {'[', '$', 0xF6, '#', 'i', 0xF7};
2643                 std::vector<uint8_t> const v5 = {'[', '$', 'I', '#', '[', 'i', 0xF5, 'i', 0xF1, ']'};
2644                 std::vector<uint8_t> const v6 = {'[', '#', '[', 'i', 0xF3, 'i', 0x02, ']'};
2645 
2646                 std::vector<uint8_t> const vI = {'[', '#', 'I', 0x00, 0xF1};
2647                 std::vector<uint8_t> const vl = {'[', '#', 'l', 0x00, 0x00, 0x00, 0xF2};
2648                 std::vector<uint8_t> const vL = {'[', '#', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF3};
2649                 std::vector<uint8_t> const vM = {'[', '$', 'M', '#', '[', 'I', 0x00, 0x20, 'M', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFF, ']'};
2650                 std::vector<uint8_t> const vMX = {'[', '$', 'U', '#', '[', 'M', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 'U', 0x01, ']'};
2651 
2652                 json _;
2653                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v1), "[json.exception.parse_error.113] parse error at byte 4: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&);
2654                 CHECK(json::from_bjdata(v1, true, false).is_discarded());
2655 
2656                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v2), "[json.exception.parse_error.113] parse error at byte 6: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&);
2657                 CHECK(json::from_bjdata(v2, true, false).is_discarded());
2658 
2659                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v3), "[json.exception.parse_error.113] parse error at byte 7: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&);
2660                 CHECK(json::from_bjdata(v3, true, false).is_discarded());
2661 
2662                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v4), "[json.exception.parse_error.113] parse error at byte 6: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&);
2663                 CHECK(json::from_bjdata(v4, true, false).is_discarded());
2664 
2665                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v5), "[json.exception.parse_error.113] parse error at byte 7: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&);
2666                 CHECK(json::from_bjdata(v5, true, false).is_discarded());
2667 
2668                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v6), "[json.exception.parse_error.113] parse error at byte 5: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&);
2669                 CHECK(json::from_bjdata(v6, true, false).is_discarded());
2670 
2671                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vI), "[json.exception.parse_error.113] parse error at byte 5: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&);
2672                 CHECK(json::from_bjdata(vI, true, false).is_discarded());
2673 
2674                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vl), "[json.exception.parse_error.113] parse error at byte 7: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&);
2675                 CHECK(json::from_bjdata(vl, true, false).is_discarded());
2676 
2677                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vL), "[json.exception.parse_error.113] parse error at byte 11: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&);
2678                 CHECK(json::from_bjdata(vL, true, false).is_discarded());
2679 
2680 #if SIZE_MAX != 0xffffffff
2681                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.out_of_range.408] syntax error while parsing BJData size: excessive ndarray size caused overflow", json::out_of_range&);
2682 #else
2683                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
2684 #endif
2685                 CHECK(json::from_bjdata(vM, true, false).is_discarded());
2686 
2687 #if SIZE_MAX != 0xffffffff
2688                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vMX), "[json.exception.out_of_range.408] syntax error while parsing BJData size: excessive ndarray size caused overflow", json::out_of_range&);
2689 #else
2690                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vMX), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
2691 #endif
2692                 CHECK(json::from_bjdata(vMX, true, false).is_discarded());
2693             }
2694 
2695             SECTION("optimized array: integer value overflow")
2696             {
2697 #if SIZE_MAX == 0xffffffff
2698                 std::vector<uint8_t> const vL = {'[', '#', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F};
2699                 std::vector<uint8_t> const vM = {'[', '$', 'M', '#', '[', 'I', 0x00, 0x20, 'M', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFF, ']'};
2700 
2701                 json _;
2702                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vL), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
2703                 CHECK(json::from_bjdata(vL, true, false).is_discarded());
2704                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
2705                 CHECK(json::from_bjdata(vM, true, false).is_discarded());
2706 #endif
2707             }
2708 
2709             SECTION("do not accept NTFZ markers in ndarray optimized type (with count)")
2710             {
2711                 json _;
2712                 std::vector<uint8_t> const v_N = {'[', '$', 'N', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2};
2713                 std::vector<uint8_t> const v_T = {'[', '$', 'T', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2};
2714                 std::vector<uint8_t> const v_F = {'[', '$', 'F', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2};
2715                 std::vector<uint8_t> const v_Z = {'[', '$', 'Z', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2};
2716 
2717                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_N), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x4E is not a permitted optimized array type", json::parse_error&);
2718                 CHECK(json::from_bjdata(v_N, true, false).is_discarded());
2719 
2720                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_T), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x54 is not a permitted optimized array type", json::parse_error&);
2721                 CHECK(json::from_bjdata(v_T, true, false).is_discarded());
2722 
2723                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_F), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x46 is not a permitted optimized array type", json::parse_error&);
2724                 CHECK(json::from_bjdata(v_F, true, false).is_discarded());
2725 
2726                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_Z), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x5A is not a permitted optimized array type", json::parse_error&);
2727                 CHECK(json::from_bjdata(v_Z, true, false).is_discarded());
2728             }
2729 
2730             SECTION("do not accept NTFZ markers in ndarray optimized type (without count)")
2731             {
2732                 json _;
2733                 std::vector<uint8_t> const v_N = {'[', '$', 'N', '#', '[', 'i', 1, 'i', 2, ']'};
2734                 std::vector<uint8_t> const v_T = {'[', '$', 'T', '#', '[', 'i', 1, 'i', 2, ']'};
2735                 std::vector<uint8_t> const v_F = {'[', '$', 'F', '#', '[', 'i', 1, 'i', 2, ']'};
2736                 std::vector<uint8_t> const v_Z = {'[', '$', 'Z', '#', '[', 'i', 1, 'i', 2, ']'};
2737 
2738                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_N), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x4E is not a permitted optimized array type", json::parse_error&);
2739                 CHECK(json::from_bjdata(v_N, true, false).is_discarded());
2740 
2741                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_T), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x54 is not a permitted optimized array type", json::parse_error&);
2742                 CHECK(json::from_bjdata(v_T, true, false).is_discarded());
2743 
2744                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_F), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x46 is not a permitted optimized array type", json::parse_error&);
2745                 CHECK(json::from_bjdata(v_F, true, false).is_discarded());
2746 
2747                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_Z), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x5A is not a permitted optimized array type", json::parse_error&);
2748                 CHECK(json::from_bjdata(v_Z, true, false).is_discarded());
2749             }
2750         }
2751 
2752         SECTION("strings")
2753         {
2754             std::vector<uint8_t> const vS = {'S'};
2755             json _;
2756             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vS), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2757             CHECK(json::from_bjdata(vS, true, false).is_discarded());
2758 
2759             std::vector<uint8_t> const v = {'S', 'i', '2', 'a'};
2760             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing BJData string: unexpected end of input", json::parse_error&);
2761             CHECK(json::from_bjdata(v, true, false).is_discarded());
2762 
2763             std::vector<uint8_t> const vC = {'C'};
2764             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vC), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing BJData char: unexpected end of input", json::parse_error&);
2765             CHECK(json::from_bjdata(vC, true, false).is_discarded());
2766         }
2767 
2768         SECTION("sizes")
2769         {
2770             std::vector<uint8_t> const vU = {'[', '#', 'U'};
2771             json _;
2772             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vU), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2773             CHECK(json::from_bjdata(vU, true, false).is_discarded());
2774 
2775             std::vector<uint8_t> const vi = {'[', '#', 'i'};
2776             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vi), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2777             CHECK(json::from_bjdata(vi, true, false).is_discarded());
2778 
2779             std::vector<uint8_t> const vI = {'[', '#', 'I'};
2780             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vI), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2781             CHECK(json::from_bjdata(vI, true, false).is_discarded());
2782 
2783             std::vector<uint8_t> const vu = {'[', '#', 'u'};
2784             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vu), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2785             CHECK(json::from_bjdata(vu, true, false).is_discarded());
2786 
2787             std::vector<uint8_t> const vl = {'[', '#', 'l'};
2788             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vl), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2789             CHECK(json::from_bjdata(vl, true, false).is_discarded());
2790 
2791             std::vector<uint8_t> const vm = {'[', '#', 'm'};
2792             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vm), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2793             CHECK(json::from_bjdata(vm, true, false).is_discarded());
2794 
2795             std::vector<uint8_t> const vL = {'[', '#', 'L'};
2796             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vL), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2797             CHECK(json::from_bjdata(vL, true, false).is_discarded());
2798 
2799             std::vector<uint8_t> const vM = {'[', '#', 'M'};
2800             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2801             CHECK(json::from_bjdata(vM, true, false).is_discarded());
2802 
2803             std::vector<uint8_t> const v0 = {'[', '#', 'T', ']'};
2804             CHECK_THROWS_WITH(_ = json::from_bjdata(v0), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing BJData size: expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x54");
2805             CHECK(json::from_bjdata(v0, true, false).is_discarded());
2806         }
2807 
2808         SECTION("parse bjdata markers as array size in ubjson")
2809         {
2810             json _;
2811             std::vector<uint8_t> const vu = {'[', '#', 'u'};
2812             CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vu), "[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: 0x75", json::parse_error&);
2813             CHECK(json::from_ubjson(vu, true, false).is_discarded());
2814 
2815             std::vector<uint8_t> const vm = {'[', '#', 'm'};
2816             CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vm), "[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: 0x6D", json::parse_error&);
2817             CHECK(json::from_ubjson(vm, true, false).is_discarded());
2818 
2819             std::vector<uint8_t> const vM = {'[', '#', 'M'};
2820             CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vM), "[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: 0x4D", json::parse_error&);
2821             CHECK(json::from_ubjson(vM, true, false).is_discarded());
2822 
2823             std::vector<uint8_t> const v0 = {'[', '#', '['};
2824             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: 0x5B", json::parse_error&);
2825             CHECK(json::from_ubjson(v0, true, false).is_discarded());
2826         }
2827 
2828         SECTION("types")
2829         {
2830             std::vector<uint8_t> const v0 = {'[', '$'};
2831             json _;
2832             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v0), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing BJData type: unexpected end of input", json::parse_error&);
2833             CHECK(json::from_bjdata(v0, true, false).is_discarded());
2834 
2835             std::vector<uint8_t> const vi = {'[', '$', '#'};
2836             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vi), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2837             CHECK(json::from_bjdata(vi, true, false).is_discarded());
2838 
2839             std::vector<uint8_t> const vU = {'[', '$', 'U'};
2840             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vU), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2841             CHECK(json::from_bjdata(vU, true, false).is_discarded());
2842 
2843             std::vector<uint8_t> const v1 = {'[', '$', '['};
2844             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v1), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x5B is not a permitted optimized array type", json::parse_error&);
2845             CHECK(json::from_bjdata(v1, true, false).is_discarded());
2846         }
2847 
2848         SECTION("arrays")
2849         {
2850             std::vector<uint8_t> const vST = {'[', '$', 'i', '#', 'i', 2, 1};
2851             json _;
2852             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vST), "[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2853             CHECK(json::from_bjdata(vST, true, false).is_discarded());
2854 
2855             std::vector<uint8_t> const vS = {'[', '#', 'i', 2, 'i', 1};
2856             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vS), "[json.exception.parse_error.110] parse error at byte 7: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2857             CHECK(json::from_bjdata(vS, true, false).is_discarded());
2858 
2859             std::vector<uint8_t> const v = {'[', 'i', 2, 'i', 1};
2860             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.110] parse error at byte 6: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2861             CHECK(json::from_bjdata(v, true, false).is_discarded());
2862         }
2863 
2864         SECTION("ndarrays")
2865         {
2866             std::vector<uint8_t> const vST = {'[', '$', 'i', '#', '[', '$', 'i', '#'};
2867             json _;
2868             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vST), "[json.exception.parse_error.113] parse error at byte 9: syntax error while parsing BJData size: expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0xFF", json::parse_error&);
2869             CHECK(json::from_bjdata(vST, true, false).is_discarded());
2870 
2871             std::vector<uint8_t> const v = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 2, 1, 2};
2872             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.110] parse error at byte 13: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2873             CHECK(json::from_bjdata(v, true, false).is_discarded());
2874 
2875             std::vector<uint8_t> const vS0 = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 2, 1};
2876             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vS0), "[json.exception.parse_error.110] parse error at byte 12: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2877             CHECK(json::from_bjdata(vS0, true, false).is_discarded());
2878 
2879             std::vector<uint8_t> const vS = {'[', '$', 'i', '#', '[', '#', 'i', 2, 1, 2, 1};
2880             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vS), "[json.exception.parse_error.113] parse error at byte 9: syntax error while parsing BJData size: expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x01", json::parse_error&);
2881             CHECK(json::from_bjdata(vS, true, false).is_discarded());
2882 
2883             std::vector<uint8_t> const vT = {'[', '$', 'i', '#', '[', 'i', 2, 'i'};
2884             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vT), "[json.exception.parse_error.110] parse error at byte 9: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2885             CHECK(json::from_bjdata(vT, true, false).is_discarded());
2886 
2887             std::vector<uint8_t> const vT0 = {'[', '$', 'i', '#', '[', 'i'};
2888             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vT0), "[json.exception.parse_error.110] parse error at byte 7: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2889             CHECK(json::from_bjdata(vT0, true, false).is_discarded());
2890 
2891             std::vector<uint8_t> const vu = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'u', 1, 0};
2892             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vu), "[json.exception.parse_error.110] parse error at byte 12: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2893             CHECK(json::from_bjdata(vu, true, false).is_discarded());
2894 
2895             std::vector<uint8_t> const vm = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'm', 1, 0, 0, 0};
2896             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vm), "[json.exception.parse_error.110] parse error at byte 14: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2897             CHECK(json::from_bjdata(vm, true, false).is_discarded());
2898 
2899             std::vector<uint8_t> const vM = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'M', 1, 0, 0, 0, 0, 0, 0, 0};
2900             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.parse_error.110] parse error at byte 18: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2901             CHECK(json::from_bjdata(vM, true, false).is_discarded());
2902 
2903             std::vector<uint8_t> const vU = {'[', '$', 'U', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 1, 2, 3, 4, 5};
2904             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vU), "[json.exception.parse_error.110] parse error at byte 18: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2905             CHECK(json::from_bjdata(vU, true, false).is_discarded());
2906 
2907             std::vector<uint8_t> const vT1 = {'[', '$', 'T', '#', '[', '$', 'i', '#', 'i', 2, 2, 3};
2908             CHECK(json::from_bjdata(vT1, true, false).is_discarded());
2909 
2910             std::vector<uint8_t> const vh = {'[', '$', 'h', '#', '[', '$', 'i', '#', 'i', 2, 2, 3};
2911             CHECK(json::from_bjdata(vh, true, false).is_discarded());
2912 
2913             std::vector<uint8_t> const vR = {'[', '$', 'i', '#', '[', 'i', 1, '[', ']', ']', 1};
2914             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR), "[json.exception.parse_error.113] parse error at byte 8: syntax error while parsing BJData size: ndarray dimensional vector is not allowed", json::parse_error&);
2915             CHECK(json::from_bjdata(vR, true, false).is_discarded());
2916 
2917             std::vector<uint8_t> const vRo = {'[', '$', 'i', '#', '[', 'i', 0, '{', '}', ']', 1};
2918             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vRo), "[json.exception.parse_error.113] parse error at byte 8: syntax error while parsing BJData size: expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x7B", json::parse_error&);
2919             CHECK(json::from_bjdata(vRo, true, false).is_discarded());
2920 
2921             std::vector<uint8_t> const vR1 = {'[', '$', 'i', '#', '[', '[', 'i', 1, ']', ']', 1};
2922             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR1), "[json.exception.parse_error.113] parse error at byte 6: syntax error while parsing BJData size: ndarray dimensional vector is not allowed", json::parse_error&);
2923             CHECK(json::from_bjdata(vR1, true, false).is_discarded());
2924 
2925             std::vector<uint8_t> const vR2 = {'[', '$', 'i', '#', '[', '#', '[', 'i', 1, ']', ']', 1};
2926             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR2), "[json.exception.parse_error.113] parse error at byte 11: syntax error while parsing BJData size: expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x5D", json::parse_error&);
2927             CHECK(json::from_bjdata(vR2, true, false).is_discarded());
2928 
2929             std::vector<uint8_t> const vR3 = {'[', '#', '[', 'i', '2', 'i', 2, ']'};
2930             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR3), "[json.exception.parse_error.112] parse error at byte 8: syntax error while parsing BJData size: ndarray requires both type and size", json::parse_error&);
2931             CHECK(json::from_bjdata(vR3, true, false).is_discarded());
2932 
2933             std::vector<uint8_t> const vR4 = {'[', '$', 'i', '#', '[', '$', 'i', '#', '[', 'i', 1, ']', 1};
2934             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR4), "[json.exception.parse_error.110] parse error at byte 14: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2935             CHECK(json::from_bjdata(vR4, true, false).is_discarded());
2936 
2937             std::vector<uint8_t> const vR5 = {'[', '$', 'i', '#', '[', '[', '[', ']', ']', ']'};
2938             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR5), "[json.exception.parse_error.113] parse error at byte 6: syntax error while parsing BJData size: ndarray dimensional vector is not allowed", json::parse_error&);
2939             CHECK(json::from_bjdata(vR5, true, false).is_discarded());
2940 
2941             std::vector<uint8_t> const vR6 = {'[', '$', 'i', '#', '[', '$', 'i', '#', '[', 'i', '2', 'i', 2, ']'};
2942             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR6), "[json.exception.parse_error.112] parse error at byte 14: syntax error while parsing BJData size: ndarray can not be recursive", json::parse_error&);
2943             CHECK(json::from_bjdata(vR6, true, false).is_discarded());
2944 
2945             std::vector<uint8_t> const vH = {'[', 'H', '[', '#', '[', '$', 'i', '#', '[', 'i', '2', 'i', 2, ']'};
2946             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vH), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing BJData size: ndarray dimensional vector is not allowed", json::parse_error&);
2947             CHECK(json::from_bjdata(vH, true, false).is_discarded());
2948         }
2949 
2950         SECTION("objects")
2951         {
2952             std::vector<uint8_t> const vST = {'{', '$', 'i', '#', 'i', 2, 'i', 1, 'a', 1};
2953             json _;
2954             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vST), "[json.exception.parse_error.110] parse error at byte 11: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2955             CHECK(json::from_bjdata(vST, true, false).is_discarded());
2956 
2957             std::vector<uint8_t> const vT = {'{', '$', 'i', 'i', 1, 'a', 1};
2958             CHECK_THROWS_WITH(_ = json::from_bjdata(vT), "[json.exception.parse_error.112] parse error at byte 4: syntax error while parsing BJData size: expected '#' after type information; last byte: 0x69");
2959             CHECK(json::from_bjdata(vT, true, false).is_discarded());
2960 
2961             std::vector<uint8_t> const vS = {'{', '#', 'i', 2, 'i', 1, 'a', 'i', 1};
2962             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vS), "[json.exception.parse_error.110] parse error at byte 10: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2963             CHECK(json::from_bjdata(vS, true, false).is_discarded());
2964 
2965             std::vector<uint8_t> const v = {'{', 'i', 1, 'a', 'i', 1};
2966             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.110] parse error at byte 7: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2967             CHECK(json::from_bjdata(v, true, false).is_discarded());
2968 
2969             std::vector<uint8_t> const v2 = {'{', 'i', 1, 'a', 'i', 1, 'i'};
2970             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v2), "[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2971             CHECK(json::from_bjdata(v2, true, false).is_discarded());
2972 
2973             std::vector<uint8_t> const v3 = {'{', 'i', 1, 'a'};
2974             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v3), "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2975             CHECK(json::from_bjdata(v3, true, false).is_discarded());
2976 
2977             std::vector<uint8_t> const vST1 = {'{', '$', 'd', '#', 'i', 2, 'i', 1, 'a'};
2978             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vST1), "[json.exception.parse_error.110] parse error at byte 10: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2979             CHECK(json::from_bjdata(vST1, true, false).is_discarded());
2980 
2981             std::vector<uint8_t> const vST2 = {'{', '#', 'i', 2, 'i', 1, 'a'};
2982             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vST2), "[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2983             CHECK(json::from_bjdata(vST2, true, false).is_discarded());
2984 
2985             std::vector<uint8_t> const vO = {'{', '#', '[', 'i', 2, 'i', 1, ']', 'i', 1, 'a', 'i', 1, 'i', 1, 'b', 'i', 2};
2986             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vO), "[json.exception.parse_error.112] parse error at byte 8: syntax error while parsing BJData size: ndarray requires both type and size", json::parse_error&);
2987             CHECK(json::from_bjdata(vO, true, false).is_discarded());
2988 
2989             std::vector<uint8_t> const vO2 = {'{', '$', 'i', '#', '[', 'i', 2, 'i', 1, ']', 'i', 1, 'a', 1, 'i', 1, 'b', 2};
2990             CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vO2), "[json.exception.parse_error.112] parse error at byte 10: syntax error while parsing BJData object: BJData object does not support ND-array size in optimized format", json::parse_error&);
2991             CHECK(json::from_bjdata(vO2, true, false).is_discarded());
2992         }
2993     }
2994 
2995     SECTION("writing optimized values")
2996     {
2997         SECTION("integer")
2998         {
2999             SECTION("array of i")
3000             {
3001                 json const j = {1, -1};
3002                 std::vector<uint8_t> const expected = {'[', '$', 'i', '#', 'i', 2, 1, 0xff};
3003                 CHECK(json::to_bjdata(j, true, true) == expected);
3004             }
3005 
3006             SECTION("array of U")
3007             {
3008                 json const j = {200, 201};
3009                 std::vector<uint8_t> const expected = {'[', '$', 'U', '#', 'i', 2, 0xC8, 0xC9};
3010                 CHECK(json::to_bjdata(j, true, true) == expected);
3011             }
3012 
3013             SECTION("array of I")
3014             {
3015                 json const j = {30000, -30000};
3016                 std::vector<uint8_t> const expected = {'[', '$', 'I', '#', 'i', 2, 0x30, 0x75, 0xd0, 0x8a};
3017                 CHECK(json::to_bjdata(j, true, true) == expected);
3018             }
3019 
3020             SECTION("array of u")
3021             {
3022                 json const j = {50000, 50001};
3023                 std::vector<uint8_t> const expected = {'[', '$', 'u', '#', 'i', 2, 0x50, 0xC3, 0x51, 0xC3};
3024                 CHECK(json::to_bjdata(j, true, true) == expected);
3025             }
3026 
3027             SECTION("array of l")
3028             {
3029                 json const j = {70000, -70000};
3030                 std::vector<uint8_t> const expected = {'[', '$', 'l', '#', 'i', 2, 0x70, 0x11, 0x01, 0x00, 0x90, 0xEE, 0xFE, 0xFF};
3031                 CHECK(json::to_bjdata(j, true, true) == expected);
3032             }
3033 
3034             SECTION("array of m")
3035             {
3036                 json const j = {3147483647, 3147483648};
3037                 std::vector<uint8_t> const expected = {'[', '$', 'm', '#', 'i', 2, 0xFF, 0xC9, 0x9A, 0xBB, 0x00, 0xCA, 0x9A, 0xBB};
3038                 CHECK(json::to_bjdata(j, true, true) == expected);
3039             }
3040 
3041             SECTION("array of L")
3042             {
3043                 json const j = {5000000000, -5000000000};
3044                 std::vector<uint8_t> const expected = {'[', '$', 'L', '#', 'i', 2, 0x00, 0xF2, 0x05, 0x2A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xFA, 0xD5, 0xFE, 0xFF, 0xFF, 0xFF};
3045                 CHECK(json::to_bjdata(j, true, true) == expected);
3046             }
3047         }
3048 
3049         SECTION("unsigned integer")
3050         {
3051             SECTION("array of i")
3052             {
3053                 json const j = {1u, 2u};
3054                 std::vector<uint8_t> const expected = {'[', '$', 'i', '#', 'i', 2, 1, 2};
3055                 std::vector<uint8_t> const expected_size = {'[', '#', 'i', 2, 'i', 1, 'i', 2};
3056                 CHECK(json::to_bjdata(j, true, true) == expected);
3057                 CHECK(json::to_bjdata(j, true) == expected_size);
3058             }
3059 
3060             SECTION("array of U")
3061             {
3062                 json const j = {200u, 201u};
3063                 std::vector<uint8_t> const expected = {'[', '$', 'U', '#', 'i', 2, 0xC8, 0xC9};
3064                 std::vector<uint8_t> const expected_size = {'[', '#', 'i', 2, 'U', 0xC8, 'U', 0xC9};
3065                 CHECK(json::to_bjdata(j, true, true) == expected);
3066                 CHECK(json::to_bjdata(j, true) == expected_size);
3067             }
3068 
3069             SECTION("array of I")
3070             {
3071                 json const j = {30000u, 30001u};
3072                 std::vector<uint8_t> const expected = {'[', '$', 'I', '#', 'i', 2, 0x30, 0x75, 0x31, 0x75};
3073                 std::vector<uint8_t> const expected_size = {'[', '#', 'i', 2, 'I', 0x30, 0x75, 'I', 0x31, 0x75};
3074                 CHECK(json::to_bjdata(j, true, true) == expected);
3075                 CHECK(json::to_bjdata(j, true) == expected_size);
3076             }
3077 
3078             SECTION("array of u")
3079             {
3080                 json const j = {50000u, 50001u};
3081                 std::vector<uint8_t> const expected = {'[', '$', 'u', '#', 'i', 2, 0x50, 0xC3, 0x51, 0xC3};
3082                 std::vector<uint8_t> const expected_size = {'[', '#', 'i', 2, 'u', 0x50, 0xC3, 'u', 0x51, 0xC3};
3083                 CHECK(json::to_bjdata(j, true, true) == expected);
3084                 CHECK(json::to_bjdata(j, true) == expected_size);
3085             }
3086 
3087             SECTION("array of l")
3088             {
3089                 json const j = {70000u, 70001u};
3090                 std::vector<uint8_t> const expected = {'[', '$', 'l', '#', 'i', 2, 0x70, 0x11, 0x01, 0x00, 0x71, 0x11, 0x01, 0x00};
3091                 std::vector<uint8_t> const expected_size = {'[', '#', 'i', 2, 'l', 0x70, 0x11, 0x01, 0x00, 'l', 0x71, 0x11, 0x01, 0x00};
3092                 CHECK(json::to_bjdata(j, true, true) == expected);
3093                 CHECK(json::to_bjdata(j, true) == expected_size);
3094             }
3095 
3096             SECTION("array of m")
3097             {
3098                 json const j = {3147483647u, 3147483648u};
3099                 std::vector<uint8_t> const expected = {'[', '$', 'm', '#', 'i', 2, 0xFF, 0xC9, 0x9A, 0xBB, 0x00, 0xCA, 0x9A, 0xBB};
3100                 std::vector<uint8_t> const expected_size = {'[', '#', 'i', 2, 'm', 0xFF, 0xC9, 0x9A, 0xBB, 'm', 0x00, 0xCA, 0x9A, 0xBB};
3101                 CHECK(json::to_bjdata(j, true, true) == expected);
3102                 CHECK(json::to_bjdata(j, true) == expected_size);
3103             }
3104 
3105             SECTION("array of L")
3106             {
3107                 json const j = {5000000000u, 5000000001u};
3108                 std::vector<uint8_t> const expected = {'[', '$', 'L', '#', 'i', 2, 0x00, 0xF2, 0x05, 0x2A, 0x01, 0x00, 0x00, 0x00, 0x01, 0xF2, 0x05, 0x2A, 0x01, 0x00, 0x00, 0x00};
3109                 std::vector<uint8_t> const expected_size = {'[', '#', 'i', 2, 'L', 0x00, 0xF2, 0x05, 0x2A, 0x01, 0x00, 0x00, 0x00, 'L', 0x01, 0xF2, 0x05, 0x2A, 0x01, 0x00, 0x00, 0x00};
3110                 CHECK(json::to_bjdata(j, true, true) == expected);
3111                 CHECK(json::to_bjdata(j, true) == expected_size);
3112             }
3113 
3114             SECTION("array of M")
3115             {
3116                 json const j = {10223372036854775807ull, 10223372036854775808ull};
3117                 std::vector<uint8_t> const expected = {'[', '$', 'M', '#', 'i', 2, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 0x00, 0x00, 0x64, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D};
3118                 std::vector<uint8_t> const expected_size = {'[', '#', 'i', 2, 'M', 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 'M', 0x00, 0x00, 0x64, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D};
3119                 CHECK(json::to_bjdata(j, true, true) == expected);
3120                 CHECK(json::to_bjdata(j, true) == expected_size);
3121             }
3122         }
3123     }
3124 }
3125 
3126 TEST_CASE("Universal Binary JSON Specification Examples 1")
3127 {
3128     SECTION("Null Value")
3129     {
3130         json const j = {{"passcode", nullptr}};
3131         std::vector<uint8_t> v = {'{', 'i', 8, 'p', 'a', 's', 's', 'c', 'o', 'd', 'e', 'Z', '}'};
3132         CHECK(json::to_bjdata(j) == v);
3133         CHECK(json::from_bjdata(v) == j);
3134     }
3135 
3136     SECTION("No-Op Value")
3137     {
3138         json const j = {"foo", "bar", "baz"};
3139         std::vector<uint8_t> v = {'[', 'S', 'i', 3, 'f', 'o', 'o',
3140                                   'S', 'i', 3, 'b', 'a', 'r',
3141                                   'S', 'i', 3, 'b', 'a', 'z', ']'
3142                                  };
3143         std::vector<uint8_t> const v2 = {'[', 'S', 'i', 3, 'f', 'o', 'o', 'N',
3144                                          'S', 'i', 3, 'b', 'a', 'r', 'N', 'N', 'N',
3145                                          'S', 'i', 3, 'b', 'a', 'z', 'N', 'N', ']'
3146                                         };
3147         CHECK(json::to_bjdata(j) == v);
3148         CHECK(json::from_bjdata(v) == j);
3149         CHECK(json::from_bjdata(v2) == j);
3150     }
3151 
3152     SECTION("Boolean Types")
3153     {
3154         json const j = {{"authorized", true}, {"verified", false}};
3155         std::vector<uint8_t> v = {'{', 'i', 10, 'a', 'u', 't', 'h', 'o', 'r', 'i', 'z', 'e', 'd', 'T',
3156                                   'i', 8, 'v', 'e', 'r', 'i', 'f', 'i', 'e', 'd', 'F', '}'
3157                                  };
3158         CHECK(json::to_bjdata(j) == v);
3159         CHECK(json::from_bjdata(v) == j);
3160     }
3161 
3162     SECTION("Numeric Types")
3163     {
3164         json j =
3165         {
3166             {"int8", 16},
3167             {"uint8", 255},
3168             {"int16", 32767},
3169             {"uint16", 42767},
3170             {"int32", 2147483647},
3171             {"uint32", 3147483647},
3172             {"int64", 9223372036854775807},
3173             {"uint64", 10223372036854775807ull},
3174             {"float64", 113243.7863123}
3175         };
3176         std::vector<uint8_t> v = {'{',
3177                                   'i', 7, 'f', 'l', 'o', 'a', 't', '6', '4', 'D', 0xcf, 0x34, 0xbc, 0x94, 0xbc, 0xa5, 0xfb, 0x40,
3178                                   'i', 5, 'i', 'n', 't', '1', '6', 'I', 0xff, 0x7f,
3179                                   'i', 5, 'i', 'n', 't', '3', '2', 'l', 0xff, 0xff, 0xff, 0x7f,
3180                                   'i', 5, 'i', 'n', 't', '6', '4', 'L', 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
3181                                   'i', 4, 'i', 'n', 't', '8', 'i', 16,
3182                                   'i', 6, 'u', 'i', 'n', 't', '1', '6', 'u', 0x0F, 0xA7,
3183                                   'i', 6, 'u', 'i', 'n', 't', '3', '2', 'm', 0xFF, 0xC9, 0x9A, 0xBB,
3184                                   'i', 6, 'u', 'i', 'n', 't', '6', '4', 'M', 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D,
3185                                   'i', 5, 'u', 'i', 'n', 't', '8', 'U', 0xff,
3186                                   '}'
3187                                  };
3188         CHECK(json::to_bjdata(j) == v);
3189         CHECK(json::from_bjdata(v) == j);
3190     }
3191 
3192     SECTION("Char Type")
3193     {
3194         json const j = {{"rolecode", "a"}, {"delim", ";"}};
3195         std::vector<uint8_t> const v = {'{', 'i', 5, 'd', 'e', 'l', 'i', 'm', 'C', ';', 'i', 8, 'r', 'o', 'l', 'e', 'c', 'o', 'd', 'e', 'C', 'a', '}'};
3196         //CHECK(json::to_bjdata(j) == v);
3197         CHECK(json::from_bjdata(v) == j);
3198     }
3199 
3200     SECTION("String Type")
3201     {
3202         SECTION("English")
3203         {
3204             json const j = "hello";
3205             std::vector<uint8_t> v = {'S', 'i', 5, 'h', 'e', 'l', 'l', 'o'};
3206             CHECK(json::to_bjdata(j) == v);
3207             CHECK(json::from_bjdata(v) == j);
3208         }
3209 
3210         SECTION("Russian")
3211         {
3212             json const j = "привет";
3213             std::vector<uint8_t> v = {'S', 'i', 12, 0xD0, 0xBF, 0xD1, 0x80, 0xD0, 0xB8, 0xD0, 0xB2, 0xD0, 0xB5, 0xD1, 0x82};
3214             CHECK(json::to_bjdata(j) == v);
3215             CHECK(json::from_bjdata(v) == j);
3216         }
3217 
3218         SECTION("Russian")
3219         {
3220             json const j = "مرحبا";
3221             std::vector<uint8_t> v = {'S', 'i', 10, 0xD9, 0x85, 0xD8, 0xB1, 0xD8, 0xAD, 0xD8, 0xA8, 0xD8, 0xA7};
3222             CHECK(json::to_bjdata(j) == v);
3223             CHECK(json::from_bjdata(v) == j);
3224         }
3225     }
3226 
3227     SECTION("Array Type")
3228     {
3229         SECTION("size=false type=false")
3230         {
3231             // note the float has been replaced by a double
3232             json const j = {nullptr, true, false, 4782345193, 153.132, "ham"};
3233             std::vector<uint8_t> v = {'[', 'Z', 'T', 'F', 'L', 0xE9, 0xCB, 0x0C, 0x1D, 0x01, 0x00, 0x00, 0x00, 'D', 0x4e, 0x62, 0x10, 0x58, 0x39, 0x24, 0x63, 0x40, 'S', 'i', 3, 'h', 'a', 'm', ']'};
3234             CHECK(json::to_bjdata(j) == v);
3235             CHECK(json::from_bjdata(v) == j);
3236         }
3237 
3238         SECTION("size=true type=false")
3239         {
3240             // note the float has been replaced by a double
3241             json const j = {nullptr, true, false, 4782345193, 153.132, "ham"};
3242             std::vector<uint8_t> v = {'[', '#', 'i', 6, 'Z', 'T', 'F', 'L', 0xE9, 0xCB, 0x0C, 0x1D, 0x01, 0x00, 0x00, 0x00, 'D', 0x4e, 0x62, 0x10, 0x58, 0x39, 0x24, 0x63, 0x40, 'S', 'i', 3, 'h', 'a', 'm'};
3243             CHECK(json::to_bjdata(j, true) == v);
3244             CHECK(json::from_bjdata(v) == j);
3245         }
3246 
3247         SECTION("size=true type=true")
3248         {
3249             // note the float has been replaced by a double
3250             json const j = {nullptr, true, false, 4782345193, 153.132, "ham"};
3251             std::vector<uint8_t> v = {'[', '#', 'i', 6, 'Z', 'T', 'F', 'L', 0xE9, 0xCB, 0x0C, 0x1D, 0x01, 0x00, 0x00, 0x00, 'D', 0x4e, 0x62, 0x10, 0x58, 0x39, 0x24, 0x63, 0x40, 'S', 'i', 3, 'h', 'a', 'm'};
3252             CHECK(json::to_bjdata(j, true, true) == v);
3253             CHECK(json::from_bjdata(v) == j);
3254         }
3255     }
3256 
3257     SECTION("Object Type")
3258     {
3259         SECTION("size=false type=false")
3260         {
3261             json j =
3262             {
3263                 {
3264                     "post", {
3265                         {"id", 1137},
3266                         {"author", "rkalla"},
3267                         {"timestamp", 1364482090592},
3268                         {"body", "I totally agree!"}
3269                     }
3270                 }
3271             };
3272             std::vector<uint8_t> v = {'{', 'i', 4, 'p', 'o', 's', 't', '{',
3273                                       'i', 6, 'a', 'u', 't', 'h', 'o', 'r', 'S', 'i', 6, 'r', 'k', 'a', 'l', 'l', 'a',
3274                                       'i', 4, 'b', 'o', 'd', 'y', 'S', 'i', 16, 'I', ' ', 't', 'o', 't', 'a', 'l', 'l', 'y', ' ', 'a', 'g', 'r', 'e', 'e', '!',
3275                                       'i', 2, 'i', 'd', 'I', 0x71, 0x04,
3276                                       'i', 9, 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'L', 0x60, 0x66, 0x78, 0xB1, 0x3D, 0x01, 0x00, 0x00,
3277                                       '}', '}'
3278                                      };
3279             CHECK(json::to_bjdata(j) == v);
3280             CHECK(json::from_bjdata(v) == j);
3281         }
3282 
3283         SECTION("size=true type=false")
3284         {
3285             json j =
3286             {
3287                 {
3288                     "post", {
3289                         {"id", 1137},
3290                         {"author", "rkalla"},
3291                         {"timestamp", 1364482090592},
3292                         {"body", "I totally agree!"}
3293                     }
3294                 }
3295             };
3296             std::vector<uint8_t> v = {'{', '#', 'i', 1, 'i', 4, 'p', 'o', 's', 't', '{', '#', 'i', 4,
3297                                       'i', 6, 'a', 'u', 't', 'h', 'o', 'r', 'S', 'i', 6, 'r', 'k', 'a', 'l', 'l', 'a',
3298                                       'i', 4, 'b', 'o', 'd', 'y', 'S', 'i', 16, 'I', ' ', 't', 'o', 't', 'a', 'l', 'l', 'y', ' ', 'a', 'g', 'r', 'e', 'e', '!',
3299                                       'i', 2, 'i', 'd', 'I', 0x71, 0x04,
3300                                       'i', 9, 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'L', 0x60, 0x66, 0x78, 0xB1, 0x3D, 0x01, 0x00, 0x00,
3301                                      };
3302             CHECK(json::to_bjdata(j, true) == v);
3303             CHECK(json::from_bjdata(v) == j);
3304         }
3305 
3306         SECTION("size=true type=true")
3307         {
3308             json j =
3309             {
3310                 {
3311                     "post", {
3312                         {"id", 1137},
3313                         {"author", "rkalla"},
3314                         {"timestamp", 1364482090592},
3315                         {"body", "I totally agree!"}
3316                     }
3317                 }
3318             };
3319             std::vector<uint8_t> v = {'{', '#', 'i', 1, 'i', 4, 'p', 'o', 's', 't', '{', '#', 'i', 4,
3320                                       'i', 6, 'a', 'u', 't', 'h', 'o', 'r', 'S', 'i', 6, 'r', 'k', 'a', 'l', 'l', 'a',
3321                                       'i', 4, 'b', 'o', 'd', 'y', 'S', 'i', 16, 'I', ' ', 't', 'o', 't', 'a', 'l', 'l', 'y', ' ', 'a', 'g', 'r', 'e', 'e', '!',
3322                                       'i', 2, 'i', 'd', 'I', 0x71, 0x04,
3323                                       'i', 9, 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'L', 0x60, 0x66, 0x78, 0xB1, 0x3D, 0x01, 0x00, 0x00,
3324                                      };
3325             CHECK(json::to_bjdata(j, true, true) == v);
3326             CHECK(json::from_bjdata(v) == j);
3327         }
3328     }
3329 
3330     SECTION("Optimized Format")
3331     {
3332         SECTION("Array Example")
3333         {
3334             SECTION("No Optimization")
3335             {
3336                 // note the floats have been replaced by doubles
3337                 json const j = {29.97, 31.13, 67.0, 2.113, 23.888};
3338                 std::vector<uint8_t> v = {'[',
3339                                           'D', 0xb8, 0x1e, 0x85, 0xeb, 0x51, 0xf8, 0x3d, 0x40,
3340                                           'D', 0xe1, 0x7a, 0x14, 0xae, 0x47, 0x21, 0x3f, 0x40,
3341                                           'D', 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x50, 0x40,
3342                                           'D', 0x81, 0x95, 0x43, 0x8b, 0x6c, 0xe7, 0x00, 0x40,
3343                                           'D', 0x17, 0xd9, 0xce, 0xf7, 0x53, 0xe3, 0x37, 0x40,
3344                                           ']'
3345                                          };
3346                 CHECK(json::to_bjdata(j) == v);
3347                 CHECK(json::from_bjdata(v) == j);
3348             }
3349 
3350             SECTION("Optimized with count")
3351             {
3352                 // note the floats have been replaced by doubles
3353                 json const j = {29.97, 31.13, 67.0, 2.113, 23.888};
3354                 std::vector<uint8_t> v = {'[', '#', 'i', 5,
3355                                           'D', 0xb8, 0x1e, 0x85, 0xeb, 0x51, 0xf8, 0x3d, 0x40,
3356                                           'D', 0xe1, 0x7a, 0x14, 0xae, 0x47, 0x21, 0x3f, 0x40,
3357                                           'D', 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x50, 0x40,
3358                                           'D', 0x81, 0x95, 0x43, 0x8b, 0x6c, 0xe7, 0x00, 0x40,
3359                                           'D', 0x17, 0xd9, 0xce, 0xf7, 0x53, 0xe3, 0x37, 0x40,
3360                                          };
3361                 CHECK(json::to_bjdata(j, true) == v);
3362                 CHECK(json::from_bjdata(v) == j);
3363             }
3364 
3365             SECTION("Optimized with type & count")
3366             {
3367                 // note the floats have been replaced by doubles
3368                 json const j = {29.97, 31.13, 67.0, 2.113, 23.888};
3369                 std::vector<uint8_t> v = {'[', '$', 'D', '#', 'i', 5,
3370                                           0xb8, 0x1e, 0x85, 0xeb, 0x51, 0xf8, 0x3d, 0x40,
3371                                           0xe1, 0x7a, 0x14, 0xae, 0x47, 0x21, 0x3f, 0x40,
3372                                           0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x50, 0x40,
3373                                           0x81, 0x95, 0x43, 0x8b, 0x6c, 0xe7, 0x00, 0x40,
3374                                           0x17, 0xd9, 0xce, 0xf7, 0x53, 0xe3, 0x37, 0x40,
3375                                          };
3376                 CHECK(json::to_bjdata(j, true, true) == v);
3377                 CHECK(json::from_bjdata(v) == j);
3378             }
3379         }
3380 
3381         SECTION("Object Example")
3382         {
3383             SECTION("No Optimization")
3384             {
3385                 // note the floats have been replaced by doubles
3386                 json const j = { {"lat", 29.976}, {"long", 31.131}, {"alt", 67.0} };
3387                 std::vector<uint8_t> v = {'{',
3388                                           'i', 3, 'a', 'l', 't', 'D',      0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x50, 0x40,
3389                                           'i', 3, 'l', 'a', 't', 'D',      0x60, 0xe5, 0xd0, 0x22, 0xdb, 0xf9, 0x3d, 0x40,
3390                                           'i', 4, 'l', 'o', 'n', 'g', 'D', 0xa8, 0xc6, 0x4b, 0x37, 0x89, 0x21, 0x3f, 0x40,
3391                                           '}'
3392                                          };
3393                 CHECK(json::to_bjdata(j) == v);
3394                 CHECK(json::from_bjdata(v) == j);
3395             }
3396 
3397             SECTION("Optimized with count")
3398             {
3399                 // note the floats have been replaced by doubles
3400                 json const j = { {"lat", 29.976}, {"long", 31.131}, {"alt", 67.0} };
3401                 std::vector<uint8_t> v = {'{', '#', 'i', 3,
3402                                           'i', 3, 'a', 'l', 't', 'D',      0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x50, 0x40,
3403                                           'i', 3, 'l', 'a', 't', 'D',      0x60, 0xe5, 0xd0, 0x22, 0xdb, 0xf9, 0x3d, 0x40,
3404                                           'i', 4, 'l', 'o', 'n', 'g', 'D', 0xa8, 0xc6, 0x4b, 0x37, 0x89, 0x21, 0x3f, 0x40,
3405                                          };
3406                 CHECK(json::to_bjdata(j, true) == v);
3407                 CHECK(json::from_bjdata(v) == j);
3408             }
3409 
3410             SECTION("Optimized with type & count")
3411             {
3412                 // note the floats have been replaced by doubles
3413                 json const j = { {"lat", 29.976}, {"long", 31.131}, {"alt", 67.0} };
3414                 std::vector<uint8_t> v = {'{', '$', 'D', '#', 'i', 3,
3415                                           'i', 3, 'a', 'l', 't',      0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x50, 0x40,
3416                                           'i', 3, 'l', 'a', 't',      0x60, 0xe5, 0xd0, 0x22, 0xdb, 0xf9, 0x3d, 0x40,
3417                                           'i', 4, 'l', 'o', 'n', 'g', 0xa8, 0xc6, 0x4b, 0x37, 0x89, 0x21, 0x3f, 0x40,
3418                                          };
3419                 CHECK(json::to_bjdata(j, true, true) == v);
3420                 CHECK(json::from_bjdata(v) == j);
3421             }
3422         }
3423 
3424         SECTION("Special Cases (Null, No-Op and Boolean)")
3425         {
3426             SECTION("Array")
3427             {
3428                 json _;
3429                 std::vector<uint8_t> const v = {'[', '$', 'N', '#', 'I', 0x00, 0x02};
3430                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x4E is not a permitted optimized array type", json::parse_error&);
3431                 CHECK(json::from_bjdata(v, true, false).is_discarded());
3432             }
3433 
3434             SECTION("Object")
3435             {
3436                 json _;
3437                 std::vector<uint8_t> const v = {'{', '$', 'Z', '#', 'i', 3, 'i', 4, 'n', 'a', 'm', 'e', 'i', 8, 'p', 'a', 's', 's', 'w', 'o', 'r', 'd', 'i', 5, 'e', 'm', 'a', 'i', 'l'};
3438                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x5A is not a permitted optimized array type", json::parse_error&);
3439                 CHECK(json::from_bjdata(v, true, false).is_discarded());
3440             }
3441         }
3442     }
3443 }
3444 
3445 #if !defined(JSON_NOEXCEPTION)
3446 TEST_CASE("all BJData first bytes")
3447 {
3448     // these bytes will fail immediately with exception parse_error.112
3449     std::set<uint8_t> supported =
3450     {
3451         'T', 'F', 'Z', 'U', 'i', 'I', 'l', 'L', 'd', 'D', 'C', 'S', '[', '{', 'N', 'H', 'u', 'm', 'M', 'h'
3452     };
3453 
3454     for (auto i = 0; i < 256; ++i)
3455     {
3456         const auto byte = static_cast<uint8_t>(i);
CAPTURE(byte)3457         CAPTURE(byte)
3458 
3459         try
3460         {
3461             auto res = json::from_bjdata(std::vector<uint8_t>(1, byte));
3462         }
3463         catch (const json::parse_error& e)
3464         {
3465             // check that parse_error.112 is only thrown if the
3466             // first byte is not in the supported set
3467             INFO_WITH_TEMP(e.what());
3468             if (supported.find(byte) == supported.end())
3469             {
3470                 CHECK(e.id == 112);
3471             }
3472             else
3473             {
3474                 CHECK(e.id != 112);
3475             }
3476         }
3477     }
3478 }
3479 #endif
3480 
skip()3481 TEST_CASE("BJData roundtrips" * doctest::skip())
3482 {
3483     SECTION("input from self-generated BJData files")
3484     {
3485         for (const std::string filename :
3486                 {
3487                     TEST_DATA_DIRECTORY "/json_nlohmann_tests/all_unicode.json",
3488                     TEST_DATA_DIRECTORY "/json.org/1.json",
3489                     TEST_DATA_DIRECTORY "/json.org/2.json",
3490                     TEST_DATA_DIRECTORY "/json.org/3.json",
3491                     TEST_DATA_DIRECTORY "/json.org/4.json",
3492                     TEST_DATA_DIRECTORY "/json.org/5.json",
3493                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip01.json",
3494                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip02.json",
3495                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip03.json",
3496                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip04.json",
3497                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip05.json",
3498                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip06.json",
3499                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip07.json",
3500                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip08.json",
3501                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip09.json",
3502                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip10.json",
3503                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip11.json",
3504                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip12.json",
3505                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip13.json",
3506                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip14.json",
3507                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip15.json",
3508                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip16.json",
3509                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip17.json",
3510                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip18.json",
3511                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip19.json",
3512                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip20.json",
3513                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip21.json",
3514                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip22.json",
3515                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip23.json",
3516                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip24.json",
3517                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip25.json",
3518                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip26.json",
3519                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip27.json",
3520                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip28.json",
3521                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip29.json",
3522                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip30.json",
3523                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip31.json",
3524                     TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip32.json",
3525                     TEST_DATA_DIRECTORY "/json_testsuite/sample.json",
3526                     TEST_DATA_DIRECTORY "/json_tests/pass1.json",
3527                     TEST_DATA_DIRECTORY "/json_tests/pass2.json",
3528                     TEST_DATA_DIRECTORY "/json_tests/pass3.json"
3529                 })
3530         {
3531             CAPTURE(filename)
3532 
3533             {
3534                 INFO_WITH_TEMP(filename + ": std::vector<uint8_t>");
3535                 // parse JSON file
3536                 std::ifstream f_json(filename);
3537                 json j1 = json::parse(f_json);
3538 
3539                 // parse BJData file
3540                 auto packed = utils::read_binary_file(filename + ".bjdata");
3541                 json j2;
3542                 CHECK_NOTHROW(j2 = json::from_bjdata(packed));
3543 
3544                 // compare parsed JSON values
3545                 CHECK(j1 == j2);
3546             }
3547 
3548             {
3549                 INFO_WITH_TEMP(filename + ": std::ifstream");
3550                 // parse JSON file
3551                 std::ifstream f_json(filename);
3552                 json j1 = json::parse(f_json);
3553 
3554                 // parse BJData file
3555                 std::ifstream f_bjdata(filename + ".bjdata", std::ios::binary);
3556                 json j2;
3557                 CHECK_NOTHROW(j2 = json::from_bjdata(f_bjdata));
3558 
3559                 // compare parsed JSON values
3560                 CHECK(j1 == j2);
3561             }
3562 
3563             {
3564                 INFO_WITH_TEMP(filename + ": output to output adapters");
3565                 // parse JSON file
3566                 std::ifstream f_json(filename);
3567                 json const j1 = json::parse(f_json);
3568 
3569                 // parse BJData file
3570                 auto packed = utils::read_binary_file(filename + ".bjdata");
3571 
3572                 {
3573                     INFO_WITH_TEMP(filename + ": output adapters: std::vector<uint8_t>");
3574                     std::vector<uint8_t> vec;
3575                     json::to_bjdata(j1, vec);
3576                     CHECK(vec == packed);
3577                 }
3578             }
3579         }
3580     }
3581 }
3582