diff options
| -rw-r--r-- | libnvxx/Makefile | 3 | ||||
| -rw-r--r-- | libnvxx/nvxx_serialize.cc | 113 | ||||
| -rw-r--r-- | libnvxx/nvxx_serialize.h | 203 | ||||
| -rw-r--r-- | libnvxx/tests/nvxx_serialize.cc | 60 |
4 files changed, 162 insertions, 217 deletions
diff --git a/libnvxx/Makefile b/libnvxx/Makefile index 473315a..a48ab01 100644 --- a/libnvxx/Makefile +++ b/libnvxx/Makefile @@ -16,8 +16,7 @@ INCS= nvxx.h \ SRCS= nvxx.cc \ nv_list.cc \ const_nv_list.cc \ - nvxx_iterator.cc \ - nvxx_serialize.cc + nvxx_iterator.cc CXXSTD= c++23 CXXFLAGS+= -W -Wall -Wextra -Werror LDADD= -lnv diff --git a/libnvxx/nvxx_serialize.cc b/libnvxx/nvxx_serialize.cc deleted file mode 100644 index 8325d40..0000000 --- a/libnvxx/nvxx_serialize.cc +++ /dev/null @@ -1,113 +0,0 @@ -/* - * SPDX-License-Identifier: Unlicense OR MIT - * Refer to the file 'LICENSE' in the nvxx distribution for license terms. - */ - -#include "nvxx.h" - -namespace bsd { - -/* - * type encoders/decoders - */ - -/* bool */ - -void -nv_encoder<bool>::encode(nv_list &nvl, std::string_view key, bool value) -{ - nvl.add_bool(key, value); -} - -bool -nv_decoder<bool>::decode(const_nv_list const &nvl, std::string_view key) -{ - return (nvl.get_bool(key)); -} - -/* uint64_t */ - -void -nv_encoder<std::uint64_t>::encode(nv_list &nvl, - std::string_view key, - std::uint64_t value) -{ - nvl.add_number(key, value); -} - -std::uint64_t -nv_decoder<std::uint64_t>::decode(const_nv_list const &nvl, - std::string_view key) -{ - return (nvl.get_number(key)); -} - -/* string */ - -void -nv_encoder<std::string>::encode(nv_list &nvl, - std::string_view key, - std::string const &value) -{ - nvl.add_string(key, value); -} - -std::string -nv_decoder<std::string>::decode(const_nv_list const &nvl, - std::string_view key) -{ - return (std::string(nvl.get_string(key))); -} - -/* string_view */ - -void -nv_encoder<std::string_view>::encode(nv_list &nvl, - std::string_view key, - std::string_view value) -{ - nvl.add_string(key, value); -} - -std::string_view -nv_decoder<std::string_view>::decode(const_nv_list const &nvl, - std::string_view key) -{ - return (nvl.get_string(key)); -} - -/* nv_list */ - -void -nv_encoder<nv_list>::encode(nv_list &nvl, - std::string_view key, - nv_list const &value) -{ - nvl.add_nvlist(key, value); -} - -nv_list -nv_decoder<nv_list>::decode(const_nv_list const &nvl, - std::string_view key) -{ - return (nv_list(nvl.get_nvlist(key))); -} - -/* const_nv_list */ - -void -nv_encoder<const_nv_list>::encode(nv_list &nvl, - std::string_view key, - const_nv_list const &value) -{ - nvl.add_nvlist(key, value); -} - -const_nv_list -nv_decoder<const_nv_list>::decode(const_nv_list const &nvl, - std::string_view key) -{ - return (nvl.get_nvlist(key)); -} - -} // namespace bsd diff --git a/libnvxx/nvxx_serialize.h b/libnvxx/nvxx_serialize.h index b0a161f..dd2f22b 100644 --- a/libnvxx/nvxx_serialize.h +++ b/libnvxx/nvxx_serialize.h @@ -53,31 +53,27 @@ concept __push_back_container_of = template<typename T> struct nv_encoder; -template<typename T> -struct nv_decoder; /* bool */ template<> struct nv_encoder<bool> { - void encode(nv_list &, std::string_view, bool); + void encode(nv_list &__nvl, std::string_view __key, bool __value) { + __nvl.add_bool(__key, __value); + } + + auto decode(const_nv_list const &__nvl, std::string_view __key) -> bool { + return (__nvl.get_bool(__key)); + } }; -template<__detail::__range_of<bool> _R> -struct nv_encoder<_R> { +template<__detail::__from_range_container_of<bool> _C> +struct nv_encoder<_C> { template<typename _U> void encode(nv_list &__nvl, std::string_view __key, _U &&__range) { __nvl.add_bool_range(__key, std::forward<_U>(__range)); } -}; -template<> -struct nv_decoder<bool> { - auto decode(const_nv_list const &, std::string_view) -> bool; -}; - -template<__detail::__from_range_container_of<bool> _C> -struct nv_decoder<_C> { auto decode(const_nv_list const &__nvl, std::string_view __key) -> _C { return (_C(std::from_range, __nvl.get_bool_array(__key))); } @@ -87,24 +83,25 @@ struct nv_decoder<_C> { template<> struct nv_encoder<std::uint64_t> { - void encode(nv_list &, std::string_view, std::uint64_t); + void encode(nv_list &__nvl, + std::string_view __key, + std::uint64_t __value) { + __nvl.add_number(__key, __value); + } + + std::uint64_t decode(const_nv_list const &__nvl, + std::string_view __key) { + return __nvl.get_number(__key); + } }; -template<__detail::__range_of<std::uint64_t> _R> -struct nv_encoder<_R> { +template<__detail::__from_range_container_of<std::uint64_t> _C> +struct nv_encoder<_C> { template<typename _U> void encode(nv_list &__nvl, std::string_view __key, _U &&__range) { __nvl.add_number_range(__key, std::forward<_U>(__range)); } -}; -template<> -struct nv_decoder<std::uint64_t> { - auto decode(const_nv_list const &, std::string_view) -> std::uint64_t; -}; - -template<__detail::__from_range_container_of<std::uint64_t> _C> -struct nv_decoder<_C> { auto decode(const_nv_list const &__nvl, std::string_view __key) -> _C { return (_C(std::from_range, __nvl.get_number_array(__key))); } @@ -114,11 +111,20 @@ struct nv_decoder<_C> { template<> struct nv_encoder<std::string> { - void encode(nv_list &, std::string_view, std::string const &); + void encode(nv_list &__nvl, + std::string_view __key, + std::string const &__value) { + __nvl.add_string(__key, __value); + } + + std::string decode(const_nv_list const &__nvl, + std::string_view __key) { + return std::string(__nvl.get_string(__key)); + } }; -template<__detail::__range_of<std::string> _R> -struct nv_encoder<_R> { +template<__detail::__from_range_container_of<std::string> _C> +struct nv_encoder<_C> { template<typename _U> void encode(nv_list &__nvl, std::string_view __key, _U &&__range) { __nvl.add_string_range(__key, @@ -126,21 +132,14 @@ struct nv_encoder<_R> { return (std::string_view(__s)); })); } -}; - -template<> -struct nv_decoder<std::string> { - auto decode(const_nv_list const &, std::string_view) -> std::string; -}; -template<__detail::__from_range_container_of<std::string> _C> -struct nv_decoder<_C> { - auto decode(const_nv_list const &__nvl, std::string_view __key) -> _C { - return (_C(std::from_range, + _C decode(const_nv_list const &__nvl, std::string_view __key) { + auto __strings = __nvl.get_string_array(__key) | std::views::transform([] (auto const &__s) { return std::string(__s); - }))); + }); + return {std::from_range, __strings}; } }; @@ -148,27 +147,27 @@ struct nv_decoder<_C> { template<> struct nv_encoder<std::string_view> { - void encode(nv_list &, std::string_view, std::string_view); + void encode(nv_list &__nvl, + std::string_view __key, + std::string_view __value) { + __nvl.add_string(__key, __value); + } + + std::string_view decode(const_nv_list const &__nvl, + std::string_view __key) { + return __nvl.get_string(__key); + } }; -template<__detail::__range_of<std::string_view> _R> -struct nv_encoder<_R> { +template<__detail::__from_range_container_of<std::string_view> _C> +struct nv_encoder<_C> { template<typename _U> void encode(nv_list &__nvl, std::string_view __key, _U &&__range) { __nvl.add_string_range(__key, std::forward<_U>(__range)); } -}; - -template<> -struct nv_decoder<std::string_view> { - auto decode(const_nv_list const &, std::string_view) - -> std::string_view; -}; -template<__detail::__from_range_container_of<std::string_view> _C> -struct nv_decoder<_C> { - auto decode(const_nv_list const &__nvl, std::string_view __key) -> _C { - return (_C(std::from_range, __nvl.get_string_array(__key))); + _C decode(const_nv_list const &__nvl, std::string_view __key) { + return {std::from_range, __nvl.get_string_array(__key)}; } }; @@ -176,32 +175,33 @@ struct nv_decoder<_C> { template<> struct nv_encoder<nv_list> { - void encode(nv_list &, std::string_view, nv_list const &); + void encode(nv_list &__nvl, + std::string_view __key, + nv_list const &__value) { + __nvl.add_nvlist(__key, __value); + } + + nv_list decode(const_nv_list const &__nvl, std::string_view __key) { + return (nv_list(__nvl.get_nvlist(__key))); + } }; +template<__detail::__from_range_container_of<nv_list> _C> +struct nv_encoder<_C> { #ifdef notyet // XXX: implement add_nvlist_range() -template<__detail::__range_of<nv_list> _R> -struct nv_encoder<_R> { template<typename _U> void encode(nv_list &__nvl, std::string_view __key, _U &&__range) { __nvl.add_nvlist_range(__key, std::forward<_U>(__range)); } -}; #endif -template<> -struct nv_decoder<nv_list> { - auto decode(const_nv_list const &, std::string_view) -> nv_list; -}; - -template<__detail::__from_range_container_of<nv_list> _C> -struct nv_decoder<_C> { - auto decode(const_nv_list const &__nvl, std::string_view __key) -> _C { - return (_C(std::from_range, + _C decode(const_nv_list const &__nvl, std::string_view __key) { + auto __nvls = __nvl.get_nvlist_array(__key) | std::views::transform([] (auto const &__s) { return nv_list(__s); - }))); + }); + return {std::from_range, __nvls}; } }; @@ -209,28 +209,29 @@ struct nv_decoder<_C> { template<> struct nv_encoder<const_nv_list> { - void encode(nv_list &, std::string_view, const_nv_list const &); + void encode(nv_list &__nvl, + std::string_view __key, + const_nv_list const &__value) { + __nvl.add_nvlist(__key, __value); + } + + const_nv_list decode(const_nv_list const &__nvl, + std::string_view __key) { + return __nvl.get_nvlist(__key); + } }; +template<__detail::__from_range_container_of<const_nv_list> _C> +struct nv_encoder<_C> { #ifdef notyet // XXX: implement add_nvlist_range() -template<__detail::__range_of<const_nv_list> _R> -struct nv_encoder<_R> { template<typename _U> void encode(nv_list &__nvl, std::string_view __key, _U &&__range) { __nvl.add_nvlist_range(__key, std::forward<_U>(__range)); } -}; #endif -template<> -struct nv_decoder<const_nv_list> { - auto decode(const_nv_list const &, std::string_view) -> const_nv_list; -}; - -template<__detail::__from_range_container_of<const_nv_list> _C> -struct nv_decoder<_C> { - auto decode(const_nv_list const &__nvl, std::string_view __key) -> _C { - return (_C(std::from_range, __nvl.get_nvlist_array(__key))); + _C decode(const_nv_list const &__nvl, std::string_view __key) { + return {std::from_range, __nvl.get_nvlist_array(__key)}; } }; @@ -238,20 +239,17 @@ struct nv_decoder<_C> { template<typename _T> struct nv_encoder<std::optional<_T>> { - auto encode(nv_list &__nvl, + void encode(nv_list &__nvl, std::string_view __key, std::optional<_T> const &__value) { if (__value) nv_encoder<_T>{}.encode(__nvl, __key, *__value); } -}; -template<typename _T> -struct nv_decoder<std::optional<_T>> { - auto decode(const_nv_list const &__nvl, - std::string_view __key) -> std::optional<_T> { + std::optional<_T> decode(const_nv_list const &__nvl, + std::string_view __key) { if (__nvl.exists(__key)) - return {nv_decoder<_T>{}.decode(__nvl, __key)}; + return {nv_encoder<_T>{}.decode(__nvl, __key)}; else return {}; } @@ -275,6 +273,9 @@ concept __serializer = } // namespace detail +template<typename _T> +struct nv_schema; + template<typename _Object, typename _Member> struct nv_field : __detail::__serializer_tag { nv_field(std::string __name, _Member _Object::* __ptr) @@ -290,7 +291,7 @@ struct nv_field : __detail::__serializer_tag { } auto deserialize(const_nv_list const &__nvl, _Object &__object) const { - __object.*__field_ptr = nv_decoder<_Member>{} + __object.*__field_ptr = nv_encoder<_Member>{} .decode(__nvl, __field_name); } @@ -303,6 +304,31 @@ template<typename _Object, typename _Member> nv_field(std::string_view, _Member _Object::*) -> nv_field<std::decay_t<_Object>, _Member>; +template<typename _Object, typename _Member> +struct nv_object : __detail::__serializer_tag { + nv_object(std::string __name, _Member _Object::* __ptr) + : __field_name(__name) + , __field_ptr(__ptr) + { + } + + auto serialize(nv_list &__nvl, _Object const &__object) const { + using __schema_type = nv_schema<_Member>; + auto __schema = __schema_type{}.get(); + __schema.serialize(__nvl, __object.*__field_ptr); + } + + auto deserialize(const_nv_list const &__nvl, _Object &__object) const { + using __schema_type = nv_schema<_Member>; + auto __schema = __schema_type{}.get(); + __schema.deserialize(__nvl, __object.*__field_ptr); + } + +private: + std::string __field_name; + _Member _Object::* __field_ptr; +}; + template<typename _Member> struct nv_literal; @@ -371,9 +397,6 @@ auto operator>> (__detail::__serializer auto const &__f1, return (__detail::__field_sequence(__f1, __f2)); } -template<typename _T> -struct nv_schema; - nv_list nv_serialize(auto &&__o, __detail::__serializer auto const &__schema) { diff --git a/libnvxx/tests/nvxx_serialize.cc b/libnvxx/tests/nvxx_serialize.cc index e6b345d..da01280 100644 --- a/libnvxx/tests/nvxx_serialize.cc +++ b/libnvxx/tests/nvxx_serialize.cc @@ -32,7 +32,7 @@ TEST_CASE(nv_encoder_bool) nv_encoder<bool>{}.encode(nvl, "test", v); - auto v2 = nv_decoder<bool>{}.decode(nvl, "test"); + auto v2 = nv_encoder<bool>{}.decode(nvl, "test"); ATF_REQUIRE_EQ(v, v2); } @@ -43,7 +43,7 @@ TEST_CASE(nv_encoder_bool_vector) nv_encoder<std::vector<bool>>{}.encode(nvl, "test", v); - auto v2 = nv_decoder<std::vector<bool>>{}.decode(nvl, "test"); + auto v2 = nv_encoder<std::vector<bool>>{}.decode(nvl, "test"); ATF_REQUIRE_EQ(true, std::ranges::equal(v, v2)); } @@ -58,7 +58,7 @@ TEST_CASE(nv_encoder_uint64) nv_encoder<std::uint64_t>{}.encode(nvl, "test", v); - auto v2 = nv_decoder<std::uint64_t>{}.decode(nvl, "test"); + auto v2 = nv_encoder<std::uint64_t>{}.decode(nvl, "test"); ATF_REQUIRE_EQ(v, v2); } @@ -69,7 +69,7 @@ TEST_CASE(nv_encoder_uint64_vector) nv_encoder<std::vector<std::uint64_t>>{}.encode(nvl, "test", v); - auto v2 = nv_decoder<std::vector<std::uint64_t>>{}.decode(nvl, "test"); + auto v2 = nv_encoder<std::vector<std::uint64_t>>{}.decode(nvl, "test"); ATF_REQUIRE_EQ(true, std::ranges::equal(v, v2)); } @@ -84,7 +84,7 @@ TEST_CASE(nv_encoder_string) nv_encoder<std::string>{}.encode(nvl, "test", v); - auto v2 = nv_decoder<std::string>{}.decode(nvl, "test"); + auto v2 = nv_encoder<std::string>{}.decode(nvl, "test"); ATF_REQUIRE_EQ(v, v2); } @@ -95,7 +95,7 @@ TEST_CASE(nv_encoder_string_vector) nv_encoder<std::vector<std::string>>{}.encode(nvl, "test", v); - auto v2 = nv_decoder<std::vector<std::string>>{}.decode(nvl, "test"); + auto v2 = nv_encoder<std::vector<std::string>>{}.decode(nvl, "test"); ATF_REQUIRE_EQ(true, std::ranges::equal(v, v2)); } @@ -109,7 +109,7 @@ TEST_CASE(nv_encoder_string_view) auto nvl = nv_list{}; nv_encoder<std::string_view>{}.encode(nvl, "test", v); - auto v2 = nv_decoder<std::string_view>{}.decode(nvl, "test"); + auto v2 = nv_encoder<std::string_view>{}.decode(nvl, "test"); ATF_REQUIRE_EQ(v, v2); } @@ -120,7 +120,7 @@ TEST_CASE(nv_encoder_string_view_vector) nv_encoder<std::vector<std::string_view>>{}.encode(nvl, "test", v); - auto v2 = nv_decoder<std::vector<std::string_view>>{} + auto v2 = nv_encoder<std::vector<std::string_view>>{} .decode(nvl, "test"); ATF_REQUIRE_EQ(true, std::ranges::equal(v, v2)); } @@ -136,7 +136,7 @@ TEST_CASE(nv_encoder_nv_list) auto nvl = nv_list{}; nv_encoder<nv_list>{}.encode(nvl, "test", v); - auto v2 = nv_decoder<nv_list>{}.decode(nvl, "test"); + auto v2 = nv_encoder<nv_list>{}.decode(nvl, "test"); ATF_REQUIRE_EQ(v.get_number("int"), v2.get_number("int")); } @@ -151,7 +151,7 @@ TEST_CASE(nv_encoder_const_nv_list) auto nvl = nv_list{}; nv_encoder<const_nv_list>{}.encode(nvl, "test", const_nv_list(v)); - auto v2 = nv_decoder<const_nv_list>{}.decode(nvl, "test"); + auto v2 = nv_encoder<const_nv_list>{}.decode(nvl, "test"); ATF_REQUIRE_EQ(v.get_number("int"), v2.get_number("int")); } @@ -166,12 +166,12 @@ TEST_CASE(nv_encoder_optional) nv_encoder<std::optional<std::uint64_t>>{}.encode(nvl, "test", v); - auto v2 = nv_decoder< + auto v2 = nv_encoder< std::optional<std::uint64_t>>{}.decode(nvl, "test"); ATF_REQUIRE_EQ(true, v2.has_value()); ATF_REQUIRE_EQ(*v, *v2); - v2 = nv_decoder<std::optional<std::uint64_t>>{}.decode(nvl, "nonesuch"); + v2 = nv_encoder<std::optional<std::uint64_t>>{}.decode(nvl, "nonesuch"); ATF_REQUIRE_EQ(false, v2.has_value()); } @@ -233,6 +233,41 @@ TEST_CASE(nv_deserialize_bad_literal) bsd::nv_deserialize(nvl, obj, test_schema)); } +struct object1 { + std::uint64_t value{}; +}; + +template<> +struct bsd::nv_schema<object1> { + auto get() { + return bsd::nv_field("value", &object1::value); + } +}; + +struct object2 { + std::uint64_t value2{}; + object1 obj; +}; + +template<> +struct bsd::nv_schema<object2> { + auto get() { + return bsd::nv_field("value2", &object2::value2) + >> bsd::nv_object("obj", &object2::obj); + } +}; + +TEST_CASE(nv_nested_serialize) +{ + auto obj = object2{42, {666}}; + auto nvl = bsd::nv_serialize(obj); + + auto obj2 = object2{}; + bsd::nv_deserialize(nvl, obj2); + ATF_REQUIRE_EQ(obj.value2, obj2.value2); + ATF_REQUIRE_EQ(obj.obj.value, obj2.obj.value); +} + ATF_INIT_TEST_CASES(tcs) { ATF_ADD_TEST_CASE(tcs, nv_encoder_bool); @@ -252,4 +287,5 @@ ATF_INIT_TEST_CASES(tcs) ATF_ADD_TEST_CASE(tcs, nv_serialize); ATF_ADD_TEST_CASE(tcs, nv_serialize_literal); ATF_ADD_TEST_CASE(tcs, nv_deserialize_bad_literal); + ATF_ADD_TEST_CASE(tcs, nv_nested_serialize); } |
