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