C# Proto2 feature : Field presence and default values (#4642)

* Compiler changes

* Generated code changes

* Library changes

* Compiler style changes

* Generated style changes

* Fix Windows build errors

* Implement changes from review

* Reintroduce proto2 check

* Compiler changes (required handling review)

* Generated code changes (required handling review)

* Library changes (required handling review

* Field presence rewrite (compiler changes)

* Field presence rewrite (generated code changes)

* Compiler comment

* IFieldAccessor.HasValue library implementation

* Remove Clear methods and default values from proto3 code (Compiler)

* Remove Clear methods and default values from proto3 code (Generated)

* Remove Clear methods and default values from proto3 code (Library)

* Fix distcheck error

* Rewrite default string values to use base64 and convert

* Library changes (IMessage2)

* Compiler changes (IMessage2)

* Generated changes (IMessage2)

* Rebased and regenerated

* Compiler changes (initialized extension)

* Generated changes (initialized extension)

* Library changes (initialized extension)

* Refactor MessageExtensions.IsRequired

* Move string default value creator and bytes default value creator back to seperate methods

* Dead code cleanup

* Fixed segmentation fault
Removed unused header method declarations
pull/5076/merge
Sydney Acksman 6 years ago committed by Jie Luo
parent fb0a74b660
commit 54176b26a9
  1. 1
      Makefile.am
  2. 8
      csharp/src/AddressBook/Addressbook.cs
  3. 4
      csharp/src/Google.Protobuf.Conformance/Conformance.cs
  4. 6
      csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs
  5. 73
      csharp/src/Google.Protobuf.Test/TestProtos/TestMessagesProto3.cs
  6. 18
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestCustomOptionsProto3.cs
  7. 10
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs
  8. 84
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs
  9. 69
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs
  10. 1542
      csharp/src/Google.Protobuf/Collections/MapField.cs
  11. 1190
      csharp/src/Google.Protobuf/Collections/RepeatedField.cs
  12. 7
      csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs
  13. 50
      csharp/src/Google.Protobuf/MessageExtensions.cs
  14. 12
      csharp/src/Google.Protobuf/MessageParser.cs
  15. 156
      csharp/src/Google.Protobuf/ProtoPreconditions.cs
  16. 2185
      csharp/src/Google.Protobuf/Reflection/Descriptor.cs
  17. 1
      csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs
  18. 31
      csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
  19. 2
      csharp/src/Google.Protobuf/Reflection/FieldType.cs
  20. 5
      csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs
  21. 5
      csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs
  22. 59
      csharp/src/Google.Protobuf/Reflection/PartialClasses.cs
  23. 10
      csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs
  24. 5
      csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs
  25. 33
      csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs
  26. 10
      csharp/src/Google.Protobuf/WellKnownTypes/Api.cs
  27. 26
      csharp/src/Google.Protobuf/WellKnownTypes/Type.cs
  28. 4
      csharp/src/Google.Protobuf/WireFormat.cs
  29. 10
      src/google/protobuf/compiler/csharp/csharp_enum_field.cc
  30. 4
      src/google/protobuf/compiler/csharp/csharp_enum_field.h
  31. 105
      src/google/protobuf/compiler/csharp/csharp_field_base.cc
  32. 9
      src/google/protobuf/compiler/csharp/csharp_field_base.h
  33. 6
      src/google/protobuf/compiler/csharp/csharp_generator.cc
  34. 61
      src/google/protobuf/compiler/csharp/csharp_helpers.cc
  35. 8
      src/google/protobuf/compiler/csharp/csharp_helpers.h
  36. 4
      src/google/protobuf/compiler/csharp/csharp_map_field.cc
  37. 2
      src/google/protobuf/compiler/csharp/csharp_map_field.h
  38. 58
      src/google/protobuf/compiler/csharp/csharp_message.cc
  39. 7
      src/google/protobuf/compiler/csharp/csharp_message.h
  40. 66
      src/google/protobuf/compiler/csharp/csharp_message_field.cc
  41. 4
      src/google/protobuf/compiler/csharp/csharp_message_field.h
  42. 120
      src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
  43. 4
      src/google/protobuf/compiler/csharp/csharp_primitive_field.h
  44. 4
      src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
  45. 2
      src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
  46. 8
      src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
  47. 2
      src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
  48. 4
      src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
  49. 2
      src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
  50. 52
      src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
  51. 4
      src/google/protobuf/compiler/csharp/csharp_wrapper_field.h

@ -179,7 +179,6 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs \
csharp/src/Google.Protobuf/Reflection/OriginalNameAttribute.cs \
csharp/src/Google.Protobuf/Reflection/PackageDescriptor.cs \
csharp/src/Google.Protobuf/Reflection/PartialClasses.cs \
csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs \
csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs \
csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs \

@ -247,7 +247,7 @@ namespace Google.Protobuf.Examples.AddressBook {
phones_.Add(other.phones_);
if (other.lastUpdated_ != null) {
if (lastUpdated_ == null) {
lastUpdated_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
LastUpdated = new global::Google.Protobuf.WellKnownTypes.Timestamp();
}
LastUpdated.MergeFrom(other.LastUpdated);
}
@ -280,9 +280,9 @@ namespace Google.Protobuf.Examples.AddressBook {
}
case 42: {
if (lastUpdated_ == null) {
lastUpdated_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
LastUpdated = new global::Google.Protobuf.WellKnownTypes.Timestamp();
}
input.ReadMessage(lastUpdated_);
input.ReadMessage(LastUpdated);
break;
}
}
@ -447,7 +447,7 @@ namespace Google.Protobuf.Examples.AddressBook {
break;
}
case 16: {
type_ = (global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType) input.ReadEnum();
Type = (global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType) input.ReadEnum();
break;
}
}

@ -354,7 +354,7 @@ namespace Conformance {
break;
}
case 24: {
requestedOutputFormat_ = (global::Conformance.WireFormat) input.ReadEnum();
RequestedOutputFormat = (global::Conformance.WireFormat) input.ReadEnum();
break;
}
case 34: {
@ -362,7 +362,7 @@ namespace Conformance {
break;
}
case 40: {
testCategory_ = (global::Conformance.TestCategory) input.ReadEnum();
TestCategory = (global::Conformance.TestCategory) input.ReadEnum();
break;
}
}

@ -724,7 +724,7 @@ namespace Google.Protobuf.TestProtos {
}
if (other.testMap_ != null) {
if (testMap_ == null) {
testMap_ = new global::Google.Protobuf.TestProtos.TestMap();
TestMap = new global::Google.Protobuf.TestProtos.TestMap();
}
TestMap.MergeFrom(other.TestMap);
}
@ -741,9 +741,9 @@ namespace Google.Protobuf.TestProtos {
break;
case 10: {
if (testMap_ == null) {
testMap_ = new global::Google.Protobuf.TestProtos.TestMap();
TestMap = new global::Google.Protobuf.TestProtos.TestMap();
}
input.ReadMessage(testMap_);
input.ReadMessage(TestMap);
break;
}
}

