Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat][dynamic reflection] small edit #290

Merged
merged 4 commits into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 21 additions & 18 deletions iguana/dynamic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ constexpr inline uint8_t ENABLE_ALL = 0x0F;

template <typename T, uint8_t ENABLE_FLAG = ENABLE_PB>
struct base_impl : public base {
void to_pb(std::string& str) override {
void to_pb(std::string& str) const override {
if constexpr ((ENABLE_FLAG & ENABLE_PB) != 0) {
to_pb_adl((iguana_adl_t*)nullptr, *(static_cast<T*>(this)), str);
to_pb_adl((iguana_adl_t*)nullptr, *(static_cast<T const*>(this)), str);
}
else {
throw std::runtime_error("Protobuf Disabled");
Expand All @@ -35,9 +35,9 @@ struct base_impl : public base {
}
}

void to_json(std::string& str) override {
void to_json(std::string& str) const override {
if constexpr ((ENABLE_FLAG & ENABLE_JSON) != 0) {
to_json_adl((iguana_adl_t*)nullptr, *(static_cast<T*>(this)), str);
to_json_adl((iguana_adl_t*)nullptr, *(static_cast<T const*>(this)), str);
}
else {
throw std::runtime_error("Json Disabled");
Expand All @@ -53,9 +53,9 @@ struct base_impl : public base {
}
}

void to_xml(std::string& str) override {
void to_xml(std::string& str) const override {
if constexpr ((ENABLE_FLAG & ENABLE_XML) != 0) {
to_xml_adl((iguana_adl_t*)nullptr, *(static_cast<T*>(this)), str);
to_xml_adl((iguana_adl_t*)nullptr, *(static_cast<T const*>(this)), str);
}
else {
throw std::runtime_error("Xml Disabled");
Expand All @@ -71,9 +71,9 @@ struct base_impl : public base {
}
}

void to_yaml(std::string& str) override {
void to_yaml(std::string& str) const override {
if constexpr ((ENABLE_FLAG & ENABLE_YAML) != 0) {
to_yaml_adl((iguana_adl_t*)nullptr, *(static_cast<T*>(this)), str);
to_yaml_adl((iguana_adl_t*)nullptr, *(static_cast<T const*>(this)), str);
}
else {
throw std::runtime_error("Yaml Disabled");
Expand All @@ -89,18 +89,20 @@ struct base_impl : public base {
}
}

iguana::detail::field_info get_field_info(std::string_view name) override {
iguana::detail::field_info get_field_info(
std::string_view name) const override {
static constexpr auto map = iguana::get_members<T>();
iguana::detail::field_info info{};
for (auto& [no, field] : map) {
for (auto const& [no, field] : map) {
if (info.offset > 0) {
break;
}
std::visit(
[&](auto val) {
[&](auto const& val) {
if (val.field_name == name) {
info.offset = member_offset((T*)this, val.member_ptr);
using value_type = typename decltype(val)::value_type;
using value_type =
typename std::remove_reference_t<decltype(val)>::value_type;
#if defined(__clang__) || defined(_MSC_VER) || \
(defined(__GNUC__) && __GNUC__ > 8)
info.type_name = type_string<value_type>();
Expand Down Expand Up @@ -136,17 +138,18 @@ struct base_impl : public base {
static constexpr auto map = iguana::get_members<T>();
std::any result;

for (auto [no, field] : map) {
for (auto const& [no, field] : map) {
if (result.has_value()) {
break;
}
std::visit(
[&](auto val) {
[&](auto const& val) {
if (val.field_name == name) {
using value_type = typename decltype(val)::value_type;
using value_type =
typename std::remove_reference_t<decltype(val)>::value_type;
auto const offset = member_offset((T*)this, val.member_ptr);
auto ptr = (((char*)this) + offset);
result = {*((value_type*)ptr)};
auto ptr = (char*)this + offset;
result = *((value_type*)ptr);
}
},
field);
Expand All @@ -157,7 +160,7 @@ struct base_impl : public base {

virtual ~base_impl() {}

size_t cache_size = 0;
mutable size_t cache_size = 0;
};

IGUANA_INLINE std::shared_ptr<base> create_instance(std::string_view name) {
Expand Down
5 changes: 3 additions & 2 deletions iguana/pb_util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,7 @@ IGUANA_INLINE size_t pb_oneof_size(Type&& t, Arr& size_arr) {
int len = 0;
std::visit(
[&len, &size_arr](auto&& value) IGUANA__INLINE_LAMBDA {
using raw_value_type = decltype(value);
using value_type =
std::remove_const_t<std::remove_reference_t<decltype(value)>>;
constexpr auto offset =
Expand All @@ -427,7 +428,7 @@ IGUANA_INLINE size_t pb_oneof_size(Type&& t, Arr& size_arr) {
((field_no + offset) << 3) |
static_cast<uint32_t>(get_wire_type<value_type>());
len = pb_key_value_size<variant_uint32_size_constexpr(key), false>(
std::forward<value_type>(value), size_arr);
std::forward<raw_value_type>(value), size_arr);
},
std::forward<Type>(t));
return len;
Expand All @@ -454,7 +455,7 @@ IGUANA_INLINE size_t pb_key_value_size(Type&& t, Arr& size_arr) {
std::decay_t<decltype(tuple)>>;
constexpr auto value = std::get<decltype(i)::value>(tuple);
using U = typename field_type::value_type;
auto& val = value.value(t);
auto const& val = value.value(t);
if constexpr (variant_v<U>) {
constexpr auto offset =
get_variant_index<U, typename field_type::sub_type,
Expand Down
7 changes: 4 additions & 3 deletions iguana/pb_writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,15 @@ IGUANA_INLINE void to_pb_oneof(Type&& t, It&& it, uint32_t*& sz_ptr) {
using T = std::decay_t<Type>;
std::visit(
[&it, &sz_ptr](auto&& value) IGUANA__INLINE_LAMBDA {
using raw_value_type = decltype(value);
using value_type =
std::remove_const_t<std::remove_reference_t<decltype(value)>>;
constexpr auto offset =
get_variant_index<T, value_type, std::variant_size_v<T> - 1>();
constexpr uint32_t key =
((field_no + offset) << 3) |
static_cast<uint32_t>(get_wire_type<value_type>());
to_pb_impl<key, false>(std::forward<value_type>(value), it, sz_ptr);
to_pb_impl<key, false>(std::forward<raw_value_type>(value), it, sz_ptr);
},
std::forward<Type>(t));
}
Expand Down Expand Up @@ -449,7 +450,7 @@ IGUANA_INLINE void build_sub_proto(Map& map, std::string_view str_type,
} // namespace detail

template <typename T, typename Stream>
IGUANA_INLINE void to_pb(T& t, Stream& out) {
IGUANA_INLINE void to_pb(T const& t, Stream& out) {
std::vector<uint32_t> size_arr;
auto byte_len = detail::pb_key_value_size<0>(t, size_arr);
detail::resize(out, byte_len);
Expand Down Expand Up @@ -491,7 +492,7 @@ IGUANA_INLINE void to_proto_file(Stream& stream, std::string_view ns = "") {
#endif

template <typename T, typename Stream>
IGUANA_INLINE void to_pb_adl(iguana_adl_t* p, T& t, Stream& out) {
IGUANA_INLINE void to_pb_adl(iguana_adl_t* p, T const& t, Stream& out) {
to_pb(t, out);
}

Expand Down
12 changes: 7 additions & 5 deletions iguana/reflection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -562,17 +562,18 @@ struct field_info {
};

struct base {
virtual void to_pb(std::string &str) {}
virtual void to_pb(std::string &str) const {}
virtual void from_pb(std::string_view str) {}
virtual void to_xml(std::string &str) {}
virtual void to_xml(std::string &str) const {}
virtual void from_xml(std::string_view str) {}
virtual void to_json(std::string &str) {}
virtual void to_json(std::string &str) const {}
virtual void from_json(std::string_view str) {}
virtual void to_yaml(std::string &str) {}
virtual void to_yaml(std::string &str) const {}
virtual void from_yaml(std::string_view str) {}
virtual std::vector<std::string_view> 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) {
virtual iguana::detail::field_info get_field_info(
std::string_view name) const {
return {};
}

Expand Down Expand Up @@ -802,6 +803,7 @@ struct field_t {
uint32_t field_no;

auto &value(owner_type &value) const { return value.*member_ptr; }
auto const &value(owner_type const &value) const { return value.*member_ptr; }
};

template <typename T>
Expand Down
24 changes: 24 additions & 0 deletions test/test_pb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,17 @@ struct numer_st PUBLIC(numer_st) {
};
REFLECTION(numer_st, a, b, c);

struct MyPerson : public iguana::base_impl<MyPerson, iguana::ENABLE_JSON> {
MyPerson() = default;
MyPerson(std::string s, int d) : name(s), age(d) {}
std::string name;
int64_t age;
bool operator==(const MyPerson &other) const {
return name == other.name && age == other.age;
}
};

REFLECTION(MyPerson, name, age);
struct person PUBLIC(person) {
person() = default;
person(int32_t a, std::string b, int c, double d)
Expand Down Expand Up @@ -386,6 +397,19 @@ TEST_CASE("test reflection") {
std::any_cast<std::variant<int, double>>(mvariant_any);
assert(mvariant == temp_variant);
}
{
// to_json is an const member_function now
MyPerson const p1{"xiaoming", 10};
std::string str;
p1.to_json(str);

// p1.to_pb(str); // compile failed
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to_pb为什么会编译失败?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

原来的to_*都是非const的函数,所以任意的T const a; a.to_*都会编译失败,所以写了这个测试用例


MyPerson p2;
p2.from_json(str);

assert(p1 == p2);
}
{
auto t = iguana::create_instance("pair_t");
t->set_field_value("x", 12);
Expand Down
Loading