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