@ -1171,6 +1171,7 @@ namespace ProtobufTestMessages.Proto3 {
}
}
/// <summary>Field number for the "optional_int32_wrapper" field.</summary>
public const int OptionalInt32WrapperFieldNumber = 202;
private static readonly pb::FieldCodec<int?> _single_optionalInt32Wrapper_codec = pb::FieldCodec.ForStructWrapper<int>(1618);
@ -1183,6 +1184,7 @@ namespace ProtobufTestMessages.Proto3 {
}
}
/// <summary>Field number for the "optional_int64_wrapper" field.</summary>
public const int OptionalInt64WrapperFieldNumber = 203;
private static readonly pb::FieldCodec<long?> _single_optionalInt64Wrapper_codec = pb::FieldCodec.ForStructWrapper<long>(1626);
@ -1195,6 +1197,7 @@ namespace ProtobufTestMessages.Proto3 {
}
}
/// <summary>Field number for the "optional_uint32_wrapper" field.</summary>
public const int OptionalUint32WrapperFieldNumber = 204;
private static readonly pb::FieldCodec<uint?> _single_optionalUint32Wrapper_codec = pb::FieldCodec.ForStructWrapper<uint>(1634);
@ -1207,6 +1210,7 @@ namespace ProtobufTestMessages.Proto3 {
}
}
/// <summary>Field number for the "optional_uint64_wrapper" field.</summary>
public const int OptionalUint64WrapperFieldNumber = 205;
private static readonly pb::FieldCodec<ulong?> _single_optionalUint64Wrapper_codec = pb::FieldCodec.ForStructWrapper<ulong>(1642);
@ -1219,6 +1223,7 @@ namespace ProtobufTestMessages.Proto3 {
}
}
/// <summary>Field number for the "optional_float_wrapper" field.</summary>
public const int OptionalFloatWrapperFieldNumber = 206;
private static readonly pb::FieldCodec<float?> _single_optionalFloatWrapper_codec = pb::FieldCodec.ForStructWrapper<float>(1650);
@ -1231,6 +1236,7 @@ namespace ProtobufTestMessages.Proto3 {
}
}
/// <summary>Field number for the "optional_double_wrapper" field.</summary>
public const int OptionalDoubleWrapperFieldNumber = 207;
private static readonly pb::FieldCodec<double?> _single_optionalDoubleWrapper_codec = pb::FieldCodec.ForStructWrapper<double>(1658);
@ -1243,6 +1249,7 @@ namespace ProtobufTestMessages.Proto3 {
}
}
/// <summary>Field number for the "optional_string_wrapper" field.</summary>
public const int OptionalStringWrapperFieldNumber = 208;
private static readonly pb::FieldCodec<string> _single_optionalStringWrapper_codec = pb::FieldCodec.ForClassWrapper<string>(1666);
@ -1255,6 +1262,7 @@ namespace ProtobufTestMessages.Proto3 {
}
}
/// <summary>Field number for the "optional_bytes_wrapper" field.</summary>
public const int OptionalBytesWrapperFieldNumber = 209;
private static readonly pb::FieldCodec<pb::ByteString> _single_optionalBytesWrapper_codec = pb::FieldCodec.ForClassWrapper<pb::ByteString>(1674);
@ -1267,6 +1275,7 @@ namespace ProtobufTestMessages.Proto3 {
}
}
/// <summary>Field number for the "repeated_bool_wrapper" field.</summary>
public const int RepeatedBoolWrapperFieldNumber = 211;
private static readonly pb::FieldCodec<bool?> _repeated_repeatedBoolWrapper_codec
@ -2598,13 +2607,13 @@ namespace ProtobufTestMessages.Proto3 {
}
if (other.optionalNestedMessage_ != null) {
if (optionalNestedMessage_ == null) {
optionalNestedMessage_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage();
OptionalNestedMessage = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage();
}
OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage);
}
if (other.optionalForeignMessage_ != null) {
if (optionalForeignMessage_ == null) {
optionalForeignMessage_ = new global::ProtobufTestMessages.Proto3.ForeignMessage();
OptionalForeignMessage = new global::ProtobufTestMessages.Proto3.ForeignMessage();
}
OptionalForeignMessage.MergeFrom(other.OptionalForeignMessage);
}
@ -2622,7 +2631,7 @@ namespace ProtobufTestMessages.Proto3 {
}
if (other.recursiveMessage_ != null) {
if (recursiveMessage_ == null) {
recursiveMessage_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
RecursiveMessage = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
}
RecursiveMessage.MergeFrom(other.RecursiveMessage);
}
@ -2722,37 +2731,37 @@ namespace ProtobufTestMessages.Proto3 {
repeatedBytesWrapper_.Add(other.repeatedBytesWrapper_);
if (other.optionalDuration_ != null) {
if (optionalDuration_ == null) {
optionalDuration_ = new global::Google.Protobuf.WellKnownTypes.Duration();
OptionalDuration = new global::Google.Protobuf.WellKnownTypes.Duration();
}
OptionalDuration.MergeFrom(other.OptionalDuration);
}
if (other.optionalTimestamp_ != null) {
if (optionalTimestamp_ == null) {
optionalTimestamp_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
OptionalTimestamp = new global::Google.Protobuf.WellKnownTypes.Timestamp();
}
OptionalTimestamp.MergeFrom(other.OptionalTimestamp);
}
if (other.optionalFieldMask_ != null) {
if (optionalFieldMask_ == null) {
optionalFieldMask_ = new global::Google.Protobuf.WellKnownTypes.FieldMask();
OptionalFieldMask = new global::Google.Protobuf.WellKnownTypes.FieldMask();
}
OptionalFieldMask.MergeFrom(other.OptionalFieldMask);
}
if (other.optionalStruct_ != null) {
if (optionalStruct_ == null) {
optionalStruct_ = new global::Google.Protobuf.WellKnownTypes.Struct();
OptionalStruct = new global::Google.Protobuf.WellKnownTypes.Struct();
}
OptionalStruct.MergeFrom(other.OptionalStruct);
}
if (other.optionalAny_ != null) {
if (optionalAny_ == null) {
optionalAny_ = new global::Google.Protobuf.WellKnownTypes.Any();
OptionalAny = new global::Google.Protobuf.WellKnownTypes.Any();
}
OptionalAny.MergeFrom(other.OptionalAny);
}
if (other.optionalValue_ != null) {
if (optionalValue_ == null) {
optionalValue_ = new global::Google.Protobuf.WellKnownTypes.Value();
OptionalValue = new global::Google.Protobuf.WellKnownTypes.Value();
}
OptionalValue.MergeFrom(other.OptionalValue);
}
@ -2922,24 +2931,24 @@ namespace ProtobufTestMessages.Proto3 {
}
case 146: {
if (optionalNestedMessage_ == null) {
optionalNestedMessage_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage();
OptionalNestedMessage = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage();
}
input.ReadMessage(optionalNestedMessage_);
input.ReadMessage(OptionalNestedMessage);
break;
}
case 154: {
if (optionalForeignMessage_ == null) {
optionalForeignMessage_ = new global::ProtobufTestMessages.Proto3.ForeignMessage();
OptionalForeignMessage = new global::ProtobufTestMessages.Proto3.ForeignMessage();
}
input.ReadMessage(optionalForeignMessage_);
input.ReadMessage(OptionalForeignMessage);
break;
}
case 168: {
optionalNestedEnum_ = (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) input.ReadEnum();
OptionalNestedEnum = (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) input.ReadEnum();
break;
}
case 176: {
optionalForeignEnum_ = (global::ProtobufTestMessages.Proto3.ForeignEnum) input.ReadEnum();
OptionalForeignEnum = (global::ProtobufTestMessages.Proto3.ForeignEnum) input.ReadEnum();
break;
}
case 194: {
@ -2952,9 +2961,9 @@ namespace ProtobufTestMessages.Proto3 {
}
case 218: {
if (recursiveMessage_ == null) {
recursiveMessage_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
RecursiveMessage = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
}
input.ReadMessage(recursiveMessage_);
input.ReadMessage(RecursiveMessage);
break;
}
case 250:
@ -3275,44 +3284,44 @@ namespace ProtobufTestMessages.Proto3 {
}
case 2410: {
if (optionalDuration_ == null) {
optionalDuration_ = new global::Google.Protobuf.WellKnownTypes.Duration();
OptionalDuration = new global::Google.Protobuf.WellKnownTypes.Duration();
}
input.ReadMessage(optionalDuration_);
input.ReadMessage(OptionalDuration);
break;
}
case 2418: {
if (optionalTimestamp_ == null) {
optionalTimestamp_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
OptionalTimestamp = new global::Google.Protobuf.WellKnownTypes.Timestamp();
}
input.ReadMessage(optionalTimestamp_);
input.ReadMessage(OptionalTimestamp);
break;
}
case 2426: {
if (optionalFieldMask_ == null) {
optionalFieldMask_ = new global::Google.Protobuf.WellKnownTypes.FieldMask();
OptionalFieldMask = new global::Google.Protobuf.WellKnownTypes.FieldMask();
}
input.ReadMessage(optionalFieldMask_);
input.ReadMessage(OptionalFieldMask);
break;
}
case 2434: {
if (optionalStruct_ == null) {
optionalStruct_ = new global::Google.Protobuf.WellKnownTypes.Struct();
OptionalStruct = new global::Google.Protobuf.WellKnownTypes.Struct();
}
input.ReadMessage(optionalStruct_);
input.ReadMessage(OptionalStruct);
break;
}
case 2442: {
if (optionalAny_ == null) {
optionalAny_ = new global::Google.Protobuf.WellKnownTypes.Any();
OptionalAny = new global::Google.Protobuf.WellKnownTypes.Any();
}
input.ReadMessage(optionalAny_);
input.ReadMessage(OptionalAny);
break;
}
case 2450: {
if (optionalValue_ == null) {
optionalValue_ = new global::Google.Protobuf.WellKnownTypes.Value();
OptionalValue = new global::Google.Protobuf.WellKnownTypes.Value();
}
input.ReadMessage(optionalValue_);
input.ReadMessage(OptionalValue);
break;
}
case 2490: {
@ -3560,7 +3569,7 @@ namespace ProtobufTestMessages.Proto3 {
}
if (other.corecursive_ != null) {
if (corecursive_ == null) {
corecursive_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
Corecursive = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
}
Corecursive.MergeFrom(other.Corecursive);
}
@ -3581,9 +3590,9 @@ namespace ProtobufTestMessages.Proto3 {
}
case 18: {
if (corecursive_ == null) {
corecursive_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
Corecursive = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
}
input.ReadMessage(corecursive_);
input.ReadMessage(Corecursive);
break;
}
}

@ -1879,7 +1879,7 @@ namespace UnitTest.Issues.TestProtos {
}
if (other.bar_ != null) {
if (bar_ == null) {
bar_ = new global::UnitTest.Issues.TestProtos.ComplexOptionType1();
Bar = new global::UnitTest.Issues.TestProtos.ComplexOptionType1();
}
Bar.MergeFrom(other.Bar);
}
@ -1888,7 +1888,7 @@ namespace UnitTest.Issues.TestProtos {
}
if (other.fred_ != null) {
if (fred_ == null) {
fred_ = new global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4();
Fred = new global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4();
}
Fred.MergeFrom(other.Fred);
}
@ -1906,9 +1906,9 @@ namespace UnitTest.Issues.TestProtos {
break;
case 10: {
if (bar_ == null) {
bar_ = new global::UnitTest.Issues.TestProtos.ComplexOptionType1();
Bar = new global::UnitTest.Issues.TestProtos.ComplexOptionType1();
}
input.ReadMessage(bar_);
input.ReadMessage(Bar);
break;
}
case 16: {
@ -1917,9 +1917,9 @@ namespace UnitTest.Issues.TestProtos {
}
case 26: {
if (fred_ == null) {
fred_ = new global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4();
Fred = new global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4();
}
input.ReadMessage(fred_);
input.ReadMessage(Fred);
break;
}
case 34: {
@ -2462,7 +2462,7 @@ namespace UnitTest.Issues.TestProtos {
}
if (other.sub_ != null) {
if (sub_ == null) {
sub_ = new global::UnitTest.Issues.TestProtos.Aggregate();
Sub = new global::UnitTest.Issues.TestProtos.Aggregate();
}
Sub.MergeFrom(other.Sub);
}
@ -2487,9 +2487,9 @@ namespace UnitTest.Issues.TestProtos {
}
case 26: {
if (sub_ == null) {
sub_ = new global::UnitTest.Issues.TestProtos.Aggregate();
Sub = new global::UnitTest.Issues.TestProtos.Aggregate();
}
input.ReadMessage(sub_);
input.ReadMessage(Sub);
break;
}
}

@ -557,7 +557,7 @@ namespace UnitTest.Issues.TestProtos {
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
value_ = (global::UnitTest.Issues.TestProtos.NegativeEnum) input.ReadEnum();
Value = (global::UnitTest.Issues.TestProtos.NegativeEnum) input.ReadEnum();
break;
}
case 18:
@ -881,7 +881,7 @@ namespace UnitTest.Issues.TestProtos {
primitiveArray_.Add(other.primitiveArray_);
if (other.messageValue_ != null) {
if (messageValue_ == null) {
messageValue_ = new global::UnitTest.Issues.TestProtos.DeprecatedChild();
MessageValue = new global::UnitTest.Issues.TestProtos.DeprecatedChild();
}
MessageValue.MergeFrom(other.MessageValue);
}
@ -912,9 +912,9 @@ namespace UnitTest.Issues.TestProtos {
}
case 26: {
if (messageValue_ == null) {
messageValue_ = new global::UnitTest.Issues.TestProtos.DeprecatedChild();
MessageValue = new global::UnitTest.Issues.TestProtos.DeprecatedChild();
}
input.ReadMessage(messageValue_);
input.ReadMessage(MessageValue);
break;
}
case 34: {
@ -922,7 +922,7 @@ namespace UnitTest.Issues.TestProtos {
break;
}
case 40: {
enumValue_ = (global::UnitTest.Issues.TestProtos.DeprecatedEnum) input.ReadEnum();
EnumValue = (global::UnitTest.Issues.TestProtos.DeprecatedEnum) input.ReadEnum();
break;
}
case 50:

@ -1307,19 +1307,19 @@ namespace Google.Protobuf.TestProtos {
}
if (other.singleNestedMessage_ != null) {
if (singleNestedMessage_ == null) {
singleNestedMessage_ = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
SingleNestedMessage = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
}
SingleNestedMessage.MergeFrom(other.SingleNestedMessage);
}
if (other.singleForeignMessage_ != null) {
if (singleForeignMessage_ == null) {
singleForeignMessage_ = new global::Google.Protobuf.TestProtos.ForeignMessage();
SingleForeignMessage = new global::Google.Protobuf.TestProtos.ForeignMessage();
}
SingleForeignMessage.MergeFrom(other.SingleForeignMessage);
}
if (other.singleImportMessage_ != null) {
if (singleImportMessage_ == null) {
singleImportMessage_ = new global::Google.Protobuf.TestProtos.ImportMessage();
SingleImportMessage = new global::Google.Protobuf.TestProtos.ImportMessage();
}
SingleImportMessage.MergeFrom(other.SingleImportMessage);
}
@ -1334,7 +1334,7 @@ namespace Google.Protobuf.TestProtos {
}
if (other.singlePublicImportMessage_ != null) {
if (singlePublicImportMessage_ == null) {
singlePublicImportMessage_ = new global::Google.Protobuf.TestProtos.PublicImportMessage();
SinglePublicImportMessage = new global::Google.Protobuf.TestProtos.PublicImportMessage();
}
SinglePublicImportMessage.MergeFrom(other.SinglePublicImportMessage);
}
@ -1451,42 +1451,42 @@ namespace Google.Protobuf.TestProtos {
}
case 146: {
if (singleNestedMessage_ == null) {
singleNestedMessage_ = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
SingleNestedMessage = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
}
input.ReadMessage(singleNestedMessage_);
input.ReadMessage(SingleNestedMessage);
break;
}
case 154: {
if (singleForeignMessage_ == null) {
singleForeignMessage_ = new global::Google.Protobuf.TestProtos.ForeignMessage();
SingleForeignMessage = new global::Google.Protobuf.TestProtos.ForeignMessage();
}
input.ReadMessage(singleForeignMessage_);
input.ReadMessage(SingleForeignMessage);
break;
}
case 162: {
if (singleImportMessage_ == null) {
singleImportMessage_ = new global::Google.Protobuf.TestProtos.ImportMessage();
SingleImportMessage = new global::Google.Protobuf.TestProtos.ImportMessage();
}
input.ReadMessage(singleImportMessage_);
input.ReadMessage(SingleImportMessage);
break;
}
case 168: {
singleNestedEnum_ = (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) input.ReadEnum();
SingleNestedEnum = (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) input.ReadEnum();
break;
}
case 176: {
singleForeignEnum_ = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum();
SingleForeignEnum = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum();
break;
}
case 184: {
singleImportEnum_ = (global::Google.Protobuf.TestProtos.ImportEnum) input.ReadEnum();
SingleImportEnum = (global::Google.Protobuf.TestProtos.ImportEnum) input.ReadEnum();
break;
}
case 210: {
if (singlePublicImportMessage_ == null) {
singlePublicImportMessage_ = new global::Google.Protobuf.TestProtos.PublicImportMessage();
SinglePublicImportMessage = new global::Google.Protobuf.TestProtos.PublicImportMessage();
}
input.ReadMessage(singlePublicImportMessage_);
input.ReadMessage(SinglePublicImportMessage);
break;
}
case 250:
@ -1918,13 +1918,13 @@ namespace Google.Protobuf.TestProtos {
}
if (other.child_ != null) {
if (child_ == null) {
child_ = new global::Google.Protobuf.TestProtos.NestedTestAllTypes();
Child = new global::Google.Protobuf.TestProtos.NestedTestAllTypes();
}
Child.MergeFrom(other.Child);
}
if (other.payload_ != null) {
if (payload_ == null) {
payload_ = new global::Google.Protobuf.TestProtos.TestAllTypes();
Payload = new global::Google.Protobuf.TestProtos.TestAllTypes();
}
Payload.MergeFrom(other.Payload);
}
@ -1942,16 +1942,16 @@ namespace Google.Protobuf.TestProtos {
break;
case 10: {
if (child_ == null) {
child_ = new global::Google.Protobuf.TestProtos.NestedTestAllTypes();
Child = new global::Google.Protobuf.TestProtos.NestedTestAllTypes();
}
input.ReadMessage(child_);
input.ReadMessage(Child);
break;
}
case 18: {
if (payload_ == null) {
payload_ = new global::Google.Protobuf.TestProtos.TestAllTypes();
Payload = new global::Google.Protobuf.TestProtos.TestAllTypes();
}
input.ReadMessage(payload_);
input.ReadMessage(Payload);
break;
}
case 26: {
@ -2438,7 +2438,7 @@ namespace Google.Protobuf.TestProtos {
}
if (other.foreignNested_ != null) {
if (foreignNested_ == null) {
foreignNested_ = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
ForeignNested = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
}
ForeignNested.MergeFrom(other.ForeignNested);
}
@ -2455,9 +2455,9 @@ namespace Google.Protobuf.TestProtos {
break;
case 10: {
if (foreignNested_ == null) {
foreignNested_ = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
ForeignNested = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
}
input.ReadMessage(foreignNested_);
input.ReadMessage(ForeignNested);
break;
}
}
@ -2758,7 +2758,7 @@ namespace Google.Protobuf.TestProtos {
}
if (other.a_ != null) {
if (a_ == null) {
a_ = new global::Google.Protobuf.TestProtos.TestRecursiveMessage();
A = new global::Google.Protobuf.TestProtos.TestRecursiveMessage();
}
A.MergeFrom(other.A);
}
@ -2778,9 +2778,9 @@ namespace Google.Protobuf.TestProtos {
break;
case 10: {
if (a_ == null) {
a_ = new global::Google.Protobuf.TestProtos.TestRecursiveMessage();
A = new global::Google.Protobuf.TestProtos.TestRecursiveMessage();
}
input.ReadMessage(a_);
input.ReadMessage(A);
break;
}
case 16: {
@ -2903,7 +2903,7 @@ namespace Google.Protobuf.TestProtos {
}
if (other.bb_ != null) {
if (bb_ == null) {
bb_ = new global::Google.Protobuf.TestProtos.TestMutualRecursionB();
Bb = new global::Google.Protobuf.TestProtos.TestMutualRecursionB();
}
Bb.MergeFrom(other.Bb);
}
@ -2920,9 +2920,9 @@ namespace Google.Protobuf.TestProtos {
break;
case 10: {
if (bb_ == null) {
bb_ = new global::Google.Protobuf.TestProtos.TestMutualRecursionB();
Bb = new global::Google.Protobuf.TestProtos.TestMutualRecursionB();
}
input.ReadMessage(bb_);
input.ReadMessage(Bb);
break;
}
}
@ -3059,7 +3059,7 @@ namespace Google.Protobuf.TestProtos {
}
if (other.a_ != null) {
if (a_ == null) {
a_ = new global::Google.Protobuf.TestProtos.TestMutualRecursionA();
A = new global::Google.Protobuf.TestProtos.TestMutualRecursionA();
}
A.MergeFrom(other.A);
}
@ -3079,9 +3079,9 @@ namespace Google.Protobuf.TestProtos {
break;
case 10: {
if (a_ == null) {
a_ = new global::Google.Protobuf.TestProtos.TestMutualRecursionA();
A = new global::Google.Protobuf.TestProtos.TestMutualRecursionA();
}
input.ReadMessage(a_);
input.ReadMessage(A);
break;
}
case 16: {
@ -3214,7 +3214,7 @@ namespace Google.Protobuf.TestProtos {
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
value_ = (global::Google.Protobuf.TestProtos.TestEnumWithDupValue) input.ReadEnum();
Value = (global::Google.Protobuf.TestProtos.TestEnumWithDupValue) input.ReadEnum();
break;
}
}
@ -3466,7 +3466,7 @@ namespace Google.Protobuf.TestProtos {
}
if (other.messageField_ != null) {
if (messageField_ == null) {
messageField_ = new global::Google.Protobuf.TestProtos.ForeignMessage();
MessageField = new global::Google.Protobuf.TestProtos.ForeignMessage();
}
MessageField.MergeFrom(other.MessageField);
}
@ -3494,14 +3494,14 @@ namespace Google.Protobuf.TestProtos {
break;
}
case 24: {
enumField_ = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum();
EnumField = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum();
break;
}
case 34: {
if (messageField_ == null) {
messageField_ = new global::Google.Protobuf.TestProtos.ForeignMessage();
MessageField = new global::Google.Protobuf.TestProtos.ForeignMessage();
}
input.ReadMessage(messageField_);
input.ReadMessage(MessageField);
break;
}
case 58:
@ -3711,7 +3711,7 @@ namespace Google.Protobuf.TestProtos {
}
if (other.singleNestedMessage_ != null) {
if (singleNestedMessage_ == null) {
singleNestedMessage_ = new global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage();
SingleNestedMessage = new global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage();
}
SingleNestedMessage.MergeFrom(other.SingleNestedMessage);
}
@ -3740,9 +3740,9 @@ namespace Google.Protobuf.TestProtos {
}
case 1602: {
if (singleNestedMessage_ == null) {
singleNestedMessage_ = new global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage();
SingleNestedMessage = new global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage();
}
input.ReadMessage(singleNestedMessage_);
input.ReadMessage(SingleNestedMessage);
break;
}
}
@ -4040,7 +4040,7 @@ namespace Google.Protobuf.TestProtos {
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
sparseEnum_ = (global::Google.Protobuf.TestProtos.TestSparseEnum) input.ReadEnum();
SparseEnum = (global::Google.Protobuf.TestProtos.TestSparseEnum) input.ReadEnum();
break;
}
}

@ -342,6 +342,7 @@ namespace Google.Protobuf.TestProtos {
}
}
/// <summary>Field number for the "float_field" field.</summary>
public const int FloatFieldFieldNumber = 11;
private static readonly pb::FieldCodec<float?> _single_floatField_codec = pb::FieldCodec.ForStructWrapper<float>(90);
@ -354,6 +355,7 @@ namespace Google.Protobuf.TestProtos {
}
}
/// <summary>Field number for the "int64_field" field.</summary>
public const int Int64FieldFieldNumber = 12;
private static readonly pb::FieldCodec<long?> _single_int64Field_codec = pb::FieldCodec.ForStructWrapper<long>(98);
@ -366,6 +368,7 @@ namespace Google.Protobuf.TestProtos {
}
}
/// <summary>Field number for the "uint64_field" field.</summary>
public const int Uint64FieldFieldNumber = 13;
private static readonly pb::FieldCodec<ulong?> _single_uint64Field_codec = pb::FieldCodec.ForStructWrapper<ulong>(106);
@ -378,6 +381,7 @@ namespace Google.Protobuf.TestProtos {
}
}
/// <summary>Field number for the "int32_field" field.</summary>
public const int Int32FieldFieldNumber = 14;
private static readonly pb::FieldCodec<int?> _single_int32Field_codec = pb::FieldCodec.ForStructWrapper<int>(114);
@ -390,6 +394,7 @@ namespace Google.Protobuf.TestProtos {
}
}
/// <summary>Field number for the "uint32_field" field.</summary>
public const int Uint32FieldFieldNumber = 15;
private static readonly pb::FieldCodec<uint?> _single_uint32Field_codec = pb::FieldCodec.ForStructWrapper<uint>(122);
@ -402,6 +407,7 @@ namespace Google.Protobuf.TestProtos {
}
}
/// <summary>Field number for the "bool_field" field.</summary>
public const int BoolFieldFieldNumber = 16;
private static readonly pb::FieldCodec<bool?> _single_boolField_codec = pb::FieldCodec.ForStructWrapper<bool>(130);
@ -414,6 +420,7 @@ namespace Google.Protobuf.TestProtos {
}
}
/// <summary>Field number for the "string_field" field.</summary>
public const int StringFieldFieldNumber = 17;
private static readonly pb::FieldCodec<string> _single_stringField_codec = pb::FieldCodec.ForClassWrapper<string>(138);
@ -426,6 +433,7 @@ namespace Google.Protobuf.TestProtos {
}
}
/// <summary>Field number for the "bytes_field" field.</summary>
public const int BytesFieldFieldNumber = 18;
private static readonly pb::FieldCodec<pb::ByteString> _single_bytesField_codec = pb::FieldCodec.ForClassWrapper<pb::ByteString>(146);
@ -438,6 +446,7 @@ namespace Google.Protobuf.TestProtos {
}
}
/// <summary>Field number for the "value_field" field.</summary>
public const int ValueFieldFieldNumber = 19;
private global::Google.Protobuf.WellKnownTypes.Value valueField_;
@ -667,55 +676,55 @@ namespace Google.Protobuf.TestProtos {
}
if (other.anyField_ != null) {
if (anyField_ == null) {
anyField_ = new global::Google.Protobuf.WellKnownTypes.Any();
AnyField = new global::Google.Protobuf.WellKnownTypes.Any();
}
AnyField.MergeFrom(other.AnyField);
}
if (other.apiField_ != null) {
if (apiField_ == null) {
apiField_ = new global::Google.Protobuf.WellKnownTypes.Api();
ApiField = new global::Google.Protobuf.WellKnownTypes.Api();
}
ApiField.MergeFrom(other.ApiField);
}
if (other.durationField_ != null) {
if (durationField_ == null) {
durationField_ = new global::Google.Protobuf.WellKnownTypes.Duration();
DurationField = new global::Google.Protobuf.WellKnownTypes.Duration();
}
DurationField.MergeFrom(other.DurationField);
}
if (other.emptyField_ != null) {
if (emptyField_ == null) {
emptyField_ = new global::Google.Protobuf.WellKnownTypes.Empty();
EmptyField = new global::Google.Protobuf.WellKnownTypes.Empty();
}
EmptyField.MergeFrom(other.EmptyField);
}
if (other.fieldMaskField_ != null) {
if (fieldMaskField_ == null) {
fieldMaskField_ = new global::Google.Protobuf.WellKnownTypes.FieldMask();
FieldMaskField = new global::Google.Protobuf.WellKnownTypes.FieldMask();
}
FieldMaskField.MergeFrom(other.FieldMaskField);
}
if (other.sourceContextField_ != null) {
if (sourceContextField_ == null) {
sourceContextField_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
SourceContextField = new global::Google.Protobuf.WellKnownTypes.SourceContext();
}
SourceContextField.MergeFrom(other.SourceContextField);
}
if (other.structField_ != null) {
if (structField_ == null) {
structField_ = new global::Google.Protobuf.WellKnownTypes.Struct();
StructField = new global::Google.Protobuf.WellKnownTypes.Struct();
}
StructField.MergeFrom(other.StructField);
}
if (other.timestampField_ != null) {
if (timestampField_ == null) {
timestampField_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
TimestampField = new global::Google.Protobuf.WellKnownTypes.Timestamp();
}
TimestampField.MergeFrom(other.TimestampField);
}
if (other.typeField_ != null) {
if (typeField_ == null) {
typeField_ = new global::Google.Protobuf.WellKnownTypes.Type();
TypeField = new global::Google.Protobuf.WellKnownTypes.Type();
}
TypeField.MergeFrom(other.TypeField);
}
@ -766,7 +775,7 @@ namespace Google.Protobuf.TestProtos {
}
if (other.valueField_ != null) {
if (valueField_ == null) {
valueField_ = new global::Google.Protobuf.WellKnownTypes.Value();
ValueField = new global::Google.Protobuf.WellKnownTypes.Value();
}
ValueField.MergeFrom(other.ValueField);
}
@ -783,65 +792,65 @@ namespace Google.Protobuf.TestProtos {
break;
case 10: {
if (anyField_ == null) {
anyField_ = new global::Google.Protobuf.WellKnownTypes.Any();
AnyField = new global::Google.Protobuf.WellKnownTypes.Any();
}
input.ReadMessage(anyField_);
input.ReadMessage(AnyField);
break;
}
case 18: {
if (apiField_ == null) {
apiField_ = new global::Google.Protobuf.WellKnownTypes.Api();
ApiField = new global::Google.Protobuf.WellKnownTypes.Api();
}
input.ReadMessage(apiField_);
input.ReadMessage(ApiField);
break;
}
case 26: {
if (durationField_ == null) {
durationField_ = new global::Google.Protobuf.WellKnownTypes.Duration();
DurationField = new global::Google.Protobuf.WellKnownTypes.Duration();
}
input.ReadMessage(durationField_);
input.ReadMessage(DurationField);
break;
}
case 34: {
if (emptyField_ == null) {
emptyField_ = new global::Google.Protobuf.WellKnownTypes.Empty();
EmptyField = new global::Google.Protobuf.WellKnownTypes.Empty();
}
input.ReadMessage(emptyField_);
input.ReadMessage(EmptyField);
break;
}
case 42: {
if (fieldMaskField_ == null) {
fieldMaskField_ = new global::Google.Protobuf.WellKnownTypes.FieldMask();
FieldMaskField = new global::Google.Protobuf.WellKnownTypes.FieldMask();
}
input.ReadMessage(fieldMaskField_);
input.ReadMessage(FieldMaskField);
break;
}
case 50: {
if (sourceContextField_ == null) {
sourceContextField_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
SourceContextField = new global::Google.Protobuf.WellKnownTypes.SourceContext();
}
input.ReadMessage(sourceContextField_);
input.ReadMessage(SourceContextField);
break;
}
case 58: {
if (structField_ == null) {
structField_ = new global::Google.Protobuf.WellKnownTypes.Struct();
StructField = new global::Google.Protobuf.WellKnownTypes.Struct();
}
input.ReadMessage(structField_);
input.ReadMessage(StructField);
break;
}
case 66: {
if (timestampField_ == null) {
timestampField_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
TimestampField = new global::Google.Protobuf.WellKnownTypes.Timestamp();
}
input.ReadMessage(timestampField_);
input.ReadMessage(TimestampField);
break;
}
case 74: {
if (typeField_ == null) {
typeField_ = new global::Google.Protobuf.WellKnownTypes.Type();
TypeField = new global::Google.Protobuf.WellKnownTypes.Type();
}
input.ReadMessage(typeField_);
input.ReadMessage(TypeField);
break;
}
case 82: {
@ -909,9 +918,9 @@ namespace Google.Protobuf.TestProtos {
}
case 154: {
if (valueField_ == null) {
valueField_ = new global::Google.Protobuf.WellKnownTypes.Value();
ValueField = new global::Google.Protobuf.WellKnownTypes.Value();
}
input.ReadMessage(valueField_);
input.ReadMessage(ValueField);
break;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -125,5 +125,10 @@ namespace Google.Protobuf
return new InvalidProtocolBufferException(
"Stream of protocol messages had invalid tag. Expected tag is length-delimited field 1.");
}
}
internal static InvalidProtocolBufferException MissingFields()
{
return new InvalidProtocolBufferException("Message was missing required fields");
}
}
}

@ -30,7 +30,10 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using Google.Protobuf.Reflection;
using System.Collections;
using System.IO;
using System.Linq;
namespace Google.Protobuf
{
@ -140,6 +143,53 @@ namespace Google.Protobuf
return ByteString.AttachBytes(message.ToByteArray());
}
/// <summary>
/// Checks if all required fields in a message have values set. For proto3 messages, this returns true
/// </summary>
public static bool IsInitialized(this IMessage message)
{
if (message.Descriptor.File.Proto.Syntax != "proto2")
{
return true;
}
return message.Descriptor
.Fields
.InDeclarationOrder()
.All(f =>
{
if (f.IsMap)
{
var map = (IDictionary)f.Accessor.GetValue(message);
return map.Values.OfType<IMessage>().All(IsInitialized);
}
else if (f.IsRepeated && f.MessageType != null)
{
var enumerable = (IEnumerable)f.Accessor.GetValue(message);
return enumerable.Cast<IMessage>().All(IsInitialized);
}
else if (f.MessageType != null)
{
if (f.Accessor.HasValue(message))
{
return ((IMessage)f.Accessor.GetValue(message)).IsInitialized();
}
else
{
return !f.IsRequired;
}
}
else if (f.IsRequired)
{
return f.Accessor.HasValue(message);
}
else
{
return true;
}
});
}
// Implementations allowing unknown fields to be discarded.
internal static void MergeFrom(this IMessage message, byte[] data, bool discardUnknownFields)
{

@ -69,6 +69,7 @@ namespace Google.Protobuf
{
IMessage message = factory();
message.MergeFrom(data, DiscardUnknownFields);
CheckMergedRequiredFields(message);
return message;
}
@ -83,6 +84,7 @@ namespace Google.Protobuf
{
IMessage message = factory();
message.MergeFrom(data, offset, length, DiscardUnknownFields);
CheckMergedRequiredFields(message);
return message;
}
@ -95,6 +97,7 @@ namespace Google.Protobuf
{
IMessage message = factory();
message.MergeFrom(data, DiscardUnknownFields);
CheckMergedRequiredFields(message);
return message;
}
@ -107,6 +110,7 @@ namespace Google.Protobuf
{
IMessage message = factory();
message.MergeFrom(input, DiscardUnknownFields);
CheckMergedRequiredFields(message);
return message;
}
@ -123,6 +127,7 @@ namespace Google.Protobuf
{
IMessage message = factory();
message.MergeDelimitedFrom(input, DiscardUnknownFields);
CheckMergedRequiredFields(message);
return message;
}
@ -135,6 +140,7 @@ namespace Google.Protobuf
{
IMessage message = factory();
MergeFrom(message, input);
CheckMergedRequiredFields(message);
return message;
}
@ -167,6 +173,12 @@ namespace Google.Protobuf
}
}
internal static void CheckMergedRequiredFields(IMessage message)
{
if (!message.IsInitialized())
throw new InvalidOperationException("Parsed message does not contain all required fields");
}
/// <summary>
/// Creates a new message parser which optionally discards unknown fields when parsing.
/// </summary>

