Skip to content

Commit

Permalink
fix get_map_tuple_impl; add oneof test[struct_pb]
Browse files Browse the repository at this point in the history
  • Loading branch information
bbbgan committed May 8, 2024
1 parent 46bbc22 commit bda33a4
Show file tree
Hide file tree
Showing 8 changed files with 239 additions and 52 deletions.
9 changes: 3 additions & 6 deletions iguana/pb_reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ inline void decode_pair_value(T& val, std::string_view& pb_str) {
if (wire_type != detail::get_wire_type<std::remove_reference_t<T>>()) {
return;
}

from_pb_impl(val, pb_str);
}

Expand Down Expand Up @@ -176,13 +175,12 @@ inline void from_pb_impl(T& val, std::string_view& pb_str, uint32_t field_no) {
}

template <typename T, typename Field>
inline void parse_oneof(T& t, Field& f, std::string_view& pb_str) {
inline void parse_oneof(T& t, const Field& f, std::string_view& pb_str) {
using item_type = typename std::decay_t<Field>::value_type;
item_type item{};
from_pb_impl(item, pb_str, f.field_no);
t = std::move(item);
}

} // namespace detail

template <typename T>
Expand All @@ -195,16 +193,15 @@ inline void from_pb(T& t, std::string_view pb_str) {
uint32_t field_number = key >> 3;

pb_str = pb_str.substr(pos);

const static auto& map = get_members<T>();
constexpr static auto map = get_members<T>();
auto& member = map.at(field_number);
std::visit(
[&t, &pb_str, wire_type](auto& val) {
using value_type = typename std::decay_t<decltype(val)>::value_type;
if (wire_type != detail::get_wire_type<value_type>()) {
throw std::runtime_error("unmatched wire_type");
}
using v_type = typename std::decay_t<decltype(val.value(t))>;
using v_type = std::decay_t<decltype(val.value(t))>;
if constexpr (variant_v<v_type>) {
detail::parse_oneof(val.value(t), val, pb_str);
}
Expand Down
3 changes: 2 additions & 1 deletion iguana/pb_util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,8 @@ inline size_t pb_oneof_size(T&& t) {
constexpr uint32_t key =
(field_no << 3) |
static_cast<uint32_t>(get_wire_type<value_type>());
len = pb_key_value_size<key>(std::forward<value_type>(value));
len = pb_key_value_size<variant_uint32_size_constexpr(key)>(
std::forward<value_type>(value));
},
std::forward<T>(t));
return len;
Expand Down
6 changes: 3 additions & 3 deletions iguana/pb_writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ constexpr size_t get_variant_index() {
}

template <uint32_t field_no, typename Type, typename Stream>
inline void render_variant(Type&& t, Stream& out) {
inline void to_pb_oneof(Type&& t, Stream& out) {
std::visit(
[&out](auto&& value) {
using value_type =
Expand All @@ -104,7 +104,7 @@ inline void render_variant(Type&& t, Stream& out) {
constexpr uint32_t key =
((field_no + offset) << 3) |
static_cast<uint32_t>(get_wire_type<value_type>());
to_pb_impl<key, true>(std::forward<value_type>(value), out);
to_pb_impl<key, false>(std::forward<value_type>(value), out);
},
std::forward<Type>(t));
}
Expand Down Expand Up @@ -132,7 +132,7 @@ inline void to_pb_impl(Type&& t, Stream& out) {
constexpr auto value = std::get<decltype(i)::value>(tp);
using U = typename std::decay_t<decltype(value.value(t))>;
if constexpr (variant_v<U>) {
render_variant<value.field_no>(value.value(t), out);
to_pb_oneof<value.field_no>(value.value(t), out);
}
else {
constexpr uint32_t sub_key =
Expand Down
43 changes: 23 additions & 20 deletions iguana/reflection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -773,8 +773,8 @@ constexpr inline auto arr_jump_n(const Arr &type_options_arr) {
return I ? type_options_arr[I - 1] - 1 : 0;
}

template <typename T, typename U, size_t... I, typename Arr>
constexpr inline auto get_field_tuple_impl(T &&tp, U &&arr,
template <typename Tuple, typename U, size_t... I, typename Arr>
constexpr inline auto get_field_tuple_impl(Tuple &&tp, U &&arr,
std::index_sequence<I...> &&,
const Arr &type_options_arr) {
return std::make_tuple(
Expand Down Expand Up @@ -819,26 +819,30 @@ constexpr inline auto get_offset_arr() {
}

template <std::size_t N, typename T>
constexpr inline auto prefix_sum(const std::array<T, N> arr) {
std::array<T, N> presums{};
presums[0] = 0;
constexpr inline auto get_remap_arr(const std::array<T, N> arr) {
std::array<T, N> remap_arr{};
remap_arr[0] = 0;
size_t offset = 0;
for (size_t i = 1; i < N; ++i) {
presums[i] = presums[i - 1] + arr[i];
if (arr[i] < arr[i - 1]) {
offset += arr[i - 1];
}
remap_arr[i] = offset + arr[i];
}
return presums;
return remap_arr;
}

template <typename T, typename U, size_t... I>
constexpr inline auto get_members_tuple_impl(T &&tp, U &&arr,
std::index_sequence<I...> &&) {
constexpr auto offset_arr = get_offset_arr<sizeof...(I), T>();
constexpr auto presums = prefix_sum(offset_arr);
constexpr auto remap_arr = get_remap_arr(offset_arr);
return std::make_tuple(
field_t<std::tuple_element_t<I - presums[I], T>,
variant_type_at_t<std::tuple_element_t<I - presums[I], T>,
field_t<std::tuple_element_t<I - remap_arr[I], T>,
variant_type_at_t<std::tuple_element_t<I - remap_arr[I], T>,
offset_arr[I]>>{
std::get<I - presums[I]>(tp), I + 1,
frozen::string(arr[I - presums[I]].data()),
std::get<I - remap_arr[I]>(tp), I + 1,
frozen::string(arr[I - remap_arr[I]].data()),
static_cast<uint32_t>(offset_arr[I])}...);
}

Expand All @@ -862,22 +866,21 @@ constexpr inline auto get_members_tuple() {
}

template <typename T, size_t Size, typename Tuple, size_t... I>
constexpr auto inline get_members_custom(Tuple &&tp,
std::index_sequence<I...>) {
constexpr auto inline get_members_impl(Tuple &&tp, std::index_sequence<I...>) {
return frozen::unordered_map<uint32_t, T, sizeof...(I)>{
{std::get<I>(tp).field_no,
T{std::in_place_index<I>, std::move(std::get<I>(tp))}}...};
}

template <typename T>
constexpr inline auto get_members() {
if constexpr (is_reflection<T>::value || is_custom_reflection_v<T>) {
if constexpr (is_reflection_v<T> || is_custom_reflection_v<T>) {
constexpr auto tp = get_members_tuple<T>();
using value_type =
typename field_type_t<std::decay_t<decltype(tp)>>::value_type;
constexpr auto Size = std::tuple_size_v<decltype(tp)>;
return get_members_custom<value_type, Size>(
tp, std::make_index_sequence<Size>{});
using Tuple = std::decay_t<decltype(tp)>;
using value_type = typename field_type_t<Tuple>::value_type;
constexpr auto Size = std::tuple_size_v<Tuple>;
return get_members_impl<value_type, Size>(tp,
std::make_index_sequence<Size>{});
}
else {
static_assert(!sizeof(T), "expected reflection or custom reflection");
Expand Down
14 changes: 9 additions & 5 deletions test/proto/unittest_proto3.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,14 @@ REFLECTION(MapMsg, sfix64_str_map, str_iguana_type_msg_map,
int_repeat_base_msg_map);

struct BaseOneofMsg {
int x;
std::variant<double, std::string> y;
double z;
int32_t optional_int32;
std::variant<double, std::string, BaseTypeMsg> one_of;
double optional_double;
};
REFLECTION(BaseOneofMsg, x, y, z);
REFLECTION(BaseOneofMsg, optional_int32, one_of, optional_double);

} // namespace stpb
struct NestOneofMsg {
std::variant<std::string, BaseOneofMsg> nest_one_of_msg;
};
REFLECTION(NestOneofMsg, nest_one_of_msg);
} // namespace stpb
22 changes: 13 additions & 9 deletions test/proto/unittest_proto3.proto
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,19 @@ message MapMsg {
}

message BaseOneofMsg {
int32 x = 1;
oneof y {
double double_value = 2;
string string_value = 3;
}
float z = 4;
int32 optional_int32 = 1;
oneof one_of {
double one_of_double = 2;
string one_of_string = 3;
BaseTypeMsg one_of_base_type_msg = 4;
}
double optional_double = 5;
}




message NestOneofMsg {
oneof nest_one_of_msg {
string base_one_of_string = 1;
BaseOneofMsg base_one_of_msg = 2;
}
}

20 changes: 12 additions & 8 deletions test/test_pb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,6 @@ constexpr inline auto get_members_impl(inner_struct *) {
iguana::field_t{&inner_struct::y, 9, "b"},
iguana::field_t{&inner_struct::z, 12, "c"});
}

inline constexpr size_t iguana_member_count(inner_struct *) { return 3; }

std::integral_constant<size_t, 3> member_count(inner_struct);

} // namespace my_space

struct test_pb_st1 {
Expand Down Expand Up @@ -438,7 +433,7 @@ TEST_CASE("test members") {

struct test_variant {
int x;
std::variant<double, std::string> y;
std::variant<double, std::string, int> y;
double z;
};
REFLECTION(test_variant, x, y, z);
Expand All @@ -448,7 +443,7 @@ TEST_CASE("test variant") {
constexpr auto tp = iguana::get_field_tuple<test_variant>();
static_assert(std::get<0>(tp).field_no == 1);
static_assert(std::get<1>(tp).field_no == 2);
static_assert(std::get<2>(tp).field_no == 4);
static_assert(std::get<2>(tp).field_no == 5);
}
{
constexpr static auto map = iguana::get_members<test_variant>();
Expand Down Expand Up @@ -477,10 +472,19 @@ TEST_CASE("test variant") {
test_variant st1 = {5, "Hello, variant!", 3.14};
std::string str;
iguana::to_pb(st1, str);
print_hex_str(str);
test_variant st2;
iguana::from_pb(st2, str);
CHECK(st1.z == st2.z);
CHECK(std::get<std::string>(st2.y) == "Hello, variant!");
}
{
test_variant st1 = {5, 3.88, 3.14};
std::string str;
iguana::to_pb(st1, str);
test_variant st2;
iguana::from_pb(st2, str);
CHECK(st1.z == st2.z);
CHECK(std::get<double>(st2.y) == 3.88);
}
}

Expand Down
Loading

0 comments on commit bda33a4

Please sign in to comment.