diff --git a/.gitignore b/.gitignore index b6e98b0..87b77ae 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,6 @@ package.json package-lock.json yarn.lock pnpm-lock.yaml + +# Clangd +.cache diff --git a/include/common/utils.hpp b/include/common/utils.hpp index e7219b1..8c656e5 100644 --- a/include/common/utils.hpp +++ b/include/common/utils.hpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include namespace json { @@ -84,6 +86,11 @@ constexpr bool is_collection = false; template constexpr bool is_collection = is_container && !is_map && !is_fixed_array; +template +constexpr bool is_variant = false; +template +constexpr bool is_variant> = true; + template class has_to_json_in_member { @@ -261,4 +268,57 @@ inline string_t to_basic_string(any_t&& arg) static_assert(!sizeof(any_t), "Unsupported type"); } } + +template +bool serialize_variant_impl(basic_value& val, variant_t&& var) +{ + if (var.index() == id) { + val = basic_value(std::get(std::forward(var))); + return false; + } + return true; +} + +template +basic_value serialize_variant(variant_t&& var, std::index_sequence) +{ + basic_value val; + (serialize_variant_impl(val, std::forward(var)) && ...); + return val; +} + +template +bool deserialize_variant_impl(const basic_value& val, variant_t& var) +{ + using alt_t = std::variant_alternative_t; + if (val.template is()) { + var = val.template as(); + return false; + } + return true; +} + +template +variant_t deserialize_variant(const basic_value& val, std::index_sequence) +{ + variant_t var; + (deserialize_variant_impl(val, var) && ...); + return var; +} + +template +bool detect_variant_impl(const basic_value& val) +{ + if (val.template is()) { + return true; + } + return false; +} + +template +bool detect_variant(const basic_value& val, std::index_sequence) +{ + return (detect_variant_impl>(val) && ...); +} + } // namespace json::_utils diff --git a/include/common/value.hpp b/include/common/value.hpp index 439c5a7..99892ef 100644 --- a/include/common/value.hpp +++ b/include/common/value.hpp @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include "exception.hpp" @@ -134,6 +136,16 @@ class basic_value { } + template < + typename variant_t, + std::enable_if_t<_utils::is_variant>, bool> = true> + basic_value(variant_t&& var) + : basic_value(_utils::serialize_variant( + std::forward(var), + std::make_index_sequence>>())) + { + } + template < typename value_t, std::enable_if_t>, bool> = true> @@ -366,13 +378,21 @@ class basic_value { return as_array().template as_tuple(); } - + template explicit operator std::pair() const { return as_array().template as_pair(); } + template + explicit operator std::variant() const + { + return _utils::deserialize_variant>( + *this, + std::make_index_sequence>>()); + } + private: friend class basic_array; friend class basic_object; @@ -566,6 +586,11 @@ inline bool basic_value::is() const noexcept return is_object() && std::is_constructible_v && all(); } + else if constexpr (_utils::is_variant) { + return _utils::detect_variant( + *this, + std::make_index_sequence>()); + } else { static_assert(!sizeof(value_t), "Unsupported type"); } @@ -637,16 +662,16 @@ inline auto basic_value::get_helper( { if constexpr (std::is_constructible_v) { return is_object() ? as_object().get_helper( - default_value, - std::forward(first), - std::forward(rest)...) + default_value, + std::forward(first), + std::forward(rest)...) : default_value; } else if constexpr (std::is_integral_v>) { return is_array() ? as_array().get_helper( - default_value, - std::forward(first), - std::forward(rest)...) + default_value, + std::forward(first), + std::forward(rest)...) : default_value; } else { diff --git a/test/serializing_test.cpp b/test/serializing_test.cpp index 72492d4..53429c0 100644 --- a/test/serializing_test.cpp +++ b/test/serializing_test.cpp @@ -13,6 +13,11 @@ bool serializing() { + std::variant> var = 1; + json::value k = var; + auto var2 = k.as>>(); + auto is_var = k.is>>(); + json::value root; root["hello"] = "meojson"; @@ -286,7 +291,7 @@ bool jsonizing() mine.w = MyStruct::W::C; json::value j_mine = mine; - std::cout << j_mine<< std::endl; + std::cout << j_mine << std::endl; MyStruct new_mine = (MyStruct)j_mine;