@ -1,79 +1,79 @@
#region Copyright notice and license
// 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.
#endregion
using System;
namespace Google.Protobuf
{
/// <summary>
/// Helper methods for throwing exceptions when preconditions are not met.
/// </summary>
/// <remarks>
/// This class is used internally and by generated code; it is not particularly
/// expected to be used from application code, although nothing prevents it
/// from being used that way.
/// </remarks>
public static class ProtoPreconditions
{
/// <summary>
/// Throws an ArgumentNullException if the given value is null, otherwise
/// return the value to the caller.
/// </summary>
public static T CheckNotNull<T>(T value, string name) where T : class
{
if (value == null)
{
throw new ArgumentNullException(name);
}
return value;
}
/// <summary>
/// Throws an ArgumentNullException if the given value is null, otherwise
/// return the value to the caller.
/// </summary>
/// <remarks>
/// This is equivalent to <see cref="CheckNotNull{T}(T, string)"/> but without the type parameter
/// constraint. In most cases, the constraint is useful to prevent you from calling CheckNotNull
/// with a value type - but it gets in the way if either you want to use it with a nullable
/// value type, or you want to use it with an unconstrained type parameter.
/// </remarks>
internal static T CheckNotNullUnconstrained<T>(T value, string name)
{
if (value == null)
{
throw new ArgumentNullException(name);
}
return value;
}
}
#region Copyright notice and license
// 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.
#endregion
using System;
namespace Google.Protobuf
{
/// <summary>
/// Helper methods for throwing exceptions when preconditions are not met.
/// </summary>
/// <remarks>
/// This class is used internally and by generated code; it is not particularly
/// expected to be used from application code, although nothing prevents it
/// from being used that way.
/// </remarks>
public static class ProtoPreconditions
{
/// <summary>
/// Throws an ArgumentNullException if the given value is null, otherwise
/// return the value to the caller.
/// </summary>
public static T CheckNotNull<T>(T value, string name) where T : class
{
if (value == null)
{
throw new ArgumentNullException(name);
}
return value;
}
/// <summary>
/// Throws an ArgumentNullException if the given value is null, otherwise
/// return the value to the caller.
/// </summary>
/// <remarks>
/// This is equivalent to <see cref="CheckNotNull{T}(T, string)"/> but without the type parameter
/// constraint. In most cases, the constraint is useful to prevent you from calling CheckNotNull
/// with a value type - but it gets in the way if either you want to use it with a nullable
/// value type, or you want to use it with an unconstrained type parameter.
/// </remarks>
internal static T CheckNotNullUnconstrained<T>(T value, string name)
{
if (value == null)
{
throw new ArgumentNullException(name);
}
return value;
}
}
}

File diff suppressed because it is too large Load Diff

@ -57,6 +57,7 @@ namespace Google.Protobuf.Reflection
return getValueDelegate(message);
}
public abstract bool HasValue(IMessage message);
public abstract void Clear(IMessage message);
public abstract void SetValue(IMessage message, object value);
}

