mirror of
https://github.com/transmission/transmission
synced 2024-12-22 07:42:37 +00:00
feat: support the JSON null
type in tr_variant
(#7255)
This commit is contained in:
parent
5c714a5599
commit
5a05b37838
5 changed files with 59 additions and 15 deletions
|
@ -277,6 +277,11 @@ namespace to_string_helpers
|
||||||
{
|
{
|
||||||
using OutBuf = libtransmission::StackBuffer<1024U * 8U, std::byte>;
|
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)
|
void saveIntFunc(tr_variant const& /*var*/, int64_t const val, void* vout)
|
||||||
{
|
{
|
||||||
auto out = static_cast<OutBuf*>(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;
|
using namespace to_string_helpers;
|
||||||
|
|
||||||
static auto constexpr Funcs = WalkFuncs{
|
static auto constexpr Funcs = WalkFuncs{
|
||||||
|
saveNullFunc, //
|
||||||
saveIntFunc, //
|
saveIntFunc, //
|
||||||
saveBoolFunc, //
|
saveBoolFunc, //
|
||||||
saveRealFunc, //
|
saveRealFunc, //
|
||||||
|
|
|
@ -50,7 +50,7 @@ struct json_to_variant_handler : public rapidjson::BaseReaderHandler<>
|
||||||
|
|
||||||
bool Null()
|
bool Null()
|
||||||
{
|
{
|
||||||
*get_leaf() = tr_variant::unmanaged_string("");
|
*get_leaf() = nullptr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,6 +311,11 @@ private:
|
||||||
|
|
||||||
using writer_var_t = std::variant<rapidjson::Writer<string_output_stream>, rapidjson::PrettyWriter<string_output_stream>>;
|
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)
|
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));
|
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;
|
using namespace to_string_helpers;
|
||||||
|
|
||||||
static auto constexpr Funcs = WalkFuncs{
|
static auto constexpr Funcs = WalkFuncs{
|
||||||
|
jsonNullFunc, //
|
||||||
jsonIntFunc, //
|
jsonIntFunc, //
|
||||||
jsonBoolFunc, //
|
jsonBoolFunc, //
|
||||||
jsonRealFunc, //
|
jsonRealFunc, //
|
||||||
|
|
|
@ -208,6 +208,10 @@ void tr_variant::Merge::operator()(std::monostate const& src)
|
||||||
{
|
{
|
||||||
tgt_ = src;
|
tgt_ = src;
|
||||||
}
|
}
|
||||||
|
void tr_variant::Merge::operator()(std::nullptr_t const& src)
|
||||||
|
{
|
||||||
|
tgt_ = src;
|
||||||
|
}
|
||||||
void tr_variant::Merge::operator()(bool const& src)
|
void tr_variant::Merge::operator()(bool const& src)
|
||||||
{
|
{
|
||||||
tgt_ = src;
|
tgt_ = src;
|
||||||
|
@ -761,6 +765,10 @@ void tr_variant_serde::walk(tr_variant const& top, WalkFuncs const& walk_funcs,
|
||||||
|
|
||||||
switch (variant_index(v))
|
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:
|
case tr_variant::BoolIndex:
|
||||||
walk_funcs.bool_func(*v, *v->get_if<tr_variant::BoolIndex>(), user_data);
|
walk_funcs.bool_func(*v, *v->get_if<tr_variant::BoolIndex>(), user_data);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -30,15 +30,16 @@
|
||||||
struct tr_variant
|
struct tr_variant
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Type : size_t
|
enum Type : uint8_t
|
||||||
{
|
{
|
||||||
NoneIndex = 0,
|
NoneIndex,
|
||||||
BoolIndex = 1,
|
NullIndex,
|
||||||
IntIndex = 2,
|
BoolIndex,
|
||||||
DoubleIndex = 3,
|
IntIndex,
|
||||||
StringIndex = 4,
|
DoubleIndex,
|
||||||
VectorIndex = 5,
|
StringIndex,
|
||||||
MapIndex = 6
|
VectorIndex,
|
||||||
|
MapIndex
|
||||||
};
|
};
|
||||||
|
|
||||||
using Vector = std::vector<tr_variant>;
|
using Vector = std::vector<tr_variant>;
|
||||||
|
@ -239,7 +240,11 @@ public:
|
||||||
template<typename Val>
|
template<typename Val>
|
||||||
tr_variant& operator=(Val value)
|
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 });
|
val_.emplace<StringHolder>(std::string{ value });
|
||||||
}
|
}
|
||||||
|
@ -392,6 +397,7 @@ private:
|
||||||
public:
|
public:
|
||||||
explicit Merge(tr_variant& tgt);
|
explicit Merge(tr_variant& tgt);
|
||||||
void operator()(std::monostate const& src);
|
void operator()(std::monostate const& src);
|
||||||
|
void operator()(std::nullptr_t const& src);
|
||||||
void operator()(bool const& src);
|
void operator()(bool const& src);
|
||||||
void operator()(int64_t const& src);
|
void operator()(int64_t const& src);
|
||||||
void operator()(double const& src);
|
void operator()(double const& src);
|
||||||
|
@ -403,7 +409,7 @@ private:
|
||||||
tr_variant& tgt_;
|
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<>
|
template<>
|
||||||
|
@ -567,6 +573,7 @@ private:
|
||||||
|
|
||||||
struct WalkFuncs
|
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 (*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 (*bool_func)(tr_variant const& var, bool val, void* user_data);
|
||||||
void (*double_func)(tr_variant const& var, double val, void* user_data);
|
void (*double_func)(tr_variant const& var, double val, void* user_data);
|
||||||
|
|
|
@ -61,7 +61,23 @@ TEST_P(JSONTest, testElements)
|
||||||
" \"null\": null }"
|
" \"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>();
|
auto const* const map = var.get_if<tr_variant::Map>();
|
||||||
ASSERT_NE(map, nullptr);
|
ASSERT_NE(map, nullptr);
|
||||||
|
|
||||||
|
@ -89,9 +105,10 @@ TEST_P(JSONTest, testElements)
|
||||||
ASSERT_TRUE(b);
|
ASSERT_TRUE(b);
|
||||||
EXPECT_FALSE(*b);
|
EXPECT_FALSE(*b);
|
||||||
|
|
||||||
sv = map->value_if<std::string_view>(tr_quark_new("null"sv));
|
auto n = map->value_if<std::nullptr_t>(tr_quark_new("null"sv));
|
||||||
ASSERT_TRUE(sv);
|
EXPECT_TRUE(n);
|
||||||
EXPECT_EQ(""sv, *sv);
|
|
||||||
|
EXPECT_EQ(serde.to_string(var), Out);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(JSONTest, testUtf8)
|
TEST_P(JSONTest, testUtf8)
|
||||||
|
|
Loading…
Reference in a new issue