diff --git a/include/ylt/standalone/iguana/pb_util.hpp b/include/ylt/standalone/iguana/pb_util.hpp index b2e467721..d1bd3d03b 100644 --- a/include/ylt/standalone/iguana/pb_util.hpp +++ b/include/ylt/standalone/iguana/pb_util.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -76,20 +77,49 @@ struct base_impl : public base { return info; } - std::vector get_fields_name() override { + std::vector get_fields_name() const override { static constexpr auto map = iguana::get_members(); + std::vector vec; - for (auto [no, val] : map) { + std::set sets; + + for (auto const& [no, val] : map) { std::visit( - [&](auto& field) { - vec.push_back(std::string_view(field.field_name.data(), - field.field_name.size())); + [&](auto const& field) { + if (auto it = sets.emplace(field.field_name.data(), + field.field_name.size()); + it.second) { + vec.push_back(*it.first); + } }, val); } return vec; } + std::any get_field_any(std::string_view name) const override { + static constexpr auto map = iguana::get_members(); + std::any result; + + for (auto [no, field] : map) { + if (result.has_value()) { + break; + } + std::visit( + [&](auto val) { + if (val.field_name == name) { + using value_type = typename decltype(val)::value_type; + auto const offset = member_offset((T*)this, val.member_ptr); + auto ptr = (((char*)this) + offset); + result = {*((value_type*)ptr)}; + } + }, + field); + } + + return result; + } + virtual ~base_impl() {} size_t cache_size = 0; diff --git a/include/ylt/standalone/iguana/reflection.hpp b/include/ylt/standalone/iguana/reflection.hpp index cb0ff86a8..354d8a119 100644 --- a/include/ylt/standalone/iguana/reflection.hpp +++ b/include/ylt/standalone/iguana/reflection.hpp @@ -4,6 +4,7 @@ #ifndef IGUANA_REFLECTION_HPP #define IGUANA_REFLECTION_HPP +#include #include #include #include @@ -563,7 +564,8 @@ struct field_info { struct base { virtual void to_pb(std::string &str) {} virtual void from_pb(std::string_view str) {} - virtual std::vector get_fields_name() { return {}; } + virtual std::vector get_fields_name() const { return {}; } + virtual std::any get_field_any(std::string_view name) const { return {}; } virtual iguana::detail::field_info get_field_info(std::string_view name) { return {}; } diff --git a/src/struct_pb/examples/main.cpp b/src/struct_pb/examples/main.cpp index 6b631d608..e2b4d08ba 100644 --- a/src/struct_pb/examples/main.cpp +++ b/src/struct_pb/examples/main.cpp @@ -18,8 +18,9 @@ struct nest : struct_pb::base_impl { std::string name; my_struct value; int var; + std::variant mv; }; -REFLECTION(nest, name, value, var); +REFLECTION(nest, name, value, var, mv); struct person { int id; @@ -52,17 +53,31 @@ int main() { // dynamic reflection auto t = struct_pb::create_instance("nest"); auto names = t->get_fields_name(); - bool r = (names == std::vector{"name", "value", "var"}); + bool r = + (names == std::vector{"name", "value", "var", "mv"}); assert(r); + t->set_field_value("mv", std::variant{1}); + auto mv = t->get_field_value>("mv"); + auto const temp = std::variant{1}; + assert(mv == temp); + t->set_field_value("name", std::string("tom")); auto name = t->get_field_value("name"); assert(name == "tom"); - auto d = dynamic_cast(t.get()); + auto d = dynamic_cast(t.get()); assert(d->name == "tom"); t->set_field_value("name", "hello"); - auto &field_name = t->get_field_value("name"); + auto& field_name = t->get_field_value("name"); assert(field_name == "hello"); + + // dynamic any + auto const& any_name = t->get_field_any("name"); + assert(std::any_cast(any_name) == "hello"); + + auto const& mvar_any = t->get_field_any("mv"); + auto const& mvar = std::any_cast>(mvar_any); + assert(mvar == temp); } \ No newline at end of file