@ -79,8 +79,7 @@ namespace Google.Protobuf.Reflection
throw new DescriptorValidationException(this, "Field numbers must be positive integers.");
}
ContainingType = parent;
// OneofIndex "defaults" to -1 due to a hack in FieldDescriptor.OnConstruction.
if (proto.OneofIndex != -1)
if (proto.HasOneofIndex)
{
if (proto.OneofIndex < 0 || proto.OneofIndex >= parent.Proto.OneofDecl.Count)
{
@ -184,6 +183,11 @@ namespace Google.Protobuf.Reflection
/// </summary>
public bool IsRepeated => Proto.Label == FieldDescriptorProto.Types.Label.Repeated;
/// <summary>
/// Returns <c>true</c> if this field is a required field; <c>false</c> otherwise.
/// </summary>
public bool IsRequired => Proto.Label == FieldDescriptorProto.Types.Label.Required;
/// <summary>
/// Returns <c>true</c> if this field is a map field; <c>false</c> otherwise.
/// </summary>
@ -192,13 +196,8 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// Returns <c>true</c> if this field is a packed, repeated field; <c>false</c> otherwise.
/// </summary>
public bool IsPacked =>
// Note the || rather than && here - we're effectively defaulting to packed, because that *is*
// the default in proto3, which is all we support. We may give the wrong result for the protos
// within descriptor.proto, but that's okay, as they're never exposed and we don't use IsPacked
// within the runtime.
Proto.Options == null || Proto.Options.Packed;
public bool IsPacked => File.Proto.Syntax == "proto2" ? Proto.Options?.Packed ?? false : !Proto.Options.HasPacked || Proto.Options.Packed;
/// <summary>
/// Returns the type of the field.
/// </summary>
@ -247,9 +246,9 @@ namespace Google.Protobuf.Reflection
{
get
{
if (fieldType != FieldType.Message)
if (fieldType != FieldType.Message && fieldType != FieldType.Group)
{
throw new InvalidOperationException("MessageType is only valid for message fields.");
throw new InvalidOperationException("MessageType is only valid for message or group fields.");
}
return messageType;
}
@ -265,12 +264,12 @@ namespace Google.Protobuf.Reflection
/// </summary>
internal void CrossLink()
{
if (Proto.TypeName != "")
if (Proto.HasTypeName)
{
IDescriptor typeDescriptor =
File.DescriptorPool.LookupSymbol(Proto.TypeName, this);
if (Proto.Type != 0)
if (Proto.HasType)
{
// Choose field type based on symbol.
if (typeDescriptor is MessageDescriptor)
@ -287,7 +286,7 @@ namespace Google.Protobuf.Reflection
}
}
if (fieldType == FieldType.Message)
if (fieldType == FieldType.Message || fieldType == FieldType.Group)
{
if (!(typeDescriptor is MessageDescriptor))
{
@ -295,7 +294,7 @@ namespace Google.Protobuf.Reflection
}
messageType = (MessageDescriptor) typeDescriptor;
if (Proto.DefaultValue != "")
if (Proto.HasDefaultValue)
{
throw new DescriptorValidationException(this, "Messages can't have default values.");
}
@ -325,7 +324,7 @@ namespace Google.Protobuf.Reflection
File.DescriptorPool.AddFieldByNumber(this);
if (ContainingType != null && ContainingType.Proto.Options != null && ContainingType.Proto.Options.MessageSetWireFormat)
if (ContainingType != null && ContainingType.Proto.HasOptions && ContainingType.Proto.Options.MessageSetWireFormat)
{
throw new DescriptorValidationException(this, "MessageSet format is not supported.");
}

@ -74,7 +74,7 @@ namespace Google.Protobuf.Reflection
/// </summary>
String,
/// <summary>
/// The field type used for groups (not supported in this implementation).
/// The field type used for groups.
/// </summary>
Group,
/// <summary>

@ -51,6 +51,11 @@ namespace Google.Protobuf.Reflection
/// </summary>
void Clear(IMessage message);
/// <summary>
/// Indicates whether the field in the specified message is set. For proto3 fields, this throws an <see cref="InvalidOperationException"/>
/// </summary>
bool HasValue(IMessage message);
/// <summary>
/// Fetches the field value. For repeated values, this will be an
/// <see cref="IList"/> implementation. For map values, this will be an

@ -51,6 +51,11 @@ namespace Google.Protobuf.Reflection
list.Clear();
}
public override bool HasValue(IMessage message)
{
throw new InvalidOperationException("HasValue is not implemented for map fields");
}
public override void SetValue(IMessage message, object value)
{
throw new InvalidOperationException("SetValue is not implemented for map fields");

@ -1,59 +0,0 @@
#region Copyright notice and license
// 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.
#endregion
// This file just contains partial classes for any autogenerated classes that need additional support.
namespace Google.Protobuf.Reflection
{
internal partial class FieldDescriptorProto
{
// We can't tell the difference between "explicitly set to 0" and "not set"
// in proto3, but we need to tell the difference for OneofIndex. descriptor.proto
// is really a proto2 file, but the runtime doesn't know about proto2 semantics...
// We fake it by defaulting to -1.
partial void OnConstruction()
{
OneofIndex = -1;
}
}
internal partial class FieldOptions
{
// We can't tell the difference between "explicitly set to false" and "not set"
// in proto3, but we need to tell the difference for FieldDescriptor.IsPacked.
// This won't work if we ever need to support proto2, but at that point we'll be
// able to remove this hack and use field presence instead.
partial void OnConstruction()
{
Packed = true;
}
}
}

@ -112,6 +112,9 @@ namespace Google.Protobuf.Reflection
internal static Action<IMessage> CreateActionIMessage(MethodInfo method) =>
GetReflectionHelper(method.DeclaringType, typeof(object)).CreateActionIMessage(method);
internal static Func<IMessage, bool> CreateFuncIMessageBool(MethodInfo method) =>
GetReflectionHelper(method.DeclaringType, method.ReturnType).CreateFuncIMessageBool(method);
/// <summary>
/// Creates a reflection helper for the given type arguments. Currently these are created on demand
/// rather than cached; this will be "busy" when initially loading a message's descriptor, but after that
@ -129,6 +132,7 @@ namespace Google.Protobuf.Reflection
Action<IMessage> CreateActionIMessage(MethodInfo method);
Func<IMessage, object> CreateFuncIMessageObject(MethodInfo method);
Action<IMessage, object> CreateActionIMessageObject(MethodInfo method);
Func<IMessage, bool> CreateFuncIMessageBool(MethodInfo method);
}
private class ReflectionHelper<T1, T2> : IReflectionHelper
@ -170,6 +174,12 @@ namespace Google.Protobuf.Reflection
var del = (Action<T1, T2>) method.CreateDelegate(typeof(Action<T1, T2>));
return (message, arg) => del((T1) message, (T2) arg);
}
public Func<IMessage, bool> CreateFuncIMessageBool(MethodInfo method)
{
var del = (Func<T1, bool>)method.CreateDelegate(typeof(Func<T1, bool>));
return message => del((T1)message);
}
}
// Runtime compatibility checking code - see ReflectionHelper<T1, T2>.CreateFuncIMessageInt32 for

@ -51,6 +51,11 @@ namespace Google.Protobuf.Reflection
list.Clear();
}
public override bool HasValue(IMessage message)
{
throw new InvalidOperationException("HasValue is not implemented for repeated fields");
}
public override void SetValue(IMessage message, object value)
{
throw new InvalidOperationException("SetValue is not implemented for repeated fields");

@ -48,6 +48,7 @@ namespace Google.Protobuf.Reflection
private readonly Action<IMessage, object> setValueDelegate;
private readonly Action<IMessage> clearDelegate;
private readonly Func<IMessage, bool> hasDelegate;
internal SingleFieldAccessor(PropertyInfo property, FieldDescriptor descriptor) : base(property, descriptor)
{
@ -56,16 +57,25 @@ namespace Google.Protobuf.Reflection
throw new ArgumentException("Not all required properties/methods available");
}
setValueDelegate = ReflectionUtil.CreateActionIMessageObject(property.GetSetMethod());
if (descriptor.File.Proto.Syntax == "proto2")
{
MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod;
hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod ?? throw new ArgumentException("Not all required properties/methods are available"));
MethodInfo clearMethod = property.DeclaringType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes);
clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod ?? throw new ArgumentException("Not all required properties/methods are available"));
}
else
{
hasDelegate = (_) => throw new InvalidOperationException("HasValue is not implemented for proto3 fields"); var clrType = property.PropertyType;
var clrType = property.PropertyType;
// TODO: Validate that this is a reasonable single field? (Should be a value type, a message type, or string/ByteString.)
object defaultValue =
descriptor.FieldType == FieldType.Message ? null
: clrType == typeof(string) ? ""
: clrType == typeof(ByteString) ? ByteString.Empty
: Activator.CreateInstance(clrType);
clearDelegate = message => SetValue(message, defaultValue);
// TODO: Validate that this is a reasonable single field? (Should be a value type, a message type, or string/ByteString.)
object defaultValue =
descriptor.FieldType == FieldType.Message ? null
: clrType == typeof(string) ? ""
: clrType == typeof(ByteString) ? ByteString.Empty
: Activator.CreateInstance(clrType);
clearDelegate = message => SetValue(message, defaultValue);
}
}
public override void Clear(IMessage message)
@ -73,6 +83,11 @@ namespace Google.Protobuf.Reflection
clearDelegate(message);
}
public override bool HasValue(IMessage message)
{
return hasDelegate(message);
}
public override void SetValue(IMessage message, object value)
{
setValueDelegate(message, value);

@ -328,7 +328,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
if (other.sourceContext_ != null) {
if (sourceContext_ == null) {
sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext();
}
SourceContext.MergeFrom(other.SourceContext);
}
@ -365,9 +365,9 @@ namespace Google.Protobuf.WellKnownTypes {
}
case 42: {
if (sourceContext_ == null) {
sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext();
}
input.ReadMessage(sourceContext_);
input.ReadMessage(SourceContext);
break;
}
case 50: {
@ -375,7 +375,7 @@ namespace Google.Protobuf.WellKnownTypes {
break;
}
case 56: {
syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
Syntax = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
break;
}
}
@ -688,7 +688,7 @@ namespace Google.Protobuf.WellKnownTypes {
break;
}
case 56: {
syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
Syntax = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
break;
}
}

@ -312,7 +312,7 @@ namespace Google.Protobuf.WellKnownTypes {
options_.Add(other.options_);
if (other.sourceContext_ != null) {
if (sourceContext_ == null) {
sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext();
}
SourceContext.MergeFrom(other.SourceContext);
}
@ -348,13 +348,13 @@ namespace Google.Protobuf.WellKnownTypes {
}
case 42: {
if (sourceContext_ == null) {
sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext();
}
input.ReadMessage(sourceContext_);
input.ReadMessage(SourceContext);
break;
}
case 48: {
syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
Syntax = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
break;
}
}
@ -726,11 +726,11 @@ namespace Google.Protobuf.WellKnownTypes {
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
kind_ = (global::Google.Protobuf.WellKnownTypes.Field.Types.Kind) input.ReadEnum();
Kind = (global::Google.Protobuf.WellKnownTypes.Field.Types.Kind) input.ReadEnum();
break;
}
case 16: {
cardinality_ = (global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality) input.ReadEnum();
Cardinality = (global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality) input.ReadEnum();
break;
}
case 24: {
@ -1084,7 +1084,7 @@ namespace Google.Protobuf.WellKnownTypes {
options_.Add(other.options_);
if (other.sourceContext_ != null) {
if (sourceContext_ == null) {
sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext();
}
SourceContext.MergeFrom(other.SourceContext);
}
@ -1116,13 +1116,13 @@ namespace Google.Protobuf.WellKnownTypes {
}
case 34: {
if (sourceContext_ == null) {
sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext();
}
input.ReadMessage(sourceContext_);
input.ReadMessage(SourceContext);
break;
}
case 40: {
syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
Syntax = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
break;
}
}
@ -1467,7 +1467,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
if (other.value_ != null) {
if (value_ == null) {
value_ = new global::Google.Protobuf.WellKnownTypes.Any();
Value = new global::Google.Protobuf.WellKnownTypes.Any();
}
Value.MergeFrom(other.Value);
}
@ -1488,9 +1488,9 @@ namespace Google.Protobuf.WellKnownTypes {
}
case 18: {
if (value_ == null) {
value_ = new global::Google.Protobuf.WellKnownTypes.Any();
Value = new global::Google.Protobuf.WellKnownTypes.Any();
}
input.ReadMessage(value_);
input.ReadMessage(Value);
break;
}
}

