Skip to content

Commit

Permalink
support custom reflection struct
Browse files Browse the repository at this point in the history
  • Loading branch information
bbbgan committed May 3, 2024
1 parent eadde96 commit 5fb40db
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 66 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/clang-format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Clang Format Diff

on:
push:
branches: [ master]
branches: [ master, struct_pb ]
pull_request:
branches: [ master]
branches: [ master, struct_pb ]

jobs:
build:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/linux-clang.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Ubuntu (clang)

on:
push:
branches: [ master]
branches: [ master, struct_pb ]
pull_request:
branches: [ master]
branches: [ master, struct_pb ]

jobs:
build:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/linux-gcc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Ubuntu (gcc)

on:
push:
branches: [ master]
branches: [ master, struct_pb ]
pull_request:
branches: [ master]
branches: [ master, struct_pb ]

jobs:
ubuntu_gcc:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/mac.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: macOS Monterey 12

on:
push:
branches: [ master]
branches: [ master, struct_pb ]
pull_request:
branches: [ master]
branches: [ master, struct_pb ]

jobs:
build:
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
name: Windows Server 2022

on:
on:
push:
branches: [ master]
branches: [ master, struct_pb ]
pull_request:
branches: [ master]
branches: [ master, struct_pb ]

jobs:
build:
Expand Down
34 changes: 17 additions & 17 deletions iguana/pb_util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,12 +328,9 @@ constexpr inline size_t variant_intergal_size(U value) {
}
}

template <typename T, typename F>
constexpr void for_each_tp(T&& t, F&& f) {
constexpr auto tp = get_members<T, false>();
using Tuple = decltype(tp);
for_each(tp, std::forward<F>(f),
std::make_index_sequence<std::tuple_size_v<Tuple>>{});
template <typename F, size_t... I>
constexpr void for_each_n(F&& f, std::index_sequence<I...>) {
(std::forward<F>(f)(std::integral_constant<size_t, I>{}), ...);
}

// cache the size of reflection type
Expand All @@ -343,23 +340,26 @@ auto& get_set_size_cache(T& t) {
return cache[reinterpret_cast<size_t>(&t)];
}

// TODO: support user-defined struct
// returns size = key_size + optional(len_size) + len
// when key_size == 0, return len
template <size_t key_size = 0, typename T>
inline size_t pb_item_size(T&& t) {
using value_type = std::remove_const_t<std::remove_reference_t<T>>;
if constexpr (is_reflection_v<value_type>) {
if constexpr (is_reflection_v<value_type> ||
is_custom_reflection_v<value_type>) {
size_t len = 0;
for_each_tp(t, [&len, &t](const auto& val, auto i) {
constexpr static auto tp = get_members_impl<T>();
constexpr auto value = std::get<decltype(i)::value>(tp);
using U = typename std::decay_t<decltype(value)>::value_type;
constexpr uint32_t sub_key =
(value.field_no << 3) | static_cast<uint32_t>(get_wire_type<U>());
constexpr auto sub_keysize = variant_uint32_size_constexpr(sub_key);
len += pb_item_size<sub_keysize>(value.value(t));
});
constexpr auto tp = get_members_impl<value_type>();
constexpr size_t SIZE = std::tuple_size_v<std::decay_t<decltype(tp)>>;
for_each_n(
[&len, &t, &tp](auto i) {
constexpr auto value = std::get<decltype(i)::value>(tp);
using U = typename std::decay_t<decltype(value)>::value_type;
constexpr uint32_t sub_key =
(value.field_no << 3) | static_cast<uint32_t>(get_wire_type<U>());
constexpr auto sub_keysize = variant_uint32_size_constexpr(sub_key);
len += pb_item_size<sub_keysize>(value.value(t));
},
std::make_index_sequence<SIZE>{});
get_set_size_cache(t) = len;
if constexpr (key_size == 0) {
return len;
Expand Down
22 changes: 13 additions & 9 deletions iguana/pb_writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ inline void encode_pair_value(V&& val, Stream& out, size_t size) {
template <uint32_t key, typename Type, typename Stream>
inline void to_pb_impl(Type& t, Stream& out) {
using T = std::remove_const_t<std::remove_reference_t<Type>>;
if constexpr (is_reflection_v<T>) {
if constexpr (is_reflection_v<T> || is_custom_reflection_v<T>) {
// TODO: improve the key serialize
auto len = pb_load_size(t);
if (len == 0) {
Expand All @@ -60,14 +60,18 @@ inline void to_pb_impl(Type& t, Stream& out) {
serialize_varint(key, out);
serialize_varint(len, out);
}
for_each_tp(t, [&t, &out](const auto& val, auto i) {
constexpr static auto tp = get_members_impl<T>();
constexpr auto value = std::get<decltype(i)::value>(tp);
using U = typename std::decay_t<decltype(value)>::value_type;
constexpr uint32_t sub_key =
(value.field_no << 3) | static_cast<uint32_t>(get_wire_type<U>());
to_pb_impl<sub_key>(value.value(t), out);
});
// TODO: constexpr static auto tp
constexpr auto tp = get_members_impl<T>();
constexpr size_t SIZE = std::tuple_size_v<std::decay_t<decltype(tp)>>;
for_each_n(
[&t, &out, &tp](auto i) {
constexpr auto value = std::get<decltype(i)::value>(tp);
using U = typename std::decay_t<decltype(value)>::value_type;
constexpr uint32_t sub_key =
(value.field_no << 3) | static_cast<uint32_t>(get_wire_type<U>());
to_pb_impl<sub_key>(value.value(t), out);
},
std::make_index_sequence<SIZE>{});
}
else if constexpr (is_sequence_container<T>::value) {
// TODO support std::array
Expand Down
38 changes: 23 additions & 15 deletions iguana/reflection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -737,7 +737,18 @@ template <typename T, typename = void>
struct is_custom_reflection : std::false_type {};

template <typename T>
struct is_custom_reflection<T, std::void_t<decltype(get_members_impl(std::declval<T*>()))>> : std::true_type {};
struct is_custom_reflection<
T, std::void_t<decltype(get_members_impl(std::declval<T *>()))>>
: std::true_type {};

template <typename T, typename = void>
struct is_reflection : std::false_type {};

template <typename T>
inline constexpr bool is_reflection_v = is_reflection<T>::value;

template <typename T>
inline constexpr bool is_custom_reflection_v = is_custom_reflection<T>::value;

struct field_helper {
template <typename T, typename U, size_t... I>
Expand All @@ -749,10 +760,16 @@ struct field_helper {

template <typename T>
constexpr inline auto get_members_impl() {
using reflect_members = decltype(iguana_reflect_type(std::declval<T>()));
using Tuple = decltype(reflect_members::apply_impl());
return field_helper{}(reflect_members::apply_impl(), reflect_members::arr(),
std::make_index_sequence<std::tuple_size_v<Tuple>>{});
if constexpr (is_reflection_v<T>) {
using reflect_members = decltype(iguana_reflect_type(std::declval<T>()));
using Tuple = decltype(reflect_members::apply_impl());
return field_helper{}(reflect_members::apply_impl(), reflect_members::arr(),
std::make_index_sequence<std::tuple_size_v<Tuple>>{});
}
else if constexpr (is_custom_reflection_v<T>) {
using U = std::remove_const_t<std::remove_reference_t<T>>;
return get_members_impl((U *)nullptr);
}
}

template <typename T, size_t Size>
Expand All @@ -766,9 +783,6 @@ struct member_helper {
}
};

template <typename T, typename = void>
struct is_reflection : std::false_type {};

template <typename T, bool is_return_map = true>
constexpr inline auto get_members() {
if constexpr (is_reflection<T>::value) {
Expand All @@ -784,7 +798,7 @@ constexpr inline auto get_members() {
return get_members_impl<T>();
}
}
else if constexpr (is_custom_reflection<T>::value) {
else if constexpr (is_custom_reflection_v<T>) {
using U = std::remove_const_t<std::remove_reference_t<T>>;
constexpr size_t Size = iguana_member_count((U *)nullptr);
using value_type = typename user_field_type_t<decltype(get_members_impl(
Expand Down Expand Up @@ -928,12 +942,6 @@ inline auto iguana_reflect_type(const T &t) {
}
}

template <typename T>
inline constexpr bool is_reflection_v = is_reflection<T>::value;

template <typename T>
inline constexpr bool is_custom_reflection_v = is_custom_reflection<T>::value;

template <std::size_t index, template <typename...> typename Condition,
typename Tuple, typename Owner>
constexpr int element_index_helper() {
Expand Down
28 changes: 14 additions & 14 deletions test/test_pb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ struct inner_struct {
int z;
};

inline auto get_members_impl(inner_struct *) {
constexpr inline auto get_members_impl(inner_struct *) {
return std::make_tuple(iguana::field_t{&inner_struct::x, 7, "a"},
iguana::field_t{&inner_struct::y, 9, "b"},
iguana::field_t{&inner_struct::z, 12, "c"});
Expand Down Expand Up @@ -173,19 +173,19 @@ struct numer_st {
REFLECTION(numer_st, a, b, c);

TEST_CASE("test struct_pb") {
// {
// my_space::inner_struct inner{41, 42, 43};

// std::string str;
// iguana::to_pb(inner, str);
// // CHECK(str.size() == iguana::detail::pb_item_size(inner));

// my_space::inner_struct inner1;
// iguana::from_pb(inner1, str);
// CHECK(inner.x == inner1.x);
// CHECK(inner.y == inner1.y);
// CHECK(inner.z == inner1.z);
// }
{
my_space::inner_struct inner{41, 42, 43};

std::string str;
iguana::to_pb(inner, str);
CHECK(str.size() == iguana::detail::pb_item_size(inner));

my_space::inner_struct inner1;
iguana::from_pb(inner1, str);
CHECK(inner.x == inner1.x);
CHECK(inner.y == inner1.y);
CHECK(inner.z == inner1.z);
}

{
test_pb_st1 st1{41, {42}, {43}};
Expand Down

0 comments on commit 5fb40db

Please sign in to comment.