Эх сурвалжийг харах

codegen for WriteContext based serialization

Jan Tattermusch 5 жил өмнө
parent
commit
dda621749c

+ 6 - 0
src/google/protobuf/compiler/csharp/csharp_field_base.cc

@@ -167,6 +167,12 @@ void FieldGeneratorBase::GenerateParsingCode(io::Printer* printer, bool use_pars
   GenerateParsingCode(printer);
 }
 
+void FieldGeneratorBase::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
+  // for some field types the value of "use_write_context" doesn't matter,
+  // so we fallback to the default implementation.
+  GenerateSerializationCode(printer);
+}
+
 void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) {
   if (descriptor_->options().deprecated()) {
     printer->Print("[global::System.ObsoleteAttribute]\n");

+ 1 - 0
src/google/protobuf/compiler/csharp/csharp_field_base.h

@@ -63,6 +63,7 @@ class FieldGeneratorBase : public SourceGeneratorBase {
   virtual void GenerateParsingCode(io::Printer* printer) = 0;
   virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context);
   virtual void GenerateSerializationCode(io::Printer* printer) = 0;
+  virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context);
   virtual void GenerateSerializedSizeCode(io::Printer* printer) = 0;
 
   virtual void WriteHash(io::Printer* printer) = 0;

+ 7 - 1
src/google/protobuf/compiler/csharp/csharp_map_field.cc

@@ -106,9 +106,15 @@ void MapFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse
 }
 
 void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  GenerateSerializationCode(printer, true);
+}
+
+void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
   printer->Print(
     variables_,
-    "$name$_.WriteTo(output, _map_$name$_codec);\n");
+    use_write_context
+    ? "$name$_.WriteTo(ref output, _map_$name$_codec);\n"
+    : "$name$_.WriteTo(output, _map_$name$_codec);\n");
 }
 
 void MapFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {

+ 1 - 0
src/google/protobuf/compiler/csharp/csharp_map_field.h

@@ -58,6 +58,7 @@ class MapFieldGenerator : public FieldGeneratorBase {
   virtual void GenerateParsingCode(io::Printer* printer);
   virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context);
   virtual void GenerateSerializationCode(io::Printer* printer);
+  virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context);
   virtual void GenerateSerializedSizeCode(io::Printer* printer);
 
   virtual void WriteHash(io::Printer* printer);

+ 50 - 25
src/google/protobuf/compiler/csharp/csharp_message.cc

@@ -520,34 +520,26 @@ void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer)
   WriteGeneratedCodeAttributes(printer);
   printer->Print(
       "public void WriteTo(pb::CodedOutputStream output) {\n");
+  printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
   printer->Indent();
+  printer->Print("output.WriteRawMessage(this);\n");
+  printer->Outdent();
+  printer->Print("#else\n");
+  printer->Indent();
+  GenerateWriteToBody(printer, false);
+  printer->Outdent();
+  printer->Print("#endif\n");
+  printer->Print("}\n\n");
 
-  // Serialize all the fields
-  for (int i = 0; i < fields_by_number().size(); i++) {
-    std::unique_ptr<FieldGeneratorBase> generator(
-      CreateFieldGeneratorInternal(fields_by_number()[i]));
-    generator->GenerateSerializationCode(printer);
-  }
-
-  if (has_extension_ranges_) {
-    // Serialize extensions
-    printer->Print(
-      "if (_extensions != null) {\n"
-      "  _extensions.WriteTo(output);\n"
-      "}\n");
-  }
-
-  // Serialize unknown fields
-  printer->Print(
-    "if (_unknownFields != null) {\n"
-    "  _unknownFields.WriteTo(output);\n"
-    "}\n");
-
-  // TODO(jonskeet): Memoize size of frozen messages?
+  printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
+  WriteGeneratedCodeAttributes(printer);
+  printer->Print("void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {\n");
+  printer->Indent();
+  GenerateWriteToBody(printer, true);
   printer->Outdent();
-  printer->Print(
-    "}\n"
-    "\n");
+  printer->Print("}\n");
+  printer->Print("#endif\n\n");
+
   WriteGeneratedCodeAttributes(printer);
   printer->Print(
     "public int CalculateSize() {\n");
@@ -576,6 +568,39 @@ void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer)
   printer->Print("}\n\n");
 }
 
+void MessageGenerator::GenerateWriteToBody(io::Printer* printer, bool use_write_context) {
+  // Serialize all the fields
+  for (int i = 0; i < fields_by_number().size(); i++) {
+    std::unique_ptr<FieldGeneratorBase> generator(
+      CreateFieldGeneratorInternal(fields_by_number()[i]));
+    generator->GenerateSerializationCode(printer, use_write_context);
+  }
+
+  if (has_extension_ranges_) {
+    // Serialize extensions
+    printer->Print(
+      use_write_context
+      ? "if (_extensions != null) {\n"
+        "  _extensions.WriteTo(ref output);\n"
+        "}\n"
+      : "if (_extensions != null) {\n"
+        "  _extensions.WriteTo(output);\n"
+        "}\n");
+  }
+
+  // Serialize unknown fields
+  printer->Print(
+    use_write_context
+    ? "if (_unknownFields != null) {\n"
+      "  _unknownFields.WriteTo(ref output);\n"
+      "}\n"
+    : "if (_unknownFields != null) {\n"
+      "  _unknownFields.WriteTo(output);\n"
+      "}\n");
+
+  // TODO(jonskeet): Memoize size of frozen messages?
+}
+
 void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
   // Note:  These are separate from GenerateMessageSerializationMethods()
   //   because they need to be generated even for messages that are optimized

