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:
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>;
|
||||
|
||||
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, //
|
||||
|
|
|
@ -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, //
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue