diff --git a/CMakeLists.txt b/CMakeLists.txt index b43e0e1..b188859 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,6 +67,11 @@ SOURCES examples/sugar.cpp ) +cppm_target_define(reflection BINARY +SOURCES + examples/reflection.cpp +) + cppm_target_define(print BINARY SOURCES examples/print.cpp @@ -135,6 +140,10 @@ cppm_target_dependencies(sugar ${serdepp_global_deps} serdepp) +cppm_target_dependencies(reflection + ${serdepp_global_deps} + serdepp) + cppm_target_dependencies(print ${serdepp_global_deps} serdepp) @@ -165,6 +174,7 @@ cppm_target_install(variant_example) cppm_target_install(parse_file_example) cppm_target_install(struct_attribute_example) cppm_target_install(sugar) +cppm_target_install(reflection) cppm_target_install(print) cppm_target_install(pointer) diff --git a/README.md b/README.md index 95c4e91..0da1995 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ c++17 low cost serialize deserialize adaptor library like rust serde.rs - [x] [attributes](#Attributes) and custom attribute support (value_or_struct, default, multi_key ...) - [x] variant support (std::variant, UserType, EnumType...>) [example](examples/variant.cpp) - [x] pointer support (T*, std::shared_ptr, std::unique_ptr) +- [x] reflection support (BETA) (mem_get(member_name) or mem_get()) ## Serdepp Strcuture ![Serdepp structure](Serdepp_Structure.png) @@ -65,12 +66,12 @@ int main() { ex.number_ = 1024; ex.vec_ = {"a", "b", "c"}; ex.tenum_ = t_enum::B; + //std::cout << ex << "\n"; nlohmann::json json_from_ex = serde::serialize(ex); example ex_from_json = serde::deserialize(json_from_ex); - fmt::print("json:{}\n",json_from_ex.dump(4)); - + std::cout << "json: " << json_from_ex.dump(4) << "\n"; fmt::print("fmt:{}\n",ex_from_json); } diff --git a/cppm.toml b/cppm.toml index 25b771c..0488f86 100644 --- a/cppm.toml +++ b/cppm.toml @@ -45,6 +45,10 @@ name = "sugar" source = ["examples/sugar.cpp"] +[[example]] + name = "reflection" + source = ["examples/reflection.cpp"] + [[example]] name = "print" source = ["examples/print.cpp"] @@ -53,6 +57,10 @@ name = "pointer" source = ["examples/pointer.cpp"] +#[[example]] +# name = "tuple_sort" +# source = ["examples/tuple_sort.cpp"] + #[[example]] # name = "sol2_example" # source = ["examples/sol2.cpp"] diff --git a/examples/example.cpp b/examples/example.cpp index f46ae40..d7125ce 100644 --- a/examples/example.cpp +++ b/examples/example.cpp @@ -6,8 +6,6 @@ #include "serdepp/adaptor/rapidjson.hpp" #include -using namespace serde::ostream; - enum class tenum {INPUT, OUTPUT, INPUT_2 , OUTPUT_2 }; @@ -16,6 +14,7 @@ struct nested { (&Self::version, "version", value_or_struct) (&Self::opt_desc ,"opt_desc") [attributes(default_{"default value"})] + (&Self::desc ,"desc") .no_remain()) std::string version; diff --git a/examples/print.cpp b/examples/print.cpp index 0093299..1bbb118 100644 --- a/examples/print.cpp +++ b/examples/print.cpp @@ -34,7 +34,7 @@ int main(int argc, char *argv[]) auto j_flatten = serde::deserialize>(jflat); - std::cout << serde::serialize(j_flatten).str(); + std::cout << serde::to_string(j_flatten) << "\n"; return 0; } diff --git a/examples/reflection.cpp b/examples/reflection.cpp new file mode 100644 index 0000000..c9a8ec2 --- /dev/null +++ b/examples/reflection.cpp @@ -0,0 +1,22 @@ +#include +#include + +struct Test { + DERIVE_SERDE(Test, + (&Self::test, "test") + (&Self::str, "str")) + int test; + std::string str; +}; + +int main(int argc, char *argv[]) +{ + auto t = Test{1,"hello"}; + std:: cout << t << "\n"; + serde::mem_get(t, "str") = "why"; + serde::mem_get(t) = 200; + std:: cout << t << "\n"; + + return 0; +} + diff --git a/examples/sugar.cpp b/examples/sugar.cpp index 2c26a41..22bc609 100644 --- a/examples/sugar.cpp +++ b/examples/sugar.cpp @@ -19,13 +19,13 @@ namespace serde::attribute { } }; } - constexpr static auto tttt = detail::tttt{}; + [[maybe_unused]] constexpr static auto tttt = detail::tttt{}; } struct Test { DERIVE_SERDE(Test, - [attributes(flatten, default_(""))] + [attributes(flatten)] (&Self::test, "test") [attributes(flatten, default_(""))] (&Self::str, "str")) @@ -35,7 +35,7 @@ struct Test { int main(int argc, char *argv[]) { - fmt::print("{}\n",Test{1}); + std::cout << Test{1} << "\n"; return 0; } diff --git a/examples/variant.cpp b/examples/variant.cpp index d0ad88f..527d325 100644 --- a/examples/variant.cpp +++ b/examples/variant.cpp @@ -41,6 +41,7 @@ int main() { fmt::print("------\n"); auto j_flatten = deserialize>(jflat); + fmt::print("------\n"); auto j_none = deserialize>(j); fmt::print("{}\n",serialize(j_flatten).dump(4)); fmt::print("{}\n",serialize(j_none).dump(4)); diff --git a/include/serdepp/adaptor/reflection.hpp b/include/serdepp/adaptor/reflection.hpp new file mode 100644 index 0000000..cbe4a02 --- /dev/null +++ b/include/serdepp/adaptor/reflection.hpp @@ -0,0 +1,116 @@ +#pragma once + +#ifndef __SERDEPP_ADAPTOR_RFLECTION_HPP__ +#define __SERDEPP_ADAPTOR_RFLECTION_HPP__ + +#include +#include + +namespace serde { + template + struct reflect_from_name { + //DERIVE_SERDE(reflect,(&Self::key, "key")(&Self::member, "member")) + reflect_from_name() = default; + reflect_from_name(std::string_view member) : key(member) {} + std::string_view key; + T* member = nullptr; + }; + + template + struct reflect_from_index { + constexpr static size_t find_idx = idx; + //DERIVE_SERDE(reflect,(&Self::key, "key")(&Self::member, "member")) + reflect_from_index() = default; + size_t index = 0; + T* member = nullptr; + }; + + template + struct serde_adaptor_helper> : derive_serde_adaptor_helper> { + inline constexpr static bool is_null(reflect_from_name &adaptor, std::string_view key) { return false; } + inline constexpr static size_t size(reflect_from_name &adaptor) { return 1; } + inline constexpr static bool is_struct(reflect_from_name &adaptor) { return true; } + }; + + template + struct serde_adaptor_helper> : derive_serde_adaptor_helper> { + inline constexpr static bool is_null(reflect_from_index &adaptor, std::string_view key) { return false; } + inline constexpr static size_t size(reflect_from_index &adaptor) { return 1; } + inline constexpr static bool is_struct(reflect_from_index &adaptor) { return true; } + }; + + template + struct serde_adaptor, T, std::enable_if_t>>> { + constexpr static void from(reflect_from_name& s, std::string_view key, T& data){ + if(key == s.key) { + s.member = &data; + } + } + static void into(reflect_from_name& s, std::string_view key, const T& data) { + throw serde::unimplemented_error("serde_adaptor::into(reflect_from_name, key, data)"); + } + }; + + template + struct serde_adaptor, T , std::enable_if_t>>> { + static void from(reflect_from_name& s, std::string_view key, T& data){ + if(key == s.key) { + std::string error = std::string(nameof::nameof_type()); + throw serde::type_error(error + " != " + std::string(nameof::nameof_type>())); + } + } + static void into(reflect_from_name& s, std::string_view key, const T& data) { + throw serde::unimplemented_error("serde_adaptor::into(reflect_from_name, key, data)"); + } + }; + + template + struct serde_adaptor, T, std::enable_if_t>>> { + constexpr static void from(reflect_from_index& s, std::string_view key, T& data){ + if(s.index == s.find_idx) { + s.member = &data; + } + s.index++; + } + static void into(reflect_from_index& s, std::string_view key, const T& data) { + throw serde::unimplemented_error("serde_adaptor::into(reflect_from_name, key, data)"); + } + }; + + template + struct serde_adaptor, T, std::enable_if_t>>> { + static void from(reflect_from_index& s, std::string_view key, T& data){ + if(s.index == s.find_idx) { + std::string error = std::string(nameof::nameof_type()); + throw serde::type_error(error + " != " + std::string(nameof::nameof_type>())); + } + s.index++; + } + static void into(reflect_from_index& s, std::string_view key, const T& data) { + throw serde::unimplemented_error("serde_adaptor::into(reflect_from_name, key, data)"); + } + }; + + + template + constexpr M& mem_get(T& type, std::string_view member_name) { + auto ref = serde::reflect_from_name(member_name); + serde::deserialize_to(ref, type); + if(ref.member == nullptr) { + throw serde::type_error("can't find member: " + std::string(member_name)); + } + return *ref.member; + } + + template + constexpr M& mem_get(T& type) { + auto ref = serde::reflect_from_index(); + serde::deserialize_to(ref, type); + if(ref.member == nullptr) { + throw serde::type_error("out of index: " + std::to_string(idx)); + } + return *ref.member; + } +} + +#endif diff --git a/include/serdepp/exception.hpp b/include/serdepp/exception.hpp index dfec819..90f7e9c 100644 --- a/include/serdepp/exception.hpp +++ b/include/serdepp/exception.hpp @@ -37,6 +37,15 @@ namespace serde { std::string what_; }; + struct type_error : exception { + public: + explicit type_error(std::string what) : what_("type error: " + what + '\n') {} + virtual ~type_error() noexcept override = default; + virtual const char* what() const noexcept override {return what_.c_str();} + protected: + std::string what_; + }; + struct unregisted_data_error : exception { public: explicit unregisted_data_error(std::string what) : what_("unregisted data: " + what + '\n') {} diff --git a/include/serdepp/serde.hpp b/include/serdepp/serde.hpp index f54004a..3b21c89 100644 --- a/include/serdepp/serde.hpp +++ b/include/serdepp/serde.hpp @@ -6,5 +6,6 @@ #include #include #include +using namespace serde::ostream; #endif diff --git a/include/serdepp/serializer.hpp b/include/serdepp/serializer.hpp index 4745a4b..6f5ac5a 100644 --- a/include/serdepp/serializer.hpp +++ b/include/serdepp/serializer.hpp @@ -513,14 +513,14 @@ namespace serde template struct serde_type_checker { - static bool is_integer(Format& format); - static bool is_sequence(Format& format); - static bool is_map(Format& format); - static bool is_float(Format& format); - static bool is_string(Format& format); - static bool is_bool(Format& format); - static bool is_null(Format& format); - static bool is_struct(Format& format); + static bool is_integer(Format& format) { return true; } + static bool is_sequence(Format& format) { return true; } + static bool is_map(Format& format) { return true; } + static bool is_float(Format& format) { return true; } + static bool is_string(Format& format) { return true; } + static bool is_bool(Format& format) { return true; } + static bool is_null(Format& format) { return true; } + static bool is_struct(Format& format) { return true; } }; template @@ -574,6 +574,7 @@ namespace serde data = deserialize(format); return false; } catch(std::exception& ex) { + std::cout << "error \n"; return true; } } @@ -581,8 +582,8 @@ namespace serde template constexpr void serde_variant_iter(Format& format, V& data) { if constexpr (sizeof...(T) != 0) { - bool is_find = serde_variant_setter(format, data); - if(!is_find) return; + bool is_not_find = serde_variant_setter(format, data); + if(!is_not_find) return; serde_variant_iter(format, data); } else { if(serde_variant_setter