From 1d8c07a64316f1eddb76851904407d5942756c4c Mon Sep 17 00:00:00 2001 From: qicosmos Date: Mon, 15 Apr 2024 15:56:26 +0800 Subject: [PATCH] fix --- iguana/struct_pb.hpp | 69 ++++++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 19 deletions(-) diff --git a/iguana/struct_pb.hpp b/iguana/struct_pb.hpp index 6a10c8ed..87c873b8 100644 --- a/iguana/struct_pb.hpp +++ b/iguana/struct_pb.hpp @@ -233,22 +233,45 @@ inline void from_pb_impl(T& val, std::string_view& pb_str, uint32_t field_no) { pb_str = pb_str.substr(size); } else if constexpr (is_sequence_container::value) { - size_t pos; - uint32_t size = detail::decode_varint(pb_str, pos); - if (pb_str.size() < size) { - throw std::invalid_argument("Invalid fixed int value: too few bytes."); + using item_type = typename value_type::value_type; + if constexpr (is_reflection_v) { + // message no size + while (!pb_str.empty()) { + item_type item; + from_pb_impl(item, pb_str); + val.push_back(std::move(item)); + if (pb_str.empty()) { + break; + } + uint32_t key = detail::decode_varint(pb_str, pos); + uint32_t field_number = key >> 3; + if (field_number != field_no) { + break; + } + else { + pb_str = pb_str.substr(pos); + } + } } - pb_str = pb_str.substr(pos); + else { + // non-message has size + size_t pos; + uint32_t size = detail::decode_varint(pb_str, pos); + if (pb_str.size() < size) { + throw std::invalid_argument("Invalid fixed int value: too few bytes."); + } + pb_str = pb_str.substr(pos); - using item_type = typename value_type::value_type; - size_t start = pb_str.size(); + using item_type = typename value_type::value_type; + size_t start = pb_str.size(); - while (!pb_str.empty()) { - item_type item; - from_pb_impl(item, pb_str); - val.push_back(std::move(item)); - if (start - pb_str.size() == size) { - break; + while (!pb_str.empty()) { + item_type item; + from_pb_impl(item, pb_str); + val.push_back(std::move(item)); + if (start - pb_str.size() == size) { + break; + } } } } @@ -360,12 +383,20 @@ inline void to_pb_impl(T& val, size_t field_no, std::string& out) { detail::encode_string_field(field_no, WireType::LengthDelimeted, temp, out); } else if constexpr (is_sequence_container::value) { - std::string temp; using item_type = typename value_type::value_type; - for (auto& item : val) { - to_pb_impl(item, 0, temp); + if constexpr (is_reflection_v) { + for (auto& item : val) { + to_pb_impl(item, field_no, out); + } + } + else { + std::string temp; + for (auto& item : val) { + to_pb_impl(item, 0, temp); + } + detail::encode_string_field(field_no, WireType::LengthDelimeted, temp, + out); } - detail::encode_string_field(field_no, WireType::LengthDelimeted, temp, out); } else if constexpr (is_map_container::value) { using first_type = typename value_type::key_type; @@ -443,7 +474,7 @@ inline void from_pb(T& t, std::string_view pb_str) { pb_str = pb_str.substr(pos); - const auto& map = get_members(t); + const static auto& map = get_members(t); uint32_t sub_val = 1; if constexpr (!is_reflection_v) { sub_val = 0; @@ -475,7 +506,7 @@ inline void from_pb(T& t, std::string_view pb_str) { template inline void to_pb(T& t, std::string& out) { - const auto& map = get_members(t); + const static auto& map = get_members(t); for (auto& [field_no, member] : map) { std::visit( [&t, &out](auto& val) {