1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2024-12-21 15:22:37 +00:00

feat: support the JSON null type in tr_variant (#7255)

This commit is contained in:
Yat Ho 2024-12-16 06:50:19 +08:00 committed by GitHub
parent 5c714a5599
commit 5a05b37838
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 59 additions and 15 deletions

View file

@ -277,6 +277,11 @@ namespace to_string_helpers
{
using OutBuf = libtransmission::StackBuffer<1024U * 8U, std::byte>;
void saveNullFunc(tr_variant const& /*var*/, std::nullptr_t /*val*/, void* vout)
{
static_cast<OutBuf*>(vout)->add("0:"sv);
}
void saveIntFunc(tr_variant const& /*var*/, int64_t const val, void* vout)
{
auto out = static_cast<OutBuf*>(vout);
@ -338,6 +343,7 @@ std::string tr_variant_serde::to_benc_string(tr_variant const& var)
using namespace to_string_helpers;
static auto constexpr Funcs = WalkFuncs{
saveNullFunc, //
saveIntFunc, //
saveBoolFunc, //
saveRealFunc, //

View file

@ -50,7 +50,7 @@ struct json_to_variant_handler : public rapidjson::BaseReaderHandler<>
bool Null()
{
*get_leaf() = tr_variant::unmanaged_string("");
*get_leaf() = nullptr;
return true;
}
@ -311,6 +311,11 @@ private:
using writer_var_t = std::variant<rapidjson::Writer<string_output_stream>, rapidjson::PrettyWriter<string_output_stream>>;
void jsonNullFunc(tr_variant const& /*var*/, std::nullptr_t /*val*/, void* vdata)
{
std::visit([](auto&& writer) { writer.Null(); }, *static_cast<writer_var_t*>(vdata));
}
void jsonIntFunc(tr_variant const& /*var*/, int64_t const val, void* vdata)
{
std::visit([val](auto&& writer) { writer.Int64(val); }, *static_cast<writer_var_t*>(vdata));
@ -363,6 +368,7 @@ std::string tr_variant_serde::to_json_string(tr_variant const& var) const
using namespace to_string_helpers;
static auto constexpr Funcs = WalkFuncs{
jsonNullFunc, //
jsonIntFunc, //
jsonBoolFunc, //
jsonRealFunc, //

View file

@ -208,6 +208,10 @@ void tr_variant::Merge::operator()(std::monostate const& src)
{
tgt_ = src;
}
void tr_variant::Merge::operator()(std::nullptr_t const& src)
{
tgt_ = src;
}
void tr_variant::Merge::operator()(bool const& src)
{
tgt_ = src;
@ -761,6 +765,10 @@ void tr_variant_serde::walk(tr_variant const& top, WalkFuncs const& walk_funcs,
switch (variant_index(v))
{
case tr_variant::NullIndex:
walk_funcs.null_func(*v, *v->get_if<tr_variant::NullIndex>(), user_data);
break;
case tr_variant::BoolIndex:
walk_funcs.bool_func(*v, *v->get_if<tr_variant::BoolIndex>(), user_data);
break;

View file

@ -30,15 +30,16 @@
struct tr_variant
{
public:
enum Type : size_t
enum Type : uint8_t
{
NoneIndex = 0,
BoolIndex = 1,
IntIndex = 2,
DoubleIndex = 3,
StringIndex = 4,
VectorIndex = 5,
MapIndex = 6
NoneIndex,
NullIndex,
BoolIndex,
IntIndex,
DoubleIndex,
StringIndex,
VectorIndex,
MapIndex
};
using Vector = std::vector<tr_variant>;
@ -239,7 +240,11 @@ public:
template<typename Val>
tr_variant& operator=(Val value)
{
if constexpr (std::is_same_v<Val, std::string_view>)
if constexpr (std::is_same_v<Val, std::nullptr_t>)
{
val_.emplace<std::nullptr_t>(value);
}
else if constexpr (std::is_same_v<Val, std::string_view>)
{
val_.emplace<StringHolder>(std::string{ value });
}
@ -392,6 +397,7 @@ private:
public:
explicit Merge(tr_variant& tgt);
void operator()(std::monostate const& src);
void operator()(std::nullptr_t const& src);
void operator()(bool const& src);
void operator()(int64_t const& src);
void operator()(double const& src);
@ -403,7 +409,7 @@ private:
tr_variant& tgt_;
};
std::variant<std::monostate, bool, int64_t, double, StringHolder, Vector, Map> val_;
std::variant<std::monostate, std::nullptr_t, bool, int64_t, double, StringHolder, Vector, Map> val_;
};
template<>
@ -567,6 +573,7 @@ private:
struct WalkFuncs
{
void (*null_func)(tr_variant const& var, std::nullptr_t val, void* user_data);
void (*int_func)(tr_variant const& var, int64_t val, void* user_data);
void (*bool_func)(tr_variant const& var, bool val, void* user_data);
void (*double_func)(tr_variant const& var, double val, void* user_data);

View file

@ -61,7 +61,23 @@ TEST_P(JSONTest, testElements)
" \"null\": null }"
};
auto const var = tr_variant_serde::json().inplace().parse(In).value_or(tr_variant{});
// Same as In, just formatted differently
static auto constexpr Out = std::string_view{
// clang-format off
"{"
"\"escaped\":\"bell \\b formfeed \\f linefeed \\n carriage return \\r tab \\t\","
"\"false\":false,"
"\"float\":6.5,"
"\"int\":5,"
"\"null\":null,"
"\"string\":\"hello world\","
"\"true\":true"
"}"
// clang-format on
};
auto serde = tr_variant_serde::json().inplace().compact();
auto var = serde.parse(In).value_or(tr_variant{});
auto const* const map = var.get_if<tr_variant::Map>();
ASSERT_NE(map, nullptr);
@ -89,9 +105,10 @@ TEST_P(JSONTest, testElements)
ASSERT_TRUE(b);
EXPECT_FALSE(*b);
sv = map->value_if<std::string_view>(tr_quark_new("null"sv));
ASSERT_TRUE(sv);
EXPECT_EQ(""sv, *sv);
auto n = map->value_if<std::nullptr_t>(tr_quark_new("null"sv));
EXPECT_TRUE(n);
EXPECT_EQ(serde.to_string(var), Out);
}
TEST_P(JSONTest, testUtf8)