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