Add binary type support to all binary file formats, as well as an internally represented binary type

This commit is contained in:
Michael Reilly 2019-07-05 00:13:25 -04:00
parent 6121fc52cf
commit 012c9665ac
21 changed files with 3008 additions and 106 deletions

Binary file not shown.

View file

@ -0,0 +1,17 @@
 













<17>ΘK€ΐxY<59>ζΏ¬?“Έ€π3"η†xU—·όF*RϊΝΟΓΥPΠgω)<29>ΘK€ΐxY<59>ζΏ¬?“Έ€π3"η†xU—·όF*RϊΝΟΓΥPΠgω)<29>ΘK€ΐxY<59>ζΏ¬?“Έ€π3"η†xU—·όF*RϊΝΟΓΥPΠgω)<29>ΘK€ΐxY<59>ζΏ¬?“Έ€π3"η†xU—·όF*RϊΝΟΓΥPΠgω)


View file

@ -492,6 +492,36 @@ TEST_CASE("BSON")
CHECK(json::from_bson(result, true, false) == j);
}
SECTION("non-empty object with binary member")
{
const size_t N = 10;
const auto s = std::vector<uint8_t>(N, 'x');
json j =
{
{ "entry", json::binary_array(s) }
};
std::vector<uint8_t> expected =
{
0x1B, 0x00, 0x00, 0x00, // size (little endian)
0x05, // entry: binary
'e', 'n', 't', 'r', 'y', '\x00',
0x0A, 0x00, 0x00, 0x00, // size of binary (little endian)
0x00, // Generic binary subtype
0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
0x00 // end marker
};
const auto result = json::to_bson(j);
CHECK(result == expected);
// roundtrip
CHECK(json::from_bson(result) == j);
CHECK(json::from_bson(result, true, false) == j);
}
SECTION("Some more complex document")
{
// directly encoding uint64 is not supported in bson (only for timestamp values)
@ -646,6 +676,11 @@ class SaxCountdown
return events_left-- > 0;
}
bool binary(std::vector<uint8_t>&)
{
return events_left-- > 0;
}
bool start_object(std::size_t)
{
return events_left-- > 0;

View file

@ -36,6 +36,7 @@ using nlohmann::json;
#include <fstream>
#include <sstream>
#include <iomanip>
#include <iostream>
#include <set>
namespace
@ -76,6 +77,11 @@ class SaxCountdown
return events_left-- > 0;
}
bool binary(std::vector<std::uint8_t>&)
{
return events_left-- > 0;
}
bool start_object(std::size_t)
{
return events_left-- > 0;
@ -1285,10 +1291,156 @@ TEST_CASE("CBOR")
CHECK(json::from_cbor(result, true, false) == j);
}
}
SECTION("binary")
{
SECTION("N = 0..23")
{
for (size_t N = 0; N <= 0x17; ++N)
{
CAPTURE(N)
// create JSON value with byte array containing of N * 'x'
const auto s = std::vector<uint8_t>(N, 'x');
json j = json::binary_array(s);
// create expected byte vector
std::vector<uint8_t> expected;
expected.push_back(static_cast<uint8_t>(0x40 + N));
for (size_t i = 0; i < N; ++i)
{
expected.push_back(0x78);
}
// compare result + size
const auto result = json::to_cbor(j);
CHECK(result == expected);
CHECK(result.size() == N + 1);
// check that no null byte is appended
if (N > 0)
{
CHECK(result.back() != '\x00');
}
// roundtrip
CHECK(json::from_cbor(result) == j);
CHECK(json::from_cbor(result, true, false) == j);
}
}
SECTION("N = 24..255")
{
for (size_t N = 24; N <= 255; ++N)
{
CAPTURE(N)
// create JSON value with string containing of N * 'x'
const auto s = std::vector<uint8_t>(N, 'x');
json j = json::binary_array(s);
// create expected byte vector
std::vector<uint8_t> expected;
expected.push_back(0x58);
expected.push_back(static_cast<uint8_t>(N));
for (size_t i = 0; i < N; ++i)
{
expected.push_back('x');
}
// compare result + size
const auto result = json::to_cbor(j);
CHECK(result == expected);
CHECK(result.size() == N + 2);
// check that no null byte is appended
CHECK(result.back() != '\x00');
// roundtrip
CHECK(json::from_cbor(result) == j);
CHECK(json::from_cbor(result, true, false) == j);
}
}
SECTION("N = 256..65535")
{
for (size_t N :
{
256u, 999u, 1025u, 3333u, 2048u, 65535u
})
{
CAPTURE(N)
// create JSON value with string containing of N * 'x'
const auto s = std::vector<uint8_t>(N, 'x');
json j = json::binary_array(s);
// create expected byte vector (hack: create string first)
std::vector<uint8_t> expected(N, 'x');
// reverse order of commands, because we insert at begin()
expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
expected.insert(expected.begin(), 0x59);
// compare result + size
const auto result = json::to_cbor(j);
CHECK(result == expected);
CHECK(result.size() == N + 3);
// check that no null byte is appended
CHECK(result.back() != '\x00');
// roundtrip
CHECK(json::from_cbor(result) == j);
CHECK(json::from_cbor(result, true, false) == j);
}
}
SECTION("N = 65536..4294967295")
{
for (size_t N :
{
65536u, 77777u, 1048576u
})
{
CAPTURE(N)
// create JSON value with string containing of N * 'x'
const auto s = std::vector<uint8_t>(N, 'x');
json j = json::binary_array(s);
// create expected byte vector (hack: create string first)
std::vector<uint8_t> expected(N, 'x');
// reverse order of commands, because we insert at begin()
expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
expected.insert(expected.begin(), static_cast<uint8_t>((N >> 16) & 0xff));
expected.insert(expected.begin(), static_cast<uint8_t>((N >> 24) & 0xff));
expected.insert(expected.begin(), 0x5a);
// compare result + size
const auto result = json::to_cbor(j);
CHECK(result == expected);
CHECK(result.size() == N + 5);
// check that no null byte is appended
CHECK(result.back() != '\x00');
// roundtrip
CHECK(json::from_cbor(result) == j);
CHECK(json::from_cbor(result, true, false) == j);
}
}
}
}
SECTION("additional deserialization")
{
SECTION("0x5b (byte array)")
{
std::vector<uint8_t> given = {0x5b, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x61
};
json j = json::from_cbor(given);
CHECK(j == json::binary_array(std::vector<uint8_t> {'a'}));
}
SECTION("0x7b (string)")
{
std::vector<uint8_t> given = {0x7b, 0x00, 0x00, 0x00, 0x00,
@ -1455,14 +1607,8 @@ TEST_CASE("CBOR")
0x1c, 0x1d, 0x1e, 0x1f,
// ?
0x3c, 0x3d, 0x3e, 0x3f,
// byte strings
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
// byte strings
0x58, 0x59, 0x5a, 0x5b,
// ?
0x5c, 0x5d, 0x5e,
// byte string
0x5f,
// ?
0x7c, 0x7d, 0x7e,
// ?
@ -1929,12 +2075,6 @@ TEST_CASE("all CBOR first bytes")
{
//// types not supported by this library
// byte strings
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
// byte strings
0x58, 0x59, 0x5a, 0x5b, 0x5f,
// date/time
0xc0, 0xc1,
// bignum
@ -2144,6 +2284,20 @@ TEST_CASE("examples from RFC 7049 Appendix A")
CHECK(json::parse("\"streaming\"") == json::from_cbor(std::vector<uint8_t>({0x7f, 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x67, 0xff})));
}
SECTION("byte arrays")
{
std::ifstream f_cbor("test/data/binary_data/cbor_binary.cbor", std::ios::binary);
std::vector<uint8_t> packed((std::istreambuf_iterator<char>(f_cbor)),
std::istreambuf_iterator<char>());
json j;
CHECK_NOTHROW(j = json::from_cbor(packed));
std::ifstream f_bin("test/data/binary_data/cbor_binary.out", std::ios::binary);
std::vector<uint8_t> expected((std::istreambuf_iterator<char>(f_bin)),
std::istreambuf_iterator<char>());
CHECK(j == json::binary_array(expected));
}
SECTION("arrays")
{
CHECK(json::to_cbor(json::parse("[]")) == std::vector<uint8_t>({0x80}));

View file

@ -77,6 +77,21 @@ class SaxEventLogger
return true;
}
bool binary(std::vector<std::uint8_t>& val)
{
std::string binary_contents = "binary(";
std::string comma_space = "";
for (auto b : val)
{
binary_contents.append(comma_space);
binary_contents.append(std::to_string(static_cast<int>(b)));
comma_space = ", ";
}
binary_contents.append(")");
events.push_back(binary_contents);
return true;
}
bool start_object(std::size_t elements)
{
if (elements == std::size_t(-1))
@ -168,6 +183,11 @@ class SaxCountdown : public nlohmann::json::json_sax_t
return events_left-- > 0;
}
bool binary(std::vector<std::uint8_t>&) override
{
return events_left-- > 0;
}
bool start_object(std::size_t) override
{
return events_left-- > 0;

View file

@ -76,6 +76,21 @@ struct SaxEventLogger : public nlohmann::json_sax<json>
return true;
}
bool binary(std::vector<std::uint8_t>& val)
{
std::string binary_contents = "binary(";
std::string comma_space = "";
for (auto b : val)
{
binary_contents.append(comma_space);
binary_contents.append(std::to_string(static_cast<int>(b)));
comma_space = ", ";
}
binary_contents.append(")");
events.push_back(binary_contents);
return true;
}
bool start_object(std::size_t elements) override
{
if (elements == std::size_t(-1))

View file

@ -75,6 +75,11 @@ class SaxCountdown
return events_left-- > 0;
}
bool binary(std::vector<std::uint8_t>&)
{
return events_left-- > 0;
}
bool start_object(std::size_t)
{
return events_left-- > 0;
@ -1115,6 +1120,261 @@ TEST_CASE("MessagePack")
CHECK(json::from_msgpack(result, true, false) == j);
}
}
SECTION("extension")
{
SECTION("N = 0..255")
{
for (size_t N = 0; N <= 0xFF; ++N)
{
CAPTURE(N)
// create JSON value with byte array containing of N * 'x'
const auto s = std::vector<uint8_t>(N, 'x');
json j = json::binary_array(s);
std::uint8_t subtype = 42;
j.set_subtype(subtype);
// create expected byte vector
std::vector<uint8_t> expected;
switch (N)
{
case 1:
expected.push_back(static_cast<std::uint8_t>(0xD4));
break;
case 2:
expected.push_back(static_cast<std::uint8_t>(0xD5));
break;
case 4:
expected.push_back(static_cast<std::uint8_t>(0xD6));
break;
case 8:
expected.push_back(static_cast<std::uint8_t>(0xD7));
break;
case 16:
expected.push_back(static_cast<std::uint8_t>(0xD8));
break;
default:
expected.push_back(static_cast<std::uint8_t>(0xC7));
expected.push_back(static_cast<std::uint8_t>(N));
break;
}
expected.push_back(subtype);
for (size_t i = 0; i < N; ++i)
{
expected.push_back(0x78);
}
// compare result + size
const auto result = json::to_msgpack(j);
CHECK(result == expected);
switch (N)
{
case 1:
case 2:
case 4:
case 8:
case 16:
CHECK(result.size() == N + 2);
break;
default:
CHECK(result.size() == N + 3);
break;
}
// check that no null byte is appended
if (N > 0)
{
CHECK(result.back() != '\x00');
}
// roundtrip
CHECK(json::from_msgpack(result) == j);
CHECK(json::from_msgpack(result, true, false) == j);
}
}
SECTION("N = 256..65535")
{
for (std::size_t N :
{
256u, 999u, 1025u, 3333u, 2048u, 65535u
})
{
CAPTURE(N)
// create JSON value with string containing of N * 'x'
const auto s = std::vector<uint8_t>(N, 'x');
json j = json::binary_array(s);
std::uint8_t subtype = 42;
j.set_subtype(subtype);
// create expected byte vector (hack: create string first)
std::vector<uint8_t> expected(N, 'x');
// reverse order of commands, because we insert at begin()
expected.insert(expected.begin(), subtype);
expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
expected.insert(expected.begin(), 0xC8);
// compare result + size
const auto result = json::to_msgpack(j);
CHECK(result == expected);
CHECK(result.size() == N + 4);
// check that no null byte is appended
CHECK(result.back() != '\x00');
// roundtrip
CHECK(json::from_msgpack(result) == j);
CHECK(json::from_msgpack(result, true, false) == j);
}
}
SECTION("N = 65536..4294967295")
{
for (std::size_t N :
{
65536u, 77777u, 1048576u
})
{
CAPTURE(N)
// create JSON value with string containing of N * 'x'
const auto s = std::vector<uint8_t>(N, 'x');
json j = json::binary_array(s);
std::uint8_t subtype = 42;
j.set_subtype(subtype);
// create expected byte vector (hack: create string first)
std::vector<uint8_t> expected(N, 'x');
// reverse order of commands, because we insert at begin()
expected.insert(expected.begin(), subtype);
expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
expected.insert(expected.begin(), static_cast<uint8_t>((N >> 16) & 0xff));
expected.insert(expected.begin(), static_cast<uint8_t>((N >> 24) & 0xff));
expected.insert(expected.begin(), 0xC9);
// compare result + size
const auto result = json::to_msgpack(j);
CHECK(result == expected);
CHECK(result.size() == N + 6);
// check that no null byte is appended
CHECK(result.back() != '\x00');
// roundtrip
CHECK(json::from_msgpack(result) == j);
CHECK(json::from_msgpack(result, true, false) == j);
}
}
}
SECTION("binary")
{
SECTION("N = 0..255")
{
for (std::size_t N = 0; N <= 0xFF; ++N)
{
CAPTURE(N)
// create JSON value with byte array containing of N * 'x'
const auto s = std::vector<uint8_t>(N, 'x');
json j = json::binary_array(s);
// create expected byte vector
std::vector<std::uint8_t> expected;
expected.push_back(static_cast<std::uint8_t>(0xC4));
expected.push_back(static_cast<std::uint8_t>(N));
for (size_t i = 0; i < N; ++i)
{
expected.push_back(0x78);
}
// compare result + size
const auto result = json::to_msgpack(j);
CHECK(result == expected);
CHECK(result.size() == N + 2);
// check that no null byte is appended
if (N > 0)
{
CHECK(result.back() != '\x00');
}
// roundtrip
CHECK(json::from_msgpack(result) == j);
CHECK(json::from_msgpack(result, true, false) == j);
}
}
SECTION("N = 256..65535")
{
for (std::size_t N :
{
256u, 999u, 1025u, 3333u, 2048u, 65535u
})
{
CAPTURE(N)
// create JSON value with string containing of N * 'x'
const auto s = std::vector<std::uint8_t>(N, 'x');
json j = json::binary_array(s);
// create expected byte vector (hack: create string first)
std::vector<std::uint8_t> expected(N, 'x');
// reverse order of commands, because we insert at begin()
expected.insert(expected.begin(), static_cast<std::uint8_t>(N & 0xff));
expected.insert(expected.begin(), static_cast<std::uint8_t>((N >> 8) & 0xff));
expected.insert(expected.begin(), 0xC5);
// compare result + size
const auto result = json::to_msgpack(j);
CHECK(result == expected);
CHECK(result.size() == N + 3);
// check that no null byte is appended
CHECK(result.back() != '\x00');
// roundtrip
CHECK(json::from_msgpack(result) == j);
CHECK(json::from_msgpack(result, true, false) == j);
}
}
SECTION("N = 65536..4294967295")
{
for (std::size_t N :
{
65536u, 77777u, 1048576u
})
{
CAPTURE(N)
// create JSON value with string containing of N * 'x'
const auto s = std::vector<std::uint8_t>(N, 'x');
json j = json::binary_array(s);
// create expected byte vector (hack: create string first)
std::vector<uint8_t> expected(N, 'x');
// reverse order of commands, because we insert at begin()
expected.insert(expected.begin(), static_cast<std::uint8_t>(N & 0xff));
expected.insert(expected.begin(), static_cast<std::uint8_t>((N >> 8) & 0xff));
expected.insert(expected.begin(), static_cast<std::uint8_t>((N >> 16) & 0xff));
expected.insert(expected.begin(), static_cast<std::uint8_t>((N >> 24) & 0xff));
expected.insert(expected.begin(), 0xC6);
// compare result + size
const auto result = json::to_msgpack(j);
CHECK(result == expected);
CHECK(result.size() == N + 5);
// check that no null byte is appended
CHECK(result.back() != '\x00');
// roundtrip
CHECK(json::from_msgpack(result) == j);
CHECK(json::from_msgpack(result, true, false) == j);
}
}
}
}
SECTION("from float32")
@ -1226,12 +1486,6 @@ TEST_CASE("MessagePack")
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xc1})), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0xc1})),
"[json.exception.parse_error.112] parse error at byte 1: syntax error while parsing MessagePack value: invalid byte: 0xC1");
CHECK(json::from_msgpack(std::vector<uint8_t>({0xc6}), true, false).is_discarded());
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xc6})), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0xc6})),
"[json.exception.parse_error.112] parse error at byte 1: syntax error while parsing MessagePack value: invalid byte: 0xC6");
CHECK(json::from_msgpack(std::vector<uint8_t>({0xc6}), true, false).is_discarded());
}
SECTION("all unsupported bytes")
@ -1239,13 +1493,7 @@ TEST_CASE("MessagePack")
for (auto byte :
{
// never used
0xc1,
// bin
0xc4, 0xc5, 0xc6,
// ext
0xc7, 0xc8, 0xc9,
// fixext
0xd4, 0xd5, 0xd6, 0xd7, 0xd8
0xc1
})
{
json _;

View file

@ -107,7 +107,7 @@ struct foo_serializer < T, typename std::enable_if < !std::is_same<foo, T>::valu
}
using foo_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t,
std::uint64_t, double, std::allocator, ns::foo_serializer>;
std::uint64_t, double, std::allocator, ns::foo_serializer, std::vector<std::uint8_t>>;
/////////////////////////////////////////////////////////////////////
// for #805

