xref: /third_party/json/tests/src/unit-cbor.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 <fstream>
15#include <sstream>
16#include <iomanip>
17#include <iostream>
18#include <set>
19#include "make_test_data_available.hpp"
20#include "test_utils.hpp"
21
22namespace
23{
24class SaxCountdown
25{
26  public:
27    explicit SaxCountdown(const int count) : events_left(count)
28    {}
29
30    bool null()
31    {
32        return events_left-- > 0;
33    }
34
35    bool boolean(bool /*unused*/)
36    {
37        return events_left-- > 0;
38    }
39
40    bool number_integer(json::number_integer_t /*unused*/)
41    {
42        return events_left-- > 0;
43    }
44
45    bool number_unsigned(json::number_unsigned_t /*unused*/)
46    {
47        return events_left-- > 0;
48    }
49
50    bool number_float(json::number_float_t /*unused*/, const std::string& /*unused*/)
51    {
52        return events_left-- > 0;
53    }
54
55    bool string(std::string& /*unused*/)
56    {
57        return events_left-- > 0;
58    }
59
60    bool binary(std::vector<std::uint8_t>& /*unused*/)
61    {
62        return events_left-- > 0;
63    }
64
65    bool start_object(std::size_t /*unused*/)
66    {
67        return events_left-- > 0;
68    }
69
70    bool key(std::string& /*unused*/)
71    {
72        return events_left-- > 0;
73    }
74
75    bool end_object()
76    {
77        return events_left-- > 0;
78    }
79
80    bool start_array(std::size_t /*unused*/)
81    {
82        return events_left-- > 0;
83    }
84
85    bool end_array()
86    {
87        return events_left-- > 0;
88    }
89
90    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const json::exception& /*unused*/) // NOLINT(readability-convert-member-functions-to-static)
91    {
92        return false;
93    }
94
95  private:
96    int events_left = 0;
97};
98} // namespace
99
100TEST_CASE("CBOR")
101{
102    SECTION("individual values")
103    {
104        SECTION("discarded")
105        {
106            // discarded values are not serialized
107            json j = json::value_t::discarded;
108            const auto result = json::to_cbor(j);
109            CHECK(result.empty());
110        }
111
112        SECTION("NaN")
113        {
114            // NaN value
115            json j = std::numeric_limits<json::number_float_t>::quiet_NaN();
116            std::vector<uint8_t> expected = {0xf9, 0x7e, 0x00};
117            const auto result = json::to_cbor(j);
118            CHECK(result == expected);
119        }
120
121        SECTION("Infinity")
122        {
123            // Infinity value
124            json j = std::numeric_limits<json::number_float_t>::infinity();
125            std::vector<uint8_t> expected = {0xf9, 0x7c, 0x00};
126            const auto result = json::to_cbor(j);
127            CHECK(result == expected);
128        }
129
130        SECTION("null")
131        {
132            json j = nullptr;
133            std::vector<uint8_t> expected = {0xf6};
134            const auto result = json::to_cbor(j);
135            CHECK(result == expected);
136
137            // roundtrip
138            CHECK(json::from_cbor(result) == j);
139            CHECK(json::from_cbor(result, true, false) == j);
140        }
141
142        SECTION("boolean")
143        {
144            SECTION("true")
145            {
146                json j = true;
147                std::vector<uint8_t> expected = {0xf5};
148                const auto result = json::to_cbor(j);
149                CHECK(result == expected);
150
151                // roundtrip
152                CHECK(json::from_cbor(result) == j);
153                CHECK(json::from_cbor(result, true, false) == j);
154            }
155
156            SECTION("false")
157            {
158                json j = false;
159                std::vector<uint8_t> expected = {0xf4};
160                const auto result = json::to_cbor(j);
161                CHECK(result == expected);
162
163                // roundtrip
164                CHECK(json::from_cbor(result) == j);
165                CHECK(json::from_cbor(result, true, false) == j);
166            }
167        }
168
169        SECTION("number")
170        {
171            SECTION("signed")
172            {
173                SECTION("-9223372036854775808..-4294967297")
174                {
175                    std::vector<int64_t> numbers;
176                    numbers.push_back(INT64_MIN);
177                    numbers.push_back(-1000000000000000000);
178                    numbers.push_back(-100000000000000000);
179                    numbers.push_back(-10000000000000000);
180                    numbers.push_back(-1000000000000000);
181                    numbers.push_back(-100000000000000);
182                    numbers.push_back(-10000000000000);
183                    numbers.push_back(-1000000000000);
184                    numbers.push_back(-100000000000);
185                    numbers.push_back(-10000000000);
186                    numbers.push_back(-4294967297);
187                    for (auto i : numbers)
188                    {
189                        CAPTURE(i)
190
191                        // create JSON value with integer number
192                        json j = i;
193
194                        // check type
195                        CHECK(j.is_number_integer());
196
197                        // create expected byte vector
198                        std::vector<uint8_t> expected;
199                        expected.push_back(static_cast<uint8_t>(0x3b));
200                        auto positive = static_cast<uint64_t>(-1 - i);
201                        expected.push_back(static_cast<uint8_t>((positive >> 56) & 0xff));
202                        expected.push_back(static_cast<uint8_t>((positive >> 48) & 0xff));
203                        expected.push_back(static_cast<uint8_t>((positive >> 40) & 0xff));
204                        expected.push_back(static_cast<uint8_t>((positive >> 32) & 0xff));
205                        expected.push_back(static_cast<uint8_t>((positive >> 24) & 0xff));
206                        expected.push_back(static_cast<uint8_t>((positive >> 16) & 0xff));
207                        expected.push_back(static_cast<uint8_t>((positive >> 8) & 0xff));
208                        expected.push_back(static_cast<uint8_t>(positive & 0xff));
209
210                        // compare result + size
211                        const auto result = json::to_cbor(j);
212                        CHECK(result == expected);
213                        CHECK(result.size() == 9);
214
215                        // check individual bytes
216                        CHECK(result[0] == 0x3b);
217                        uint64_t restored = (static_cast<uint64_t>(result[1]) << 070) +
218                                            (static_cast<uint64_t>(result[2]) << 060) +
219                                            (static_cast<uint64_t>(result[3]) << 050) +
220                                            (static_cast<uint64_t>(result[4]) << 040) +
221                                            (static_cast<uint64_t>(result[5]) << 030) +
222                                            (static_cast<uint64_t>(result[6]) << 020) +
223                                            (static_cast<uint64_t>(result[7]) << 010) +
224                                            static_cast<uint64_t>(result[8]);
225                        CHECK(restored == positive);
226                        CHECK(-1 - static_cast<int64_t>(restored) == i);
227
228                        // roundtrip
229                        CHECK(json::from_cbor(result) == j);
230                        CHECK(json::from_cbor(result, true, false) == j);
231                    }
232                }
233
234                SECTION("-4294967296..-65537")
235                {
236                    std::vector<int64_t> numbers;
237                    numbers.push_back(-65537);
238                    numbers.push_back(-100000);
239                    numbers.push_back(-1000000);
240                    numbers.push_back(-10000000);
241                    numbers.push_back(-100000000);
242                    numbers.push_back(-1000000000);
243                    numbers.push_back(-4294967296);
244                    for (auto i : numbers)
245                    {
246                        CAPTURE(i)
247
248                        // create JSON value with integer number
249                        json j = i;
250
251                        // check type
252                        CHECK(j.is_number_integer());
253
254                        // create expected byte vector
255                        std::vector<uint8_t> expected;
256                        expected.push_back(static_cast<uint8_t>(0x3a));
257                        auto positive = static_cast<uint32_t>(static_cast<uint64_t>(-1 - i) & 0x00000000ffffffff);
258                        expected.push_back(static_cast<uint8_t>((positive >> 24) & 0xff));
259                        expected.push_back(static_cast<uint8_t>((positive >> 16) & 0xff));
260                        expected.push_back(static_cast<uint8_t>((positive >> 8) & 0xff));
261                        expected.push_back(static_cast<uint8_t>(positive & 0xff));
262
263                        // compare result + size
264                        const auto result = json::to_cbor(j);
265                        CHECK(result == expected);
266                        CHECK(result.size() == 5);
267
268                        // check individual bytes
269                        CHECK(result[0] == 0x3a);
270                        uint32_t restored = (static_cast<uint32_t>(result[1]) << 030) +
271                                            (static_cast<uint32_t>(result[2]) << 020) +
272                                            (static_cast<uint32_t>(result[3]) << 010) +
273                                            static_cast<uint32_t>(result[4]);
274                        CHECK(restored == positive);
275                        CHECK(-1LL - restored == i);
276
277                        // roundtrip
278                        CHECK(json::from_cbor(result) == j);
279                        CHECK(json::from_cbor(result, true, false) == j);
280                    }
281                }
282
283                SECTION("-65536..-257")
284                {
285                    for (int32_t i = -65536; i <= -257; ++i)
286                    {
287                        CAPTURE(i)
288
289                        // create JSON value with integer number
290                        json j = i;
291
292                        // check type
293                        CHECK(j.is_number_integer());
294
295                        // create expected byte vector
296                        std::vector<uint8_t> expected;
297                        expected.push_back(static_cast<uint8_t>(0x39));
298                        auto positive = static_cast<uint16_t>(-1 - i);
299                        expected.push_back(static_cast<uint8_t>((positive >> 8) & 0xff));
300                        expected.push_back(static_cast<uint8_t>(positive & 0xff));
301
302                        // compare result + size
303                        const auto result = json::to_cbor(j);
304                        CHECK(result == expected);
305                        CHECK(result.size() == 3);
306
307                        // check individual bytes
308                        CHECK(result[0] == 0x39);
309                        auto restored = static_cast<uint16_t>(static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]));
310                        CHECK(restored == positive);
311                        CHECK(-1 - restored == i);
312
313                        // roundtrip
314                        CHECK(json::from_cbor(result) == j);
315                        CHECK(json::from_cbor(result, true, false) == j);
316                    }
317                }
318
319                SECTION("-9263 (int 16)")
320                {
321                    json j = -9263;
322                    std::vector<uint8_t> expected = {0x39, 0x24, 0x2e};
323
324                    const auto result = json::to_cbor(j);
325                    CHECK(result == expected);
326
327                    auto restored = static_cast<int16_t>(-1 - ((result[1] << 8) + result[2]));
328                    CHECK(restored == -9263);
329
330                    // roundtrip
331                    CHECK(json::from_cbor(result) == j);
332                    CHECK(json::from_cbor(result, true, false) == j);
333                }
334
335                SECTION("-256..-24")
336                {
337                    for (auto i = -256; i < -24; ++i)
338                    {
339                        CAPTURE(i)
340
341                        // create JSON value with integer number
342                        json j = i;
343
344                        // check type
345                        CHECK(j.is_number_integer());
346
347                        // create expected byte vector
348                        std::vector<uint8_t> expected;
349                        expected.push_back(0x38);
350                        expected.push_back(static_cast<uint8_t>(-1 - i));
351
352                        // compare result + size
353                        const auto result = json::to_cbor(j);
354                        CHECK(result == expected);
355                        CHECK(result.size() == 2);
356
357                        // check individual bytes
358                        CHECK(result[0] == 0x38);
359                        CHECK(static_cast<int16_t>(-1 - result[1]) == i);
360
361                        // roundtrip
362                        CHECK(json::from_cbor(result) == j);
363                        CHECK(json::from_cbor(result, true, false) == j);
364                    }
365                }
366
367                SECTION("-24..-1")
368                {
369                    for (auto i = -24; i <= -1; ++i)
370                    {
371                        CAPTURE(i)
372
373                        // create JSON value with integer number
374                        json j = i;
375
376                        // check type
377                        CHECK(j.is_number_integer());
378
379                        // create expected byte vector
380                        std::vector<uint8_t> expected;
381                        expected.push_back(static_cast<uint8_t>(0x20 - 1 - static_cast<uint8_t>(i)));
382
383                        // compare result + size
384                        const auto result = json::to_cbor(j);
385                        CHECK(result == expected);
386                        CHECK(result.size() == 1);
387
388                        // check individual bytes
389                        CHECK(static_cast<int8_t>(0x20 - 1 - result[0]) == i);
390
391                        // roundtrip
392                        CHECK(json::from_cbor(result) == j);
393                        CHECK(json::from_cbor(result, true, false) == j);
394                    }
395                }
396
397                SECTION("0..23")
398                {
399                    for (size_t i = 0; i <= 23; ++i)
400                    {
401                        CAPTURE(i)
402
403                        // create JSON value with integer number
404                        json j = -1;
405                        j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
406
407                        // check type
408                        CHECK(j.is_number_integer());
409
410                        // create expected byte vector
411                        std::vector<uint8_t> expected;
412                        expected.push_back(static_cast<uint8_t>(i));
413
414                        // compare result + size
415                        const auto result = json::to_cbor(j);
416                        CHECK(result == expected);
417                        CHECK(result.size() == 1);
418
419                        // check individual bytes
420                        CHECK(result[0] == i);
421
422                        // roundtrip
423                        CHECK(json::from_cbor(result) == j);
424                        CHECK(json::from_cbor(result, true, false) == j);
425                    }
426                }
427
428                SECTION("24..255")
429                {
430                    for (size_t i = 24; i <= 255; ++i)
431                    {
432                        CAPTURE(i)
433
434                        // create JSON value with integer number
435                        json j = -1;
436                        j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
437
438                        // check type
439                        CHECK(j.is_number_integer());
440
441                        // create expected byte vector
442                        std::vector<uint8_t> expected;
443                        expected.push_back(static_cast<uint8_t>(0x18));
444                        expected.push_back(static_cast<uint8_t>(i));
445
446                        // compare result + size
447                        const auto result = json::to_cbor(j);
448                        CHECK(result == expected);
449                        CHECK(result.size() == 2);
450
451                        // check individual bytes
452                        CHECK(result[0] == 0x18);
453                        CHECK(result[1] == i);
454
455                        // roundtrip
456                        CHECK(json::from_cbor(result) == j);
457                        CHECK(json::from_cbor(result, true, false) == j);
458                    }
459                }
460
461                SECTION("256..65535")
462                {
463                    for (size_t i = 256; i <= 65535; ++i)
464                    {
465                        CAPTURE(i)
466
467                        // create JSON value with integer number
468                        json j = -1;
469                        j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
470
471                        // check type
472                        CHECK(j.is_number_integer());
473
474                        // create expected byte vector
475                        std::vector<uint8_t> expected;
476                        expected.push_back(static_cast<uint8_t>(0x19));
477                        expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
478                        expected.push_back(static_cast<uint8_t>(i & 0xff));
479
480                        // compare result + size
481                        const auto result = json::to_cbor(j);
482                        CHECK(result == expected);
483                        CHECK(result.size() == 3);
484
485                        // check individual bytes
486                        CHECK(result[0] == 0x19);
487                        auto restored = static_cast<uint16_t>(static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]));
488                        CHECK(restored == i);
489
490                        // roundtrip
491                        CHECK(json::from_cbor(result) == j);
492                        CHECK(json::from_cbor(result, true, false) == j);
493                    }
494                }
495
496                SECTION("65536..4294967295")
497                {
498                    for (uint32_t i :
499                            {
500                                65536u, 77777u, 1048576u
501                            })
502                    {
503                        CAPTURE(i)
504
505                        // create JSON value with integer number
506                        json j = -1;
507                        j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
508
509                        // check type
510                        CHECK(j.is_number_integer());
511
512                        // create expected byte vector
513                        std::vector<uint8_t> expected;
514                        expected.push_back(0x1a);
515                        expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
516                        expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
517                        expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
518                        expected.push_back(static_cast<uint8_t>(i & 0xff));
519
520                        // compare result + size
521                        const auto result = json::to_cbor(j);
522                        CHECK(result == expected);
523                        CHECK(result.size() == 5);
524
525                        // check individual bytes
526                        CHECK(result[0] == 0x1a);
527                        uint32_t restored = (static_cast<uint32_t>(result[1]) << 030) +
528                                            (static_cast<uint32_t>(result[2]) << 020) +
529                                            (static_cast<uint32_t>(result[3]) << 010) +
530                                            static_cast<uint32_t>(result[4]);
531                        CHECK(restored == i);
532
533                        // roundtrip
534                        CHECK(json::from_cbor(result) == j);
535                        CHECK(json::from_cbor(result, true, false) == j);
536                    }
537                }
538
539                SECTION("4294967296..4611686018427387903")
540                {
541                    for (uint64_t i :
542                            {
543                                4294967296ul, 4611686018427387903ul
544                            })
545                    {
546                        CAPTURE(i)
547
548                        // create JSON value with integer number
549                        json j = -1;
550                        j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
551
552                        // check type
553                        CHECK(j.is_number_integer());
554
555                        // create expected byte vector
556                        std::vector<uint8_t> expected;
557                        expected.push_back(0x1b);
558                        expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff));
559                        expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff));
560                        expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff));
561                        expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff));
562                        expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff));
563                        expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff));
564                        expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff));
565                        expected.push_back(static_cast<uint8_t>(i & 0xff));
566
567                        // compare result + size
568                        const auto result = json::to_cbor(j);
569                        CHECK(result == expected);
570                        CHECK(result.size() == 9);
571
572                        // check individual bytes
573                        CHECK(result[0] == 0x1b);
574                        uint64_t restored = (static_cast<uint64_t>(result[1]) << 070) +
575                                            (static_cast<uint64_t>(result[2]) << 060) +
576                                            (static_cast<uint64_t>(result[3]) << 050) +
577                                            (static_cast<uint64_t>(result[4]) << 040) +
578                                            (static_cast<uint64_t>(result[5]) << 030) +
579                                            (static_cast<uint64_t>(result[6]) << 020) +
580                                            (static_cast<uint64_t>(result[7]) << 010) +
581                                            static_cast<uint64_t>(result[8]);
582                        CHECK(restored == i);
583
584                        // roundtrip
585                        CHECK(json::from_cbor(result) == j);
586                        CHECK(json::from_cbor(result, true, false) == j);
587                    }
588                }
589
590                SECTION("-32768..-129 (int 16)")
591                {
592                    for (int16_t i = -32768; i <= static_cast<std::int16_t>(-129); ++i)
593                    {
594                        CAPTURE(i)
595
596                        // create JSON value with integer number
597                        json j = i;
598
599                        // check type
600                        CHECK(j.is_number_integer());
601
602                        // create expected byte vector
603                        std::vector<uint8_t> expected;
604                        expected.push_back(0xd1);
605                        expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
606                        expected.push_back(static_cast<uint8_t>(i & 0xff));
607
608                        // compare result + size
609                        const auto result = json::to_msgpack(j);
610                        CHECK(result == expected);
611                        CHECK(result.size() == 3);
612
613                        // check individual bytes
614                        CHECK(result[0] == 0xd1);
615                        auto restored = static_cast<int16_t>((result[1] << 8) + result[2]);
616                        CHECK(restored == i);
617
618                        // roundtrip
619                        CHECK(json::from_msgpack(result) == j);
620                    }
621                }
622            }
623
624            SECTION("unsigned")
625            {
626                SECTION("0..23 (Integer)")
627                {
628                    for (size_t i = 0; i <= 23; ++i)
629                    {
630                        CAPTURE(i)
631
632                        // create JSON value with unsigned integer number
633                        json j = i;
634
635                        // check type
636                        CHECK(j.is_number_unsigned());
637
638                        // create expected byte vector
639                        std::vector<uint8_t> expected;
640                        expected.push_back(static_cast<uint8_t>(i));
641
642                        // compare result + size
643                        const auto result = json::to_cbor(j);
644                        CHECK(result == expected);
645                        CHECK(result.size() == 1);
646
647                        // check individual bytes
648                        CHECK(result[0] == i);
649
650                        // roundtrip
651                        CHECK(json::from_cbor(result) == j);
652                        CHECK(json::from_cbor(result, true, false) == j);
653                    }
654                }
655
656                SECTION("24..255 (one-byte uint8_t)")
657                {
658                    for (size_t i = 24; i <= 255; ++i)
659                    {
660                        CAPTURE(i)
661
662                        // create JSON value with unsigned integer number
663                        json j = i;
664
665                        // check type
666                        CHECK(j.is_number_unsigned());
667
668                        // create expected byte vector
669                        std::vector<uint8_t> expected;
670                        expected.push_back(0x18);
671                        expected.push_back(static_cast<uint8_t>(i));
672
673                        // compare result + size
674                        const auto result = json::to_cbor(j);
675                        CHECK(result == expected);
676                        CHECK(result.size() == 2);
677
678                        // check individual bytes
679                        CHECK(result[0] == 0x18);
680                        auto restored = static_cast<uint8_t>(result[1]);
681                        CHECK(restored == i);
682
683                        // roundtrip
684                        CHECK(json::from_cbor(result) == j);
685                        CHECK(json::from_cbor(result, true, false) == j);
686                    }
687                }
688
689                SECTION("256..65535 (two-byte uint16_t)")
690                {
691                    for (size_t i = 256; i <= 65535; ++i)
692                    {
693                        CAPTURE(i)
694
695                        // create JSON value with unsigned integer number
696                        json j = i;
697
698                        // check type
699                        CHECK(j.is_number_unsigned());
700
701                        // create expected byte vector
702                        std::vector<uint8_t> expected;
703                        expected.push_back(0x19);
704                        expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
705                        expected.push_back(static_cast<uint8_t>(i & 0xff));
706
707                        // compare result + size
708                        const auto result = json::to_cbor(j);
709                        CHECK(result == expected);
710                        CHECK(result.size() == 3);
711
712                        // check individual bytes
713                        CHECK(result[0] == 0x19);
714                        auto restored = static_cast<uint16_t>(static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]));
715                        CHECK(restored == i);
716
717                        // roundtrip
718                        CHECK(json::from_cbor(result) == j);
719                        CHECK(json::from_cbor(result, true, false) == j);
720                    }
721                }
722
723                SECTION("65536..4294967295 (four-byte uint32_t)")
724                {
725                    for (uint32_t i :
726                            {
727                                65536u, 77777u, 1048576u
728                            })
729                    {
730                        CAPTURE(i)
731
732                        // create JSON value with unsigned integer number
733                        json j = i;
734
735                        // check type
736                        CHECK(j.is_number_unsigned());
737
738                        // create expected byte vector
739                        std::vector<uint8_t> expected;
740                        expected.push_back(0x1a);
741                        expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
742                        expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
743                        expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
744                        expected.push_back(static_cast<uint8_t>(i & 0xff));
745
746                        // compare result + size
747                        const auto result = json::to_cbor(j);
748                        CHECK(result == expected);
749                        CHECK(result.size() == 5);
750
751                        // check individual bytes
752                        CHECK(result[0] == 0x1a);
753                        uint32_t restored = (static_cast<uint32_t>(result[1]) << 030) +
754                                            (static_cast<uint32_t>(result[2]) << 020) +
755                                            (static_cast<uint32_t>(result[3]) << 010) +
756                                            static_cast<uint32_t>(result[4]);
757                        CHECK(restored == i);
758
759                        // roundtrip
760                        CHECK(json::from_cbor(result) == j);
761                        CHECK(json::from_cbor(result, true, false) == j);
762                    }
763                }
764
765                SECTION("4294967296..4611686018427387903 (eight-byte uint64_t)")
766                {
767                    for (uint64_t i :
768                            {
769                                4294967296ul, 4611686018427387903ul
770                            })
771                    {
772                        CAPTURE(i)
773
774                        // create JSON value with integer number
775                        json j = i;
776
777                        // check type
778                        CHECK(j.is_number_unsigned());
779
780                        // create expected byte vector
781                        std::vector<uint8_t> expected;
782                        expected.push_back(0x1b);
783                        expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff));
784                        expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff));
785                        expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff));
786                        expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff));
787                        expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff));
788                        expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff));
789                        expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff));
790                        expected.push_back(static_cast<uint8_t>(i & 0xff));
791
792                        // compare result + size
793                        const auto result = json::to_cbor(j);
794                        CHECK(result == expected);
795                        CHECK(result.size() == 9);
796
797                        // check individual bytes
798                        CHECK(result[0] == 0x1b);
799                        uint64_t restored = (static_cast<uint64_t>(result[1]) << 070) +
800                                            (static_cast<uint64_t>(result[2]) << 060) +
801                                            (static_cast<uint64_t>(result[3]) << 050) +
802                                            (static_cast<uint64_t>(result[4]) << 040) +
803                                            (static_cast<uint64_t>(result[5]) << 030) +
804                                            (static_cast<uint64_t>(result[6]) << 020) +
805                                            (static_cast<uint64_t>(result[7]) << 010) +
806                                            static_cast<uint64_t>(result[8]);
807                        CHECK(restored == i);
808
809                        // roundtrip
810                        CHECK(json::from_cbor(result) == j);
811                        CHECK(json::from_cbor(result, true, false) == j);
812                    }
813                }
814            }
815
816            SECTION("double-precision float")
817            {
818                SECTION("3.1415925")
819                {
820                    double v = 3.1415925;
821                    json j = v;
822                    std::vector<uint8_t> expected =
823                    {
824                        0xfb, 0x40, 0x09, 0x21, 0xfb, 0x3f, 0xa6, 0xde, 0xfc
825                    };
826                    const auto result = json::to_cbor(j);
827                    CHECK(result == expected);
828
829                    // roundtrip
830                    CHECK(json::from_cbor(result) == j);
831                    CHECK(json::from_cbor(result) == v);
832
833                    CHECK(json::from_cbor(result, true, false) == j);
834                }
835            }
836
837            SECTION("single-precision float")
838            {
839                SECTION("0.5")
840                {
841                    double v = 0.5;
842                    json j = v;
843                    // its double-precision float binary value is
844                    // {0xfb, 0x3f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
845                    // but to save memory, we can store it as single-precision float.
846                    std::vector<uint8_t> expected = {0xfa, 0x3f, 0x00, 0x00, 0x00};
847                    const auto result = json::to_cbor(j);
848                    CHECK(result == expected);
849                    // roundtrip
850                    CHECK(json::from_cbor(result) == j);
851                    CHECK(json::from_cbor(result) == v);
852                }
853                SECTION("0.0")
854                {
855                    double v = 0.0;
856                    json j = v;
857                    // its double-precision binary value is:
858                    // {0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
859                    std::vector<uint8_t> expected = {0xfa, 0x00, 0x00, 0x00, 0x00};
860                    const auto result = json::to_cbor(j);
861                    CHECK(result == expected);
862                    // roundtrip
863                    CHECK(json::from_cbor(result) == j);
864                    CHECK(json::from_cbor(result) == v);
865                }
866                SECTION("-0.0")
867                {
868                    double v = -0.0;
869                    json j = v;
870                    // its double-precision binary value is:
871                    // {0xfb, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
872                    std::vector<uint8_t> expected = {0xfa, 0x80, 0x00, 0x00, 0x00};
873                    const auto result = json::to_cbor(j);
874                    CHECK(result == expected);
875                    // roundtrip
876                    CHECK(json::from_cbor(result) == j);
877                    CHECK(json::from_cbor(result) == v);
878                }
879                SECTION("100.0")
880                {
881                    double v = 100.0;
882                    json j = v;
883                    // its double-precision binary value is:
884                    // {0xfb, 0x40, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
885                    std::vector<uint8_t> expected = {0xfa, 0x42, 0xc8, 0x00, 0x00};
886                    const auto result = json::to_cbor(j);
887                    CHECK(result == expected);
888                    // roundtrip
889                    CHECK(json::from_cbor(result) == j);
890                    CHECK(json::from_cbor(result) == v);
891                }
892                SECTION("200.0")
893                {
894                    double v = 200.0;
895                    json j = v;
896                    // its double-precision binary value is:
897                    // {0xfb, 0x40, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
898                    std::vector<uint8_t> expected = {0xfa, 0x43, 0x48, 0x00, 0x00};
899                    const auto result = json::to_cbor(j);
900                    CHECK(result == expected);
901                    // roundtrip
902                    CHECK(json::from_cbor(result) == j);
903                    CHECK(json::from_cbor(result) == v);
904                }
905                SECTION("3.40282e+38(max float)")
906                {
907                    float v = (std::numeric_limits<float>::max)();
908                    json j = v;
909                    std::vector<uint8_t> expected =
910                    {
911                        0xfa, 0x7f, 0x7f, 0xff, 0xff
912                    };
913                    const auto result = json::to_cbor(j);
914                    CHECK(result == expected);
915                    // roundtrip
916                    CHECK(json::from_cbor(result) == j);
917                    CHECK(json::from_cbor(result) == v);
918                }
919                SECTION("-3.40282e+38(lowest float)")
920                {
921                    auto v = static_cast<double>(std::numeric_limits<float>::lowest());
922                    json j = v;
923                    std::vector<uint8_t> expected =
924                    {
925                        0xfa, 0xff, 0x7f, 0xff, 0xff
926                    };
927                    const auto result = json::to_cbor(j);
928                    CHECK(result == expected);
929                    // roundtrip
930                    CHECK(json::from_cbor(result) == j);
931                    CHECK(json::from_cbor(result) == v);
932                }
933                SECTION("1 + 3.40282e+38(more than max float)")
934                {
935                    double v = static_cast<double>((std::numeric_limits<float>::max)()) + 0.1e+34;
936                    json j = v;
937                    std::vector<uint8_t> expected =
938                    {
939                        0xfb, 0x47, 0xf0, 0x00, 0x03, 0x04, 0xdc, 0x64, 0x49
940                    };
941                    // double
942                    const auto result = json::to_cbor(j);
943                    CHECK(result == expected);
944                    // roundtrip
945                    CHECK(json::from_cbor(result) == j);
946                    CHECK(json::from_cbor(result) == v);
947                }
948                SECTION("-1 - 3.40282e+38(less than lowest float)")
949                {
950                    double v = static_cast<double>(std::numeric_limits<float>::lowest()) - 1.0;
951                    json j = v;
952                    std::vector<uint8_t> expected =
953                    {
954                        0xfa, 0xff, 0x7f, 0xff, 0xff
955                    };
956                    // the same with lowest float
957                    const auto result = json::to_cbor(j);
958                    CHECK(result == expected);
959                    // roundtrip
960                    CHECK(json::from_cbor(result) == j);
961                    CHECK(json::from_cbor(result) == v);
962                }
963
964            }
965
966            SECTION("half-precision float (edge cases)")
967            {
968                SECTION("errors")
969                {
970                    SECTION("no byte follows")
971                    {
972                        json _;
973                        CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xf9})), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR number: unexpected end of input", json::parse_error&);
974                        CHECK(json::from_cbor(std::vector<uint8_t>({0xf9}), true, false).is_discarded());
975                    }
976                    SECTION("only one byte follows")
977                    {
978                        json _;
979                        CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c})), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR number: unexpected end of input", json::parse_error&);
980                        CHECK(json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c}), true, false).is_discarded());
981                    }
982                }
983
984                SECTION("exp = 0b00000")
985                {
986                    SECTION("0 (0 00000 0000000000)")
987                    {
988                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x00, 0x00}));
989                        json::number_float_t d{j};
990                        CHECK(d == 0.0);
991                    }
992
993                    SECTION("-0 (1 00000 0000000000)")
994                    {
995                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x80, 0x00}));
996                        json::number_float_t d{j};
997                        CHECK(d == -0.0);
998                    }
999
1000                    SECTION("2**-24 (0 00000 0000000001)")
1001                    {
1002                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x00, 0x01}));
1003                        json::number_float_t d{j};
1004                        CHECK(d == std::pow(2.0, -24.0));
1005                    }
1006                }
1007
1008                SECTION("exp = 0b11111")
1009                {
1010                    SECTION("infinity (0 11111 0000000000)")
1011                    {
1012                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c, 0x00}));
1013                        json::number_float_t d{j};
1014                        CHECK(d == std::numeric_limits<json::number_float_t>::infinity());
1015                        CHECK(j.dump() == "null");
1016                    }
1017
1018                    SECTION("-infinity (1 11111 0000000000)")
1019                    {
1020                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0xfc, 0x00}));
1021                        json::number_float_t d{j};
1022                        CHECK(d == -std::numeric_limits<json::number_float_t>::infinity());
1023                        CHECK(j.dump() == "null");
1024                    }
1025                }
1026
1027                SECTION("other values from https://en.wikipedia.org/wiki/Half-precision_floating-point_format")
1028                {
1029                    SECTION("1 (0 01111 0000000000)")
1030                    {
1031                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x3c, 0x00}));
1032                        json::number_float_t d{j};
1033                        CHECK(d == 1);
1034                    }
1035
1036                    SECTION("-2 (1 10000 0000000000)")
1037                    {
1038                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0xc0, 0x00}));
1039                        json::number_float_t d{j};
1040                        CHECK(d == -2);
1041                    }
1042
1043                    SECTION("65504 (0 11110 1111111111)")
1044                    {
1045                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7b, 0xff}));
1046                        json::number_float_t d{j};
1047                        CHECK(d == 65504);
1048                    }
1049                }
1050
1051                SECTION("infinity")
1052                {
1053                    json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c, 0x00}));
1054                    json::number_float_t d{j};
1055                    CHECK(!std::isfinite(d));
1056                    CHECK(j.dump() == "null");
1057                }
1058
1059                SECTION("NaN")
1060                {
1061                    json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7e, 0x00}));
1062                    json::number_float_t d{j};
1063                    CHECK(std::isnan(d));
1064                    CHECK(j.dump() == "null");
1065                }
1066            }
1067        }
1068
1069        SECTION("string")
1070        {
1071            SECTION("N = 0..23")
1072            {
1073                for (size_t N = 0; N <= 0x17; ++N)
1074                {
1075                    CAPTURE(N)
1076
1077                    // create JSON value with string containing of N * 'x'
1078                    const auto s = std::string(N, 'x');
1079                    json j = s;
1080
1081                    // create expected byte vector
1082                    std::vector<uint8_t> expected;
1083                    expected.push_back(static_cast<uint8_t>(0x60 + N));
1084                    for (size_t i = 0; i < N; ++i)
1085                    {
1086                        expected.push_back('x');
1087                    }
1088
1089                    // compare result + size
1090                    const auto result = json::to_cbor(j);
1091                    CHECK(result == expected);
1092                    CHECK(result.size() == N + 1);
1093                    // check that no null byte is appended
1094                    if (N > 0)
1095                    {
1096                        CHECK(result.back() != '\x00');
1097                    }
1098
1099                    // roundtrip
1100                    CHECK(json::from_cbor(result) == j);
1101                    CHECK(json::from_cbor(result, true, false) == j);
1102                }
1103            }
1104
1105            SECTION("N = 24..255")
1106            {
1107                for (size_t N = 24; N <= 255; ++N)
1108                {
1109                    CAPTURE(N)
1110
1111                    // create JSON value with string containing of N * 'x'
1112                    const auto s = std::string(N, 'x');
1113                    json j = s;
1114
1115                    // create expected byte vector
1116                    std::vector<uint8_t> expected;
1117                    expected.push_back(0x78);
1118                    expected.push_back(static_cast<uint8_t>(N));
1119                    for (size_t i = 0; i < N; ++i)
1120                    {
1121                        expected.push_back('x');
1122                    }
1123
1124                    // compare result + size
1125                    const auto result = json::to_cbor(j);
1126                    CHECK(result == expected);
1127                    CHECK(result.size() == N + 2);
1128                    // check that no null byte is appended
1129                    CHECK(result.back() != '\x00');
1130
1131                    // roundtrip
1132                    CHECK(json::from_cbor(result) == j);
1133                    CHECK(json::from_cbor(result, true, false) == j);
1134                }
1135            }
1136
1137            SECTION("N = 256..65535")
1138            {
1139                for (size_t N :
1140                        {
1141                            256u, 999u, 1025u, 3333u, 2048u, 65535u
1142                        })
1143                {
1144                    CAPTURE(N)
1145
1146                    // create JSON value with string containing of N * 'x'
1147                    const auto s = std::string(N, 'x');
1148                    json j = s;
1149
1150                    // create expected byte vector (hack: create string first)
1151                    std::vector<uint8_t> expected(N, 'x');
1152                    // reverse order of commands, because we insert at begin()
1153                    expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
1154                    expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
1155                    expected.insert(expected.begin(), 0x79);
1156
1157                    // compare result + size
1158                    const auto result = json::to_cbor(j);
1159                    CHECK(result == expected);
1160                    CHECK(result.size() == N + 3);
1161                    // check that no null byte is appended
1162                    CHECK(result.back() != '\x00');
1163
1164                    // roundtrip
1165                    CHECK(json::from_cbor(result) == j);
1166                    CHECK(json::from_cbor(result, true, false) == j);
1167                }
1168            }
1169
1170            SECTION("N = 65536..4294967295")
1171            {
1172                for (size_t N :
1173                        {
1174                            65536u, 77777u, 1048576u
1175                        })
1176                {
1177                    CAPTURE(N)
1178
1179                    // create JSON value with string containing of N * 'x'
1180                    const auto s = std::string(N, 'x');
1181                    json j = s;
1182
1183                    // create expected byte vector (hack: create string first)
1184                    std::vector<uint8_t> expected(N, 'x');
1185                    // reverse order of commands, because we insert at begin()
1186                    expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
1187                    expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
1188                    expected.insert(expected.begin(), static_cast<uint8_t>((N >> 16) & 0xff));
1189                    expected.insert(expected.begin(), static_cast<uint8_t>((N >> 24) & 0xff));
1190                    expected.insert(expected.begin(), 0x7a);
1191
1192                    // compare result + size
1193                    const auto result = json::to_cbor(j);
1194                    CHECK(result == expected);
1195                    CHECK(result.size() == N + 5);
1196                    // check that no null byte is appended
1197                    CHECK(result.back() != '\x00');
1198
1199                    // roundtrip
1200                    CHECK(json::from_cbor(result) == j);
1201                    CHECK(json::from_cbor(result, true, false) == j);
1202                }
1203            }
1204        }
1205
1206        SECTION("array")
1207        {
1208            SECTION("empty")
1209            {
1210                json j = json::array();
1211                std::vector<uint8_t> expected = {0x80};
1212                const auto result = json::to_cbor(j);
1213                CHECK(result == expected);
1214
1215                // roundtrip
1216                CHECK(json::from_cbor(result) == j);
1217                CHECK(json::from_cbor(result, true, false) == j);
1218            }
1219
1220            SECTION("[null]")
1221            {
1222                json j = {nullptr};
1223                std::vector<uint8_t> expected = {0x81, 0xf6};
1224                const auto result = json::to_cbor(j);
1225                CHECK(result == expected);
1226
1227                // roundtrip
1228                CHECK(json::from_cbor(result) == j);
1229                CHECK(json::from_cbor(result, true, false) == j);
1230            }
1231
1232            SECTION("[1,2,3,4,5]")
1233            {
1234                json j = json::parse("[1,2,3,4,5]");
1235                std::vector<uint8_t> expected = {0x85, 0x01, 0x02, 0x03, 0x04, 0x05};
1236                const auto result = json::to_cbor(j);
1237                CHECK(result == expected);
1238
1239                // roundtrip
1240                CHECK(json::from_cbor(result) == j);
1241                CHECK(json::from_cbor(result, true, false) == j);
1242            }
1243
1244            SECTION("[[[[]]]]")
1245            {
1246                json j = json::parse("[[[[]]]]");
1247                std::vector<uint8_t> expected = {0x81, 0x81, 0x81, 0x80};
1248                const auto result = json::to_cbor(j);
1249                CHECK(result == expected);
1250
1251                // roundtrip
1252                CHECK(json::from_cbor(result) == j);
1253                CHECK(json::from_cbor(result, true, false) == j);
1254            }
1255
1256            SECTION("array with uint16_t elements")
1257            {
1258                json j(257, nullptr);
1259                std::vector<uint8_t> expected(j.size() + 3, 0xf6); // all null
1260                expected[0] = 0x99; // array 16 bit
1261                expected[1] = 0x01; // size (0x0101), byte 0
1262                expected[2] = 0x01; // size (0x0101), byte 1
1263                const auto result = json::to_cbor(j);
1264                CHECK(result == expected);
1265
1266                // roundtrip
1267                CHECK(json::from_cbor(result) == j);
1268                CHECK(json::from_cbor(result, true, false) == j);
1269            }
1270
1271            SECTION("array with uint32_t elements")
1272            {
1273                json j(65793, nullptr);
1274                std::vector<uint8_t> expected(j.size() + 5, 0xf6); // all null
1275                expected[0] = 0x9a; // array 32 bit
1276                expected[1] = 0x00; // size (0x00010101), byte 0
1277                expected[2] = 0x01; // size (0x00010101), byte 1
1278                expected[3] = 0x01; // size (0x00010101), byte 2
1279                expected[4] = 0x01; // size (0x00010101), byte 3
1280                const auto result = json::to_cbor(j);
1281                CHECK(result == expected);
1282
1283                // roundtrip
1284                CHECK(json::from_cbor(result) == j);
1285                CHECK(json::from_cbor(result, true, false) == j);
1286            }
1287        }
1288
1289        SECTION("object")
1290        {
1291            SECTION("empty")
1292            {
1293                json j = json::object();
1294                std::vector<uint8_t> expected = {0xa0};
1295                const auto result = json::to_cbor(j);
1296                CHECK(result == expected);
1297
1298                // roundtrip
1299                CHECK(json::from_cbor(result) == j);
1300                CHECK(json::from_cbor(result, true, false) == j);
1301            }
1302
1303            SECTION("{\"\":null}")
1304            {
1305                json j = {{"", nullptr}};
1306                std::vector<uint8_t> expected = {0xa1, 0x60, 0xf6};
1307                const auto result = json::to_cbor(j);
1308                CHECK(result == expected);
1309
1310                // roundtrip
1311                CHECK(json::from_cbor(result) == j);
1312                CHECK(json::from_cbor(result, true, false) == j);
1313            }
1314
1315            SECTION("{\"a\": {\"b\": {\"c\": {}}}}")
1316            {
1317                json j = json::parse(R"({"a": {"b": {"c": {}}}})");
1318                std::vector<uint8_t> expected =
1319                {
1320                    0xa1, 0x61, 0x61, 0xa1, 0x61, 0x62, 0xa1, 0x61, 0x63, 0xa0
1321                };
1322                const auto result = json::to_cbor(j);
1323                CHECK(result == expected);
1324
1325                // roundtrip
1326                CHECK(json::from_cbor(result) == j);
1327                CHECK(json::from_cbor(result, true, false) == j);
1328            }
1329
1330            SECTION("object with uint8_t elements")
1331            {
1332                json j;
1333                for (auto i = 0; i < 255; ++i)
1334                {
1335                    // format i to a fixed width of 5
1336                    // each entry will need 7 bytes: 6 for string, 1 for null
1337                    std::stringstream ss;
1338                    ss << std::setw(5) << std::setfill('0') << i;
1339                    j.emplace(ss.str(), nullptr);
1340                }
1341
1342                const auto result = json::to_cbor(j);
1343
1344                // Checking against an expected vector byte by byte is
1345                // difficult, because no assumption on the order of key/value
1346                // pairs are made. We therefore only check the prefix (type and
1347                // size and the overall size. The rest is then handled in the
1348                // roundtrip check.
1349                CHECK(result.size() == 1787); // 1 type, 1 size, 255*7 content
1350                CHECK(result[0] == 0xb8); // map 8 bit
1351                CHECK(result[1] == 0xff); // size byte (0xff)
1352                // roundtrip
1353                CHECK(json::from_cbor(result) == j);
1354                CHECK(json::from_cbor(result, true, false) == j);
1355            }
1356
1357            SECTION("object with uint16_t elements")
1358            {
1359                json j;
1360                for (auto i = 0; i < 256; ++i)
1361                {
1362                    // format i to a fixed width of 5
1363                    // each entry will need 7 bytes: 6 for string, 1 for null
1364                    std::stringstream ss;
1365                    ss << std::setw(5) << std::setfill('0') << i;
1366                    j.emplace(ss.str(), nullptr);
1367                }
1368
1369                const auto result = json::to_cbor(j);
1370
1371                // Checking against an expected vector byte by byte is
1372                // difficult, because no assumption on the order of key/value
1373                // pairs are made. We therefore only check the prefix (type and
1374                // size and the overall size. The rest is then handled in the
1375                // roundtrip check.
1376                CHECK(result.size() == 1795); // 1 type, 2 size, 256*7 content
1377                CHECK(result[0] == 0xb9); // map 16 bit
1378                CHECK(result[1] == 0x01); // byte 0 of size (0x0100)
1379                CHECK(result[2] == 0x00); // byte 1 of size (0x0100)
1380
1381                // roundtrip
1382                CHECK(json::from_cbor(result) == j);
1383                CHECK(json::from_cbor(result, true, false) == j);
1384            }
1385
1386            SECTION("object with uint32_t elements")
1387            {
1388                json j;
1389                for (auto i = 0; i < 65536; ++i)
1390                {
1391                    // format i to a fixed width of 5
1392                    // each entry will need 7 bytes: 6 for string, 1 for null
1393                    std::stringstream ss;
1394                    ss << std::setw(5) << std::setfill('0') << i;
1395                    j.emplace(ss.str(), nullptr);
1396                }
1397
1398                const auto result = json::to_cbor(j);
1399
1400                // Checking against an expected vector byte by byte is
1401                // difficult, because no assumption on the order of key/value
1402                // pairs are made. We therefore only check the prefix (type and
1403                // size and the overall size. The rest is then handled in the
1404                // roundtrip check.
1405                CHECK(result.size() == 458757); // 1 type, 4 size, 65536*7 content
1406                CHECK(result[0] == 0xba); // map 32 bit
1407                CHECK(result[1] == 0x00); // byte 0 of size (0x00010000)
1408                CHECK(result[2] == 0x01); // byte 1 of size (0x00010000)
1409                CHECK(result[3] == 0x00); // byte 2 of size (0x00010000)
1410                CHECK(result[4] == 0x00); // byte 3 of size (0x00010000)
1411
1412                // roundtrip
1413                CHECK(json::from_cbor(result) == j);
1414                CHECK(json::from_cbor(result, true, false) == j);
1415            }
1416        }
1417
1418        SECTION("binary")
1419        {
1420            SECTION("N = 0..23")
1421            {
1422                for (size_t N = 0; N <= 0x17; ++N)
1423                {
1424                    CAPTURE(N)
1425
1426                    // create JSON value with byte array containing of N * 'x'
1427                    const auto s = std::vector<uint8_t>(N, 'x');
1428                    json j = json::binary(s);
1429
1430                    // create expected byte vector
1431                    std::vector<uint8_t> expected;
1432                    expected.push_back(static_cast<uint8_t>(0x40 + N));
1433                    for (size_t i = 0; i < N; ++i)
1434                    {
1435                        expected.push_back(0x78);
1436                    }
1437
1438                    // compare result + size
1439                    const auto result = json::to_cbor(j);
1440                    CHECK(result == expected);
1441                    CHECK(result.size() == N + 1);
1442                    // check that no null byte is appended
1443                    if (N > 0)
1444                    {
1445                        CHECK(result.back() != '\x00');
1446                    }
1447
1448                    // roundtrip
1449                    CHECK(json::from_cbor(result) == j);
1450                    CHECK(json::from_cbor(result, true, false) == j);
1451                }
1452            }
1453
1454            SECTION("N = 24..255")
1455            {
1456                for (size_t N = 24; N <= 255; ++N)
1457                {
1458                    CAPTURE(N)
1459
1460                    // create JSON value with string containing of N * 'x'
1461                    const auto s = std::vector<uint8_t>(N, 'x');
1462                    json j = json::binary(s);
1463
1464                    // create expected byte vector
1465                    std::vector<uint8_t> expected;
1466                    expected.push_back(0x58);
1467                    expected.push_back(static_cast<uint8_t>(N));
1468                    for (size_t i = 0; i < N; ++i)
1469                    {
1470                        expected.push_back('x');
1471                    }
1472
1473                    // compare result + size
1474                    const auto result = json::to_cbor(j);
1475                    CHECK(result == expected);
1476                    CHECK(result.size() == N + 2);
1477                    // check that no null byte is appended
1478                    CHECK(result.back() != '\x00');
1479
1480                    // roundtrip
1481                    CHECK(json::from_cbor(result) == j);
1482                    CHECK(json::from_cbor(result, true, false) == j);
1483                }
1484            }
1485
1486            SECTION("N = 256..65535")
1487            {
1488                for (size_t N :
1489                        {
1490                            256u, 999u, 1025u, 3333u, 2048u, 65535u
1491                        })
1492                {
1493                    CAPTURE(N)
1494
1495                    // create JSON value with string containing of N * 'x'
1496                    const auto s = std::vector<uint8_t>(N, 'x');
1497                    json j = json::binary(s);
1498
1499                    // create expected byte vector (hack: create string first)
1500                    std::vector<uint8_t> expected(N, 'x');
1501                    // reverse order of commands, because we insert at begin()
1502                    expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
1503                    expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
1504                    expected.insert(expected.begin(), 0x59);
1505
1506                    // compare result + size
1507                    const auto result = json::to_cbor(j);
1508                    CHECK(result == expected);
1509                    CHECK(result.size() == N + 3);
1510                    // check that no null byte is appended
1511                    CHECK(result.back() != '\x00');
1512
1513                    // roundtrip
1514                    CHECK(json::from_cbor(result) == j);
1515                    CHECK(json::from_cbor(result, true, false) == j);
1516                }
1517            }
1518
1519            SECTION("N = 65536..4294967295")
1520            {
1521                for (size_t N :
1522                        {
1523                            65536u, 77777u, 1048576u
1524                        })
1525                {
1526                    CAPTURE(N)
1527
1528                    // create JSON value with string containing of N * 'x'
1529                    const auto s = std::vector<uint8_t>(N, 'x');
1530                    json j = json::binary(s);
1531
1532                    // create expected byte vector (hack: create string first)
1533                    std::vector<uint8_t> expected(N, 'x');
1534                    // reverse order of commands, because we insert at begin()
1535                    expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
1536                    expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
1537                    expected.insert(expected.begin(), static_cast<uint8_t>((N >> 16) & 0xff));
1538                    expected.insert(expected.begin(), static_cast<uint8_t>((N >> 24) & 0xff));
1539                    expected.insert(expected.begin(), 0x5a);
1540
1541                    // compare result + size
1542                    const auto result = json::to_cbor(j);
1543                    CHECK(result == expected);
1544                    CHECK(result.size() == N + 5);
1545                    // check that no null byte is appended
1546                    CHECK(result.back() != '\x00');
1547
1548                    // roundtrip
1549                    CHECK(json::from_cbor(result) == j);
1550                    CHECK(json::from_cbor(result, true, false) == j);
1551                }
1552            }
1553
1554            SECTION("indefinite size")
1555            {
1556                std::vector<std::uint8_t> input = {0x5F, 0x44, 0xaa, 0xbb, 0xcc, 0xdd, 0x43, 0xee, 0xff, 0x99, 0xFF};
1557                auto j = json::from_cbor(input);
1558                CHECK(j.is_binary());
1559                auto k = json::binary({0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x99});
1560                CAPTURE(j.dump(0, ' ', false, json::error_handler_t::strict))
1561                CHECK(j == k);
1562            }
1563
1564            SECTION("binary in array")
1565            {
1566                // array with three empty byte strings
1567                std::vector<std::uint8_t> input = {0x83, 0x40, 0x40, 0x40};
1568                json _;
1569                CHECK_NOTHROW(_ = json::from_cbor(input));
1570            }
1571
1572            SECTION("binary in object")
1573            {
1574                // object mapping "foo" to empty byte string
1575                std::vector<std::uint8_t> input = {0xA1, 0x63, 0x66, 0x6F, 0x6F, 0x40};
1576                json _;
1577                CHECK_NOTHROW(_ = json::from_cbor(input));
1578            }
1579
1580            SECTION("SAX callback with binary")
1581            {
1582                // object mapping "foo" to byte string
1583                std::vector<std::uint8_t> input = {0xA1, 0x63, 0x66, 0x6F, 0x6F, 0x41, 0x00};
1584
1585                // callback to set binary_seen to true if a binary value was seen
1586                bool binary_seen = false;
1587                auto callback = [&binary_seen](int /*depth*/, json::parse_event_t /*event*/, json & parsed) noexcept
1588                {
1589                    if (parsed.is_binary())
1590                    {
1591                        binary_seen = true;
1592                    }
1593                    return true;
1594                };
1595
1596                json j;
1597                auto cbp = nlohmann::detail::json_sax_dom_callback_parser<json>(j, callback, true);
1598                CHECK(json::sax_parse(input, &cbp, json::input_format_t::cbor));
1599                CHECK(j.at("foo").is_binary());
1600                CHECK(binary_seen);
1601            }
1602        }
1603    }
1604
1605    SECTION("additional deserialization")
1606    {
1607        SECTION("0x5b (byte array)")
1608        {
1609            std::vector<uint8_t> given = {0x5b, 0x00, 0x00, 0x00, 0x00,
1610                                          0x00, 0x00, 0x00, 0x01, 0x61
1611                                         };
1612            json j = json::from_cbor(given);
1613            CHECK(j == json::binary(std::vector<uint8_t> {'a'}));
1614        }
1615
1616        SECTION("0x7b (string)")
1617        {
1618            std::vector<uint8_t> given = {0x7b, 0x00, 0x00, 0x00, 0x00,
1619                                          0x00, 0x00, 0x00, 0x01, 0x61
1620                                         };
1621            json j = json::from_cbor(given);
1622            CHECK(j == "a");
1623        }
1624
1625        SECTION("0x9b (array)")
1626        {
1627            std::vector<uint8_t> given = {0x9b, 0x00, 0x00, 0x00, 0x00,
1628                                          0x00, 0x00, 0x00, 0x01, 0xf4
1629                                         };
1630            json j = json::from_cbor(given);
1631            CHECK(j == json::parse("[false]"));
1632        }
1633
1634        SECTION("0xbb (map)")
1635        {
1636            std::vector<uint8_t> given = {0xbb, 0x00, 0x00, 0x00, 0x00,
1637                                          0x00, 0x00, 0x00, 0x01, 0x60, 0xf4
1638                                         };
1639            json j = json::from_cbor(given);
1640            CHECK(j == json::parse("{\"\": false}"));
1641        }
1642    }
1643
1644    SECTION("errors")
1645    {
1646        SECTION("empty byte vector")
1647        {
1648            json _;
1649            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>()), "[json.exception.parse_error.110] parse error at byte 1: syntax error while parsing CBOR value: unexpected end of input", json::parse_error&);
1650            CHECK(json::from_cbor(std::vector<uint8_t>(), true, false).is_discarded());
1651        }
1652
1653        SECTION("too short byte vector")
1654        {
1655            json _;
1656            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x18})), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR number: unexpected end of input", json::parse_error&);
1657            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x19})), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR number: unexpected end of input", json::parse_error&);
1658            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x19, 0x00})), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR number: unexpected end of input", json::parse_error&);
1659            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1a})), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR number: unexpected end of input", json::parse_error&);
1660            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1a, 0x00})), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR number: unexpected end of input", json::parse_error&);
1661            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x00})), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing CBOR number: unexpected end of input", json::parse_error&);
1662            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x00, 0x00})), "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing CBOR number: unexpected end of input", json::parse_error&);
1663            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1b})), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR number: unexpected end of input", json::parse_error&);
1664            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00})), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR number: unexpected end of input", json::parse_error&);
1665            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00})), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing CBOR number: unexpected end of input", json::parse_error&);
1666            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00})), "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing CBOR number: unexpected end of input", json::parse_error&);
1667            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00})), "[json.exception.parse_error.110] parse error at byte 6: syntax error while parsing CBOR number: unexpected end of input", json::parse_error&);
1668            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00})), "[json.exception.parse_error.110] parse error at byte 7: syntax error while parsing CBOR number: unexpected end of input", json::parse_error&);
1669            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), "[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing CBOR number: unexpected end of input", json::parse_error&);
1670            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), "[json.exception.parse_error.110] parse error at byte 9: syntax error while parsing CBOR number: unexpected end of input", json::parse_error&);
1671            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x62})), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR string: unexpected end of input", json::parse_error&);
1672            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x62, 0x60})), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR string: unexpected end of input", json::parse_error&);
1673            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x7F})), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR string: unexpected end of input", json::parse_error&);
1674            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x7F, 0x60})), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR string: unexpected end of input", json::parse_error&);
1675            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x82, 0x01})), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR value: unexpected end of input", json::parse_error&);
1676            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x9F, 0x01})), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR value: unexpected end of input", json::parse_error&);
1677            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xBF, 0x61, 0x61, 0xF5})), "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing CBOR string: unexpected end of input", json::parse_error&);
1678            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xA1, 0x61, 0X61})), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing CBOR value: unexpected end of input", json::parse_error&);
1679            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xBF, 0x61, 0X61})), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing CBOR value: unexpected end of input", json::parse_error&);
1680            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x5F})), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR binary: unexpected end of input", json::parse_error&);
1681            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x5F, 0x00})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR binary: expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x00", json::parse_error&);
1682            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x41})), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR binary: unexpected end of input", json::parse_error&);
1683
1684            CHECK(json::from_cbor(std::vector<uint8_t>({0x18}), true, false).is_discarded());
1685            CHECK(json::from_cbor(std::vector<uint8_t>({0x19}), true, false).is_discarded());
1686            CHECK(json::from_cbor(std::vector<uint8_t>({0x19, 0x00}), true, false).is_discarded());
1687            CHECK(json::from_cbor(std::vector<uint8_t>({0x1a}), true, false).is_discarded());
1688            CHECK(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00}), true, false).is_discarded());
1689            CHECK(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x00}), true, false).is_discarded());
1690            CHECK(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x00, 0x00}), true, false).is_discarded());
1691            CHECK(json::from_cbor(std::vector<uint8_t>({0x1b}), true, false).is_discarded());
1692            CHECK(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00}), true, false).is_discarded());
1693            CHECK(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00}), true, false).is_discarded());
1694            CHECK(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00}), true, false).is_discarded());
1695            CHECK(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00}), true, false).is_discarded());
1696            CHECK(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00}), true, false).is_discarded());
1697            CHECK(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}), true, false).is_discarded());
1698            CHECK(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}), true, false).is_discarded());
1699            CHECK(json::from_cbor(std::vector<uint8_t>({0x62}), true, false).is_discarded());
1700            CHECK(json::from_cbor(std::vector<uint8_t>({0x62, 0x60}), true, false).is_discarded());
1701            CHECK(json::from_cbor(std::vector<uint8_t>({0x7F}), true, false).is_discarded());
1702            CHECK(json::from_cbor(std::vector<uint8_t>({0x7F, 0x60}), true, false).is_discarded());
1703            CHECK(json::from_cbor(std::vector<uint8_t>({0x82, 0x01}), true, false).is_discarded());
1704            CHECK(json::from_cbor(std::vector<uint8_t>({0x9F, 0x01}), true, false).is_discarded());
1705            CHECK(json::from_cbor(std::vector<uint8_t>({0xBF, 0x61, 0x61, 0xF5}), true, false).is_discarded());
1706            CHECK(json::from_cbor(std::vector<uint8_t>({0xA1, 0x61, 0x61}), true, false).is_discarded());
1707            CHECK(json::from_cbor(std::vector<uint8_t>({0xBF, 0x61, 0x61}), true, false).is_discarded());
1708            CHECK(json::from_cbor(std::vector<uint8_t>({0x5F}), true, false).is_discarded());
1709            CHECK(json::from_cbor(std::vector<uint8_t>({0x5F, 0x00}), true, false).is_discarded());
1710            CHECK(json::from_cbor(std::vector<uint8_t>({0x41}), true, false).is_discarded());
1711        }
1712
1713        SECTION("unsupported bytes")
1714        {
1715            SECTION("concrete examples")
1716            {
1717                json _;
1718                CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1c})), "[json.exception.parse_error.112] parse error at byte 1: syntax error while parsing CBOR value: invalid byte: 0x1C", json::parse_error&);
1719                CHECK(json::from_cbor(std::vector<uint8_t>({0x1c}), true, false).is_discarded());
1720
1721                CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xf8})), "[json.exception.parse_error.112] parse error at byte 1: syntax error while parsing CBOR value: invalid byte: 0xF8", json::parse_error&);
1722                CHECK(json::from_cbor(std::vector<uint8_t>({0xf8}), true, false).is_discarded());
1723            }
1724
1725            SECTION("all unsupported bytes")
1726            {
1727                for (auto byte :
1728                        {
1729                            // ?
1730                            0x1c, 0x1d, 0x1e, 0x1f,
1731                            // ?
1732                            0x3c, 0x3d, 0x3e, 0x3f,
1733                            // ?
1734                            0x5c, 0x5d, 0x5e,
1735                            // ?
1736                            0x7c, 0x7d, 0x7e,
1737                            // ?
1738                            0x9c, 0x9d, 0x9e,
1739                            // ?
1740                            0xbc, 0xbd, 0xbe,
1741                            // date/time
1742                            0xc0, 0xc1,
1743                            // bignum
1744                            0xc2, 0xc3,
1745                            // fraction
1746                            0xc4,
1747                            // bigfloat
1748                            0xc5,
1749                            // tagged item
1750                            0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4,
1751                            // expected conversion
1752                            0xd5, 0xd6, 0xd7,
1753                            // more tagged items
1754                            0xd8, 0xd9, 0xda, 0xdb,
1755                            // ?
1756                            0xdc, 0xdd, 0xde, 0xdf,
1757                            // (simple value)
1758                            0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3,
1759                            // undefined
1760                            0xf7,
1761                            // simple value
1762                            0xf8
1763                        })
1764                {
1765                    json _;
1766                    CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({static_cast<uint8_t>(byte)})), json::parse_error&);
1767                    CHECK(json::from_cbor(std::vector<uint8_t>({static_cast<uint8_t>(byte)}), true, false).is_discarded());
1768                }
1769            }
1770        }
1771
1772        SECTION("invalid string in map")
1773        {
1774            json _;
1775            CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xa1, 0xff, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xFF", json::parse_error&);
1776            CHECK(json::from_cbor(std::vector<uint8_t>({0xa1, 0xff, 0x01}), true, false).is_discarded());
1777        }
1778
1779        SECTION("strict mode")
1780        {
1781            std::vector<uint8_t> vec = {0xf6, 0xf6};
1782            SECTION("non-strict mode")
1783            {
1784                const auto result = json::from_cbor(vec, false);
1785                CHECK(result == json());
1786                CHECK(!json::from_cbor(vec, false, false).is_discarded());
1787            }
1788
1789            SECTION("strict mode")
1790            {
1791                json _;
1792                CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR value: expected end of input; last byte: 0xF6", json::parse_error&);
1793                CHECK(json::from_cbor(vec, true, false).is_discarded());
1794            }
1795        }
1796    }
1797
1798    SECTION("SAX aborts")
1799    {
1800        SECTION("start_array(len)")
1801        {
1802            std::vector<uint8_t> v = {0x83, 0x01, 0x02, 0x03};
1803            SaxCountdown scp(0);
1804            CHECK(!json::sax_parse(v, &scp, json::input_format_t::cbor));
1805        }
1806
1807        SECTION("start_object(len)")
1808        {
1809            std::vector<uint8_t> v = {0xA1, 0x63, 0x66, 0x6F, 0x6F, 0xF4};
1810            SaxCountdown scp(0);
1811            CHECK(!json::sax_parse(v, &scp, json::input_format_t::cbor));
1812        }
1813
1814        SECTION("key()")
1815        {
1816            std::vector<uint8_t> v = {0xA1, 0x63, 0x66, 0x6F, 0x6F, 0xF4};
1817            SaxCountdown scp(1);
1818            CHECK(!json::sax_parse(v, &scp, json::input_format_t::cbor));
1819        }
1820    }
1821}
1822
1823// use this testcase outside [hide] to run it with Valgrind
1824TEST_CASE("single CBOR roundtrip")
1825{
1826    SECTION("sample.json")
1827    {
1828        std::string filename = TEST_DATA_DIRECTORY "/json_testsuite/sample.json";
1829
1830        // parse JSON file
1831        std::ifstream f_json(filename);
1832        json j1 = json::parse(f_json);
1833
1834        // parse CBOR file
1835        auto packed = utils::read_binary_file(filename + ".cbor");
1836        json j2;
1837        CHECK_NOTHROW(j2 = json::from_cbor(packed));
1838
1839        // compare parsed JSON values
1840        CHECK(j1 == j2);
1841
1842        SECTION("roundtrips")
1843        {
1844            SECTION("std::ostringstream")
1845            {
1846                std::basic_ostringstream<std::uint8_t> ss;
1847                json::to_cbor(j1, ss);
1848                json j3 = json::from_cbor(ss.str());
1849                CHECK(j1 == j3);
1850            }
1851
1852            SECTION("std::string")
1853            {
1854                std::string s;
1855                json::to_cbor(j1, s);
1856                json j3 = json::from_cbor(s);
1857                CHECK(j1 == j3);
1858            }
1859        }
1860
1861        // check with different start index
1862        packed.insert(packed.begin(), 5, 0xff);
1863        CHECK(j1 == json::from_cbor(packed.begin() + 5, packed.end()));
1864    }
1865}
1866
1867#if !defined(JSON_NOEXCEPTION)
1868TEST_CASE("CBOR regressions")
1869{
1870    SECTION("fuzz test results")
1871    {
1872        /*
1873        The following test cases were found during a two-day session with
1874        AFL-Fuzz. As a result, empty byte vectors and excessive lengths are
1875        detected.
1876        */
1877        for (std::string filename :
1878                {
1879                    TEST_DATA_DIRECTORY "/cbor_regression/test01",
1880                    TEST_DATA_DIRECTORY "/cbor_regression/test02",
1881                    TEST_DATA_DIRECTORY "/cbor_regression/test03",
1882                    TEST_DATA_DIRECTORY "/cbor_regression/test04",
1883                    TEST_DATA_DIRECTORY "/cbor_regression/test05",
1884                    TEST_DATA_DIRECTORY "/cbor_regression/test06",
1885                    TEST_DATA_DIRECTORY "/cbor_regression/test07",
1886                    TEST_DATA_DIRECTORY "/cbor_regression/test08",
1887                    TEST_DATA_DIRECTORY "/cbor_regression/test09",
1888                    TEST_DATA_DIRECTORY "/cbor_regression/test10",
1889                    TEST_DATA_DIRECTORY "/cbor_regression/test11",
1890                    TEST_DATA_DIRECTORY "/cbor_regression/test12",
1891                    TEST_DATA_DIRECTORY "/cbor_regression/test13",
1892                    TEST_DATA_DIRECTORY "/cbor_regression/test14",
1893                    TEST_DATA_DIRECTORY "/cbor_regression/test15",
1894                    TEST_DATA_DIRECTORY "/cbor_regression/test16",
1895                    TEST_DATA_DIRECTORY "/cbor_regression/test17",
1896                    TEST_DATA_DIRECTORY "/cbor_regression/test18",
1897                    TEST_DATA_DIRECTORY "/cbor_regression/test19",
1898                    TEST_DATA_DIRECTORY "/cbor_regression/test20",
1899                    TEST_DATA_DIRECTORY "/cbor_regression/test21"
1900                })
1901        {
1902            CAPTURE(filename)
1903
1904            try
1905            {
1906                // parse CBOR file
1907                auto vec1 = utils::read_binary_file(filename);
1908                json j1 = json::from_cbor(vec1);
1909
1910                try
1911                {
1912                    // step 2: round trip
1913                    std::vector<uint8_t> vec2 = json::to_cbor(j1);
1914
1915                    // parse serialization
1916                    json j2 = json::from_cbor(vec2);
1917
1918                    // deserializations must match
1919                    CHECK(j1 == j2);
1920                }
1921                catch (const json::parse_error&)
1922                {
1923                    // parsing a CBOR serialization must not fail
1924                    CHECK(false);
1925                }
1926            }
1927            catch (const json::parse_error&)
1928            {
1929                // parse errors are ok, because input may be random bytes
1930            }
1931        }
1932    }
1933}
1934#endif
1935
1936TEST_CASE("CBOR roundtrips" * doctest::skip())
1937{
1938    SECTION("input from flynn")
1939    {
1940        // most of these are excluded due to differences in key order (not a real problem)
1941        std::set<std::string> exclude_packed;
1942        exclude_packed.insert(TEST_DATA_DIRECTORY "/json.org/1.json");
1943        exclude_packed.insert(TEST_DATA_DIRECTORY "/json.org/2.json");
1944        exclude_packed.insert(TEST_DATA_DIRECTORY "/json.org/3.json");
1945        exclude_packed.insert(TEST_DATA_DIRECTORY "/json.org/4.json");
1946        exclude_packed.insert(TEST_DATA_DIRECTORY "/json.org/5.json");
1947        exclude_packed.insert(TEST_DATA_DIRECTORY "/json_testsuite/sample.json"); // kills AppVeyor
1948        exclude_packed.insert(TEST_DATA_DIRECTORY "/json_tests/pass1.json");
1949        exclude_packed.insert(TEST_DATA_DIRECTORY "/regression/working_file.json");
1950        exclude_packed.insert(TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_object.json");
1951        exclude_packed.insert(TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_object_duplicated_key.json");
1952        exclude_packed.insert(TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_object_long_strings.json");
1953
1954        for (std::string filename :
1955                {
1956                    TEST_DATA_DIRECTORY "/json_nlohmann_tests/all_unicode.json",
1957                    TEST_DATA_DIRECTORY "/json.org/1.json",
1958                    TEST_DATA_DIRECTORY "/json.org/2.json",
1959                    TEST_DATA_DIRECTORY "/json.org/3.json",
1960                    TEST_DATA_DIRECTORY "/json.org/4.json",
1961                    TEST_DATA_DIRECTORY "/json.org/5.json",
1962                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip01.json",
1963                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip02.json",
1964                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip03.json",
1965                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip04.json",
1966                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip05.json",
1967                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip06.json",
1968                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip07.json",
1969                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip08.json",
1970                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip09.json",
1971                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip10.json",
1972                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip11.json",
1973                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip12.json",
1974                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip13.json",
1975                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip14.json",
1976                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip15.json",
1977                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip16.json",
1978                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip17.json",
1979                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip18.json",
1980                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip19.json",
1981                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip20.json",
1982                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip21.json",
1983                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip22.json",
1984                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip23.json",
1985                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip24.json",
1986                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip25.json",
1987                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip26.json",
1988                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip27.json",
1989                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip28.json",
1990                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip29.json",
1991                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip30.json",
1992                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip31.json",
1993                    TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip32.json",
1994                    TEST_DATA_DIRECTORY "/json_testsuite/sample.json", // kills AppVeyor
1995                    TEST_DATA_DIRECTORY "/json_tests/pass1.json",
1996                    TEST_DATA_DIRECTORY "/json_tests/pass2.json",
1997                    TEST_DATA_DIRECTORY "/json_tests/pass3.json",
1998                    TEST_DATA_DIRECTORY "/regression/floats.json",
1999                    TEST_DATA_DIRECTORY "/regression/signed_ints.json",
2000                    TEST_DATA_DIRECTORY "/regression/unsigned_ints.json",
2001                    TEST_DATA_DIRECTORY "/regression/working_file.json",
2002                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_array_arraysWithSpaces.json",
2003                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_array_empty-string.json",
2004                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_array_empty.json",
2005                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_array_ending_with_newline.json",
2006                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_array_false.json",
2007                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_array_heterogeneous.json",
2008                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_array_null.json",
2009                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_array_with_1_and_newline.json",
2010                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_array_with_leading_space.json",
2011                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_array_with_several_null.json",
2012                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_array_with_trailing_space.json",
2013                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number.json",
2014                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_0e+1.json",
2015                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_0e1.json",
2016                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_after_space.json",
2017                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json",
2018                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json",
2019                    //TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_huge_exp.json",
2020                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_int_with_exp.json",
2021                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_minus_zero.json",
2022                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_negative_int.json",
2023                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_negative_one.json",
2024                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_negative_zero.json",
2025                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_real_capital_e.json",
2026                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_real_capital_e_neg_exp.json",
2027                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_real_capital_e_pos_exp.json",
2028                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_real_exponent.json",
2029                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json",
2030                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json",
2031                    //TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json",
2032                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json",
2033                    //TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json",
2034                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_real_underflow.json",
2035                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_simple_int.json",
2036                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_simple_real.json",
2037                    //TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_too_big_neg_int.json",
2038                    //TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_too_big_pos_int.json",
2039                    //TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_number_very_big_negative_int.json",
2040                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_object.json",
2041                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_object_basic.json",
2042                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_object_duplicated_key.json",
2043                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_object_duplicated_key_and_value.json",
2044                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_object_empty.json",
2045                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_object_empty_key.json",
2046                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_object_escaped_null_in_key.json",
2047                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_object_extreme_numbers.json",
2048                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_object_long_strings.json",
2049                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_object_simple.json",
2050                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_object_string_unicode.json",
2051                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_object_with_newlines.json",
2052                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json",
2053                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_UTF-16_Surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json",
2054                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pair.json",
2055                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pairs.json",
2056                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_allowed_escapes.json",
2057                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_backslash_and_u_escaped_zero.json",
2058                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_backslash_doublequotes.json",
2059                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_comments.json",
2060                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_double_escape_a.json",
2061                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_double_escape_n.json",
2062                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_escaped_control_character.json",
2063                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_escaped_noncharacter.json",
2064                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_in_array.json",
2065                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_in_array_with_leading_space.json",
2066                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_last_surrogates_1_and_2.json",
2067                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_newline_uescaped.json",
2068                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json",
2069                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+1FFFF.json",
2070                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json",
2071                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_null_escape.json",
2072                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_one-byte-utf-8.json",
2073                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_pi.json",
2074                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_simple_ascii.json",
2075                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_space.json",
2076                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_three-byte-utf-8.json",
2077                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_two-byte-utf-8.json",
2078                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_u+2028_line_sep.json",
2079                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_u+2029_par_sep.json",
2080                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_uEscape.json",
2081                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_unescaped_char_delete.json",
2082                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_unicode.json",
2083                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_unicodeEscapedBackslash.json",
2084                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_unicode_2.json",
2085                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json",
2086                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json",
2087                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_unicode_escaped_double_quote.json",
2088                    // TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_utf16.json",
2089                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_utf8.json",
2090                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_string_with_del_character.json",
2091                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_structure_lonely_false.json",
2092                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_structure_lonely_int.json",
2093                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_structure_lonely_negative_real.json",
2094                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_structure_lonely_null.json",
2095                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_structure_lonely_string.json",
2096                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_structure_lonely_true.json",
2097                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_structure_string_empty.json",
2098                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_structure_trailing_newline.json",
2099                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_structure_true_in_array.json",
2100                    TEST_DATA_DIRECTORY "/nst_json_testsuite/test_parsing/y_structure_whitespace_array.json"
2101                })
2102        {
2103            CAPTURE(filename)
2104
2105            {
2106                INFO_WITH_TEMP(filename + ": std::vector<uint8_t>");
2107                // parse JSON file
2108                std::ifstream f_json(filename);
2109                json j1 = json::parse(f_json);
2110
2111                // parse CBOR file
2112                auto packed = utils::read_binary_file(filename + ".cbor");
2113                json j2;
2114                CHECK_NOTHROW(j2 = json::from_cbor(packed));
2115
2116                // compare parsed JSON values
2117                CHECK(j1 == j2);
2118            }
2119
2120            {
2121                INFO_WITH_TEMP(filename + ": std::ifstream");
2122                // parse JSON file
2123                std::ifstream f_json(filename);
2124                json j1 = json::parse(f_json);
2125
2126                // parse CBOR file
2127                std::ifstream f_cbor(filename + ".cbor", std::ios::binary);
2128                json j2;
2129                CHECK_NOTHROW(j2 = json::from_cbor(f_cbor));
2130
2131                // compare parsed JSON values
2132                CHECK(j1 == j2);
2133            }
2134
2135            {
2136                INFO_WITH_TEMP(filename + ": uint8_t* and size");
2137                // parse JSON file
2138                std::ifstream f_json(filename);
2139                json j1 = json::parse(f_json);
2140
2141                // parse CBOR file
2142                auto packed = utils::read_binary_file(filename + ".cbor");
2143                json j2;
2144                CHECK_NOTHROW(j2 = json::from_cbor({packed.data(), packed.size()}));
2145
2146                // compare parsed JSON values
2147                CHECK(j1 == j2);
2148            }
2149
2150            {
2151                INFO_WITH_TEMP(filename + ": output to output adapters");
2152                // parse JSON file
2153                std::ifstream f_json(filename);
2154                json j1 = json::parse(f_json);
2155
2156                // parse CBOR file
2157                auto packed = utils::read_binary_file(filename + ".cbor");
2158
2159                if (exclude_packed.count(filename) == 0u)
2160                {
2161                    {
2162                        INFO_WITH_TEMP(filename + ": output adapters: std::vector<uint8_t>");
2163                        std::vector<uint8_t> vec;
2164                        json::to_cbor(j1, vec);
2165                        CHECK(vec == packed);
2166                    }
2167                }
2168            }
2169        }
2170    }
2171}
2172
2173#if !defined(JSON_NOEXCEPTION)
2174TEST_CASE("all CBOR first bytes")
2175{
2176    // these bytes will fail immediately with exception parse_error.112
2177    std::set<uint8_t> unsupported =
2178    {
2179        //// types not supported by this library
2180
2181        // date/time
2182        0xc0, 0xc1,
2183        // bignum
2184        0xc2, 0xc3,
2185        // decimal fracion
2186        0xc4,
2187        // bigfloat
2188        0xc5,
2189        // tagged item
2190        0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd,
2191        0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd8,
2192        0xd9, 0xda, 0xdb,
2193        // expected conversion
2194        0xd5, 0xd6, 0xd7,
2195        // simple value
2196        0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
2197        0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xef, 0xf0,
2198        0xf1, 0xf2, 0xf3,
2199        0xf8,
2200        // undefined
2201        0xf7,
2202
2203        //// bytes not specified by CBOR
2204
2205        0x1c, 0x1d, 0x1e, 0x1f,
2206        0x3c, 0x3d, 0x3e, 0x3f,
2207        0x5c, 0x5d, 0x5e,
2208        0x7c, 0x7d, 0x7e,
2209        0x9c, 0x9d, 0x9e,
2210        0xbc, 0xbd, 0xbe,
2211        0xdc, 0xdd, 0xde, 0xdf,
2212        0xee,
2213        0xfc, 0xfe, 0xfd,
2214
2215        /// break cannot be the first byte
2216
2217        0xff
2218    };
2219
2220    for (auto i = 0; i < 256; ++i)
2221    {
2222        const auto byte = static_cast<uint8_t>(i);
2223
2224        try
2225        {
2226            auto res = json::from_cbor(std::vector<uint8_t>(1, byte));
2227        }
2228        catch (const json::parse_error& e)
2229        {
2230            // check that parse_error.112 is only thrown if the
2231            // first byte is in the unsupported set
2232            INFO_WITH_TEMP(e.what());
2233            if (unsupported.find(byte) != unsupported.end())
2234            {
2235                CHECK(e.id == 112);
2236            }
2237            else
2238            {
2239                CHECK(e.id != 112);
2240            }
2241        }
2242    }
2243}
2244#endif
2245
2246TEST_CASE("examples from RFC 7049 Appendix A")
2247{
2248    SECTION("numbers")
2249    {
2250        CHECK(json::to_cbor(json::parse("0")) == std::vector<uint8_t>({0x00}));
2251        CHECK(json::parse("0") == json::from_cbor(std::vector<uint8_t>({0x00})));
2252
2253        CHECK(json::to_cbor(json::parse("1")) == std::vector<uint8_t>({0x01}));
2254        CHECK(json::parse("1") == json::from_cbor(std::vector<uint8_t>({0x01})));
2255
2256        CHECK(json::to_cbor(json::parse("10")) == std::vector<uint8_t>({0x0a}));
2257        CHECK(json::parse("10") == json::from_cbor(std::vector<uint8_t>({0x0a})));
2258
2259        CHECK(json::to_cbor(json::parse("23")) == std::vector<uint8_t>({0x17}));
2260        CHECK(json::parse("23") == json::from_cbor(std::vector<uint8_t>({0x17})));
2261
2262        CHECK(json::to_cbor(json::parse("24")) == std::vector<uint8_t>({0x18, 0x18}));
2263        CHECK(json::parse("24") == json::from_cbor(std::vector<uint8_t>({0x18, 0x18})));
2264
2265        CHECK(json::to_cbor(json::parse("25")) == std::vector<uint8_t>({0x18, 0x19}));
2266        CHECK(json::parse("25") == json::from_cbor(std::vector<uint8_t>({0x18, 0x19})));
2267
2268        CHECK(json::to_cbor(json::parse("100")) == std::vector<uint8_t>({0x18, 0x64}));
2269        CHECK(json::parse("100") == json::from_cbor(std::vector<uint8_t>({0x18, 0x64})));
2270
2271        CHECK(json::to_cbor(json::parse("1000")) == std::vector<uint8_t>({0x19, 0x03, 0xe8}));
2272        CHECK(json::parse("1000") == json::from_cbor(std::vector<uint8_t>({0x19, 0x03, 0xe8})));
2273
2274        CHECK(json::to_cbor(json::parse("1000000")) == std::vector<uint8_t>({0x1a, 0x00, 0x0f, 0x42, 0x40}));
2275        CHECK(json::parse("1000000") == json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x0f, 0x42, 0x40})));
2276
2277        CHECK(json::to_cbor(json::parse("1000000000000")) == std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0xe8, 0xd4, 0xa5, 0x10, 0x00}));
2278        CHECK(json::parse("1000000000000") == json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0xe8, 0xd4, 0xa5, 0x10, 0x00})));
2279
2280        CHECK(json::to_cbor(json::parse("18446744073709551615")) == std::vector<uint8_t>({0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}));
2281        CHECK(json::parse("18446744073709551615") == json::from_cbor(std::vector<uint8_t>({0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff})));
2282
2283        // positive bignum is not supported
2284        //CHECK(json::to_cbor(json::parse("18446744073709551616")) == std::vector<uint8_t>({0xc2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}));
2285        //CHECK(json::parse("18446744073709551616") == json::from_cbor(std::vector<uint8_t>({0xc2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})));
2286
2287        //CHECK(json::to_cbor(json::parse("-18446744073709551616")) == std::vector<uint8_t>({0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}));
2288        //CHECK(json::parse("-18446744073709551616") == json::from_cbor(std::vector<uint8_t>({0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff})));
2289
2290        // negative bignum is not supported
2291        //CHECK(json::to_cbor(json::parse("-18446744073709551617")) == std::vector<uint8_t>({0xc3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}));
2292        //CHECK(json::parse("-18446744073709551617") == json::from_cbor(std::vector<uint8_t>({0xc3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})));
2293
2294        CHECK(json::to_cbor(json::parse("-1")) == std::vector<uint8_t>({0x20}));
2295        CHECK(json::parse("-1") == json::from_cbor(std::vector<uint8_t>({0x20})));
2296
2297        CHECK(json::to_cbor(json::parse("-10")) == std::vector<uint8_t>({0x29}));
2298        CHECK(json::parse("-10") == json::from_cbor(std::vector<uint8_t>({0x29})));
2299
2300        CHECK(json::to_cbor(json::parse("-100")) == std::vector<uint8_t>({0x38, 0x63}));
2301        CHECK(json::parse("-100") == json::from_cbor(std::vector<uint8_t>({0x38, 0x63})));
2302
2303        CHECK(json::to_cbor(json::parse("-1000")) == std::vector<uint8_t>({0x39, 0x03, 0xe7}));
2304        CHECK(json::parse("-1000") == json::from_cbor(std::vector<uint8_t>({0x39, 0x03, 0xe7})));
2305
2306        // half-precision float
2307        //CHECK(json::to_cbor(json::parse("0.0")) == std::vector<uint8_t>({0xf9, 0x00, 0x00}));
2308        CHECK(json::parse("0.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x00, 0x00})));
2309
2310        // half-precision float
2311        //CHECK(json::to_cbor(json::parse("-0.0")) == std::vector<uint8_t>({0xf9, 0x80, 0x00}));
2312        CHECK(json::parse("-0.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x80, 0x00})));
2313
2314        // half-precision float
2315        //CHECK(json::to_cbor(json::parse("1.0")) == std::vector<uint8_t>({0xf9, 0x3c, 0x00}));
2316        CHECK(json::parse("1.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x3c, 0x00})));
2317
2318        CHECK(json::to_cbor(json::parse("1.1")) == std::vector<uint8_t>({0xfb, 0x3f, 0xf1, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a}));
2319        CHECK(json::parse("1.1") == json::from_cbor(std::vector<uint8_t>({0xfb, 0x3f, 0xf1, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a})));
2320
2321        // half-precision float
2322        //CHECK(json::to_cbor(json::parse("1.5")) == std::vector<uint8_t>({0xf9, 0x3e, 0x00}));
2323        CHECK(json::parse("1.5") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x3e, 0x00})));
2324
2325        // half-precision float
2326        //CHECK(json::to_cbor(json::parse("65504.0")) == std::vector<uint8_t>({0xf9, 0x7b, 0xff}));
2327        CHECK(json::parse("65504.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x7b, 0xff})));
2328
2329        //CHECK(json::to_cbor(json::parse("100000.0")) == std::vector<uint8_t>({0xfa, 0x47, 0xc3, 0x50, 0x00}));
2330        CHECK(json::parse("100000.0") == json::from_cbor(std::vector<uint8_t>({0xfa, 0x47, 0xc3, 0x50, 0x00})));
2331
2332        //CHECK(json::to_cbor(json::parse("3.4028234663852886e+38")) == std::vector<uint8_t>({0xfa, 0x7f, 0x7f, 0xff, 0xff}));
2333        CHECK(json::parse("3.4028234663852886e+38") == json::from_cbor(std::vector<uint8_t>({0xfa, 0x7f, 0x7f, 0xff, 0xff})));
2334
2335        CHECK(json::to_cbor(json::parse("1.0e+300")) == std::vector<uint8_t>({0xfb, 0x7e, 0x37, 0xe4, 0x3c, 0x88, 0x00, 0x75, 0x9c}));
2336        CHECK(json::parse("1.0e+300") == json::from_cbor(std::vector<uint8_t>({0xfb, 0x7e, 0x37, 0xe4, 0x3c, 0x88, 0x00, 0x75, 0x9c})));
2337
2338        // half-precision float
2339        //CHECK(json::to_cbor(json::parse("5.960464477539063e-8")) == std::vector<uint8_t>({0xf9, 0x00, 0x01}));
2340        CHECK(json::parse("-4.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0xc4, 0x00})));
2341
2342        // half-precision float
2343        //CHECK(json::to_cbor(json::parse("0.00006103515625")) == std::vector<uint8_t>({0xf9, 0x04, 0x00}));
2344        CHECK(json::parse("-4.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0xc4, 0x00})));
2345
2346        // half-precision float
2347        //CHECK(json::to_cbor(json::parse("-4.0")) == std::vector<uint8_t>({0xf9, 0xc4, 0x00}));
2348        CHECK(json::parse("-4.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0xc4, 0x00})));
2349
2350        CHECK(json::to_cbor(json::parse("-4.1")) == std::vector<uint8_t>({0xfb, 0xc0, 0x10, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}));
2351        CHECK(json::parse("-4.1") == json::from_cbor(std::vector<uint8_t>({0xfb, 0xc0, 0x10, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66})));
2352    }
2353
2354    SECTION("simple values")
2355    {
2356        CHECK(json::to_cbor(json::parse("false")) == std::vector<uint8_t>({0xf4}));
2357        CHECK(json::parse("false") == json::from_cbor(std::vector<uint8_t>({0xf4})));
2358
2359        CHECK(json::to_cbor(json::parse("true")) == std::vector<uint8_t>({0xf5}));
2360        CHECK(json::parse("true") == json::from_cbor(std::vector<uint8_t>({0xf5})));
2361
2362        CHECK(json::to_cbor(json::parse("true")) == std::vector<uint8_t>({0xf5}));
2363        CHECK(json::parse("true") == json::from_cbor(std::vector<uint8_t>({0xf5})));
2364    }
2365
2366    SECTION("strings")
2367    {
2368        CHECK(json::to_cbor(json::parse("\"\"")) == std::vector<uint8_t>({0x60}));
2369        CHECK(json::parse("\"\"") == json::from_cbor(std::vector<uint8_t>({0x60})));
2370
2371        CHECK(json::to_cbor(json::parse("\"a\"")) == std::vector<uint8_t>({0x61, 0x61}));
2372        CHECK(json::parse("\"a\"") == json::from_cbor(std::vector<uint8_t>({0x61, 0x61})));
2373
2374        CHECK(json::to_cbor(json::parse("\"IETF\"")) == std::vector<uint8_t>({0x64, 0x49, 0x45, 0x54, 0x46}));
2375        CHECK(json::parse("\"IETF\"") == json::from_cbor(std::vector<uint8_t>({0x64, 0x49, 0x45, 0x54, 0x46})));
2376
2377        CHECK(json::to_cbor(json::parse("\"\\u00fc\"")) == std::vector<uint8_t>({0x62, 0xc3, 0xbc}));
2378        CHECK(json::parse("\"\\u00fc\"") == json::from_cbor(std::vector<uint8_t>({0x62, 0xc3, 0xbc})));
2379
2380        CHECK(json::to_cbor(json::parse("\"\\u6c34\"")) == std::vector<uint8_t>({0x63, 0xe6, 0xb0, 0xb4}));
2381        CHECK(json::parse("\"\\u6c34\"") == json::from_cbor(std::vector<uint8_t>({0x63, 0xe6, 0xb0, 0xb4})));
2382
2383        CHECK(json::to_cbor(json::parse("\"\\ud800\\udd51\"")) == std::vector<uint8_t>({0x64, 0xf0, 0x90, 0x85, 0x91}));
2384        CHECK(json::parse("\"\\ud800\\udd51\"") == json::from_cbor(std::vector<uint8_t>({0x64, 0xf0, 0x90, 0x85, 0x91})));
2385
2386        // indefinite length strings
2387        CHECK(json::parse("\"streaming\"") == json::from_cbor(std::vector<uint8_t>({0x7f, 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x67, 0xff})));
2388    }
2389
2390    SECTION("byte arrays")
2391    {
2392        auto packed = utils::read_binary_file(TEST_DATA_DIRECTORY "/binary_data/cbor_binary.cbor");
2393        json j;
2394        CHECK_NOTHROW(j = json::from_cbor(packed));
2395
2396        auto expected = utils::read_binary_file(TEST_DATA_DIRECTORY "/binary_data/cbor_binary.out");
2397        CHECK(j == json::binary(expected));
2398
2399        // 0xd8
2400        CHECK(json::to_cbor(json::binary(std::vector<uint8_t> {}, 0x42)) == std::vector<uint8_t> {0xd8, 0x42, 0x40});
2401        CHECK(!json::from_cbor(json::to_cbor(json::binary(std::vector<uint8_t> {}, 0x42)), true, true, json::cbor_tag_handler_t::ignore).get_binary().has_subtype());
2402        CHECK(json::from_cbor(json::to_cbor(json::binary(std::vector<uint8_t> {}, 0x42)), true, true, json::cbor_tag_handler_t::store).get_binary().subtype() == 0x42);
2403        // 0xd9
2404        CHECK(json::to_cbor(json::binary(std::vector<uint8_t> {}, 1000)) == std::vector<uint8_t> {0xd9, 0x03, 0xe8, 0x40});
2405        CHECK(!json::from_cbor(json::to_cbor(json::binary(std::vector<uint8_t> {}, 1000)), true, true, json::cbor_tag_handler_t::ignore).get_binary().has_subtype());
2406        CHECK(json::from_cbor(json::to_cbor(json::binary(std::vector<uint8_t> {}, 1000)), true, true, json::cbor_tag_handler_t::store).get_binary().subtype() == 1000);
2407        // 0xda
2408        CHECK(json::to_cbor(json::binary(std::vector<uint8_t> {}, 394216)) == std::vector<uint8_t> {0xda, 0x00, 0x06, 0x03, 0xe8, 0x40});
2409        CHECK(!json::from_cbor(json::to_cbor(json::binary(std::vector<uint8_t> {}, 394216)), true, true, json::cbor_tag_handler_t::ignore).get_binary().has_subtype());
2410        CHECK(json::from_cbor(json::to_cbor(json::binary(std::vector<uint8_t> {}, 394216)), true, true, json::cbor_tag_handler_t::store).get_binary().subtype() == 394216);
2411        // 0xdb
2412        CHECK(json::to_cbor(json::binary(std::vector<uint8_t> {}, 8589934590)) == std::vector<uint8_t> {0xdb, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xfe, 0x40});
2413        CHECK(!json::from_cbor(json::to_cbor(json::binary(std::vector<uint8_t> {}, 8589934590)), true, true, json::cbor_tag_handler_t::ignore).get_binary().has_subtype());
2414        CHECK(json::from_cbor(json::to_cbor(json::binary(std::vector<uint8_t> {}, 8589934590)), true, true, json::cbor_tag_handler_t::store).get_binary().subtype() == 8589934590);
2415    }
2416
2417    SECTION("arrays")
2418    {
2419        CHECK(json::to_cbor(json::parse("[]")) == std::vector<uint8_t>({0x80}));
2420        CHECK(json::parse("[]") == json::from_cbor(std::vector<uint8_t>({0x80})));
2421
2422        CHECK(json::to_cbor(json::parse("[1, 2, 3]")) == std::vector<uint8_t>({0x83, 0x01, 0x02, 0x03}));
2423        CHECK(json::parse("[1, 2, 3]") == json::from_cbor(std::vector<uint8_t>({0x83, 0x01, 0x02, 0x03})));
2424
2425        CHECK(json::to_cbor(json::parse("[1, [2, 3], [4, 5]]")) == std::vector<uint8_t>({0x83, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05}));
2426        CHECK(json::parse("[1, [2, 3], [4, 5]]") == json::from_cbor(std::vector<uint8_t>({0x83, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05})));
2427
2428        CHECK(json::to_cbor(json::parse("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]")) == std::vector<uint8_t>({0x98, 0x19, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19}));
2429        CHECK(json::parse("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]") == json::from_cbor(std::vector<uint8_t>({0x98, 0x19, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19})));
2430
2431        // indefinite length arrays
2432        CHECK(json::parse("[]") == json::from_cbor(std::vector<uint8_t>({0x9f, 0xff})));
2433        CHECK(json::parse("[1, [2, 3], [4, 5]] ") == json::from_cbor(std::vector<uint8_t>({0x9f, 0x01, 0x82, 0x02, 0x03, 0x9f, 0x04, 0x05, 0xff, 0xff})));
2434        CHECK(json::parse("[1, [2, 3], [4, 5]]") == json::from_cbor(std::vector<uint8_t>({0x9f, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05, 0xff})));
2435        CHECK(json::parse("[1, [2, 3], [4, 5]]") == json::from_cbor(std::vector<uint8_t>({0x83, 0x01, 0x82, 0x02, 0x03, 0x9f, 0x04, 0x05, 0xff})));
2436        CHECK(json::parse("[1, [2, 3], [4, 5]]") == json::from_cbor(std::vector<uint8_t>({0x83, 0x01, 0x9f, 0x02, 0x03, 0xff, 0x82, 0x04, 0x05})));
2437        CHECK(json::parse("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]") == json::from_cbor(std::vector<uint8_t>({0x9f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19, 0xff})));
2438    }
2439
2440    SECTION("objects")
2441    {
2442        CHECK(json::to_cbor(json::parse("{}")) == std::vector<uint8_t>({0xa0}));
2443        CHECK(json::parse("{}") == json::from_cbor(std::vector<uint8_t>({0xa0})));
2444
2445        CHECK(json::to_cbor(json::parse("{\"a\": 1, \"b\": [2, 3]}")) == std::vector<uint8_t>({0xa2, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03}));
2446        CHECK(json::parse("{\"a\": 1, \"b\": [2, 3]}") == json::from_cbor(std::vector<uint8_t>({0xa2, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03})));
2447
2448        CHECK(json::to_cbor(json::parse("[\"a\", {\"b\": \"c\"}]")) == std::vector<uint8_t>({0x82, 0x61, 0x61, 0xa1, 0x61, 0x62, 0x61, 0x63}));
2449        CHECK(json::parse("[\"a\", {\"b\": \"c\"}]") == json::from_cbor(std::vector<uint8_t>({0x82, 0x61, 0x61, 0xa1, 0x61, 0x62, 0x61, 0x63})));
2450
2451        CHECK(json::to_cbor(json::parse("{\"a\": \"A\", \"b\": \"B\", \"c\": \"C\", \"d\": \"D\", \"e\": \"E\"}")) == std::vector<uint8_t>({0xa5, 0x61, 0x61, 0x61, 0x41, 0x61, 0x62, 0x61, 0x42, 0x61, 0x63, 0x61, 0x43, 0x61, 0x64, 0x61, 0x44, 0x61, 0x65, 0x61, 0x45}));
2452        CHECK(json::parse("{\"a\": \"A\", \"b\": \"B\", \"c\": \"C\", \"d\": \"D\", \"e\": \"E\"}") == json::from_cbor(std::vector<uint8_t>({0xa5, 0x61, 0x61, 0x61, 0x41, 0x61, 0x62, 0x61, 0x42, 0x61, 0x63, 0x61, 0x43, 0x61, 0x64, 0x61, 0x44, 0x61, 0x65, 0x61, 0x45})));
2453
2454        // indefinite length objects
2455        CHECK(json::parse("{\"a\": 1, \"b\": [2, 3]}") == json::from_cbor(std::vector<uint8_t>({0xbf, 0x61, 0x61, 0x01, 0x61, 0x62, 0x9f, 0x02, 0x03, 0xff, 0xff})));
2456        CHECK(json::parse("[\"a\", {\"b\": \"c\"}]") == json::from_cbor(std::vector<uint8_t>({0x82, 0x61, 0x61, 0xbf, 0x61, 0x62, 0x61, 0x63, 0xff})));
2457        CHECK(json::parse("{\"Fun\": true, \"Amt\": -2}") == json::from_cbor(std::vector<uint8_t>({0xbf, 0x63, 0x46, 0x75, 0x6e, 0xf5, 0x63, 0x41, 0x6d, 0x74, 0x21, 0xff})));
2458    }
2459}
2460
2461TEST_CASE("Tagged values")
2462{
2463    json j = "s";
2464    auto v = json::to_cbor(j);
2465
2466    SECTION("0xC6..0xD4")
2467    {
2468        for (auto b : std::vector<std::uint8_t>
2469    {
2470        0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4
2471    })
2472        {
2473            CAPTURE(b);
2474
2475            // add tag to value
2476            auto v_tagged = v;
2477            v_tagged.insert(v_tagged.begin(), b);
2478
2479            // check that parsing fails in error mode
2480            json _;
2481            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged), json::parse_error);
2482            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
2483
2484            // check that parsing succeeds and gets original value in ignore mode
2485            auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
2486            CHECK(j_tagged == j);
2487
2488            auto j_tagged_stored = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::store);
2489            CHECK(j_tagged_stored == j);
2490        }
2491    }
2492
2493    SECTION("0xD8 - 1 byte follows")
2494    {
2495        SECTION("success")
2496        {
2497            // add tag to value
2498            auto v_tagged = v;
2499            v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
2500            v_tagged.insert(v_tagged.begin(), 0xD8); // tag
2501
2502            // check that parsing fails in error mode
2503            json _;
2504            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged), json::parse_error);
2505            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
2506
2507            // check that parsing succeeds and gets original value in ignore mode
2508            auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
2509            CHECK(j_tagged == j);
2510        }
2511
2512        SECTION("missing byte after tag")
2513        {
2514            // add tag to value
2515            auto v_tagged = v;
2516            v_tagged.insert(v_tagged.begin(), 0xD8); // tag
2517
2518            // check that parsing fails in all modes
2519            json _;
2520            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged), json::parse_error);
2521            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
2522            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
2523        }
2524    }
2525
2526    SECTION("0xD9 - 2 byte follow")
2527    {
2528        SECTION("success")
2529        {
2530            // add tag to value
2531            auto v_tagged = v;
2532            v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
2533            v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
2534            v_tagged.insert(v_tagged.begin(), 0xD9); // tag
2535
2536            // check that parsing fails in error mode
2537            json _;
2538            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged), json::parse_error);
2539            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
2540
2541            // check that parsing succeeds and gets original value in ignore mode
2542            auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
2543            CHECK(j_tagged == j);
2544        }
2545
2546        SECTION("missing byte after tag")
2547        {
2548            // add tag to value
2549            auto v_tagged = v;
2550            v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
2551            v_tagged.insert(v_tagged.begin(), 0xD9); // tag
2552
2553            // check that parsing fails in all modes
2554            json _;
2555            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged), json::parse_error);
2556            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
2557            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
2558        }
2559    }
2560
2561    SECTION("0xDA - 4 bytes follow")
2562    {
2563        SECTION("success")
2564        {
2565            // add tag to value
2566            auto v_tagged = v;
2567            v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
2568            v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
2569            v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
2570            v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
2571            v_tagged.insert(v_tagged.begin(), 0xDA); // tag
2572
2573            // check that parsing fails in error mode
2574            json _;
2575            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged), json::parse_error);
2576            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
2577
2578            // check that parsing succeeds and gets original value in ignore mode
2579            auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
2580            CHECK(j_tagged == j);
2581        }
2582
2583        SECTION("missing bytes after tag")
2584        {
2585            // add tag to value
2586            auto v_tagged = v;
2587            v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
2588            v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
2589            v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
2590            v_tagged.insert(v_tagged.begin(), 0xDA); // tag
2591
2592            // check that parsing fails in all modes
2593            json _;
2594            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged), json::parse_error);
2595            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
2596            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
2597        }
2598    }
2599
2600    SECTION("0xDB - 8 bytes follow")
2601    {
2602        SECTION("success")
2603        {
2604            // add tag to value
2605            auto v_tagged = v;
2606            v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
2607            v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
2608            v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
2609            v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
2610            v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
2611            v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
2612            v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
2613            v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
2614            v_tagged.insert(v_tagged.begin(), 0xDB); // tag
2615
2616            // check that parsing fails in error mode
2617            json _;
2618            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged), json::parse_error);
2619            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
2620
2621            // check that parsing succeeds and gets original value in ignore mode
2622            auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
2623            CHECK(j_tagged == j);
2624        }
2625
2626        SECTION("missing byte after tag")
2627        {
2628            // add tag to value
2629            auto v_tagged = v;
2630            v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
2631            v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
2632            v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
2633            v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
2634            v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
2635            v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
2636            v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
2637            v_tagged.insert(v_tagged.begin(), 0xDB); // tag
2638
2639            // check that parsing fails in all modes
2640            json _;
2641            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged), json::parse_error);
2642            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
2643            CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
2644        }
2645    }
2646
2647    SECTION("tagged binary")
2648    {
2649        // create a binary value of subtype 42
2650        json j_binary;
2651        j_binary["binary"] = json::binary({0xCA, 0xFE, 0xBA, 0xBE}, 42);
2652
2653        // convert to CBOR
2654        const auto vec = json::to_cbor(j_binary);
2655        CHECK(vec == std::vector<std::uint8_t> {0xA1, 0x66, 0x62, 0x69, 0x6E, 0x61, 0x72, 0x79, 0xD8, 0x2A, 0x44, 0xCA, 0xFE, 0xBA, 0xBE});
2656
2657        // parse error when parsing tagged value
2658        json _;
2659        CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec), "[json.exception.parse_error.112] parse error at byte 9: syntax error while parsing CBOR value: invalid byte: 0xD8", json::parse_error);
2660
2661        // binary without subtype when tags are ignored
2662        json jb = json::from_cbor(vec, true, true, json::cbor_tag_handler_t::ignore);
2663        CHECK(jb.is_object());
2664        CHECK(jb["binary"].is_binary());
2665        CHECK(!jb["binary"].get_binary().has_subtype());
2666    }
2667}
2668