diff options
Diffstat (limited to 'src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc')
-rw-r--r-- | src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc | 83 |
1 files changed, 41 insertions, 42 deletions
diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc index eb3791ec..75ef5e50 100644 --- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc @@ -50,35 +50,34 @@ WrapperFieldGenerator::WrapperFieldGenerator(const FieldDescriptor* descriptor, : FieldGeneratorBase(descriptor, fieldOrdinal) { variables_["has_property_check"] = name() + "_ != null"; variables_["has_not_property_check"] = name() + "_ == null"; - variables_["message_type_name"] = GetClassName(descriptor->message_type()); const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0); is_value_type = wrapped_field->type() != FieldDescriptor::TYPE_STRING && wrapped_field->type() != FieldDescriptor::TYPE_BYTES; - variables_["deref"] = is_value_type ? ".Value" : ""; - // This will always be a single byte, because it's always field 1. - variables_["message_tag_bytes"] = SimpleItoa(FixedMakeTag(wrapped_field)); + if (is_value_type) { + variables_["nonnullable_type_name"] = type_name(wrapped_field); + } } WrapperFieldGenerator::~WrapperFieldGenerator() { } void WrapperFieldGenerator::GenerateMembers(io::Printer* printer) { - // Back the underlying property with an underlying message. This isn't efficient, - // but it makes it easier to be compliant with what platforms which don't support wrapper - // types would do. Currently, each time the value is changed, we create a new instance. - // With suitable care to avoid aliasing, we could probably check whether or not we've already - // got an instance, and simply mutate the existing one. + printer->Print( + variables_, + "private static readonly pb::FieldCodec<$type_name$> _single_$name$_codec = "); + GenerateCodecCode(printer); printer->Print( variables_, - "private $message_type_name$ $name$_;\n"); + ";\n" + "private $type_name$ $name$_;\n"); AddDeprecatedFlag(printer); printer->Print( variables_, "$access_level$ $type_name$ $property_name$ {\n" - " get { return $name$_ == null ? ($type_name$) null : $name$_.Value; }\n" + " get { return $name$_; }\n" " set {\n" " pb::Freezable.CheckMutable(this);\n" - " $name$_ = value == null ? null : new $message_type_name$ { Value = value$deref$ };\n" + " $name$_ = value;\n" " }\n" "}\n"); } @@ -87,28 +86,26 @@ void WrapperFieldGenerator::GenerateMergingCode(io::Printer* printer) { printer->Print( variables_, "if (other.$has_property_check$) {\n" - " if ($has_not_property_check$) {\n" - " $name$_ = new $message_type_name$();\n" + " if ($has_not_property_check$ || other.$property_name$ != $default_value$) {\n" + " $property_name$ = other.$property_name$;\n" " }\n" - " $name$_.MergeFrom(other.$name$_);\n" "}\n"); } void WrapperFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "if ($has_not_property_check$) {\n" - " $name$_ = new $message_type_name$();\n" - "}\n" - "input.ReadMessage($name$_);\n"); // No need to support TYPE_GROUP... + "$type_name$ value = _single_$name$_codec.Read(input);\n" + "if ($has_not_property_check$ || value != $default_value$) {\n" + " $property_name$ = value;\n" + "}\n"); } void WrapperFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " output.WriteRawTag($tag_bytes$);\n" - " output.WriteMessage($name$_);\n" + " _single_$name$_codec.WriteTagAndValue(output, $property_name$);\n" "}\n"); } @@ -116,7 +113,7 @@ void WrapperFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($name$_);\n" + " size += _single_$name$_codec.CalculateSizeWithTag($property_name$);\n" "}\n"); } @@ -137,16 +134,20 @@ void WrapperFieldGenerator::WriteToString(io::Printer* printer) { } void WrapperFieldGenerator::GenerateCloningCode(io::Printer* printer) { - // This will effectively perform a deep clone - it will create a new - // underlying message if necessary printer->Print(variables_, "$property_name$ = other.$property_name$;\n"); } void WrapperFieldGenerator::GenerateCodecCode(io::Printer* printer) { - printer->Print( - variables_, - "pb::FieldCodec.ForWrapperType<$type_name$, $message_type_name$>($tag$, $message_type_name$.Parser)"); + if (is_value_type) { + printer->Print( + variables_, + "pb::FieldCodec.ForStructWrapper<$nonnullable_type_name$>($tag$)"); + } else { + printer->Print( + variables_, + "pb::FieldCodec.ForClassWrapper<$type_name$>($tag$)"); + } } WrapperOneofFieldGenerator::WrapperOneofFieldGenerator(const FieldDescriptor* descriptor, @@ -159,48 +160,46 @@ WrapperOneofFieldGenerator::~WrapperOneofFieldGenerator() { } void WrapperOneofFieldGenerator::GenerateMembers(io::Printer* printer) { + // Note: deliberately _oneof_$name$_codec, not _$oneof_name$_codec... we have one codec per field. + printer->Print( + variables_, + "private static readonly pb::FieldCodec<$type_name$> _oneof_$name$_codec = "); + GenerateCodecCode(printer); + printer->Print(";\n"); AddDeprecatedFlag(printer); printer->Print( variables_, "$access_level$ $type_name$ $property_name$ {\n" - " get { return $has_property_check$ ? (($message_type_name$) $oneof_name$_).Value : ($type_name$) null; }\n" + " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : ($type_name$) null; }\n" " set {\n" " pb::Freezable.CheckMutable(this);\n" - " $oneof_name$_ = value == null ? null : new $message_type_name$ { Value = value$deref$ };\n" + " $oneof_name$_ = value;\n" " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n" " }\n" "}\n"); } - - void WrapperOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "$message_type_name$ subBuilder = new $message_type_name$();\n" - "if ($has_property_check$) {\n" - " subBuilder.MergeFrom(($message_type_name$) $oneof_name$_);\n" - "}\n" - "input.ReadMessage(subBuilder);\n" - // Don't set the property, which would create a new and equivalent message; just set the two fields. - "$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" - "$oneof_name$_ = subBuilder;\n"); + "$property_name$ = _oneof_$name$_codec.Read(input);\n"); } void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + // TODO: I suspect this is wrong... printer->Print( variables_, "if ($has_property_check$) {\n" - " output.WriteRawTag($tag_bytes$);\n" - " output.WriteMessage(($message_type_name$) $oneof_name$_);\n" + " _oneof_$name$_codec.WriteTagAndValue(output, ($type_name$) $oneof_name$_);\n" "}\n"); } void WrapperOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + // TODO: I suspect this is wrong... printer->Print( variables_, "if ($has_property_check$) {\n" - " size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize((($message_type_name$) $oneof_name$_));\n" + " size += _oneof_$name$_codec.CalculateSizeWithTag($property_name$);\n" "}\n"); } |