diff --git a/conformance/failure_list_csharp.txt b/conformance/failure_list_csharp.txt index f5ddea6f0f..e16578c329 100644 --- a/conformance/failure_list_csharp.txt +++ b/conformance/failure_list_csharp.txt @@ -33,8 +33,3 @@ Recommended.Editions_Proto3.ValueRejectInfNumberValue.JsonOutput Recommended.Editions_Proto3.ValueRejectNanNumberValue.JsonOutput Required.Editions_Proto2.ProtobufInput.UnknownOrdering.ProtobufOutput Required.Editions_Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput - -# TODO C# doesn't handle delimited parsing well. -Required.Editions.ProtobufInput.ValidDelimitedExtension.NotGroupLike.ProtobufOutput -Required.Editions.ProtobufInput.ValidDelimitedField.NotGroupLike.JsonOutput -Required.Editions.ProtobufInput.ValidDelimitedField.NotGroupLike.ProtobufOutput diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index 0d14be0a4b..7a6a4b9d32 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -192,44 +192,6 @@ std::string GetEnumValueName(absl::string_view enum_name, return result; } -uint GetGroupEndTag(const Descriptor* descriptor) { - const Descriptor* containing_type = descriptor->containing_type(); - if (containing_type != nullptr) { - const FieldDescriptor* field; - for (int i = 0; i < containing_type->field_count(); i++) { - field = containing_type->field(i); - if (field->type() == FieldDescriptor::Type::TYPE_GROUP && - field->message_type() == descriptor) { - return internal::WireFormatLite::MakeTag( - field->number(), internal::WireFormatLite::WIRETYPE_END_GROUP); - } - } - for (int i = 0; i < containing_type->extension_count(); i++) { - field = containing_type->extension(i); - if (field->type() == FieldDescriptor::Type::TYPE_GROUP && - field->message_type() == descriptor) { - return internal::WireFormatLite::MakeTag( - field->number(), internal::WireFormatLite::WIRETYPE_END_GROUP); - } - } - } else { - const FileDescriptor* containing_file = descriptor->file(); - if (containing_file != nullptr) { - const FieldDescriptor* field; - for (int i = 0; i < containing_file->extension_count(); i++) { - field = containing_file->extension(i); - if (field->type() == FieldDescriptor::Type::TYPE_GROUP && - field->message_type() == descriptor) { - return internal::WireFormatLite::MakeTag( - field->number(), internal::WireFormatLite::WIRETYPE_END_GROUP); - } - } - } - } - - return 0; -} - std::string GetFullExtensionName(const FieldDescriptor* descriptor) { if (descriptor->extension_scope()) { return absl::StrCat(GetClassName(descriptor->extension_scope()), diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h index 0396abe280..a7158d23a8 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.h +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h @@ -85,9 +85,6 @@ inline bool IsMapEntryMessage(const Descriptor* descriptor) { return descriptor->options().map_entry(); } -// Checks if this descriptor is for a group and gets its end tag or 0 if it's not a group -uint GetGroupEndTag(const Descriptor* descriptor); - // Determines whether we're generating code for the proto representation of // descriptors etc, for use in the runtime. This is the only type which is // allowed to use proto2 syntax, and it generates internal classes. diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 57e8a71b1e..f8d57cf207 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -43,7 +43,6 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor, : SourceGeneratorBase(options), descriptor_(descriptor), has_bit_field_count_(0), - end_tag_(GetGroupEndTag(descriptor)), has_extension_ranges_(descriptor->extension_range_count() > 0) { // fields by number for (int i = 0; i < descriptor_->field_count(); i++) { @@ -668,18 +667,17 @@ void MessageGenerator::GenerateMainParseLoop(io::Printer* printer, absl::flat_hash_map vars; vars["maybe_ref_input"] = use_parse_context ? "ref input" : "input"; - printer->Print( - "uint tag;\n" - "while ((tag = input.ReadTag()) != 0) {\n" - " switch(tag) {\n"); + printer->Emit(R"csharp( + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + )csharp"); printer->Indent(); printer->Indent(); - if (end_tag_ != 0) { - printer->Print( - "case $end_tag$:\n" - " return;\n", - "end_tag", absl::StrCat(end_tag_)); - } if (has_extension_ranges_) { printer->Print(vars, "default:\n" diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h index 6b08ebd54f..9adced0be8 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.h +++ b/src/google/protobuf/compiler/csharp/csharp_message.h @@ -39,7 +39,6 @@ class MessageGenerator : public SourceGeneratorBase { const Descriptor* descriptor_; std::vector fields_by_number_; int has_bit_field_count_; - uint end_tag_; bool has_extension_ranges_; void GenerateMessageSerializationMethods(io::Printer* printer);