diff --git a/docs/mkdocs/docs/features/binary_formats/cbor.md b/docs/mkdocs/docs/features/binary_formats/cbor.md index 5952bce39..670a23455 100644 --- a/docs/mkdocs/docs/features/binary_formats/cbor.md +++ b/docs/mkdocs/docs/features/binary_formats/cbor.md @@ -160,14 +160,11 @@ The library maps CBOR types to JSON value types as follows: The mapping is **incomplete** in the sense that not all CBOR types can be converted to a JSON value. The following CBOR types are not supported and will yield parse errors: - - date/time (0xC0..0xC1) - - bignum (0xC2..0xC3) - - decimal fraction (0xC4) - - bigfloat (0xC5) - - expected conversions (0xD5..0xD7) - simple values (0xE0..0xF3, 0xF8) - undefined (0xF7) + Tagged items (0xC0..0xDB) are not interpreted either; see the note on tagged items below. + !!! warning "Negative integer overflow" CBOR negative integers (major type 1) are decoded as `-1 - n`. If the encoded magnitude `n` is too large for the @@ -181,7 +178,7 @@ The library maps CBOR types to JSON value types as follows: !!! warning "Tagged items" - Tagged items will throw a parse error by default. They can be ignored by passing `cbor_tag_handler_t::ignore` to function `from_cbor`. They can be stored by passing `cbor_tag_handler_t::store` to function `from_cbor`. + Tagged items (0xC0..0xDB) will throw a parse error by default. They can be ignored by passing `cbor_tag_handler_t::ignore` to function `from_cbor`, in which case the tag is skipped and the enclosed data item is parsed on its own. They can be stored by passing `cbor_tag_handler_t::store` to function `from_cbor`. Note that no tag is ever interpreted: for instance, a text string tagged with tag 0 (date/time) stays a string. ??? example diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index e3574d778..557d7669c 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -773,7 +773,13 @@ class binary_reader case 0xBF: // map (indefinite length) return get_cbor_object(detail::unknown_size(), tag_handler); - case 0xC6: // tagged item + case 0xC0: // tagged item + case 0xC1: + case 0xC2: + case 0xC3: + case 0xC4: + case 0xC5: + case 0xC6: case 0xC7: case 0xC8: case 0xC9: @@ -788,6 +794,9 @@ class binary_reader case 0xD2: case 0xD3: case 0xD4: + case 0xD5: + case 0xD6: + case 0xD7: case 0xD8: // tagged item (1 byte follows) case 0xD9: // tagged item (2 bytes follow) case 0xDA: // tagged item (4 bytes follow) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index fff350ee4..0ea563fb9 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -11395,7 +11395,13 @@ class binary_reader case 0xBF: // map (indefinite length) return get_cbor_object(detail::unknown_size(), tag_handler); - case 0xC6: // tagged item + case 0xC0: // tagged item + case 0xC1: + case 0xC2: + case 0xC3: + case 0xC4: + case 0xC5: + case 0xC6: case 0xC7: case 0xC8: case 0xC9: @@ -11410,6 +11416,9 @@ class binary_reader case 0xD2: case 0xD3: case 0xD4: + case 0xD5: + case 0xD6: + case 0xD7: case 0xD8: // tagged item (1 byte follows) case 0xD9: // tagged item (2 bytes follow) case 0xDA: // tagged item (4 bytes follow) diff --git a/tests/src/unit-cbor.cpp b/tests/src/unit-cbor.cpp index 1b4b95dbf..2a6bd41d7 100644 --- a/tests/src/unit-cbor.cpp +++ b/tests/src/unit-cbor.cpp @@ -2565,11 +2565,16 @@ TEST_CASE("Tagged values") const json j = "s"; auto v = json::to_cbor(j); - SECTION("0xC6..0xD4") + const json j_bin_payload = json::binary(std::vector {0x01, 0x02, 0x03}); + auto v_bin_payload = json::to_cbor(j_bin_payload); + + SECTION("0xC0..0xD7") { for (const auto b : std::vector { - 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4 + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, + 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, + 0xD5, 0xD6, 0xD7 }) { CAPTURE(b); @@ -2589,6 +2594,12 @@ TEST_CASE("Tagged values") auto j_tagged_stored = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::store); CHECK(j_tagged_stored == j); + + auto v_binary_tagged = v_bin_payload; + v_binary_tagged.insert(v_binary_tagged.begin(), b); + auto j_binary_tagged_stored = json::from_cbor(v_binary_tagged, true, true, json::cbor_tag_handler_t::store); + CHECK(j_binary_tagged_stored == j_bin_payload); + CHECK(!j_binary_tagged_stored.get_binary().has_subtype()); } }