diff --git a/include/ylt/standalone/iguana/pb_util.hpp b/include/ylt/standalone/iguana/pb_util.hpp index 3aa2b1997..f46580a6c 100644 --- a/include/ylt/standalone/iguana/pb_util.hpp +++ b/include/ylt/standalone/iguana/pb_util.hpp @@ -54,25 +54,20 @@ struct base_impl : public base { } std::any get_field_any(std::string_view name) const override { - static constexpr auto map = iguana::get_members(); - std::any result; - for (auto const& [no, field] : map) { - if (result.has_value()) { - break; - } + static constexpr auto map = iguana::get_members_fieldname_map(); - std::visit( - [&](auto val) { - if (val.field_name == name) { - auto const offset = member_offset((T*)this, val.member_ptr); - auto const ptr = (((char*)this) + offset); - using value_type = typename decltype(val)::value_type; - result = *((value_type*)ptr); - } - }, - field); + if (map.find(name) == map.end()) { + return {}; } - return result; + + return std::visit( + [&](auto val) { + auto const offset = member_offset((T*)this, val.member_ptr); + auto const ptr = (((char*)this) + offset); + using value_type = typename decltype(val)::value_type; + return std::any{*((value_type*)ptr)}; + }, + map.at(name)); } iguana::detail::field_info get_field_info(std::string_view name) override { diff --git a/include/ylt/standalone/iguana/reflection.hpp b/include/ylt/standalone/iguana/reflection.hpp index 11d74b482..a59f5ad46 100644 --- a/include/ylt/standalone/iguana/reflection.hpp +++ b/include/ylt/standalone/iguana/reflection.hpp @@ -874,6 +874,13 @@ constexpr auto inline get_members_impl(Tuple &&tp, std::index_sequence) { T{std::in_place_index, std::move(std::get(tp))}}...}; } +template +constexpr auto inline get_members_fieldname_map_impl(Tuple &&tp, std::index_sequence) { + return frozen::unordered_map{ + {std::get(tp).field_name, + T{std::in_place_index, std::move(std::get(tp))}}...}; +} + template constexpr size_t count_variant_size() { if constexpr (is_variant::value) { @@ -912,6 +919,21 @@ constexpr inline auto get_members() { } } +template +constexpr inline auto get_members_fieldname_map() { + if constexpr (is_reflection_v || is_custom_reflection_v) { + constexpr auto tp = get_members_tuple(); + using Tuple = std::decay_t; + using value_type = typename field_type_t::value_type; + constexpr auto Size = tuple_type_count(); + return get_members_fieldname_map_impl(tp, + std::make_index_sequence{}); + } + else { + static_assert(!sizeof(T), "expected reflection or custom reflection"); + } +} + #define REFLECTION(STRUCT_NAME, ...) \ MAKE_META_DATA(STRUCT_NAME, #STRUCT_NAME, GET_ARG_COUNT(__VA_ARGS__), \ __VA_ARGS__)