diff options
Diffstat (limited to 'src')
13 files changed, 628 insertions, 107 deletions
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc index 8865702d..ee9d6a1d 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc @@ -61,7 +61,7 @@ void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print(variables_, "if ($has_property_check$) {\n" - " output.WriteEnum($number$, fieldNames[$field_ordinal$], (long) $property_name$, $property_name$);\n" + " output.WriteEnum($number$, fieldNames[$field_ordinal$], $property_name$);\n" "}\n"); } @@ -69,7 +69,7 @@ void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.ComputeEnumSize($number$, (long) $property_name$);\n" + " size += pb::CodedOutputStream.ComputeEnumSize($number$, $property_name$);\n" "}\n"); } @@ -87,8 +87,8 @@ void EnumOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { variables_, "$type_name$ enumValue = $default_value$;\n" "if(input.ReadEnum(ref enumValue)) {\n" - " result.$oneof_name$_ = enumValue;\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + " $oneof_name$_ = enumValue;\n" + " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" "}\n"); } diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc index 367e54c2..ec0d51ca 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -38,6 +38,7 @@ #include <google/protobuf/io/printer.h> #include <google/protobuf/io/zero_copy_stream.h> #include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/wire_format.h> #include <google/protobuf/compiler/csharp/csharp_field_base.h> #include <google/protobuf/compiler/csharp/csharp_helpers.h> @@ -51,6 +52,11 @@ namespace csharp { void FieldGeneratorBase::SetCommonFieldVariables( map<string, string>* variables) { + // Note: this will be valid even though the tag emitted for packed and unpacked versions of + // repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which + // never effects the tag size. + int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); + (*variables)["tag_size"] = SimpleItoa(tagSize); (*variables)["property_name"] = property_name(); (*variables)["type_name"] = type_name(); (*variables)["name"] = name(); @@ -65,15 +71,10 @@ void FieldGeneratorBase::SetCommonFieldVariables( (*variables)["capitalized_type_name"] = capitalized_type_name(); (*variables)["number"] = number(); (*variables)["field_ordinal"] = field_ordinal(); - if (SupportFieldPresence(descriptor_->file())) { - (*variables)["has_property_check"] = "has" + (*variables)["property_name"]; - (*variables)["other_has_property_check"] = "other.Has" + (*variables)["property_name"]; - } else { - (*variables)["has_property_check"] = - (*variables)["property_name"] + " != " + (*variables)["default_value"]; - (*variables)["other_has_property_check"] = "other." + - (*variables)["property_name"] + " != " + (*variables)["default_value"]; - } + (*variables)["has_property_check"] = + (*variables)["property_name"] + " != " + (*variables)["default_value"]; + (*variables)["other_has_property_check"] = "other." + + (*variables)["property_name"] + " != " + (*variables)["default_value"]; } void FieldGeneratorBase::SetCommonOneofFieldVariables( diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 1defcf94..b5929bcd 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -179,11 +179,15 @@ void MessageGenerator::Generate(io::Printer* printer) { WriteGeneratedCodeAttributes(printer); printer->Print( vars, - "$access_level$ sealed partial class $class_name$ : pb::IMessage<$class_name$> {\n"); + "$access_level$ sealed partial class $class_name$ : pb::IMessage<$class_name$>, global::System.IEquatable<$class_name$> {\n"); printer->Indent(); // All static fields and properties printer->Print( + vars, + "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n" + "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n"); + printer->Print( "private static readonly string[] _fieldNames = " "new string[] { $slash$$field_names$$slash$ };\n", "field_names", JoinStrings(field_names(), "\", \""), @@ -204,7 +208,7 @@ void MessageGenerator::Generate(io::Printer* printer) { " get { return $umbrella_class_name$.internal__$identifier$__Descriptor; }\n" "}\n" "\n" - "protected override pb::FieldAccess.FieldAccessorTable<$class_name$> InternalFieldAccessors {\n" + "public pb::FieldAccess.FieldAccessorTable<$class_name$> Fields {\n" " get { return $umbrella_class_name$.internal__$identifier$__FieldAccessorTable; }\n" "}\n" "\n"); @@ -217,7 +221,7 @@ void MessageGenerator::Generate(io::Printer* printer) { printer->Print( vars, "public $class_name$($class_name$ other) {\n" - " MergeWith(other);\n" + " MergeFrom(other);\n" "}\n"); // Merge ctor. // Fields/properties @@ -259,15 +263,16 @@ void MessageGenerator::Generate(io::Printer* printer) { "public $property_name$OneofCase $property_name$Case {\n" " get { return $name$Case_; }\n" "}\n\n" - "private Clear$property_name$() {;\n" - " $name$Case_ = $property_name$OneofCase.None;" - " $name$_ = null;" + "public void Clear$property_name$() {\n" + " $name$Case_ = $property_name$OneofCase.None;\n" + " $name$_ = null;\n" "}\n\n"); } // TODO(jonskeet): Map properties // Standard methods + GenerateFrameworkMethods(printer); GenerateMessageSerializationMethods(printer); GenerateMergingMethods(printer); @@ -298,6 +303,51 @@ void MessageGenerator::Generate(io::Printer* printer) { } +void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) { + map<string, string> vars; + vars["class_name"] = class_name(); + + // Equality + printer->Print( + vars, + "public override bool Equals(object other) {\n" + " return Equals(other as $class_name$);\n" + "}\n\n" + "public bool Equals($class_name$ other) {\n" + " if (ReferenceEquals(other, null)) {\n" + " return false;\n" + " }\n" + " if (ReferenceEquals(other, this)) {\n" + " return true;\n" + " }\n"); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + scoped_ptr<FieldGeneratorBase> generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->WriteEquals(printer); + } + printer->Outdent(); + printer->Print( + " return true;\n" + "}\n\n"); + + // GetHashCode + printer->Print( + "public override int GetHashCode() {\n" + " int hash = 0;\n"); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + scoped_ptr<FieldGeneratorBase> generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->WriteHash(printer); + } + printer->Print("return hash;\n"); + printer->Outdent(); + printer->Print("}\n\n"); + + // TODO(jonskeet): ToString. +} + void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) { printer->Print( "public void WriteTo(pb::ICodedOutputStream output) {\n"); @@ -316,7 +366,7 @@ void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) printer->Print( "}\n" "\n" - "public int CalculateSerializedSize() {\n"); + "public int CalculateSize() {\n"); printer->Indent(); printer->Print("int size = 0;\n"); for (int i = 0; i < descriptor_->field_count(); i++) { @@ -338,7 +388,7 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { printer->Print( vars, - "public void MergeWith($class_name$ other) {\n"); + "public void MergeFrom($class_name$ other) {\n"); printer->Indent(); printer->Print( "if (other == null) {\n" @@ -378,39 +428,38 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { printer->Print( "uint tag;\n" "string fieldName;\n" - "while (input.ReadTag(out tag, out fieldName)) {\n" - " if (tag == 0 && fieldName != null) {"); - printer->Indent(); + "while (input.ReadTag(out tag, out fieldName)) {\n"); printer->Indent(); printer->Print( - "int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.String.String.Ordinal);\n" - "if (fieldOrdinal >= 0) {\n" - " tag = _fieldTags[fieldOrdinal];\n" + "if (tag == 0 && fieldName != null) {\n" + " int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal);\n" + " if (fieldOrdinal >= 0) {\n" + " tag = _fieldTags[fieldOrdinal];\n" + " }\n" "}\n" "switch(tag) {\n"); printer->Indent(); printer->Print( - "case 0: {\n" // 0 signals EOF / limit reached + "case 0:\n" // 0 signals EOF / limit reached " throw pb::InvalidProtocolBufferException.InvalidTag();\n" - "}\n" "default:\n" " if (pb::WireFormat.IsEndGroupTag(tag)) {\n" " return;\n" " }\n" - " break;"); // Note: we're ignoring unknown fields here. + " break;\n"); // Note: we're ignoring unknown fields here. for (int i = 0; i < fields_by_number().size(); i++) { const FieldDescriptor* field = fields_by_number()[i]; internal::WireFormatLite::WireType wt = internal::WireFormat::WireTypeForFieldType(field->type()); uint32 tag = internal::WireFormatLite::MakeTag(field->number(), wt); - // TODO(jonskeet): Understand what this is trying to do - if (field->is_repeated() - && (wt == internal::WireFormatLite::WIRETYPE_VARINT - || wt == internal::WireFormatLite::WIRETYPE_FIXED32 - || wt == internal::WireFormatLite::WIRETYPE_FIXED64)) { + // Handle both packed and unpacked repeated fields with the same Read*Array call; + // the two generated cases are the packed and unpacked tags. + // TODO(jonskeet): Check that is_packable is equivalent to is_repeated && wt in { VARINT, FIXED32, FIXED64 }. + // It looks like it is... + if (field->is_packable()) { printer->Print( - "case $number$:\n", - "number", + "case $packed_tag$:\n", + "packed_tag", SimpleItoa( internal::WireFormatLite::MakeTag( field->number(), @@ -429,8 +478,6 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { printer->Outdent(); printer->Print("}\n"); // switch printer->Outdent(); - printer->Print("}\n"); // if - printer->Outdent(); printer->Print("}\n"); // while printer->Outdent(); printer->Print("}\n\n"); // method diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h index f5f41c73..eb90ce67 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.h +++ b/src/google/protobuf/compiler/csharp/csharp_message.h @@ -50,6 +50,7 @@ class MessageGenerator : public SourceGeneratorBase { MessageGenerator(const Descriptor* descriptor); ~MessageGenerator(); + void GenerateFrameworkMethods(io::Printer* printer); void GenerateStaticVariables(io::Printer* printer); void GenerateStaticVariableInitializers(io::Printer* printer); void Generate(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc index 90aa201b..4b7ac88f 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc @@ -49,8 +49,8 @@ namespace csharp { MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { - variables_["has_property_check"] = property_name() + "_ != null"; - variables_["has_not_property_check"] = property_name() + "_ == null"; + variables_["has_property_check"] = name() + "_ != null"; + variables_["has_not_property_check"] = name() + "_ == null"; } MessageFieldGenerator::~MessageFieldGenerator() { @@ -66,7 +66,7 @@ void MessageFieldGenerator::GenerateMembers(io::Printer* printer) { variables_, "public $type_name$ $property_name$ {\n" " get { return $name$_; }\n" - " set { return $name$_ = value; }\n" + " set { $name$_ = value; }\n" "}\n"); } @@ -74,17 +74,17 @@ void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { printer->Print( variables_, "if (other.$has_property_check$) {\n" - " if ($has_not_property_check) {\n" + " if ($has_not_property_check$) {\n" " $name$_ = new $type_name$();\n" " }\n" - " $property_name$.MergeWith(other.$property_name);\n" + " $property_name$.MergeFrom(other.$property_name$);\n" "}\n"); } void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "if ($has_not_property_check) {\n" + "if ($has_not_property_check$) {\n" " $name$_ = new $type_name$();\n" "}\n" "input.ReadMessage($name$_);\n"); // No need to support TYPE_GROUP... @@ -110,12 +110,12 @@ void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { void MessageFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "if ($has_property_check$) hash ^= $name$_.GetHashCode();\n"); + "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n"); } void MessageFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if (!object.Equals($property_name$_, other.$property_name$_)) return false;\n"); + "if (!object.Equals($property_name$, other.$property_name$)) return false;"); } void MessageFieldGenerator::WriteToString(io::Printer* printer) { variables_["field_name"] = GetFieldName(descriptor_); @@ -140,10 +140,10 @@ void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) { variables_, "public $type_name$ $property_name$ {\n" " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : null; }\n" - " set { \n" - " $name$_ = value;" - " $oneof_name$Case_ = value == null ? $oneof_property_name$Case.None : $oneof_property_name$Case.$property_name$; }\n" - " } \n" + " set {\n" + " $oneof_name$_ = value;\n" + " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n" + " }\n" "}\n"); } @@ -151,12 +151,12 @@ void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { // TODO(jonskeet): We may be able to do better than this printer->Print( variables_, - "$type_name$ subBuilder = new type_name$();\n" + "$type_name$ subBuilder = new $type_name$();\n" "if ($has_property_check$) {\n" - " subBuilder.MergeWith($property_name$);\n" + " subBuilder.MergeFrom($property_name$);\n" "}\n" "input.ReadMessage(subBuilder);\n" // No support of TYPE_GROUP - "$oneof_property_name$ = subBuilder;\n"); + "$property_name$ = subBuilder;\n"); } void MessageOneofFieldGenerator::WriteToString(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index bc4858fc..f2b66a00 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -93,7 +93,7 @@ void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) { void PrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "input.Read$capitalized_type_name$(ref result.$name$_);\n"); + "input.Read$capitalized_type_name$(ref $name$_);\n"); } void PrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) { @@ -115,9 +115,7 @@ void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "if ($has_property_check$) {\n" - " hash ^= $property_name$.GetHashCode();\n" - "}\n"); + "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n"); } void PrimitiveFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( @@ -147,17 +145,17 @@ void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) { variables_, "public $type_name$ $property_name$ {\n" " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n" - " set {"); + " set {\n"); if (is_value_type) { printer->Print( variables_, - " $oneof_name$_ = value;\n" - " $oneof_name$Case_ = $oneof_property_name$Case.$property_name$;\n"); + " $oneof_name$_ = value;\n" + " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"); } else { printer->Print( variables_, - " $oneof_name$_ = value ?? $default_value$;\n" - " $oneof_name$Case_ = value == null ? $oneof_property_name$Case.None : $oneof_property_name$Case.$property_name$;\n"); + " $oneof_name$_ = value ?? $default_value$;\n" + " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"); } printer->Print( " }\n" diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc index f5d5a126..ebbbf3be 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc @@ -49,6 +49,7 @@ namespace csharp { RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator( const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { + variables_["packed"] = descriptor->is_packed() ? "Packed" : ""; } RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() { @@ -75,27 +76,21 @@ void RepeatedEnumFieldGenerator::GenerateMergingCode(io::Printer* printer) { void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "input.ReadEnumArray<$type_name$>(tag, fieldName, result.$name$_);\n"); + "input.ReadEnumArray<$type_name$>(tag, fieldName, $name$_);\n"); } void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { // TODO(jonskeet): Originally, this checked for Count > 0 first. // The Write* call should make that cheap though - no need to generate it every time. - if (descriptor_->is_packed()) { - printer->Print( - variables_, - "output.WritePackedEnumArray($number$, fieldNames[$field_ordinal$], $name$_);\n"); - } else { - printer->Print(variables_, - "output.WriteEnumArray($number$, fieldNames[$field_ordinal$], $name$_);\n"); - } - printer->Print("}\n"); + printer->Print( + variables_, + "output.Write$packed$EnumArray($number$, fieldNames[$field_ordinal$], $name$_);\n"); } void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + // TODO(jonskeet): Move all this code into CodedOutputStream? It's a lot to repeat everywhere... printer->Print("{\n"); printer->Indent(); - // TODO(jonskeet): Move all this code into CodedOutputStream? It's a lot to repeat everywhere... printer->Print( variables_, "int dataSize = 0;\n" @@ -104,7 +99,7 @@ void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer printer->Print( variables_, "foreach ($type_name$ element in $name$_) {\n" - " dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((long) element);\n" + " dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element);\n" "}\n" "size += dataSize;\n"); int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); @@ -127,15 +122,13 @@ void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer void RepeatedEnumFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "foreach($type_name$ i in $name$_) {\n" - " hash ^= i.GetHashCode();\n" - "}\n"); + "hash ^= $name$_.GetHashCode();\n"); } void RepeatedEnumFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if(!$name$_.Equals(other.$name$)) return false;\n"); + "if(!$name$_.Equals(other.$name$_)) return false;\n"); } void RepeatedEnumFieldGenerator::WriteToString(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc index 2a6a01f5..963f841e 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc @@ -64,21 +64,6 @@ void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) { "public pbc::RepeatedField<$type_name$> $property_name$ {\n" " get { return $name$_; }\n" "}\n"); - - // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option. - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public int $property_name$Count {\n" - " get { return $name$_.Count; }\n" - "}\n"); - - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ Get$property_name$(int index) {\n" - " return $name$_[index];\n" - "}\n"); } void RepeatedMessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { @@ -90,7 +75,7 @@ void RepeatedMessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "input.ReadMessageArray(tag, fieldName, $name$_);\n"); + "input.ReadMessageArray(tag, fieldName, $name$_, $type_name$.Parser);\n"); } void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { @@ -105,7 +90,7 @@ void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* prin // TODO(jonskeet): Put this into CodedOutputStream. printer->Print( variables_, - "foreach ($type_name$ element in $property_name$) {\n" + "foreach ($type_name$ element in $name$_) {\n" " size += pb::CodedOutputStream.ComputeMessageSize($number$, element);\n" "}\n"); } @@ -113,15 +98,15 @@ void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* prin void RepeatedMessageFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "foreach($type_name$ i in $name$_) {\n" - " hash ^= i.GetHashCode();\n" - "}\n"); + "hash ^= $name$_.GetHashCode();\n"); } + void RepeatedMessageFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if(!$name$_.Equals(other.$name$)) return false;\n"); + "if(!$name$_.Equals(other.$name$_)) return false;\n"); } + void RepeatedMessageFieldGenerator::WriteToString(io::Printer* printer) { variables_["field_name"] = GetFieldName(descriptor_); printer->Print( diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc index 2001b849..0a91c3c6 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc @@ -92,7 +92,7 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode( void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( io::Printer* printer) { - // TODO(jonskeet): Get rid of most of this - move it into the runtime. + // TODO(jonskeet): Do this in the runtime if possible. It's a pain, but it must be feasible... printer->Print("{\n"); printer->Indent(); printer->Print("int dataSize = 0;\n"); @@ -100,7 +100,7 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( if (fixedSize == -1) { printer->Print( variables_, - "foreach ($type_name$ element in $property_name$List) {\n" + "foreach ($type_name$ element in $name$_) {\n" " dataSize += pb::CodedOutputStream.Compute$capitalized_type_name$SizeNoTag(element);\n" "}\n"); } else { @@ -128,14 +128,12 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( void RepeatedPrimitiveFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "foreach($type_name$ i in $name$_)\n {" - " hash ^= i.GetHashCode();\n" - "}\n"); + "hash ^= $name$_.GetHashCode();\n"); } void RepeatedPrimitiveFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if(!$name$_.Equals(other.$name$)) return false;\n"); + "if(!$name$_.Equals(other.$name$_)) return false;\n"); } void RepeatedPrimitiveFieldGenerator::WriteToString(io::Printer* printer) { printer->Print(variables_, diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index 20a60080..97741b6a 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -42,7 +42,7 @@ syntax = "proto2"; package google.protobuf; option java_package = "com.google.protobuf"; option java_outer_classname = "DescriptorProtos"; -option csharp_namespace = "Google.ProtocolBuffers.DescriptorProtos"; +option csharp_namespace = "Google.Protobuf.DescriptorProtos"; option objc_class_prefix = "GPB"; // descriptor.proto must be optimized for speed because reflection-based diff --git a/src/google/protobuf/unittest_import_proto3.proto b/src/google/protobuf/unittest_import_proto3.proto new file mode 100644 index 00000000..59673eaf --- /dev/null +++ b/src/google/protobuf/unittest_import_proto3.proto @@ -0,0 +1,68 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file which is imported by unittest_proto3.proto to test importing. + +syntax = "proto3"; + +// We don't put this in a package within proto2 because we need to make sure +// that the generated code doesn't depend on being in the proto2 namespace. +// In test_util.h we do +// "using namespace unittest_import = protobuf_unittest_import". +package protobuf_unittest_import; + +option optimize_for = SPEED; +option cc_enable_arenas = true; + +// Exercise the java_package option. +option java_package = "com.google.protobuf.test"; +option csharp_namespace = "Google.Protobuf.TestProtos"; + +// Do not set a java_outer_classname here to verify that Proto2 works without +// one. + +// Test public import +import public "google/protobuf/unittest_import_public_proto3.proto"; + +message ImportMessage { + int32 d = 1; +} + +enum ImportEnum { + IMPORT_ENUM_UNSPECIFIED = 0; + IMPORT_FOO = 7; + IMPORT_BAR = 8; + IMPORT_BAZ = 9; +} + diff --git a/src/google/protobuf/unittest_import_public_proto3.proto b/src/google/protobuf/unittest_import_public_proto3.proto new file mode 100644 index 00000000..d6f11e28 --- /dev/null +++ b/src/google/protobuf/unittest_import_public_proto3.proto @@ -0,0 +1,42 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: liujisi@google.com (Pherl Liu) + +syntax = "proto3"; + +package protobuf_unittest_import; + +option java_package = "com.google.protobuf.test"; +option csharp_namespace = "Google.Protobuf.TestProtos"; + +message PublicImportMessage { + int32 e = 1; +} diff --git a/src/google/protobuf/unittest_proto3.proto b/src/google/protobuf/unittest_proto3.proto new file mode 100644 index 00000000..f59d2178 --- /dev/null +++ b/src/google/protobuf/unittest_proto3.proto @@ -0,0 +1,388 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file we will use for unit testing. + +syntax = "proto3"; + +// Some generic_services option(s) added automatically. +// See: http://go/proto2-generic-services-default +option cc_generic_services = true; // auto-added +option java_generic_services = true; // auto-added +option py_generic_services = true; // auto-added +option cc_enable_arenas = true; +option csharp_namespace = "Google.Protobuf.TestProtos"; + +import "google/protobuf/unittest_import_proto3.proto"; + +// We don't put this in a package within proto2 because we need to make sure +// that the generated code doesn't depend on being in the proto2 namespace. +// In test_util.h we do "using namespace unittest = protobuf_unittest". +package protobuf_unittest; + +// Protos optimized for SPEED use a strict superset of the generated code +// of equivalent ones optimized for CODE_SIZE, so we should optimize all our +// tests for speed unless explicitly testing code size optimization. +option optimize_for = SPEED; + +option java_outer_classname = "UnittestProto"; + +// This proto includes every type of field in both singular and repeated +// forms. +message TestAllTypes { + message NestedMessage { + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + int32 bb = 1; + } + + enum NestedEnum { + NESTED_ENUM_UNSPECIFIED = 0; + FOO = 1; + BAR = 2; + BAZ = 3; + NEG = -1; // Intentionally negative. + } + + // Singular + int32 single_int32 = 1; + int64 single_int64 = 2; + uint32 single_uint32 = 3; + uint64 single_uint64 = 4; + sint32 single_sint32 = 5; + sint64 single_sint64 = 6; + fixed32 single_fixed32 = 7; + fixed64 single_fixed64 = 8; + sfixed32 single_sfixed32 = 9; + sfixed64 single_sfixed64 = 10; + float single_float = 11; + double single_double = 12; + bool single_bool = 13; + string single_string = 14; + bytes single_bytes = 15; + + NestedMessage single_nested_message = 18; + ForeignMessage single_foreign_message = 19; + protobuf_unittest_import.ImportMessage single_import_message = 20; + + NestedEnum single_nested_enum = 21; + ForeignEnum single_foreign_enum = 22; + protobuf_unittest_import.ImportEnum single_import_enum = 23; + + // Defined in unittest_import_public.proto + protobuf_unittest_import.PublicImportMessage + single_public_import_message = 26; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessage repeated_foreign_message = 49; + repeated protobuf_unittest_import.ImportMessage repeated_import_message = 50; + + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnum repeated_foreign_enum = 52; + repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53; + // Defined in unittest_import_public.proto + repeated protobuf_unittest_import.PublicImportMessage + repeated_public_import_message = 54; + + // For oneof test + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + } +} + +// This proto includes a recusively nested message. +message NestedTestAllTypes { + NestedTestAllTypes child = 1; + TestAllTypes payload = 2; + repeated NestedTestAllTypes repeated_child = 3; +} + +message TestDeprecatedFields { + int32 deprecated_int32 = 1 [deprecated=true]; +} + +// Define these after TestAllTypes to make sure the compiler can handle +// that. +message ForeignMessage { + int32 c = 1; +} + +enum ForeignEnum { + FOREIGN_UNSPECIFIED = 0; + FOREIGN_FOO = 4; + FOREIGN_BAR = 5; + FOREIGN_BAZ = 6; +} + +message TestReservedFields { + reserved 2, 15, 9 to 11; + reserved "bar", "baz"; +} + + +// Test that we can use NestedMessage from outside TestAllTypes. +message TestForeignNested { + TestAllTypes.NestedMessage foreign_nested = 1; +} + +// Test that really large tag numbers don't break anything. +message TestReallyLargeTagNumber { + // The largest possible tag number is 2^28 - 1, since the wire format uses + // three bits to communicate wire type. + int32 a = 1; + int32 bb = 268435455; +} + +message TestRecursiveMessage { + TestRecursiveMessage a = 1; + int32 i = 2; +} + +// Test that mutual recursion works. +message TestMutualRecursionA { + TestMutualRecursionB bb = 1; +} + +message TestMutualRecursionB { + TestMutualRecursionA a = 1; + int32 optional_int32 = 2; +} + + +// Test an enum that has multiple values with the same number. +enum TestEnumWithDupValue { + TEST_ENUM_WITH_DUP_VALUE_UNSPECIFIED = 0; + option allow_alias = true; + + FOO1 = 1; + BAR1 = 2; + BAZ = 3; + FOO2 = 1; + BAR2 = 2; +} + +// Test an enum with large, unordered values. +enum TestSparseEnum { + TEST_SPARSE_ENUM_UNSPECIFIED = 0; + SPARSE_A = 123; + SPARSE_B = 62374; + SPARSE_C = 12589234; + SPARSE_D = -15; + SPARSE_E = -53452; + // In proto3, value 0 must be the first one specified + // SPARSE_F = 0; + SPARSE_G = 2; +} + +// Test message with CamelCase field names. This violates Protocol Buffer +// standard style. +message TestCamelCaseFieldNames { + int32 PrimitiveField = 1; + string StringField = 2; + ForeignEnum EnumField = 3; + ForeignMessage MessageField = 4; + + repeated int32 RepeatedPrimitiveField = 7; + repeated string RepeatedStringField = 8; + repeated ForeignEnum RepeatedEnumField = 9; + repeated ForeignMessage RepeatedMessageField = 10; +} + + +// We list fields out of order, to ensure that we're using field number and not +// field index to determine serialization order. +message TestFieldOrderings { + string my_string = 11; + int64 my_int = 1; + float my_float = 101; + message NestedMessage { + int64 oo = 2; + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + int32 bb = 1; + } + + NestedMessage single_nested_message = 200; +} + +message SparseEnumMessage { + TestSparseEnum sparse_enum = 1; +} + +// Test String and Bytes: string is for valid UTF-8 strings +message OneString { + string data = 1; +} + +message MoreString { + repeated string data = 1; +} + +message OneBytes { + bytes data = 1; +} + +message MoreBytes { + bytes data = 1; +} + +// Test int32, uint32, int64, uint64, and bool are all compatible +message Int32Message { + int32 data = 1; +} + +message Uint32Message { + uint32 data = 1; +} + +message Int64Message { + int64 data = 1; +} + +message Uint64Message { + uint64 data = 1; +} + +message BoolMessage { + bool data = 1; +} + +// Test oneofs. +message TestOneof { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + TestAllTypes foo_message = 3; + } +} + +// Test messages for packed fields + +message TestPackedTypes { + repeated int32 packed_int32 = 90 [packed = true]; + repeated int64 packed_int64 = 91 [packed = true]; + repeated uint32 packed_uint32 = 92 [packed = true]; + repeated uint64 packed_uint64 = 93 [packed = true]; + repeated sint32 packed_sint32 = 94 [packed = true]; + repeated sint64 packed_sint64 = 95 [packed = true]; + repeated fixed32 packed_fixed32 = 96 [packed = true]; + repeated fixed64 packed_fixed64 = 97 [packed = true]; + repeated sfixed32 packed_sfixed32 = 98 [packed = true]; + repeated sfixed64 packed_sfixed64 = 99 [packed = true]; + repeated float packed_float = 100 [packed = true]; + repeated double packed_double = 101 [packed = true]; + repeated bool packed_bool = 102 [packed = true]; + repeated ForeignEnum packed_enum = 103 [packed = true]; +} + +// A message with the same fields as TestPackedTypes, but without packing. Used +// to test packed <-> unpacked wire compatibility. +message TestUnpackedTypes { + repeated int32 unpacked_int32 = 90 [packed = false]; + repeated int64 unpacked_int64 = 91 [packed = false]; + repeated uint32 unpacked_uint32 = 92 [packed = false]; + repeated uint64 unpacked_uint64 = 93 [packed = false]; + repeated sint32 unpacked_sint32 = 94 [packed = false]; + repeated sint64 unpacked_sint64 = 95 [packed = false]; + repeated fixed32 unpacked_fixed32 = 96 [packed = false]; + repeated fixed64 unpacked_fixed64 = 97 [packed = false]; + repeated sfixed32 unpacked_sfixed32 = 98 [packed = false]; + repeated sfixed64 unpacked_sfixed64 = 99 [packed = false]; + repeated float unpacked_float = 100 [packed = false]; + repeated double unpacked_double = 101 [packed = false]; + repeated bool unpacked_bool = 102 [packed = false]; + repeated ForeignEnum unpacked_enum = 103 [packed = false]; +} + +message TestRepeatedScalarDifferentTagSizes { + // Parsing repeated fixed size values used to fail. This message needs to be + // used in order to get a tag of the right size; all of the repeated fields + // in TestAllTypes didn't trigger the check. + repeated fixed32 repeated_fixed32 = 12; + // Check for a varint type, just for good measure. + repeated int32 repeated_int32 = 13; + + // These have two-byte tags. + repeated fixed64 repeated_fixed64 = 2046; + repeated int64 repeated_int64 = 2047; + + // Three byte tags. + repeated float repeated_float = 262142; + repeated uint64 repeated_uint64 = 262143; +} + +message TestCommentInjectionMessage { + // */ <- This should not close the generated doc comment + string a = 1; +} + + +// Test that RPC services work. +message FooRequest {} +message FooResponse {} + +message FooClientMessage {} +message FooServerMessage{} + +service TestService { + rpc Foo(FooRequest) returns (FooResponse); + rpc Bar(BarRequest) returns (BarResponse); +} + + +message BarRequest {} +message BarResponse {} + |