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