+ 1 - 0
src/google/protobuf/compiler/csharp/csharp_message.h

@@ -66,6 +66,7 @@ class MessageGenerator : public SourceGeneratorBase {
   bool has_extension_ranges_;
 
   void GenerateMessageSerializationMethods(io::Printer* printer);
+  void GenerateWriteToBody(io::Printer* printer, bool use_write_context);
   void GenerateMergingMethods(io::Printer* printer);
   void GenerateMainParseLoop(io::Printer* printer, bool use_parse_context);
 

+ 7 - 1
src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc

@@ -90,9 +90,15 @@ void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer, bool
 }
 
 void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  GenerateSerializationCode(printer, true);
+}
+
+void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
   printer->Print(
     variables_,
-    "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
+    use_write_context
+    ? "$name$_.WriteTo(ref output, _repeated_$name$_codec);\n"
+    : "$name$_.WriteTo(ref output, _repeated_$name$_codec);\n");
 }
 
 void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {

+ 1 - 0
src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h

@@ -61,6 +61,7 @@ class RepeatedEnumFieldGenerator : public FieldGeneratorBase {
   virtual void GenerateParsingCode(io::Printer* printer);
   virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context);
   virtual void GenerateSerializationCode(io::Printer* printer);
+  virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context);
   virtual void GenerateSerializedSizeCode(io::Printer* printer);
   virtual void GenerateExtensionCode(io::Printer* printer);
 

+ 7 - 1
src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc

@@ -105,9 +105,15 @@ void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer, bo
 }
 
 void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  GenerateSerializationCode(printer, true);
+}
+
+void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
   printer->Print(
     variables_,
-    "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
+    use_write_context
+    ? "$name$_.WriteTo(ref output, _repeated_$name$_codec);\n"
+    : "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
 }
 
 void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {

+ 1 - 0
src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h

@@ -61,6 +61,7 @@ class RepeatedMessageFieldGenerator : public FieldGeneratorBase {
   virtual void GenerateParsingCode(io::Printer* printer);
   virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context);
   virtual void GenerateSerializationCode(io::Printer* printer);
+  virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context);
   virtual void GenerateSerializedSizeCode(io::Printer* printer);
   virtual void GenerateExtensionCode(io::Printer* printer);
 

+ 7 - 1
src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc

@@ -90,9 +90,15 @@ void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer,
 }
 
 void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  GenerateSerializationCode(printer, true);
+}
+
+void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
   printer->Print(
     variables_,
-    "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
+    use_write_context
+    ? "$name$_.WriteTo(ref output, _repeated_$name$_codec);\n"
+    : "$name$_.WriteTo(output, _repeated_$name$_codec);\n");
 }
 
 void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {

+ 1 - 0
src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h

@@ -57,6 +57,7 @@ class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase {
   virtual void GenerateParsingCode(io::Printer* printer);
   virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context);
   virtual void GenerateSerializationCode(io::Printer* printer);
+  virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context);
   virtual void GenerateSerializedSizeCode(io::Printer* printer);
   virtual void GenerateExtensionCode(io::Printer* printer);
 

+ 22 - 6
src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc

@@ -132,11 +132,19 @@ void WrapperFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_p
 }
 
 void WrapperFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  GenerateSerializationCode(printer, true);
+}
+
+void WrapperFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
   printer->Print(
     variables_,
-    "if ($has_property_check$) {\n"
-    "  _single_$name$_codec.WriteTagAndValue(output, $property_name$);\n"
-    "}\n");
+    use_write_context
+    ? "if ($has_property_check$) {\n"
+      "  _single_$name$_codec.WriteTagAndValue(ref output, $property_name$);\n"
+      "}\n"
+    : "if ($has_property_check$) {\n"
+      "  _single_$name$_codec.WriteTagAndValue(output, $property_name$);\n"
+      "}\n");
 }
 
 void WrapperFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
@@ -269,12 +277,20 @@ void WrapperOneofFieldGenerator::GenerateParsingCode(io::Printer* printer, bool
 }
 
 void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  GenerateSerializationCode(printer, true);
+}
+
+void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
   // TODO: I suspect this is wrong...
   printer->Print(
     variables_,
-    "if ($has_property_check$) {\n"
-    "  _oneof_$name$_codec.WriteTagAndValue(output, ($type_name$) $oneof_name$_);\n"
-    "}\n");
+    use_write_context
+    ? "if ($has_property_check$) {\n"
+      "  _oneof_$name$_codec.WriteTagAndValue(ref output, ($type_name$) $oneof_name$_);\n"
+      "}\n"
+    : "if ($has_property_check$) {\n"
+      "  _oneof_$name$_codec.WriteTagAndValue(output, ($type_name$) $oneof_name$_);\n"
+      "}\n");
 }
 
 void WrapperOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {

+ 2 - 0
src/google/protobuf/compiler/csharp/csharp_wrapper_field.h

@@ -60,6 +60,7 @@ class WrapperFieldGenerator : public FieldGeneratorBase {
   virtual void GenerateParsingCode(io::Printer* printer);
   virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context);
   virtual void GenerateSerializationCode(io::Printer* printer);
+  virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context);
   virtual void GenerateSerializedSizeCode(io::Printer* printer);
   virtual void GenerateExtensionCode(io::Printer* printer);
 
@@ -86,6 +87,7 @@ class WrapperOneofFieldGenerator : public WrapperFieldGenerator {
   virtual void GenerateParsingCode(io::Printer* printer);
   virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context);
   virtual void GenerateSerializationCode(io::Printer* printer);
+  virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context);
   virtual void GenerateSerializedSizeCode(io::Printer* printer);
 };