aboutsummaryrefslogtreecommitdiff
path: root/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc')
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc83
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");
}