3737#include < utility>
3838
3939#include " absl/base/optimization.h"
40+ #include " absl/log/absl_check.h"
4041#include " google/protobuf/generated_message_tctable_decl.h"
4142#include " google/protobuf/generated_message_tctable_impl.h"
4243#include " google/protobuf/inlined_string_field.h"
@@ -2357,7 +2358,17 @@ PROTOBUF_NOINLINE const char* TcParser::MpMessage(PROTOBUF_TC_PARAM_DECL) {
23572358
23582359 // Check for repeated parsing:
23592360 if (card == field_layout::kFcRepeated ) {
2360- PROTOBUF_MUSTTAIL return MpRepeatedMessage (PROTOBUF_TC_PARAM_PASS);
2361+ const uint16_t rep = type_card & field_layout::kRepMask ;
2362+ switch (rep) {
2363+ case field_layout::kRepMessage :
2364+ PROTOBUF_MUSTTAIL return MpRepeatedMessageOrGroup<false >(
2365+ PROTOBUF_TC_PARAM_PASS);
2366+ case field_layout::kRepGroup :
2367+ PROTOBUF_MUSTTAIL return MpRepeatedMessageOrGroup<true >(
2368+ PROTOBUF_TC_PARAM_PASS);
2369+ default :
2370+ PROTOBUF_MUSTTAIL return table->fallback (PROTOBUF_TC_PARAM_PASS);
2371+ }
23612372 }
23622373
23632374 const uint32_t decoded_tag = data.tag ();
@@ -2422,30 +2433,26 @@ PROTOBUF_NOINLINE const char* TcParser::MpMessage(PROTOBUF_TC_PARAM_DECL) {
24222433 }
24232434}
24242435
2425- const char * TcParser::MpRepeatedMessage (PROTOBUF_TC_PARAM_DECL) {
2436+ template <bool is_group>
2437+ const char * TcParser::MpRepeatedMessageOrGroup (PROTOBUF_TC_PARAM_DECL) {
24262438 const auto & entry = RefAt<FieldEntry>(table, data.entry_offset ());
24272439 const uint16_t type_card = entry.type_card ;
24282440 ABSL_DCHECK_EQ (type_card & field_layout::kFcMask ,
24292441 static_cast <uint16_t >(field_layout::kFcRepeated ));
24302442 const uint32_t decoded_tag = data.tag ();
24312443 const uint32_t decoded_wiretype = decoded_tag & 7 ;
2432- const uint16_t rep = type_card & field_layout::kRepMask ;
2433- const bool is_group = rep == field_layout::kRepGroup ;
24342444
24352445 // Validate wiretype:
2436- switch (rep) {
2437- case field_layout::kRepMessage :
2438- if (decoded_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
2439- goto fallback;
2440- }
2441- break ;
2442- case field_layout::kRepGroup :
2443- if (decoded_wiretype != WireFormatLite::WIRETYPE_START_GROUP) {
2444- goto fallback;
2445- }
2446- break ;
2447- default : {
2448- fallback:
2446+ if (!is_group) {
2447+ ABSL_DCHECK_EQ (type_card & field_layout::kRepMask ,
2448+ static_cast <uint16_t >(field_layout::kRepMessage ));
2449+ if (decoded_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
2450+ PROTOBUF_MUSTTAIL return table->fallback (PROTOBUF_TC_PARAM_PASS);
2451+ }
2452+ } else {
2453+ ABSL_DCHECK_EQ (type_card & field_layout::kRepMask ,
2454+ static_cast <uint16_t >(field_layout::kRepGroup ));
2455+ if (decoded_wiretype != WireFormatLite::WIRETYPE_START_GROUP) {
24492456 PROTOBUF_MUSTTAIL return table->fallback (PROTOBUF_TC_PARAM_PASS);
24502457 }
24512458 }
@@ -2455,27 +2462,47 @@ const char* TcParser::MpRepeatedMessage(PROTOBUF_TC_PARAM_DECL) {
24552462 const auto aux = *table->field_aux (&entry);
24562463 if ((type_card & field_layout::kTvMask ) == field_layout::kTvTable ) {
24572464 auto * inner_table = aux.table ;
2458- MessageLite* value = field.Add <GenericTypeHandler<MessageLite>>(
2459- inner_table->default_instance );
2460- if (is_group) {
2461- return ctx->ParseGroup <TcParser>(value, ptr, decoded_tag, inner_table);
2462- }
2463- return ctx->ParseMessage <TcParser>(value, ptr, inner_table);
2465+ const MessageLite* default_instance = inner_table->default_instance ;
2466+ const char * ptr2 = ptr;
2467+ uint32_t next_tag;
2468+ do {
2469+ MessageLite* value =
2470+ field.Add <GenericTypeHandler<MessageLite>>(default_instance);
2471+ ptr = is_group ? ctx->ParseGroup <TcParser>(value, ptr2, decoded_tag,
2472+ inner_table)
2473+ : ctx->ParseMessage <TcParser>(value, ptr2, inner_table);
2474+ if (ptr == nullptr ) goto error;
2475+ if (!ctx->DataAvailable (ptr)) goto parse_loop;
2476+ ptr2 = ReadTag (ptr, &next_tag);
2477+ if (ptr2 == nullptr ) goto error;
2478+ } while (next_tag == decoded_tag);
24642479 } else {
2465- const MessageLite* def ;
2480+ const MessageLite* default_instance ;
24662481 if ((type_card & field_layout::kTvMask ) == field_layout::kTvDefault ) {
2467- def = aux.message_default ();
2482+ default_instance = aux.message_default ();
24682483 } else {
24692484 ABSL_DCHECK_EQ (type_card & field_layout::kTvMask ,
24702485 +field_layout::kTvWeakPtr );
2471- def = aux.message_default_weak ();
2486+ default_instance = aux.message_default_weak ();
24722487 }
2473- MessageLite* value = field.Add <GenericTypeHandler<MessageLite>>(def);
2474- if (is_group) {
2475- return ctx->ParseGroup (value, ptr, decoded_tag);
2476- }
2477- return ctx->ParseMessage (value, ptr);
2488+ const char * ptr2 = ptr;
2489+ uint32_t next_tag;
2490+ do {
2491+ MessageLite* value =
2492+ field.Add <GenericTypeHandler<MessageLite>>(default_instance);
2493+ ptr = is_group ? ctx->ParseGroup (value, ptr2, decoded_tag)
2494+ : ctx->ParseMessage (value, ptr2);
2495+ if (ptr == nullptr ) goto error;
2496+ if (!ctx->DataAvailable (ptr)) goto parse_loop;
2497+ ptr2 = ReadTag (ptr, &next_tag);
2498+ if (ptr2 == nullptr ) goto error;
2499+ } while (next_tag == decoded_tag);
24782500 }
2501+ PROTOBUF_MUSTTAIL return ToTagDispatch (PROTOBUF_TC_PARAM_NO_DATA_PASS);
2502+ parse_loop:
2503+ PROTOBUF_MUSTTAIL return ToParseLoop (PROTOBUF_TC_PARAM_NO_DATA_PASS);
2504+ error:
2505+ PROTOBUF_MUSTTAIL return Error (PROTOBUF_TC_PARAM_NO_DATA_PASS);
24792506}
24802507
24812508static void SerializeMapKey (const NodeBase* node, MapTypeCard type_card,
0 commit comments