xref: /third_party/json/tests/src/unit-bjdata.cpp (revision c5f01b2f)
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>
13using 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
24namespace
25{
26class SaxCountdown
27{
28  public:
29    explicit SaxCountdown(const int count) : events_left(count)
30    {}
31
32    bool null()
33    {
34        return events_left-- > 0;
35    }
36
37    bool boolean(bool /*unused*/)
38    {
39        return events_left-- > 0;
40    }
41
42    bool number_integer(json::number_integer_t /*unused*/)
43    {
44        return events_left-- > 0;
45    }
46
47    bool number_unsigned(json::number_unsigned_t /*unused*/)
48    {
49        return events_left-- > 0;
50    }
51
52    bool number_float(json::number_float_t /*unused*/, const std::string& /*unused*/)
53    {
54        return events_left-- > 0;
55    }
56
57    bool string(std::string& /*unused*/)
58    {
59        return events_left-- > 0;
60    }
61
62    bool binary(std::vector<std::uint8_t>& /*unused*/)
63    {
64        return events_left-- > 0;
65    }
66
67    bool start_object(std::size_t /*unused*/)
68    {
69        return events_left-- > 0;
70    }
71
72    bool key(std::string& /*unused*/)
73    {
74        return events_left-- > 0;
75    }
76
77    bool end_object()
78    {
79        return events_left-- > 0;
80    }
81
82    bool start_array(std::size_t /*unused*/)
83    {
84        return events_left-- > 0;
85    }
86
87    bool end_array()
88    {
89        return events_left-- > 0;
90    }
91
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
103template <typename OfType, typename T, bool MinInRange, bool MaxInRange>
104struct 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
112TEST_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
176TEST_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
195TEST_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
201TEST_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
208TEST_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
3094TEST_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)
3414TEST_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);
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
3449TEST_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        {
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