View file

@ -73,6 +73,11 @@ class SaxCountdown
return events_left-- > 0;
}
bool binary(std::vector<std::uint8_t>&)
{
return events_left-- > 0;
}
bool start_object(std::size_t)
{
return events_left-- > 0;
@ -905,6 +910,231 @@ TEST_CASE("UBJSON")
}
}
SECTION("binary")
{
SECTION("N = 0..127")
{
for (std::size_t N = 0; N <= 127; ++N)
{
CAPTURE(N)
// create JSON value with byte array containing of N * 'x'
const auto s = std::vector<std::uint8_t>(N, 'x');
json j = json::binary_array(s);
// create expected byte vector
std::vector<std::uint8_t> expected;
expected.push_back(static_cast<std::uint8_t>('['));
if (N != 0)
{
expected.push_back(static_cast<std::uint8_t>('$'));
expected.push_back(static_cast<std::uint8_t>('U'));
}
expected.push_back(static_cast<std::uint8_t>('#'));
expected.push_back(static_cast<std::uint8_t>('i'));
expected.push_back(static_cast<std::uint8_t>(N));
for (size_t i = 0; i < N; ++i)
{
expected.push_back(0x78);
}
// compare result + size
const auto result = json::to_ubjson(j, true, true);
CHECK(result == expected);
if (N == 0)
{
CHECK(result.size() == N + 4);
}
else
{
CHECK(result.size() == N + 6);
}
// check that no null byte is appended
if (N > 0)
{
CHECK(result.back() != '\x00');
}
// roundtrip only works to an array of numbers
json j_out = s;
CHECK(json::from_ubjson(result) == j_out);
CHECK(json::from_ubjson(result, true, false) == j_out);
}
}
SECTION("N = 128..255")
{
for (std::size_t N = 128; N <= 255; ++N)
{
CAPTURE(N)
// create JSON value with byte array containing of N * 'x'
const auto s = std::vector<std::uint8_t>(N, 'x');
json j = json::binary_array(s);
// create expected byte vector
std::vector<uint8_t> expected;
expected.push_back(static_cast<std::uint8_t>('['));
expected.push_back(static_cast<std::uint8_t>('$'));
expected.push_back(static_cast<std::uint8_t>('U'));
expected.push_back(static_cast<std::uint8_t>('#'));
expected.push_back(static_cast<std::uint8_t>('U'));
expected.push_back(static_cast<std::uint8_t>(N));
for (size_t i = 0; i < N; ++i)
{
expected.push_back(0x78);
}
// compare result + size
const auto result = json::to_ubjson(j, true, true);
CHECK(result == expected);
CHECK(result.size() == N + 6);
// check that no null byte is appended
CHECK(result.back() != '\x00');
// roundtrip only works to an array of numbers
json j_out = s;
CHECK(json::from_ubjson(result) == j_out);
CHECK(json::from_ubjson(result, true, false) == j_out);
}
}
SECTION("N = 256..32767")
{
for (std::size_t N :
{
256u, 999u, 1025u, 3333u, 2048u, 32767u
})
{
CAPTURE(N)
// create JSON value with byte array containing of N * 'x'
const auto s = std::vector<std::uint8_t>(N, 'x');
json j = json::binary_array(s);
// create expected byte vector
std::vector<std::uint8_t> expected(N + 7, 'x');
expected[0] = '[';
expected[1] = '$';
expected[2] = 'U';
expected[3] = '#';
expected[4] = 'I';
expected[5] = static_cast<std::uint8_t>((N >> 8) & 0xFF);
expected[6] = static_cast<std::uint8_t>(N & 0xFF);
// compare result + size
const auto result = json::to_ubjson(j, true, true);
CHECK(result == expected);
CHECK(result.size() == N + 7);
// check that no null byte is appended
CHECK(result.back() != '\x00');
// roundtrip only works to an array of numbers
json j_out = s;
CHECK(json::from_ubjson(result) == j_out);
CHECK(json::from_ubjson(result, true, false) == j_out);
}
}
SECTION("N = 32768..2147483647")
{
for (std::size_t N :
{
32768u, 77777u, 1048576u
})
{
CAPTURE(N)
// create JSON value with byte array containing of N * 'x'
const auto s = std::vector<std::uint8_t>(N, 'x');
json j = json::binary_array(s);
// create expected byte vector
std::vector<std::uint8_t> expected(N + 9, 'x');
expected[0] = '[';
expected[1] = '$';
expected[2] = 'U';
expected[3] = '#';
expected[4] = 'l';
expected[5] = static_cast<std::uint8_t>((N >> 24) & 0xFF);
expected[6] = static_cast<std::uint8_t>((N >> 16) & 0xFF);
expected[7] = static_cast<std::uint8_t>((N >> 8) & 0xFF);
expected[8] = static_cast<std::uint8_t>(N & 0xFF);
// compare result + size
const auto result = json::to_ubjson(j, true, true);
CHECK(result == expected);
CHECK(result.size() == N + 9);
// check that no null byte is appended
CHECK(result.back() != '\x00');
// roundtrip only works to an array of numbers
json j_out = s;
CHECK(json::from_ubjson(result) == j_out);
CHECK(json::from_ubjson(result, true, false) == j_out);
}
}
SECTION("Other Serializations")
{
const std::size_t N = 10;
const auto s = std::vector<std::uint8_t>(N, 'x');
json j = json::binary_array(s);
SECTION("No Count No Type")
{
std::vector<uint8_t> expected;
expected.push_back(static_cast<std::uint8_t>('['));
for (std::size_t i = 0; i < N; ++i)
{
expected.push_back(static_cast<std::uint8_t>('U'));
expected.push_back(static_cast<std::uint8_t>(0x78));
}
expected.push_back(static_cast<std::uint8_t>(']'));
// compare result + size
const auto result = json::to_ubjson(j, false, false);
CHECK(result == expected);
CHECK(result.size() == N + 12);
// check that no null byte is appended
CHECK(result.back() != '\x00');
// roundtrip only works to an array of numbers
json j_out = s;
CHECK(json::from_ubjson(result) == j_out);
CHECK(json::from_ubjson(result, true, false) == j_out);
}
SECTION("Yes Count No Type")
{
std::vector<std::uint8_t> expected;
expected.push_back(static_cast<std::uint8_t>('['));
expected.push_back(static_cast<std::uint8_t>('#'));
expected.push_back(static_cast<std::uint8_t>('i'));
expected.push_back(static_cast<std::uint8_t>(N));
for (size_t i = 0; i < N; ++i)
{
expected.push_back(static_cast<std::uint8_t>('U'));
expected.push_back(static_cast<std::uint8_t>(0x78));
}
// compare result + size
const auto result = json::to_ubjson(j, true, false);
CHECK(result == expected);
CHECK(result.size() == N + 14);
// check that no null byte is appended
CHECK(result.back() != '\x00');
// roundtrip only works to an array of numbers
json j_out = s;
CHECK(json::from_ubjson(result) == j_out);
CHECK(json::from_ubjson(result, true, false) == j_out);
}
}
}
SECTION("array")
{
SECTION("empty")

View file

@ -653,8 +653,7 @@ TEST_CASE("custom serializer for pods" * doctest::test_suite("udt"))
{
using custom_json =
nlohmann::basic_json<std::map, std::vector, std::string, bool,
std::int64_t, std::uint64_t, double, std::allocator,
pod_serializer>;
std::int64_t, std::uint64_t, double, std::allocator, pod_serializer>;
auto p = udt::small_pod{42, '/', 42};
custom_json j = p;