mirror of
https://github.com/nlohmann/json.git
synced 2025-08-07 18:02:57 +03:00
* Specialize char_traits for std::byte to fix from_msgpack (fixes #4756) Provide a char_traits<std::byte> specialization under __cpp_lib_byte to allow parsing MessagePack data from containers of std::byte. Signed-off-by: xuesongtap <tap91624@gmail.com> Signed-off-by: yexiaochuan <tap91624@gmail.com> * Fix comments for cstddef include and MessagePack tests Signed-off-by: xuesongtap <tap91624@gmail.com> Signed-off-by: yexiaochuan <tap91624@gmail.com> * Fix include <cstddef> only when __cpp_lib_byte is defined and sufficient Signed-off-by: yexiaochuan <tap91624@gmail.com> * Fix clang-tidy warnings in MessagePack std::byte tests Signed-off-by: yexiaochuan <tap91624@gmail.com> * Fix handle return value in MessagePack tests Signed-off-by: yexiaochuan <tap91624@gmail.com> --------- Signed-off-by: xuesongtap <tap91624@gmail.com> Signed-off-by: yexiaochuan <tap91624@gmail.com>
This commit is contained in:
@@ -13,7 +13,9 @@
|
||||
#include <tuple> // tuple
|
||||
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
|
||||
#include <utility> // declval
|
||||
|
||||
#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
|
||||
#include <cstddef> // byte
|
||||
#endif
|
||||
#include <nlohmann/detail/iterators/iterator_traits.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
#include <nlohmann/detail/meta/call_std/begin.hpp>
|
||||
@@ -239,6 +241,30 @@ struct char_traits<signed char> : std::char_traits<char>
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
|
||||
template<>
|
||||
struct char_traits<std::byte> : std::char_traits<char>
|
||||
{
|
||||
using char_type = std::byte;
|
||||
using int_type = uint64_t;
|
||||
|
||||
static int_type to_int_type(char_type c) noexcept
|
||||
{
|
||||
return static_cast<int_type>(std::to_integer<unsigned char>(c));
|
||||
}
|
||||
|
||||
static char_type to_char_type(int_type i) noexcept
|
||||
{
|
||||
return std::byte(static_cast<unsigned char>(i));
|
||||
}
|
||||
|
||||
static constexpr int_type eof() noexcept
|
||||
{
|
||||
return static_cast<int_type>(std::char_traits<char>::eof());
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
///////////////////
|
||||
// is_ functions //
|
||||
///////////////////
|
||||
|
@@ -3367,7 +3367,9 @@ NLOHMANN_JSON_NAMESPACE_END
|
||||
#include <tuple> // tuple
|
||||
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
|
||||
#include <utility> // declval
|
||||
|
||||
#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
|
||||
#include <cstddef> // byte
|
||||
#endif
|
||||
// #include <nlohmann/detail/iterators/iterator_traits.hpp>
|
||||
// __ _____ _____ _____
|
||||
// __| | __| | | | JSON for Modern C++
|
||||
@@ -3776,6 +3778,30 @@ struct char_traits<signed char> : std::char_traits<char>
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
|
||||
template<>
|
||||
struct char_traits<std::byte> : std::char_traits<char>
|
||||
{
|
||||
using char_type = std::byte;
|
||||
using int_type = uint64_t;
|
||||
|
||||
static int_type to_int_type(char_type c) noexcept
|
||||
{
|
||||
return static_cast<int_type>(std::to_integer<unsigned char>(c));
|
||||
}
|
||||
|
||||
static char_type to_char_type(int_type i) noexcept
|
||||
{
|
||||
return std::byte(static_cast<unsigned char>(i));
|
||||
}
|
||||
|
||||
static constexpr int_type eof() noexcept
|
||||
{
|
||||
return static_cast<int_type>(std::char_traits<char>::eof());
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
///////////////////
|
||||
// is_ functions //
|
||||
///////////////////
|
||||
|
@@ -1880,3 +1880,80 @@ TEST_CASE("MessagePack roundtrips" * doctest::skip())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
// Test suite for verifying MessagePack handling with std::byte input
|
||||
TEST_CASE("MessagePack with std::byte")
|
||||
{
|
||||
|
||||
SECTION("std::byte compatibility")
|
||||
{
|
||||
SECTION("vector roundtrip")
|
||||
{
|
||||
json original =
|
||||
{
|
||||
{"name", "test"},
|
||||
{"value", 42},
|
||||
{"array", {1, 2, 3}}
|
||||
};
|
||||
|
||||
std::vector<uint8_t> temp = json::to_msgpack(original);
|
||||
// Convert the uint8_t vector to std::byte vector
|
||||
std::vector<std::byte> msgpack_data(temp.size());
|
||||
for (size_t i = 0; i < temp.size(); ++i)
|
||||
{
|
||||
msgpack_data[i] = std::byte(temp[i]);
|
||||
}
|
||||
// Deserialize from std::byte vector back to JSON
|
||||
json from_bytes;
|
||||
CHECK_NOTHROW(from_bytes = json::from_msgpack(msgpack_data));
|
||||
|
||||
CHECK(from_bytes == original);
|
||||
}
|
||||
|
||||
SECTION("empty vector")
|
||||
{
|
||||
const std::vector<std::byte> empty_data;
|
||||
CHECK_THROWS_WITH_AS([&]() {
|
||||
[[maybe_unused]] auto result = json::from_msgpack(empty_data);
|
||||
return true;
|
||||
}(),
|
||||
"[json.exception.parse_error.110] parse error at byte 1: syntax error while parsing MessagePack value: unexpected end of input",
|
||||
json::parse_error&);
|
||||
}
|
||||
|
||||
SECTION("comparison with workaround")
|
||||
{
|
||||
json original =
|
||||
{
|
||||
{"string", "hello"},
|
||||
{"integer", 42},
|
||||
{"float", 3.14},
|
||||
{"boolean", true},
|
||||
{"null", nullptr},
|
||||
{"array", {1, 2, 3}},
|
||||
{"object", {{"key", "value"}}}
|
||||
};
|
||||
|
||||
std::vector<uint8_t> temp = json::to_msgpack(original);
|
||||
|
||||
std::vector<std::byte> msgpack_data(temp.size());
|
||||
for (size_t i = 0; i < temp.size(); ++i)
|
||||
{
|
||||
msgpack_data[i] = std::byte(temp[i]);
|
||||
}
|
||||
// Attempt direct deserialization using std::byte input
|
||||
json direct_result = json::from_msgpack(msgpack_data);
|
||||
|
||||
// Test the workaround approach: reinterpret as unsigned char* and use iterator range
|
||||
const auto *const char_start = reinterpret_cast<unsigned char const*>(msgpack_data.data());
|
||||
const auto *const char_end = char_start + msgpack_data.size();
|
||||
json workaround_result = json::from_msgpack(char_start, char_end);
|
||||
|
||||
// Verify that the final deserialized JSON matches the original JSON
|
||||
CHECK(direct_result == workaround_result);
|
||||
CHECK(direct_result == original);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user