aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libnvxx/Makefile3
-rw-r--r--libnvxx/nvxx_serialize.cc113
-rw-r--r--libnvxx/nvxx_serialize.h203
-rw-r--r--libnvxx/tests/nvxx_serialize.cc60
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);
}