diff --git a/iguana/pb_reader.hpp b/iguana/pb_reader.hpp index 791a5c39..d5482508 100644 --- a/iguana/pb_reader.hpp +++ b/iguana/pb_reader.hpp @@ -38,8 +38,7 @@ inline void from_pb_impl(T& val, std::string_view& pb_str, uint32_t field_no) { if (size == 0) { return; } - - from_pb(val, pb_str); + from_pb(val, pb_str.substr(0, size)); pb_str = pb_str.substr(size); } else if constexpr (is_sequence_container::value) { @@ -47,7 +46,7 @@ inline void from_pb_impl(T& val, std::string_view& pb_str, uint32_t field_no) { if constexpr (is_lenprefix_v) { // item_type non-packed while (!pb_str.empty()) { - item_type item; + item_type item{}; // init the default value from_pb_impl(item, pb_str); val.push_back(std::move(item)); if (pb_str.empty()) { @@ -187,9 +186,6 @@ inline constexpr size_t get_member_count_impl() { template inline void from_pb(T& t, std::string_view pb_str) { - using U = std::remove_const_t>; - constexpr size_t Count = get_member_count_impl(); - size_t pos = 0; while (!pb_str.empty()) { uint32_t key = detail::decode_varint(pb_str, pos); @@ -208,7 +204,7 @@ inline void from_pb(T& t, std::string_view pb_str) { [&t, &pb_str, wire_type](auto& val) { using value_type = typename std::decay_t::value_type; if (wire_type != detail::get_wire_type()) { - return; + throw std::runtime_error("unmatched wire_type"); } if constexpr (detail::is_signed_varint_v || detail::is_fixed_v) { @@ -220,10 +216,6 @@ inline void from_pb(T& t, std::string_view pb_str) { } }, member); - - if (field_number == Count) { - break; - } } } } // namespace iguana \ No newline at end of file diff --git a/test/proto/unittest_proto3.h b/test/proto/unittest_proto3.h index c28e2b0b..cf692d34 100644 --- a/test/proto/unittest_proto3.h +++ b/test/proto/unittest_proto3.h @@ -72,23 +72,28 @@ REFLECTION(RepeatBaseTypeMsg, repeated_uint32, repeated_uint64, repeated_int32, repeated_int64, repeated_float, repeated_double, repeated_string, repeated_enum); -// struct RepeatIguanaTypeMSg { -// std::vector repeated_sint32; -// std::vector repeated_sint64; -// std::vector repeated_fixed32; -// std::vector repeated_fixed64; -// std::vector repeated_sfixed32; -// std::vector repeated_sfixed64; -// }; +struct RepeatIguanaTypeMsg { + std::vector repeated_sint32; + std::vector repeated_sint64; + std::vector repeated_fixed32; + std::vector repeated_fixed64; + std::vector repeated_sfixed32; + std::vector repeated_sfixed64; +}; -// struct NestedMsg { -// BaseTypeMsg base_msg; -// std::vector repeat_base_msg; -// std::vector repeat_repeat_base_msg; -// std::vector repeat_iguna_msg; -// std::vector repeat_repeat_iguana_msg; -// iguana::one_of_t> nest_oneof; -// }; +REFLECTION(RepeatIguanaTypeMsg, repeated_sint32, repeated_sint64, + repeated_fixed32, repeated_fixed64, repeated_sfixed32, + repeated_sfixed64); + +struct NestedMsg { + BaseTypeMsg base_msg; + std::vector repeat_base_msg; + IguanaTypeMsg iguana_type_msg; + std::vector repeat_iguna_msg; + std::vector repeat_repeat_base_msg; +}; +REFLECTION(NestedMsg, base_msg, repeat_base_msg, iguana_type_msg, + repeat_iguna_msg, repeat_repeat_base_msg); // struct MapMsg { // std::unordered_map sfix64_str_map; diff --git a/test/proto/unittest_proto3.proto b/test/proto/unittest_proto3.proto index 2a5aeca1..28022c9e 100644 --- a/test/proto/unittest_proto3.proto +++ b/test/proto/unittest_proto3.proto @@ -56,13 +56,9 @@ message RepeatIguanaTypeMsg { message NestedMsg { BaseTypeMsg base_msg = 1; repeated BaseTypeMsg repeat_base_msg = 2; - repeated RepeatBaseTypeMsg repeat_repeat_base_msg = 3; + IguanaTypeMsg iguana_type_msg = 3; repeated IguanaTypeMsg repeat_iguna_msg = 4; - repeated RepeatIguanaTypeMsg repeat_repeat_iguana_msg = 5; - oneof nest_oneof { - BaseTypeMsg nest_oneof_base_msg = 6; - string nest_oneof_string = 7; - } + repeated RepeatBaseTypeMsg repeat_repeat_base_msg = 5; } message MapMsg { diff --git a/test/test_pb.cpp b/test/test_pb.cpp index a1d1c9b5..a72e8618 100644 --- a/test/test_pb.cpp +++ b/test/test_pb.cpp @@ -152,8 +152,8 @@ REFLECTION(person, name, age); struct my_struct { int x; - int y; - int z; + bool y; + iguana::fixed64_t z; }; REFLECTION(my_struct, x, y, z); @@ -265,11 +265,13 @@ TEST_CASE("test struct_pb") { } { // sub nested objects - nest1 v{"Hi", {1, 2, 3}, 5}, v2; + nest1 v{"Hi", {1, false, {3}}, 5}, v2{}; std::string s; iguana::to_pb(v, s); iguana::from_pb(v2, s); CHECK(v.var == v2.var); + CHECK(v.value.y == v2.value.y); + CHECK(v.value.z == v2.value.z); test_pb_st8 st1{1, {3, 4}, {5, {7, 8}}}; std::string str; diff --git a/test/test_proto3.cpp b/test/test_proto3.cpp index 3108d930..9831e09f 100644 --- a/test/test_proto3.cpp +++ b/test/test_proto3.cpp @@ -216,6 +216,187 @@ TEST_CASE("test RepeatBaseTypeMsg") { } } +void SetRepeatIguanaTypeMsg(const stpb::RepeatIguanaTypeMsg& st, + pb::RepeatIguanaTypeMsg& msg) { + for (auto v : st.repeated_sint32) { + msg.add_repeated_sint32(v.val); + } + for (auto v : st.repeated_sint64) { + msg.add_repeated_sint64(v.val); + } + for (auto v : st.repeated_fixed32) { + msg.add_repeated_fixed32(v.val); + } + for (auto v : st.repeated_fixed64) { + msg.add_repeated_fixed64(v.val); + } + for (auto v : st.repeated_sfixed32) { + msg.add_repeated_sfixed32(v.val); + } + for (auto v : st.repeated_sfixed64) { + msg.add_repeated_sfixed64(v.val); + } +} + +void CheckRepeatIguanaTypeMsg(const stpb::RepeatIguanaTypeMsg& st, + const pb::RepeatIguanaTypeMsg& msg) { + for (int i = 0; i < st.repeated_sint32.size(); ++i) { + CHECK(st.repeated_sint32[i].val == msg.repeated_sint32(i)); + } + for (int i = 0; i < st.repeated_sint64.size(); ++i) { + CHECK(st.repeated_sint64[i].val == msg.repeated_sint64(i)); + } + for (int i = 0; i < st.repeated_fixed32.size(); ++i) { + CHECK(st.repeated_fixed32[i].val == msg.repeated_fixed32(i)); + } + for (int i = 0; i < st.repeated_fixed64.size(); ++i) { + CHECK(st.repeated_fixed64[i].val == msg.repeated_fixed64(i)); + } + for (int i = 0; i < st.repeated_sfixed32.size(); ++i) { + CHECK(st.repeated_sfixed32[i].val == msg.repeated_sfixed32(i)); + } + for (int i = 0; i < st.repeated_sfixed64.size(); ++i) { + CHECK(st.repeated_sfixed64[i].val == msg.repeated_sfixed64(i)); + } +} + +TEST_CASE("test RepeatIguanaTypeMsg") { + { + stpb::RepeatIguanaTypeMsg se_st{ + {{1}, {2}, {3}}, {{4}, {5}, {6}}, {{7}, {8}, {9}}, + {{10}, {11}, {12}}, {{13}, {14}, {15}}, {{16}, {17}, {18}}, + }; + std::string st_ss; + iguana::to_pb(se_st, st_ss); + + pb::RepeatIguanaTypeMsg se_msg; + SetRepeatIguanaTypeMsg(se_st, se_msg); + std::string pb_ss; + se_msg.SerializeToString(&pb_ss); + CHECK(st_ss == pb_ss); + + stpb::RepeatIguanaTypeMsg dese_st; + iguana::from_pb(dese_st, st_ss); + pb::RepeatIguanaTypeMsg dese_msg; + dese_msg.ParseFromString(pb_ss); + CheckRepeatIguanaTypeMsg(dese_st, dese_msg); + } +} + +void SetNestedMsg(const stpb::NestedMsg& st, pb::NestedMsg& msg) { + SetBaseTypeMsg(st.base_msg, *msg.mutable_base_msg()); + + for (const auto& base_msg : st.repeat_base_msg) { + auto* base_msg_ptr = msg.add_repeat_base_msg(); + SetBaseTypeMsg(base_msg, *base_msg_ptr); + } + + SetIguanaTypeMsg(st.iguana_type_msg, *msg.mutable_iguana_type_msg()); + + for (const auto& iguana_type_msg : st.repeat_iguna_msg) { + auto* iguana_type_msg_ptr = msg.add_repeat_iguna_msg(); + SetIguanaTypeMsg(iguana_type_msg, *iguana_type_msg_ptr); + } + + for (const auto& repeat_base_msg : st.repeat_repeat_base_msg) { + auto* repeat_base_msg_ptr = msg.add_repeat_repeat_base_msg(); + SetRepeatBaseTypeMsg(repeat_base_msg, *repeat_base_msg_ptr); + } +} + +void CheckNestedMsg(const stpb::NestedMsg& st, const pb::NestedMsg& msg) { + CheckBaseTypeMsg(st.base_msg, msg.base_msg()); + + CHECK(st.repeat_base_msg.size() == msg.repeat_base_msg_size()); + for (int i = 0; i < st.repeat_base_msg.size(); ++i) { + CheckBaseTypeMsg(st.repeat_base_msg[i], msg.repeat_base_msg(i)); + } + + CheckIguanaTypeMsg(st.iguana_type_msg, msg.iguana_type_msg()); + + CHECK(st.repeat_iguna_msg.size() == msg.repeat_iguna_msg_size()); + for (int i = 0; i < st.repeat_iguna_msg.size(); ++i) { + CheckIguanaTypeMsg(st.repeat_iguna_msg[i], msg.repeat_iguna_msg(i)); + } + + CHECK(st.repeat_repeat_base_msg.size() == msg.repeat_repeat_base_msg_size()); + for (int i = 0; i < st.repeat_repeat_base_msg.size(); ++i) { + CheckRepeatBaseTypeMsg(st.repeat_repeat_base_msg[i], + msg.repeat_repeat_base_msg(i)); + } +} + +TEST_CASE("test RepeatIguanaTypeMsg") { + { + stpb::RepeatIguanaTypeMsg se_st{ + {{1}, {2}, {3}}, {{4}, {5}, {6}}, {{7}, {8}, {9}}, + {{10}, {11}, {12}}, {{13}, {14}, {15}}, {{16}, {17}, {18}}, + }; + std::string st_ss; + iguana::to_pb(se_st, st_ss); + + pb::RepeatIguanaTypeMsg se_msg; + SetRepeatIguanaTypeMsg(se_st, se_msg); + std::string pb_ss; + se_msg.SerializeToString(&pb_ss); + CHECK(st_ss == pb_ss); + + stpb::RepeatIguanaTypeMsg dese_st; + iguana::from_pb(dese_st, st_ss); + pb::RepeatIguanaTypeMsg dese_msg; + dese_msg.ParseFromString(pb_ss); + CheckRepeatIguanaTypeMsg(dese_st, dese_msg); + } +} + +TEST_CASE("test NestedMsg") { + stpb::NestedMsg se_st{ + /* base_msg */ {100, 200, 300, 400, 31.4f, 62.8, false, "World", + stpb::Enum::BAZ}, + /* repeat_base_msg */ + {{1, 2, 3, 4, 5.5f, 6.6, true, "Hello", stpb::Enum::FOO}, + {7, 8, 9, 10, 11.11f, 12.12, false, "Hi", stpb::Enum::BAR}}, + /* iguana_type_msg */ {{100}, {200}, {300}, {400}, {31}, {32}}, + /* repeat_iguna_msg */ + {{{1}, {2}, {3}}, {{4}, {5}, {6}}, {{7}, {8}, {9}}}, + /* repeat_repeat_base_msg */ + {{{1, 2, 3}, + {4, 5, 6}, + {7, 8, 9}, + {10, 11, 12}, + {13.1, 14.2, 15.3}, + {16.4, 17.5, 18.6}, + {"a", "b", "c"}, + {stpb::Enum::FOO, stpb::Enum::BAR, stpb::Enum::BAZ}}, + {{19, 20, 21}, + {22, 23, 24}, + {25, 26, 27}, + {28, 29, 30}, + {31.1, 32.2, 33.3}, + {34.4, 35.5, 36.6}, + {"x", "y", "z"}, + {stpb::Enum::ZERO, stpb::Enum::NEG, stpb::Enum::FOO}}}}; + + std::string st_ss; + iguana::to_pb(se_st, st_ss); + + pb::NestedMsg se_msg; + SetNestedMsg(se_st, se_msg); + + std::string pb_ss; + se_msg.SerializeToString(&pb_ss); + + CHECK(st_ss == pb_ss); + + stpb::NestedMsg dese_st; + iguana::from_pb(dese_st, st_ss); + + pb::NestedMsg dese_msg; + dese_msg.ParseFromString(pb_ss); + + CheckNestedMsg(dese_st, dese_msg); +} + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4007) int main(int argc, char** argv) { return doctest::Context(argc, argv).run(); } DOCTEST_MSVC_SUPPRESS_WARNING_POP \ No newline at end of file