@ -61,11 +61,11 @@ namespace Google.Protobuf
/// </summary>
LengthDelimited = 2,
/// <summary>
/// A "start group" value - not supported by this implementation.
/// A "start group" value
/// </summary>
StartGroup = 3,
/// <summary>
/// An "end group" value - not supported by this implementation.
/// An "end group" value
/// </summary>
EndGroup = 4,
/// <summary>

@ -47,8 +47,8 @@ namespace compiler {
namespace csharp {
EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
int fieldOrdinal, const Options *options)
: PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) {
int presenceIndex, const Options *options)
: PrimitiveFieldGenerator(descriptor, presenceIndex, options) {
}
EnumFieldGenerator::~EnumFieldGenerator() {
@ -56,7 +56,7 @@ EnumFieldGenerator::~EnumFieldGenerator() {
void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
printer->Print(variables_,
"$name$_ = ($type_name$) input.ReadEnum();\n");
"$property_name$ = ($type_name$) input.ReadEnum();\n");
}
void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
@ -82,8 +82,8 @@ void EnumFieldGenerator::GenerateCodecCode(io::Printer* printer) {
}
EnumOneofFieldGenerator::EnumOneofFieldGenerator(
const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
: PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options) {
const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
: PrimitiveOneofFieldGenerator(descriptor, presenceIndex, options) {
}
EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {

@ -44,7 +44,7 @@ namespace csharp {
class EnumFieldGenerator : public PrimitiveFieldGenerator {
public:
EnumFieldGenerator(const FieldDescriptor* descriptor,
int fieldOrdinal,
int presenceIndex,
const Options *options);
~EnumFieldGenerator();
@ -60,7 +60,7 @@ class EnumFieldGenerator : public PrimitiveFieldGenerator {
class EnumOneofFieldGenerator : public PrimitiveOneofFieldGenerator {
public:
EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
int fieldOrdinal,
int presenceIndex,
const Options *options);
~EnumOneofFieldGenerator();

@ -57,6 +57,9 @@ void FieldGeneratorBase::SetCommonFieldVariables(
// repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which
// never effects the tag size.
int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
tag_size /= 2;
}
uint tag = internal::WireFormat::MakeTag(descriptor_);
uint8 tag_array[5];
io::CodedOutputStream::WriteTagToArray(tag, tag_array);
@ -75,34 +78,52 @@ void FieldGeneratorBase::SetCommonFieldVariables(
(*variables)["name"] = name();
(*variables)["descriptor_name"] = descriptor_->name();
(*variables)["default_value"] = default_value();
if (has_default_value()) {
(*variables)["capitalized_type_name"] = capitalized_type_name();
(*variables)["number"] = number();
if (has_default_value() && !IsProto2(descriptor_->file())) {
(*variables)["name_def_message"] =
(*variables)["name"] + "_ = " + (*variables)["default_value"];
} else {
(*variables)["name_def_message"] = (*variables)["name"] + "_";
}
(*variables)["capitalized_type_name"] = capitalized_type_name();
(*variables)["number"] = number();
(*variables)["has_property_check"] =
(*variables)["property_name"] + " != " + (*variables)["default_value"];
(*variables)["other_has_property_check"] = "other." +
(*variables)["property_name"] + " != " + (*variables)["default_value"];
if (IsProto2(descriptor_->file())) {
(*variables)["has_property_check"] = "Has" + (*variables)["property_name"];
(*variables)["other_has_property_check"] = "other.Has" + (*variables)["property_name"];
(*variables)["has_not_property_check"] = "!" + (*variables)["has_property_check"];
(*variables)["other_has_not_property_check"] = "!" + (*variables)["other_has_property_check"];
if (presenceIndex_ != -1) {
string hasBitsNumber = SimpleItoa(presenceIndex_ / 32);
string hasBitsMask = SimpleItoa(1 << (presenceIndex_ % 32));
(*variables)["has_field_check"] = "(_hasBits" + hasBitsNumber + " & " + hasBitsMask + ") != 0";
(*variables)["set_has_field"] = "_hasBits" + hasBitsNumber + " |= " + hasBitsMask;
(*variables)["clear_has_field"] = "_hasBits" + hasBitsNumber + " &= ~" + hasBitsMask;
}
} else {
(*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(
std::map<string, string>* variables) {
(*variables)["oneof_name"] = oneof_name();
(*variables)["has_property_check"] =
oneof_name() + "Case_ == " + oneof_property_name() +
"OneofCase." + property_name();
if (IsProto2(descriptor_->file())) {
(*variables)["has_property_check"] = "Has" + property_name();
} else {
(*variables)["has_property_check"] =
oneof_name() + "Case_ == " + oneof_property_name() +
"OneofCase." + property_name();
}
(*variables)["oneof_property_name"] = oneof_property_name();
}
FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor,
int fieldOrdinal, const Options* options)
int presenceIndex, const Options* options)
: SourceGeneratorBase(descriptor->file(), options),
descriptor_(descriptor),
fieldOrdinal_(fieldOrdinal) {
presenceIndex_(presenceIndex) {
SetCommonFieldVariables(&variables_);
}
@ -251,36 +272,6 @@ bool FieldGeneratorBase::has_default_value() {
}
}
bool FieldGeneratorBase::is_nullable_type() {
switch (descriptor_->type()) {
case FieldDescriptor::TYPE_ENUM:
case FieldDescriptor::TYPE_DOUBLE:
case FieldDescriptor::TYPE_FLOAT:
case FieldDescriptor::TYPE_INT64:
case FieldDescriptor::TYPE_UINT64:
case FieldDescriptor::TYPE_INT32:
case FieldDescriptor::TYPE_FIXED64:
case FieldDescriptor::TYPE_FIXED32:
case FieldDescriptor::TYPE_BOOL:
case FieldDescriptor::TYPE_UINT32:
case FieldDescriptor::TYPE_SFIXED32:
case FieldDescriptor::TYPE_SFIXED64:
case FieldDescriptor::TYPE_SINT32:
case FieldDescriptor::TYPE_SINT64:
return false;
case FieldDescriptor::TYPE_MESSAGE:
case FieldDescriptor::TYPE_GROUP:
case FieldDescriptor::TYPE_STRING:
case FieldDescriptor::TYPE_BYTES:
return true;
default:
GOOGLE_LOG(FATAL)<< "Unknown field type.";
return true;
}
}
bool AllPrintableAscii(const std::string& text) {
for(int i = 0; i < text.size(); i++) {
if (text[i] < 0x20 || text[i] > 0x7e) {
@ -290,14 +281,18 @@ bool AllPrintableAscii(const std::string& text) {
return true;
}
std::string FieldGeneratorBase::GetStringDefaultValueInternal() {
// No other default values needed for proto3...
return "\"\"";
std::string FieldGeneratorBase::GetStringDefaultValueInternal(const FieldDescriptor* descriptor) {
if (descriptor->default_value_string().empty())
return "\"\"";
else
return "global::System.Encoding.UTF8.GetString(global::System.Convert.FromBase64String(\" +" + StringToBase64(descriptor->default_value_string()) + " +\"))";
}
std::string FieldGeneratorBase::GetBytesDefaultValueInternal() {
// No other default values needed for proto3...
return "pb::ByteString.Empty";
std::string FieldGeneratorBase::GetBytesDefaultValueInternal(const FieldDescriptor* descriptor) {
if (descriptor->default_value_string().empty())
return "pb::ByteString.Empty";
else
return "pb::ByteString.FromBase64(\"" + StringToBase64(descriptor->default_value_string()) + "\")";
}
std::string FieldGeneratorBase::default_value() {
@ -307,9 +302,13 @@ std::string FieldGeneratorBase::default_value() {
std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) {
switch (descriptor->type()) {
case FieldDescriptor::TYPE_ENUM:
// All proto3 enums have a default value of 0, and there's an implicit conversion from the constant 0 to
// any C# enum. This means we don't need to work out what we actually mapped the enum value name to.
return "0";
if (IsProto2(descriptor_->file())) {
return GetClassName(descriptor->default_value_enum()->type()) + "." +
GetEnumValueName(descriptor->default_value_enum()->type()->name(), descriptor->default_value_enum()->name());
}
else {
return "0";
}
case FieldDescriptor::TYPE_MESSAGE:
case FieldDescriptor::TYPE_GROUP:
if (IsWrapperType(descriptor)) {
@ -357,9 +356,9 @@ std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor)
return "false";
}
case FieldDescriptor::TYPE_STRING:
return GetStringDefaultValueInternal();
return GetStringDefaultValueInternal(descriptor);
case FieldDescriptor::TYPE_BYTES:
return GetBytesDefaultValueInternal();
return GetBytesDefaultValueInternal(descriptor);
case FieldDescriptor::TYPE_UINT32:
return SimpleItoa(descriptor->default_value_uint32());
case FieldDescriptor::TYPE_SFIXED32:

@ -47,7 +47,7 @@ namespace csharp {
class FieldGeneratorBase : public SourceGeneratorBase {
public:
FieldGeneratorBase(const FieldDescriptor* descriptor,
int fieldOrdinal,
int presenceIndex,
const Options* options);
~FieldGeneratorBase();
@ -67,7 +67,7 @@ class FieldGeneratorBase : public SourceGeneratorBase {
protected:
const FieldDescriptor* descriptor_;
const int fieldOrdinal_;
const int presenceIndex_;
std::map<string, string> variables_;
void AddDeprecatedFlag(io::Printer* printer);
@ -84,7 +84,6 @@ class FieldGeneratorBase : public SourceGeneratorBase {
std::string type_name();
std::string type_name(const FieldDescriptor* descriptor);
bool has_default_value();
bool is_nullable_type();
std::string default_value();
std::string default_value(const FieldDescriptor* descriptor);
std::string number();
@ -92,8 +91,8 @@ class FieldGeneratorBase : public SourceGeneratorBase {
private:
void SetCommonFieldVariables(std::map<string, string>* variables);
std::string GetStringDefaultValueInternal();
std::string GetBytesDefaultValueInternal();
std::string GetStringDefaultValueInternal(const FieldDescriptor* descriptor);
std::string GetBytesDefaultValueInternal(const FieldDescriptor* descriptor);
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorBase);
};

@ -65,11 +65,11 @@ bool Generator::Generate(
std::vector<std::pair<string, string> > options;
ParseGeneratorParameter(parameter, &options);
// We only support proto3 - but we make an exception for descriptor.proto.
// We only support proto3 - but we make an exception for descriptor.proto.
if (file->syntax() != FileDescriptor::SYNTAX_PROTO3 && !IsDescriptorProto(file)) {
*error = "C# code generation only supports proto3 syntax";
*error = "C# code generation only supports proto3 syntax";
return false;
}
}
struct Options cli_options;

@ -36,6 +36,7 @@
#include <google/protobuf/stubs/hash.h>
#include <limits>
#include <vector>
#include <sstream>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_names.h>
@ -452,55 +453,89 @@ std::string FileDescriptorToBase64(const FileDescriptor* descriptor) {
}
FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
int fieldOrdinal,
int presenceIndex,
const Options* options) {
switch (descriptor->type()) {
case FieldDescriptor::TYPE_GROUP:
case FieldDescriptor::TYPE_MESSAGE:
if (descriptor->is_repeated()) {
if (descriptor->is_map()) {
return new MapFieldGenerator(descriptor, fieldOrdinal, options);
return new MapFieldGenerator(descriptor, presenceIndex, options);
} else {
return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal, options);
return new RepeatedMessageFieldGenerator(descriptor, presenceIndex, options);
}
} else {
if (IsWrapperType(descriptor)) {
if (descriptor->containing_oneof()) {
return new WrapperOneofFieldGenerator(descriptor, fieldOrdinal, options);
return new WrapperOneofFieldGenerator(descriptor, presenceIndex, options);
} else {
return new WrapperFieldGenerator(descriptor, fieldOrdinal, options);
return new WrapperFieldGenerator(descriptor, presenceIndex, options);
}
} else {
if (descriptor->containing_oneof()) {
return new MessageOneofFieldGenerator(descriptor, fieldOrdinal, options);
return new MessageOneofFieldGenerator(descriptor, presenceIndex, options);
} else {
return new MessageFieldGenerator(descriptor, fieldOrdinal, options);
return new MessageFieldGenerator(descriptor, presenceIndex, options);
}
}
}
case FieldDescriptor::TYPE_ENUM:
if (descriptor->is_repeated()) {
return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal, options);
return new RepeatedEnumFieldGenerator(descriptor, presenceIndex, options);
} else {
if (descriptor->containing_oneof()) {
return new EnumOneofFieldGenerator(descriptor, fieldOrdinal, options);
return new EnumOneofFieldGenerator(descriptor, presenceIndex, options);
} else {
return new EnumFieldGenerator(descriptor, fieldOrdinal, options);
return new EnumFieldGenerator(descriptor, presenceIndex, options);
}
}
default:
if (descriptor->is_repeated()) {
return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal, options);
return new RepeatedPrimitiveFieldGenerator(descriptor, presenceIndex, options);
} else {
if (descriptor->containing_oneof()) {
return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options);
return new PrimitiveOneofFieldGenerator(descriptor, presenceIndex, options);
} else {
return new PrimitiveFieldGenerator(descriptor, fieldOrdinal, options);
return new PrimitiveFieldGenerator(descriptor, presenceIndex, options);
}
}
}
}
bool IsNullable(const FieldDescriptor* descriptor) {
if (descriptor->is_repeated()) {
return true;
}
switch (descriptor->type()) {
case FieldDescriptor::TYPE_ENUM:
case FieldDescriptor::TYPE_DOUBLE:
case FieldDescriptor::TYPE_FLOAT:
case FieldDescriptor::TYPE_INT64:
case FieldDescriptor::TYPE_UINT64:
case FieldDescriptor::TYPE_INT32:
case FieldDescriptor::TYPE_FIXED64:
case FieldDescriptor::TYPE_FIXED32:
case FieldDescriptor::TYPE_BOOL:
case FieldDescriptor::TYPE_UINT32:
case FieldDescriptor::TYPE_SFIXED32:
case FieldDescriptor::TYPE_SFIXED64:
case FieldDescriptor::TYPE_SINT32:
case FieldDescriptor::TYPE_SINT64:
return false;
case FieldDescriptor::TYPE_MESSAGE:
case FieldDescriptor::TYPE_GROUP:
case FieldDescriptor::TYPE_STRING:
case FieldDescriptor::TYPE_BYTES:
return true;
default:
GOOGLE_LOG(FATAL) << "Unknown field type.";
return true;
}
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf

@ -107,9 +107,11 @@ std::string StringToBase64(const std::string& input);
std::string FileDescriptorToBase64(const FileDescriptor* descriptor);
FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
int fieldOrdinal,
int presenceIndex,
const Options* options);
bool IsNullable(const FieldDescriptor* descriptor);
// Determines whether the given message is a map entry message,
// i.e. one implicitly created by protoc due to a map<key, value> field.
inline bool IsMapEntryMessage(const Descriptor* descriptor) {
@ -144,6 +146,10 @@ inline bool IsWrapperType(const FieldDescriptor* descriptor) {
descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto";
}
inline bool IsProto2(const FileDescriptor* descriptor) {
return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2;
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf

@ -48,9 +48,9 @@ namespace compiler {
namespace csharp {
MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
int fieldOrdinal,
int presenceIndex,
const Options* options)
: FieldGeneratorBase(descriptor, fieldOrdinal, options) {
: FieldGeneratorBase(descriptor, presenceIndex, options) {
}
MapFieldGenerator::~MapFieldGenerator() {

@ -44,7 +44,7 @@ namespace csharp {
class MapFieldGenerator : public FieldGeneratorBase {
public:
MapFieldGenerator(const FieldDescriptor* descriptor,
int fieldOrdinal,
int presenceIndex,
const Options* options);
~MapFieldGenerator();

@ -61,20 +61,27 @@ bool CompareFieldNumbers(const FieldDescriptor* d1, const FieldDescriptor* d2) {
MessageGenerator::MessageGenerator(const Descriptor* descriptor,
const Options* options)
: SourceGeneratorBase(descriptor->file(), options),
descriptor_(descriptor) {
// sorted field names
for (int i = 0; i < descriptor_->field_count(); i++) {
field_names_.push_back(descriptor_->field(i)->name());
}
std::sort(field_names_.begin(), field_names_.end());
descriptor_(descriptor),
has_bit_field_count_(0) {
// fields by number
for (int i = 0; i < descriptor_->field_count(); i++) {
fields_by_number_.push_back(descriptor_->field(i));
}
std::sort(fields_by_number_.begin(), fields_by_number_.end(),
CompareFieldNumbers);
if (IsProto2(descriptor_->file())) {
int primitiveCount = 0;
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
if (!IsNullable(field)) {
primitiveCount++;
if (has_bit_field_count_ == 0 || (primitiveCount % 32) == 0) {
has_bit_field_count_++;
}
}
}
}
}
MessageGenerator::~MessageGenerator() {
@ -88,10 +95,6 @@ std::string MessageGenerator::full_class_name() {
return GetClassName(descriptor_);
}
const std::vector<std::string>& MessageGenerator::field_names() {
return field_names_;
}
const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number() {
return fields_by_number_;
}
@ -123,6 +126,12 @@ void MessageGenerator::Generate(io::Printer* printer) {
printer->Print(
"private pb::UnknownFieldSet _unknownFields;\n");
for (int i = 0; i < has_bit_field_count_; i++) {
// don't use arrays since all arrays are heap allocated, saving allocations
// use ints instead of bytes since bytes lack bitwise operators, saving casts
printer->Print("private int _hasBits$i$;\n", "i", SimpleItoa(i));
}
WriteGeneratedCodeAttributes(printer);
printer->Print(
@ -288,6 +297,9 @@ void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
vars,
"public $class_name$($class_name$ other) : this() {\n");
printer->Indent();
for (int i = 0; i < has_bit_field_count_; i++) {
printer->Print("_hasBits$i$ = other._hasBits$i$;\n", "i", SimpleItoa(i));
}
// Clone non-oneof fields first
for (int i = 0; i < descriptor_->field_count(); i++) {
if (!descriptor_->field(i)->containing_oneof()) {
@ -559,19 +571,29 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
printer->Print("}\n\n"); // method
}
int MessageGenerator::GetFieldOrdinal(const FieldDescriptor* descriptor) {
for (int i = 0; i < field_names().size(); i++) {
if (field_names()[i] == descriptor->name()) {
return i;
// it's a waste of space to track presence for all values, so we only track them if they're not nullable
int MessageGenerator::GetPresenceIndex(const FieldDescriptor* descriptor) {
if (IsNullable(descriptor) || !IsProto2(descriptor_->file())) {
return -1;
}
int index = 0;
for (int i = 0; i < fields_by_number().size(); i++) {
const FieldDescriptor* field = fields_by_number()[i];
if (field == descriptor) {
return index;
}
if (!IsNullable(field)) {
index++;
}
}
GOOGLE_LOG(DFATAL)<< "Could not find ordinal for field " << descriptor->name();
GOOGLE_LOG(DFATAL)<< "Could not find presence index for field " << descriptor->name();
return -1;
}
FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal(
const FieldDescriptor* descriptor) {
return CreateFieldGenerator(descriptor, GetFieldOrdinal(descriptor), this->options());
return CreateFieldGenerator(descriptor, GetPresenceIndex(descriptor), this->options());
}
} // namespace csharp

@ -57,13 +57,13 @@ class MessageGenerator : public SourceGeneratorBase {
private:
const Descriptor* descriptor_;
std::vector<std::string> field_names_;
std::vector<const FieldDescriptor*> fields_by_number_;
int has_bit_field_count_;
void GenerateMessageSerializationMethods(io::Printer* printer);
void GenerateMergingMethods(io::Printer* printer);
int GetFieldOrdinal(const FieldDescriptor* descriptor);
int GetPresenceIndex(const FieldDescriptor* descriptor);
FieldGeneratorBase* CreateFieldGeneratorInternal(
const FieldDescriptor* descriptor);
@ -74,9 +74,6 @@ class MessageGenerator : public SourceGeneratorBase {
std::string class_name();
std::string full_class_name();
// field names sorted alphabetically
const std::vector<std::string>& field_names();
// field descriptors sorted by number
const std::vector<const FieldDescriptor*>& fields_by_number();

@ -49,11 +49,13 @@ namespace compiler {
namespace csharp {
MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
int fieldOrdinal,
int presenceIndex,
const Options *options)
: FieldGeneratorBase(descriptor, fieldOrdinal, options) {
variables_["has_property_check"] = name() + "_ != null";
variables_["has_not_property_check"] = name() + "_ == null";
: FieldGeneratorBase(descriptor, presenceIndex, options) {
if (!IsProto2(descriptor_->file())) {
variables_["has_property_check"] = name() + "_ != null";
variables_["has_not_property_check"] = name() + "_ == null";
}
}
MessageFieldGenerator::~MessageFieldGenerator() {
@ -74,6 +76,26 @@ void MessageFieldGenerator::GenerateMembers(io::Printer* printer) {
" $name$_ = value;\n"
" }\n"
"}\n");
if (IsProto2(descriptor_->file())) {
printer->Print(
variables_,
"/// <summary>Gets whether the $descriptor_name$ field is set</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ bool Has$property_name$ {\n"
" get { return $name$_ != null; }\n"
"}\n");
printer->Print(
variables_,
"/// <summary>Clears the value of the $descriptor_name$ field</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ void Clear$property_name$() {\n"
" $name$_ = null;\n"
"}\n");
}
}
void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) {
@ -81,7 +103,7 @@ void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) {
variables_,
"if (other.$has_property_check$) {\n"
" if ($has_not_property_check$) {\n"
" $name$_ = new $type_name$();\n"
" $property_name$ = new $type_name$();\n"
" }\n"
" $property_name$.MergeFrom(other.$property_name$);\n"
"}\n");
@ -91,10 +113,9 @@ void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_not_property_check$) {\n"
" $name$_ = new $type_name$();\n"
" $property_name$ = new $type_name$();\n"
"}\n"
// TODO(jonskeet): Do we really need merging behaviour like this?
"input.ReadMessage($name$_);\n"); // No need to support TYPE_GROUP...
"input.ReadMessage($property_name$);\n");
}
void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
@ -130,7 +151,6 @@ void MessageFieldGenerator::WriteToString(io::Printer* printer) {
variables_,
"PrintField(\"$field_name$\", has$property_name$, $name$_, writer);\n");
}
void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) {
printer->Print(variables_,
"$name$_ = other.$has_property_check$ ? other.$name$_.Clone() : null;\n");
@ -147,9 +167,9 @@ void MessageFieldGenerator::GenerateCodecCode(io::Printer* printer) {
MessageOneofFieldGenerator::MessageOneofFieldGenerator(
const FieldDescriptor* descriptor,
int fieldOrdinal,
int presenceIndex,
const Options *options)
: MessageFieldGenerator(descriptor, fieldOrdinal, options) {
: MessageFieldGenerator(descriptor, presenceIndex, options) {
SetCommonOneofFieldVariables(&variables_);
}
@ -169,6 +189,28 @@ void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
" $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"
" }\n"
"}\n");
if (IsProto2(descriptor_->file())) {
printer->Print(
variables_,
"/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ bool Has$property_name$ {\n"
" get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n"
"}\n");
printer->Print(
variables_,
"/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ void Clear$property_name$() {\n"
" if ($has_property_check$) {\n"
" Clear$oneof_property_name$();\n"
" }\n"
"}\n");
}
}
void MessageOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
@ -187,7 +229,7 @@ void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
"if ($has_property_check$) {\n"
" subBuilder.MergeFrom($property_name$);\n"
"}\n"
"input.ReadMessage(subBuilder);\n" // No support of TYPE_GROUP
"input.ReadMessage(subBuilder);\n"
"$property_name$ = subBuilder;\n");
}

@ -44,7 +44,7 @@ namespace csharp {
class MessageFieldGenerator : public FieldGeneratorBase {
public:
MessageFieldGenerator(const FieldDescriptor* descriptor,
int fieldOrdinal,
int presenceIndex,
const Options *options);
~MessageFieldGenerator();
@ -68,7 +68,7 @@ class MessageFieldGenerator : public FieldGeneratorBase {
class MessageOneofFieldGenerator : public MessageFieldGenerator {
public:
MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
int fieldOrdinal,
int presenceIndex,
const Options *options);
~MessageOneofFieldGenerator();

@ -49,12 +49,12 @@ namespace compiler {
namespace csharp {
PrimitiveFieldGenerator::PrimitiveFieldGenerator(
const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
: FieldGeneratorBase(descriptor, fieldOrdinal, options) {
const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
: FieldGeneratorBase(descriptor, presenceIndex, options) {
// TODO(jonskeet): Make this cleaner...
is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING
&& descriptor->type() != FieldDescriptor::TYPE_BYTES;
if (!is_value_type) {
if (!is_value_type && !IsProto2(descriptor_->file())) {
variables_["has_property_check"] = variables_["property_name"] + ".Length != 0";
variables_["other_has_property_check"] = "other." + variables_["property_name"] + ".Length != 0";
}
@ -67,16 +67,44 @@ void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
// TODO(jonskeet): Work out whether we want to prevent the fields from ever being
// null, or whether we just handle it, in the cases of bytes and string.
// (Basically, should null-handling code be in the getter or the setter?)
if (IsProto2(descriptor_->file())) {
printer->Print(
variables_,
"private readonly static $type_name$ $property_name$DefaultValue = $default_value$;\n\n");
}
printer->Print(
variables_,
"private $type_name$ $name_def_message$;\n");
WritePropertyDocComment(printer, descriptor_);
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ $type_name$ $property_name$ {\n"
" get { return $name$_; }\n"
" set {\n");
if (IsProto2(descriptor_->file())) {
if (presenceIndex_ == -1) {
printer->Print(
variables_,
"$access_level$ $type_name$ $property_name$ {\n"
" get { return $name$_ ?? $property_name$DefaultValue; }\n"
" set {\n");
} else {
printer->Print(
variables_,
"$access_level$ $type_name$ $property_name$ {\n"
" get { if ($has_field_check$) { return $name$_; } else { return $property_name$DefaultValue; } }\n"
" set {\n");
}
} else {
printer->Print(
variables_,
"$access_level$ $type_name$ $property_name$ {\n"
" get { return $name$_; }\n"
" set {\n");
}
if (presenceIndex_ != -1) {
printer->Print(
variables_,
" $set_has_field$;\n");
}
if (is_value_type) {
printer->Print(
variables_,
@ -89,6 +117,36 @@ void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
printer->Print(
" }\n"
"}\n");
if (IsProto2(descriptor_->file())) {
printer->Print(variables_, "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ bool Has$property_name$ {\n"
" get { return ");
if (IsNullable(descriptor_)) {
printer->Print(
variables_,
"$name$_ != null; }\n}\n");
} else {
printer->Print(
variables_,
"$has_field_check$; }\n}\n");
}
}
if (IsProto2(descriptor_->file())) {
printer->Print(variables_, "/// <summary>Clears the value of the \"$descriptor_name$\" field</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ void Clear$property_name$() {\n");
if (IsNullable(descriptor_)) {
printer->Print(variables_, " $name$_ = null;\n");
} else {
printer->Print(variables_, " $clear_has_field$;\n");
}
printer->Print("}\n");
}
}
void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) {
@ -172,8 +230,8 @@ void PrimitiveFieldGenerator::GenerateCodecCode(io::Printer* printer) {
}
PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
: PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) {
const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
: PrimitiveFieldGenerator(descriptor, presenceIndex, options) {
SetCommonOneofFieldVariables(&variables_);
}
@ -188,20 +246,42 @@ void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
"$access_level$ $type_name$ $property_name$ {\n"
" get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n"
" set {\n");
if (is_value_type) {
printer->Print(
variables_,
" $oneof_name$_ = value;\n");
} else {
printer->Print(
variables_,
" $oneof_name$_ = pb::ProtoPreconditions.CheckNotNull(value, \"value\");\n");
}
if (is_value_type) {
printer->Print(
variables_,
" $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"
" $oneof_name$_ = value;\n");
} else {
printer->Print(
variables_,
" $oneof_name$_ = pb::ProtoPreconditions.CheckNotNull(value, \"value\");\n");
}
printer->Print(
variables_,
" $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"
" }\n"
"}\n");
if (IsProto2(descriptor_->file())) {
printer->Print(
variables_,
"/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ bool Has$property_name$ {\n"
" get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n"
"}\n");
printer->Print(
variables_,
"/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ void Clear$property_name$() {\n"
" if ($has_property_check$) {\n"
" Clear$oneof_property_name$();\n"
" }\n"
"}\n");
}
}
void PrimitiveOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {

@ -46,7 +46,7 @@ struct Options;
class PrimitiveFieldGenerator : public FieldGeneratorBase {
public:
PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
int fieldOrdinal,
int presenceIndex,
const Options *options);
~PrimitiveFieldGenerator();
@ -72,7 +72,7 @@ class PrimitiveFieldGenerator : public FieldGeneratorBase {
class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
public:
PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
int fieldOrdinal,
int presenceIndex,
const Options *options);
~PrimitiveOneofFieldGenerator();

@ -48,8 +48,8 @@ namespace compiler {
namespace csharp {
RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
: FieldGeneratorBase(descriptor, fieldOrdinal, options) {
const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
: FieldGeneratorBase(descriptor, presenceIndex, options) {
}
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {

@ -46,7 +46,7 @@ namespace csharp {
class RepeatedEnumFieldGenerator : public FieldGeneratorBase {
public:
RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
int fieldOrdinal,
int presenceIndex,
const Options *options);
~RepeatedEnumFieldGenerator();

@ -49,8 +49,8 @@ namespace compiler {
namespace csharp {
RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
: FieldGeneratorBase(descriptor, fieldOrdinal, options) {
const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
: FieldGeneratorBase(descriptor, presenceIndex, options) {
}
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {
@ -67,11 +67,11 @@ void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) {
// function, but it doesn't seem worth it for just this.
if (IsWrapperType(descriptor_)) {
std::unique_ptr<FieldGeneratorBase> single_generator(
new WrapperFieldGenerator(descriptor_, fieldOrdinal_, this->options()));
new WrapperFieldGenerator(descriptor_, presenceIndex_, this->options()));
single_generator->GenerateCodecCode(printer);
} else {
std::unique_ptr<FieldGeneratorBase> single_generator(
new MessageFieldGenerator(descriptor_, fieldOrdinal_, this->options()));
new MessageFieldGenerator(descriptor_, presenceIndex_, this->options()));
single_generator->GenerateCodecCode(printer);
}
printer->Print(";\n");

@ -46,7 +46,7 @@ struct Options;
class RepeatedMessageFieldGenerator : public FieldGeneratorBase {
public:
RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
int fieldOrdinal,
int presenceIndex,
const Options *options);
~RepeatedMessageFieldGenerator();

@ -48,8 +48,8 @@ namespace compiler {
namespace csharp {
RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
: FieldGeneratorBase(descriptor, fieldOrdinal, options) {
const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
: FieldGeneratorBase(descriptor, presenceIndex, options) {
}
RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {

@ -43,7 +43,7 @@ namespace csharp {
class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase {
public:
RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options);
RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int presenceIndex, const Options *options);
~RepeatedPrimitiveFieldGenerator();
virtual void GenerateCloningCode(io::Printer* printer);

@ -48,8 +48,8 @@ namespace compiler {
namespace csharp {
WrapperFieldGenerator::WrapperFieldGenerator(const FieldDescriptor* descriptor,
int fieldOrdinal, const Options *options)
: FieldGeneratorBase(descriptor, fieldOrdinal, options) {
int presenceIndex, const Options *options)
: FieldGeneratorBase(descriptor, presenceIndex, options) {
variables_["has_property_check"] = name() + "_ != null";
variables_["has_not_property_check"] = name() + "_ == null";
const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
@ -81,7 +81,27 @@ void WrapperFieldGenerator::GenerateMembers(io::Printer* printer) {
" set {\n"
" $name$_ = value;\n"
" }\n"
"}\n");
"}\n\n");
if (IsProto2(descriptor_->file())) {
printer->Print(
variables_,
"/// <summary>Gets whether the $descriptor_name$ field is set</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ bool Has$property_name$ {\n"
" get { return $name$_ != null; }\n"
"}\n\n");
printer->Print(
variables_,
"/// <summary>Clears the value of the $descriptor_name$ field</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ void Clear$property_name$() {\n"
" $name$_ = null;\n"
"}\n");
}
}
void WrapperFieldGenerator::GenerateMergingCode(io::Printer* printer) {
@ -163,8 +183,8 @@ void WrapperFieldGenerator::GenerateCodecCode(io::Printer* printer) {
}
WrapperOneofFieldGenerator::WrapperOneofFieldGenerator(
const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
: WrapperFieldGenerator(descriptor, fieldOrdinal, options) {
const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
: WrapperFieldGenerator(descriptor, presenceIndex, options) {
SetCommonOneofFieldVariables(&variables_);
}
@ -189,6 +209,28 @@ void WrapperOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
" $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"
" }\n"
"}\n");
if (IsProto2(descriptor_->file())) {
printer->Print(
variables_,
"/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ bool Has$property_name$ {\n"
" get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n"
"}\n");
printer->Print(
variables_,
"/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"$access_level$ void Clear$property_name$() {\n"
" if ($has_property_check$) {\n"
" Clear$oneof_property_name$();\n"
" }\n"
"}\n");
}
}
void WrapperOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {

@ -46,7 +46,7 @@ struct Options;
class WrapperFieldGenerator : public FieldGeneratorBase {
public:
WrapperFieldGenerator(const FieldDescriptor* descriptor,
int fieldOrdinal,
int presenceIndex,
const Options *options);
~WrapperFieldGenerator();
@ -70,7 +70,7 @@ class WrapperFieldGenerator : public FieldGeneratorBase {
class WrapperOneofFieldGenerator : public WrapperFieldGenerator {
public:
WrapperOneofFieldGenerator(const FieldDescriptor* descriptor,
int fieldOrdinal,
int presenceIndex,
const Options *options);
~WrapperOneofFieldGenerator();

Loading…
Cancel
Save