Merge remote-tracking branch 'upstream/master' into protobuf_csharp_new_parsing

pull/7351/head
Jan Tattermusch 5 years ago
commit 7134d25eb8
  1. 2
      Makefile.am
  2. 2
      README.md
  3. 3
      csharp/generate_protos.sh
  4. 144
      csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs
  5. 12
      csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs
  6. 1072
      csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs
  7. 143
      csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs
  8. 50
      csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs
  9. 37
      csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs
  10. BIN
      csharp/src/Google.Protobuf.Test/testprotos.pb
  11. 17
      csharp/src/Google.Protobuf/Reflection/Descriptor.cs
  12. 6
      csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
  13. 3
      csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs
  14. 24
      csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
  15. 47
      csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs
  16. 40
      csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs
  17. 36
      csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs
  18. 476
      docs/field_presence.md
  19. 350
      docs/implementing_proto3_presence.md
  20. 1
      docs/third_party.md
  21. 4
      java/pom.xml
  22. 2
      kokoro/linux/dockerfile/push_testing_images.sh
  23. 3
      kokoro/linux/dockerfile/release/ruby_rake_compiler/Dockerfile
  24. 23
      kokoro/linux/dockerfile/test/python27/Dockerfile
  25. 23
      kokoro/linux/dockerfile/test/python35/Dockerfile
  26. 23
      kokoro/linux/dockerfile/test/python36/Dockerfile
  27. 23
      kokoro/linux/dockerfile/test/python37/Dockerfile
  28. 23
      kokoro/linux/dockerfile/test/python38/Dockerfile
  29. 39
      kokoro/linux/dockerfile/test/python_jessie/Dockerfile
  30. 49
      kokoro/linux/dockerfile/test/python_stretch/Dockerfile
  31. 1
      kokoro/linux/dockerfile/test/ruby/Dockerfile
  32. 2
      kokoro/linux/python27/build.sh
  33. 2
      kokoro/linux/python27_cpp/build.sh
  34. 18
      kokoro/linux/python33/build.sh
  35. 11
      kokoro/linux/python33/continuous.cfg
  36. 11
      kokoro/linux/python33/presubmit.cfg
  37. 18
      kokoro/linux/python33_cpp/build.sh
  38. 11
      kokoro/linux/python33_cpp/continuous.cfg
  39. 11
      kokoro/linux/python33_cpp/presubmit.cfg
  40. 18
      kokoro/linux/python34_cpp/build.sh
  41. 11
      kokoro/linux/python34_cpp/continuous.cfg
  42. 11
      kokoro/linux/python34_cpp/presubmit.cfg
  43. 2
      kokoro/linux/python35/build.sh
  44. 2
      kokoro/linux/python35_cpp/build.sh
  45. 2
      kokoro/linux/python36/build.sh
  46. 2
      kokoro/linux/python36_cpp/build.sh
  47. 2
      kokoro/linux/python37/build.sh
  48. 2
      kokoro/linux/python37_cpp/build.sh
  49. 2
      kokoro/linux/python38/build.sh
  50. 2
      kokoro/linux/python38_cpp/build.sh
  51. 4
      kokoro/linux/ruby27/build.sh
  52. 2
      kokoro/linux/ruby27/continuous.cfg
  53. 2
      kokoro/linux/ruby27/presubmit.cfg
  54. 11
      kokoro/macos/ruby27/build.sh
  55. 5
      kokoro/macos/ruby27/continuous.cfg
  56. 5
      kokoro/macos/ruby27/presubmit.cfg
  57. 6
      kokoro/release/ruby/linux/prepare_build.sh
  58. 1
      kokoro/release/ruby/linux/ruby/ruby_build.sh
  59. 29
      kokoro/release/ruby/macos/ruby/ruby_build_environment.sh
  60. 1
      objectivec/DevTools/compile_testing_protos.sh
  61. 5
      objectivec/DevTools/full_mac_build.sh
  62. 4
      objectivec/GPBAny.pbobjc.h
  63. 6
      objectivec/GPBAny.pbobjc.m
  64. 4
      objectivec/GPBApi.pbobjc.h
  65. 36
      objectivec/GPBApi.pbobjc.m
  66. 2
      objectivec/GPBBootstrap.h
  67. 41
      objectivec/GPBDescriptor.m
  68. 19
      objectivec/GPBDescriptor_PackagePrivate.h
  69. 4
      objectivec/GPBDuration.pbobjc.h
  70. 6
      objectivec/GPBDuration.pbobjc.m
  71. 4
      objectivec/GPBEmpty.pbobjc.h
  72. 2
      objectivec/GPBEmpty.pbobjc.m
  73. 4
      objectivec/GPBFieldMask.pbobjc.h
  74. 2
      objectivec/GPBFieldMask.pbobjc.m
  75. 116
      objectivec/GPBMessage.m
  76. 4
      objectivec/GPBSourceContext.pbobjc.h
  77. 4
      objectivec/GPBSourceContext.pbobjc.m
  78. 4
      objectivec/GPBStruct.pbobjc.h
  79. 14
      objectivec/GPBStruct.pbobjc.m
  80. 4
      objectivec/GPBTimestamp.pbobjc.h
  81. 6
      objectivec/GPBTimestamp.pbobjc.m
  82. 4
      objectivec/GPBType.pbobjc.h
  83. 58
      objectivec/GPBType.pbobjc.m
  84. 10
      objectivec/GPBUtilities.h
  85. 477
      objectivec/GPBUtilities.m
  86. 104
      objectivec/GPBUtilities_PackagePrivate.h
  87. 4
      objectivec/GPBWrappers.pbobjc.h
  88. 36
      objectivec/GPBWrappers.pbobjc.m
  89. 272
      objectivec/Tests/GPBMessageTests+Runtime.m
  90. 311
      objectivec/Tests/GPBMessageTests+Serialization.m
  91. 2
      objectivec/Tests/GPBSwiftTests.swift
  92. 28
      objectivec/Tests/unittest_runtime_proto3.proto
  93. 64
      php/src/Google/Protobuf/Internal/FieldDescriptorProto.php
  94. 35
      python/docs/generate_docs.py
  95. 21
      python/docs/google/protobuf/internal/containers.rst
  96. 1
      python/docs/index.rst
  97. 38
      python/google/protobuf/pyext/message.cc
  98. 60
      python/google/protobuf/text_format.py
  99. 11
      ruby/Rakefile
  100. 1
      ruby/compatibility_tests/v3.0.0/tests/repeated_field_test.rb
  101. Some files were not shown because too many files have changed in this diff Show More

@ -124,6 +124,7 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs \
csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs \
csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs \
csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs \
csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs \
csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs \
csharp/src/Google.Protobuf.Test/Reflection/DescriptorDeclarationTest.cs \
@ -151,6 +152,7 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs \
csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs \
csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs \
csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs \
csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs \
csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs \
csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs \

@ -56,7 +56,7 @@ how to install protobuf runtime for that specific language:
|--------------------------------------|-------------------------------------------------------------|--------|-------|---------|
| C++ (include C++ runtime and protoc) | [src](src) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-cpp_distcheck.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fcpp_distcheck%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-bazel.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fbazel%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-dist_install.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fdist_install%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fcpp%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-cpp_distcheck.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fcpp_distcheck%2Fcontinuous) | [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf) |
| Java | [java](java) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-java_compatibility.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_compatibility%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-java_jdk7.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_jdk7%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-java_oracle7.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_oracle7%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-java_linkage_monitor.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_linkage_monitor%2Fcontinuous) | | |
| Python | [python](python) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python27.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython27%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python33.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython33%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python34.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython34%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python35.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython35%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python36.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython36%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python37.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython37%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python_compatibility.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython_compatibility%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python27_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython27_cpp%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python33_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython33_cpp%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python34_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython34_cpp%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python35_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython35_cpp%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python36_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython36_cpp%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python37_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython37_cpp%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython_release%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython_cpp%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython_release%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/windows-python-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fwindows%2Fpython_release%2Fcontinuous) |
| Python | [python](python) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python27.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython27%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python35.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython35%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python36.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython36%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python37.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython37%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python_compatibility.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython_compatibility%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python27_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython27_cpp%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python35_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython35_cpp%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python36_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython36_cpp%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python37_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython37_cpp%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython_release%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython_cpp%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython_release%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/windows-python-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fwindows%2Fpython_release%2Fcontinuous) |
| Objective-C | [objectivec](objectivec) | | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_cocoapods_integration.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_cocoapods_integration%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_ios_debug.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_ios_debug%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_ios_release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_ios_release%2Fcontinuous)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_osx.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_osx%2Fcontinuous) | |
| C# | [csharp](csharp) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-csharp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fcsharp%2Fcontinuous) | | [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf)<br/>[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/windows-csharp-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fwindows%2Fcsharp_release%2Fcontinuous) |
| JavaScript | [js](js) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-javascript.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjavascript%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-javascript.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fjavascript%2Fcontinuous) | |

@ -63,7 +63,8 @@ $PROTOC -Isrc -Icsharp/protos \
csharp/protos/unittest_issue6936_c.proto \
src/google/protobuf/unittest_well_known_types.proto \
src/google/protobuf/test_messages_proto3.proto \
src/google/protobuf/test_messages_proto2.proto
src/google/protobuf/test_messages_proto2.proto \
src/google/protobuf/unittest_proto3_optional.proto
# AddressBook sample protos
$PROTOC -Iexamples -Isrc --csharp_out=csharp/src/AddressBook \

@ -1872,21 +1872,21 @@ namespace ProtobufTestMessages.Proto2 {
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int Fieldname1 {
get { if ((_hasBits0 & 2097152) != 0) { return fieldname1_; } else { return Fieldname1DefaultValue; } }
get { if ((_hasBits0 & 32768) != 0) { return fieldname1_; } else { return Fieldname1DefaultValue; } }
set {
_hasBits0 |= 2097152;
_hasBits0 |= 32768;
fieldname1_ = value;
}
}
/// <summary>Gets whether the "fieldname1" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasFieldname1 {
get { return (_hasBits0 & 2097152) != 0; }
get { return (_hasBits0 & 32768) != 0; }
}
/// <summary>Clears the value of the "fieldname1" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearFieldname1() {
_hasBits0 &= ~2097152;
_hasBits0 &= ~32768;
}
/// <summary>Field number for the "field_name2" field.</summary>
@ -1896,21 +1896,21 @@ namespace ProtobufTestMessages.Proto2 {
private int fieldName2_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int FieldName2 {
get { if ((_hasBits0 & 4194304) != 0) { return fieldName2_; } else { return FieldName2DefaultValue; } }
get { if ((_hasBits0 & 65536) != 0) { return fieldName2_; } else { return FieldName2DefaultValue; } }
set {
_hasBits0 |= 4194304;
_hasBits0 |= 65536;
fieldName2_ = value;
}
}
/// <summary>Gets whether the "field_name2" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasFieldName2 {
get { return (_hasBits0 & 4194304) != 0; }
get { return (_hasBits0 & 65536) != 0; }
}
/// <summary>Clears the value of the "field_name2" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearFieldName2() {
_hasBits0 &= ~4194304;
_hasBits0 &= ~65536;
}
/// <summary>Field number for the "_field_name3" field.</summary>
@ -1920,21 +1920,21 @@ namespace ProtobufTestMessages.Proto2 {
private int FieldName3_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int FieldName3 {
get { if ((_hasBits0 & 8388608) != 0) { return FieldName3_; } else { return FieldName3DefaultValue; } }
get { if ((_hasBits0 & 131072) != 0) { return FieldName3_; } else { return FieldName3DefaultValue; } }
set {
_hasBits0 |= 8388608;
_hasBits0 |= 131072;
FieldName3_ = value;
}
}
/// <summary>Gets whether the "_field_name3" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasFieldName3 {
get { return (_hasBits0 & 8388608) != 0; }
get { return (_hasBits0 & 131072) != 0; }
}
/// <summary>Clears the value of the "_field_name3" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearFieldName3() {
_hasBits0 &= ~8388608;
_hasBits0 &= ~131072;
}
/// <summary>Field number for the "field__name4_" field.</summary>
@ -1944,21 +1944,21 @@ namespace ProtobufTestMessages.Proto2 {
private int fieldName4_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int FieldName4 {
get { if ((_hasBits0 & 16777216) != 0) { return fieldName4_; } else { return FieldName4DefaultValue; } }
get { if ((_hasBits0 & 262144) != 0) { return fieldName4_; } else { return FieldName4DefaultValue; } }
set {
_hasBits0 |= 16777216;
_hasBits0 |= 262144;
fieldName4_ = value;
}
}
/// <summary>Gets whether the "field__name4_" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasFieldName4 {
get { return (_hasBits0 & 16777216) != 0; }
get { return (_hasBits0 & 262144) != 0; }
}
/// <summary>Clears the value of the "field__name4_" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearFieldName4() {
_hasBits0 &= ~16777216;
_hasBits0 &= ~262144;
}
/// <summary>Field number for the "field0name5" field.</summary>
@ -1968,21 +1968,21 @@ namespace ProtobufTestMessages.Proto2 {
private int field0Name5_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int Field0Name5 {
get { if ((_hasBits0 & 33554432) != 0) { return field0Name5_; } else { return Field0Name5DefaultValue; } }
get { if ((_hasBits0 & 524288) != 0) { return field0Name5_; } else { return Field0Name5DefaultValue; } }
set {
_hasBits0 |= 33554432;
_hasBits0 |= 524288;
field0Name5_ = value;
}
}
/// <summary>Gets whether the "field0name5" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasField0Name5 {
get { return (_hasBits0 & 33554432) != 0; }
get { return (_hasBits0 & 524288) != 0; }
}
/// <summary>Clears the value of the "field0name5" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearField0Name5() {
_hasBits0 &= ~33554432;
_hasBits0 &= ~524288;
}
/// <summary>Field number for the "field_0_name6" field.</summary>
@ -1992,21 +1992,21 @@ namespace ProtobufTestMessages.Proto2 {
private int field0Name6_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int Field0Name6 {
get { if ((_hasBits0 & 67108864) != 0) { return field0Name6_; } else { return Field0Name6DefaultValue; } }
get { if ((_hasBits0 & 1048576) != 0) { return field0Name6_; } else { return Field0Name6DefaultValue; } }
set {
_hasBits0 |= 67108864;
_hasBits0 |= 1048576;
field0Name6_ = value;
}
}
/// <summary>Gets whether the "field_0_name6" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasField0Name6 {
get { return (_hasBits0 & 67108864) != 0; }
get { return (_hasBits0 & 1048576) != 0; }
}
/// <summary>Clears the value of the "field_0_name6" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearField0Name6() {
_hasBits0 &= ~67108864;
_hasBits0 &= ~1048576;
}
/// <summary>Field number for the "fieldName7" field.</summary>
@ -2016,21 +2016,21 @@ namespace ProtobufTestMessages.Proto2 {
private int fieldName7_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int FieldName7 {
get { if ((_hasBits0 & 134217728) != 0) { return fieldName7_; } else { return FieldName7DefaultValue; } }
get { if ((_hasBits0 & 2097152) != 0) { return fieldName7_; } else { return FieldName7DefaultValue; } }
set {
_hasBits0 |= 134217728;
_hasBits0 |= 2097152;
fieldName7_ = value;
}
}
/// <summary>Gets whether the "fieldName7" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasFieldName7 {
get { return (_hasBits0 & 134217728) != 0; }
get { return (_hasBits0 & 2097152) != 0; }
}
/// <summary>Clears the value of the "fieldName7" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearFieldName7() {
_hasBits0 &= ~134217728;
_hasBits0 &= ~2097152;
}
/// <summary>Field number for the "FieldName8" field.</summary>
@ -2040,21 +2040,21 @@ namespace ProtobufTestMessages.Proto2 {
private int fieldName8_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int FieldName8 {
get { if ((_hasBits0 & 268435456) != 0) { return fieldName8_; } else { return FieldName8DefaultValue; } }
get { if ((_hasBits0 & 4194304) != 0) { return fieldName8_; } else { return FieldName8DefaultValue; } }
set {
_hasBits0 |= 268435456;
_hasBits0 |= 4194304;
fieldName8_ = value;
}
}
/// <summary>Gets whether the "FieldName8" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasFieldName8 {
get { return (_hasBits0 & 268435456) != 0; }
get { return (_hasBits0 & 4194304) != 0; }
}
/// <summary>Clears the value of the "FieldName8" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearFieldName8() {
_hasBits0 &= ~268435456;
_hasBits0 &= ~4194304;
}
/// <summary>Field number for the "field_Name9" field.</summary>
@ -2064,21 +2064,21 @@ namespace ProtobufTestMessages.Proto2 {
private int fieldName9_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int FieldName9 {
get { if ((_hasBits0 & 536870912) != 0) { return fieldName9_; } else { return FieldName9DefaultValue; } }
get { if ((_hasBits0 & 8388608) != 0) { return fieldName9_; } else { return FieldName9DefaultValue; } }
set {
_hasBits0 |= 536870912;
_hasBits0 |= 8388608;
fieldName9_ = value;
}
}
/// <summary>Gets whether the "field_Name9" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasFieldName9 {
get { return (_hasBits0 & 536870912) != 0; }
get { return (_hasBits0 & 8388608) != 0; }
}
/// <summary>Clears the value of the "field_Name9" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearFieldName9() {
_hasBits0 &= ~536870912;
_hasBits0 &= ~8388608;
}
/// <summary>Field number for the "Field_Name10" field.</summary>
@ -2088,21 +2088,21 @@ namespace ProtobufTestMessages.Proto2 {
private int fieldName10_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int FieldName10 {
get { if ((_hasBits0 & 1073741824) != 0) { return fieldName10_; } else { return FieldName10DefaultValue; } }
get { if ((_hasBits0 & 16777216) != 0) { return fieldName10_; } else { return FieldName10DefaultValue; } }
set {
_hasBits0 |= 1073741824;
_hasBits0 |= 16777216;
fieldName10_ = value;
}
}
/// <summary>Gets whether the "Field_Name10" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasFieldName10 {
get { return (_hasBits0 & 1073741824) != 0; }
get { return (_hasBits0 & 16777216) != 0; }
}
/// <summary>Clears the value of the "Field_Name10" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearFieldName10() {
_hasBits0 &= ~1073741824;
_hasBits0 &= ~16777216;
}
/// <summary>Field number for the "FIELD_NAME11" field.</summary>
@ -2112,21 +2112,21 @@ namespace ProtobufTestMessages.Proto2 {
private int fIELDNAME11_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int FIELDNAME11 {
get { if ((_hasBits0 & -2147483648) != 0) { return fIELDNAME11_; } else { return FIELDNAME11DefaultValue; } }
get { if ((_hasBits0 & 33554432) != 0) { return fIELDNAME11_; } else { return FIELDNAME11DefaultValue; } }
set {
_hasBits0 |= -2147483648;
_hasBits0 |= 33554432;
fIELDNAME11_ = value;
}
}
/// <summary>Gets whether the "FIELD_NAME11" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasFIELDNAME11 {
get { return (_hasBits0 & -2147483648) != 0; }
get { return (_hasBits0 & 33554432) != 0; }
}
/// <summary>Clears the value of the "FIELD_NAME11" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearFIELDNAME11() {
_hasBits0 &= ~-2147483648;
_hasBits0 &= ~33554432;
}
/// <summary>Field number for the "FIELD_name12" field.</summary>
@ -2136,21 +2136,21 @@ namespace ProtobufTestMessages.Proto2 {
private int fIELDName12_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int FIELDName12 {
get { if ((_hasBits1 & 1) != 0) { return fIELDName12_; } else { return FIELDName12DefaultValue; } }
get { if ((_hasBits0 & 67108864) != 0) { return fIELDName12_; } else { return FIELDName12DefaultValue; } }
set {
_hasBits1 |= 1;
_hasBits0 |= 67108864;
fIELDName12_ = value;
}
}
/// <summary>Gets whether the "FIELD_name12" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasFIELDName12 {
get { return (_hasBits1 & 1) != 0; }
get { return (_hasBits0 & 67108864) != 0; }
}
/// <summary>Clears the value of the "FIELD_name12" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearFIELDName12() {
_hasBits1 &= ~1;
_hasBits0 &= ~67108864;
}
/// <summary>Field number for the "__field_name13" field.</summary>
@ -2160,21 +2160,21 @@ namespace ProtobufTestMessages.Proto2 {
private int FieldName13_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int FieldName13 {
get { if ((_hasBits1 & 2) != 0) { return FieldName13_; } else { return FieldName13DefaultValue; } }
get { if ((_hasBits0 & 134217728) != 0) { return FieldName13_; } else { return FieldName13DefaultValue; } }
set {
_hasBits1 |= 2;
_hasBits0 |= 134217728;
FieldName13_ = value;
}
}
/// <summary>Gets whether the "__field_name13" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasFieldName13 {
get { return (_hasBits1 & 2) != 0; }
get { return (_hasBits0 & 134217728) != 0; }
}
/// <summary>Clears the value of the "__field_name13" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearFieldName13() {
_hasBits1 &= ~2;
_hasBits0 &= ~134217728;
}
/// <summary>Field number for the "__Field_name14" field.</summary>
@ -2184,21 +2184,21 @@ namespace ProtobufTestMessages.Proto2 {
private int FieldName14_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int FieldName14 {
get { if ((_hasBits1 & 4) != 0) { return FieldName14_; } else { return FieldName14DefaultValue; } }
get { if ((_hasBits0 & 268435456) != 0) { return FieldName14_; } else { return FieldName14DefaultValue; } }
set {
_hasBits1 |= 4;
_hasBits0 |= 268435456;
FieldName14_ = value;
}
}
/// <summary>Gets whether the "__Field_name14" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasFieldName14 {
get { return (_hasBits1 & 4) != 0; }
get { return (_hasBits0 & 268435456) != 0; }
}
/// <summary>Clears the value of the "__Field_name14" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearFieldName14() {
_hasBits1 &= ~4;
_hasBits0 &= ~268435456;
}
/// <summary>Field number for the "field__name15" field.</summary>
@ -2208,21 +2208,21 @@ namespace ProtobufTestMessages.Proto2 {
private int fieldName15_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int FieldName15 {
get { if ((_hasBits1 & 8) != 0) { return fieldName15_; } else { return FieldName15DefaultValue; } }
get { if ((_hasBits0 & 536870912) != 0) { return fieldName15_; } else { return FieldName15DefaultValue; } }
set {
_hasBits1 |= 8;
_hasBits0 |= 536870912;
fieldName15_ = value;
}
}
/// <summary>Gets whether the "field__name15" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasFieldName15 {
get { return (_hasBits1 & 8) != 0; }
get { return (_hasBits0 & 536870912) != 0; }
}
/// <summary>Clears the value of the "field__name15" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearFieldName15() {
_hasBits1 &= ~8;
_hasBits0 &= ~536870912;
}
/// <summary>Field number for the "field__Name16" field.</summary>
@ -2232,21 +2232,21 @@ namespace ProtobufTestMessages.Proto2 {
private int fieldName16_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int FieldName16 {
get { if ((_hasBits1 & 16) != 0) { return fieldName16_; } else { return FieldName16DefaultValue; } }
get { if ((_hasBits0 & 1073741824) != 0) { return fieldName16_; } else { return FieldName16DefaultValue; } }
set {
_hasBits1 |= 16;
_hasBits0 |= 1073741824;
fieldName16_ = value;
}
}
/// <summary>Gets whether the "field__Name16" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasFieldName16 {
get { return (_hasBits1 & 16) != 0; }
get { return (_hasBits0 & 1073741824) != 0; }
}
/// <summary>Clears the value of the "field__Name16" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearFieldName16() {
_hasBits1 &= ~16;
_hasBits0 &= ~1073741824;
}
/// <summary>Field number for the "field_name17__" field.</summary>
@ -2256,21 +2256,21 @@ namespace ProtobufTestMessages.Proto2 {
private int fieldName17_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int FieldName17 {
get { if ((_hasBits1 & 32) != 0) { return fieldName17_; } else { return FieldName17DefaultValue; } }
get { if ((_hasBits0 & -2147483648) != 0) { return fieldName17_; } else { return FieldName17DefaultValue; } }
set {
_hasBits1 |= 32;
_hasBits0 |= -2147483648;
fieldName17_ = value;
}
}
/// <summary>Gets whether the "field_name17__" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasFieldName17 {
get { return (_hasBits1 & 32) != 0; }
get { return (_hasBits0 & -2147483648) != 0; }
}
/// <summary>Clears the value of the "field_name17__" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearFieldName17() {
_hasBits1 &= ~32;
_hasBits0 &= ~-2147483648;
}
/// <summary>Field number for the "Field_name18__" field.</summary>
@ -2280,21 +2280,21 @@ namespace ProtobufTestMessages.Proto2 {
private int fieldName18_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int FieldName18 {
get { if ((_hasBits1 & 64) != 0) { return fieldName18_; } else { return FieldName18DefaultValue; } }
get { if ((_hasBits1 & 1) != 0) { return fieldName18_; } else { return FieldName18DefaultValue; } }
set {
_hasBits1 |= 64;
_hasBits1 |= 1;
fieldName18_ = value;
}
}
/// <summary>Gets whether the "Field_name18__" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasFieldName18 {
get { return (_hasBits1 & 64) != 0; }
get { return (_hasBits1 & 1) != 0; }
}
/// <summary>Clears the value of the "Field_name18__" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearFieldName18() {
_hasBits1 &= ~64;
_hasBits1 &= ~1;
}
private object oneofField_;

@ -15806,7 +15806,6 @@ namespace Google.Protobuf.TestProtos.Proto2 {
public sealed partial class TestOneof : pb::IMessage<TestOneof>, pb::IBufferMessage {
private static readonly pb::MessageParser<TestOneof> _parser = new pb::MessageParser<TestOneof>(() => new TestOneof());
private pb::UnknownFieldSet _unknownFields;
private int _hasBits0;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<TestOneof> Parser { get { return _parser; } }
@ -15829,7 +15828,6 @@ namespace Google.Protobuf.TestProtos.Proto2 {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public TestOneof(TestOneof other) : this() {
_hasBits0 = other._hasBits0;
switch (other.FooCase) {
case FooOneofCase.FooInt:
FooInt = other.FooInt;
@ -17239,21 +17237,21 @@ namespace Google.Protobuf.TestProtos.Proto2 {
private int bazInt_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int BazInt {
get { if ((_hasBits0 & 16) != 0) { return bazInt_; } else { return BazIntDefaultValue; } }
get { if ((_hasBits0 & 1) != 0) { return bazInt_; } else { return BazIntDefaultValue; } }
set {
_hasBits0 |= 16;
_hasBits0 |= 1;
bazInt_ = value;
}
}
/// <summary>Gets whether the "baz_int" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasBazInt {
get { return (_hasBits0 & 16) != 0; }
get { return (_hasBits0 & 1) != 0; }
}
/// <summary>Clears the value of the "baz_int" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearBazInt() {
_hasBits0 &= ~16;
_hasBits0 &= ~1;
}
/// <summary>Field number for the "baz_string" field.</summary>
@ -18087,7 +18085,6 @@ namespace Google.Protobuf.TestProtos.Proto2 {
public sealed partial class TestRequiredOneof : pb::IMessage<TestRequiredOneof>, pb::IBufferMessage {
private static readonly pb::MessageParser<TestRequiredOneof> _parser = new pb::MessageParser<TestRequiredOneof>(() => new TestRequiredOneof());
private pb::UnknownFieldSet _unknownFields;
private int _hasBits0;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<TestRequiredOneof> Parser { get { return _parser; } }
@ -18110,7 +18107,6 @@ namespace Google.Protobuf.TestProtos.Proto2 {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public TestRequiredOneof(TestRequiredOneof other) : this() {
_hasBits0 = other._hasBits0;
switch (other.FooCase) {
case FooOneofCase.FooInt:
FooInt = other.FooInt;

@ -0,0 +1,143 @@
#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 NUnit.Framework;
using ProtobufUnittest;
using System;
using System.IO;
namespace Google.Protobuf.Test
{
class Proto3OptionalTest
{
[Test]
public void OptionalInt32FieldLifecycle()
{
var message = new TestProto3Optional();
Assert.IsFalse(message.HasOptionalInt32);
Assert.AreEqual(0, message.OptionalInt32);
message.OptionalInt32 = 5;
Assert.IsTrue(message.HasOptionalInt32);
Assert.AreEqual(5, message.OptionalInt32);
message.OptionalInt32 = 0;
Assert.IsTrue(message.HasOptionalInt32);
Assert.AreEqual(0, message.OptionalInt32);
message.ClearOptionalInt32();
Assert.IsFalse(message.HasOptionalInt32);
Assert.AreEqual(0, message.OptionalInt32);
}
[Test]
public void OptionalStringFieldLifecycle()
{
var message = new TestProto3Optional();
Assert.IsFalse(message.HasOptionalString);
Assert.AreEqual("", message.OptionalString);
message.OptionalString = "x";
Assert.IsTrue(message.HasOptionalString);
Assert.AreEqual("x", message.OptionalString);
message.OptionalString = "";
Assert.IsTrue(message.HasOptionalString);
Assert.AreEqual("", message.OptionalString);
message.ClearOptionalString();
Assert.IsFalse(message.HasOptionalString);
Assert.AreEqual("", message.OptionalString);
Assert.Throws<ArgumentNullException>(() => message.OptionalString = null);
}
[Test]
public void Clone()
{
var original = new TestProto3Optional { OptionalInt64 = 0L };
var clone = original.Clone();
Assert.False(clone.HasOptionalInt32);
Assert.AreEqual(0, clone.OptionalInt32);
Assert.True(clone.HasOptionalInt64);
Assert.AreEqual(0L, clone.OptionalInt64);
}
[Test]
public void Serialization_NotSet()
{
var stream = new MemoryStream();
var message = new TestProto3Optional();
message.WriteTo(stream);
Assert.AreEqual(0, stream.Length);
}
[Test]
public void Serialization_SetToDefault()
{
var stream = new MemoryStream();
var message = new TestProto3Optional { OptionalInt32 = 0 };
message.WriteTo(stream);
Assert.AreEqual(2, stream.Length); // Tag and value
}
[Test]
public void Serialization_Roundtrip()
{
var original = new TestProto3Optional { OptionalInt64 = 0L, OptionalFixed32 = 5U };
var stream = new MemoryStream();
original.WriteTo(stream);
stream.Position = 0;
var deserialized = TestProto3Optional.Parser.ParseFrom(stream);
Assert.AreEqual(0, deserialized.OptionalInt32);
Assert.IsFalse(deserialized.HasOptionalInt32);
Assert.AreEqual(0L, deserialized.OptionalInt64);
Assert.IsTrue(deserialized.HasOptionalInt64);
Assert.AreEqual(5U, deserialized.OptionalFixed32);
Assert.IsTrue(deserialized.HasOptionalFixed32);
}
[Test]
public void Equality_IgnoresPresence()
{
var message1 = new TestProto3Optional { OptionalInt32 = 0 };
var message2 = new TestProto3Optional();
Assert.IsTrue(message1.Equals(message2));
message1.ClearOptionalInt32();
}
}
}

@ -32,6 +32,7 @@
using Google.Protobuf.TestProtos;
using NUnit.Framework;
using ProtobufUnittest;
using System;
using System.Collections.Generic;
using System.Linq;
@ -247,6 +248,7 @@ namespace Google.Protobuf.Reflection
FieldDescriptor enumField = testAllTypesDescriptor.FindDescriptor<FieldDescriptor>("single_nested_enum");
FieldDescriptor foreignMessageField = testAllTypesDescriptor.FindDescriptor<FieldDescriptor>("single_foreign_message");
FieldDescriptor importMessageField = testAllTypesDescriptor.FindDescriptor<FieldDescriptor>("single_import_message");
FieldDescriptor fieldInOneof = testAllTypesDescriptor.FindDescriptor<FieldDescriptor>("oneof_string");
Assert.AreEqual("single_int32", primitiveField.Name);
Assert.AreEqual("protobuf_unittest3.TestAllTypes.single_int32",
@ -268,6 +270,10 @@ namespace Google.Protobuf.Reflection
Assert.AreEqual("single_import_message", importMessageField.Name);
Assert.AreEqual(FieldType.Message, importMessageField.FieldType);
Assert.AreEqual(importMessageDescriptor, importMessageField.MessageType);
// For a field in a regular onoef, ContainingOneof and RealContainingOneof should be the same.
Assert.AreEqual("oneof_field", fieldInOneof.ContainingOneof.Name);
Assert.AreSame(fieldInOneof.ContainingOneof, fieldInOneof.RealContainingOneof);
}
[Test]
@ -318,6 +324,7 @@ namespace Google.Protobuf.Reflection
public void OneofDescriptor()
{
OneofDescriptor descriptor = TestAllTypes.Descriptor.FindDescriptor<OneofDescriptor>("oneof_field");
Assert.IsFalse(descriptor.IsSynthetic);
Assert.AreEqual("oneof_field", descriptor.Name);
Assert.AreEqual("protobuf_unittest3.TestAllTypes.oneof_field", descriptor.FullName);
@ -383,5 +390,48 @@ namespace Google.Protobuf.Reflection
var importingDescriptor = TestProtos.OldGenerator.OldExtensions1Reflection.Descriptor;
Assert.NotNull(importingDescriptor);
}
[Test]
public void Proto3OptionalDescriptors()
{
var descriptor = TestProto3Optional.Descriptor;
var field = descriptor.Fields[TestProto3Optional.OptionalInt32FieldNumber];
Assert.NotNull(field.ContainingOneof);
Assert.IsTrue(field.ContainingOneof.IsSynthetic);
Assert.Null(field.RealContainingOneof);
}
[Test]
public void SyntheticOneofReflection()
{
// Expect every oneof in TestProto3Optional to be synthetic
var proto3OptionalDescriptor = TestProto3Optional.Descriptor;
Assert.AreEqual(0, proto3OptionalDescriptor.RealOneofCount);
foreach (var oneof in proto3OptionalDescriptor.Oneofs)
{
Assert.True(oneof.IsSynthetic);
}
// Expect no oneof in the original proto3 unit test file to be synthetic.
foreach (var descriptor in ProtobufTestMessages.Proto3.TestMessagesProto3Reflection.Descriptor.MessageTypes)
{
Assert.AreEqual(descriptor.Oneofs.Count, descriptor.RealOneofCount);
foreach (var oneof in descriptor.Oneofs)
{
Assert.False(oneof.IsSynthetic);
}
}
// Expect no oneof in the original proto2 unit test file to be synthetic.
foreach (var descriptor in ProtobufTestMessages.Proto2.TestMessagesProto2Reflection.Descriptor.MessageTypes)
{
Assert.AreEqual(descriptor.Oneofs.Count, descriptor.RealOneofCount);
foreach (var oneof in descriptor.Oneofs)
{
Assert.False(oneof.IsSynthetic);
}
}
}
}
}

@ -38,6 +38,7 @@ using System.Collections;
using System.Collections.Generic;
using static Google.Protobuf.TestProtos.Proto2.UnittestExtensions;
using ProtobufUnittest;
namespace Google.Protobuf.Reflection
{
@ -104,6 +105,21 @@ namespace Google.Protobuf.Reflection
Assert.Throws<InvalidOperationException>(() => fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].Accessor.HasValue(message));
}
[Test]
public void HasValue_Proto3Optional()
{
IMessage message = new TestProto3Optional
{
OptionalInt32 = 0,
LazyNestedMessage = new TestProto3Optional.Types.NestedMessage()
};
var fields = message.Descriptor.Fields;
Assert.IsFalse(fields[TestProto3Optional.OptionalInt64FieldNumber].Accessor.HasValue(message));
Assert.IsFalse(fields[TestProto3Optional.OptionalNestedMessageFieldNumber].Accessor.HasValue(message));
Assert.IsTrue(fields[TestProto3Optional.LazyNestedMessageFieldNumber].Accessor.HasValue(message));
Assert.IsTrue(fields[TestProto3Optional.OptionalInt32FieldNumber].Accessor.HasValue(message));
}
[Test]
public void HasValue()
{
@ -225,6 +241,27 @@ namespace Google.Protobuf.Reflection
Assert.AreEqual(0, mapMessage.MapStringString.Count);
}
[Test]
public void Clear_Proto3Optional()
{
TestProto3Optional message = new TestProto3Optional
{
OptionalInt32 = 0,
OptionalNestedMessage = new TestProto3Optional.Types.NestedMessage()
};
var primitiveField = TestProto3Optional.Descriptor.Fields[TestProto3Optional.OptionalInt32FieldNumber];
var messageField = TestProto3Optional.Descriptor.Fields[TestProto3Optional.OptionalNestedMessageFieldNumber];
Assert.True(message.HasOptionalInt32);
Assert.NotNull(message.OptionalNestedMessage);
primitiveField.Accessor.Clear(message);
messageField.Accessor.Clear(message);
Assert.False(message.HasOptionalInt32);
Assert.Null(message.OptionalNestedMessage);
}
[Test]
public void FieldDescriptor_ByName()
{

@ -2104,10 +2104,21 @@ namespace Google.Protobuf.Reflection {
/// If true, this is a proto3 "optional". When a proto3 field is optional, it
/// tracks presence regardless of field type.
///
/// For message fields this doesn't create any semantic change, since
/// non-repeated message fields always track presence. However it still
/// When proto3_optional is true, this field must be belong to a oneof to
/// signal to old proto3 clients that presence is tracked for this field. This
/// oneof is known as a "synthetic" oneof, and this field must be its sole
/// member (each proto3 optional field gets its own synthetic oneof). Synthetic
/// oneofs exist in the descriptor only, and do not generate any API. Synthetic
/// oneofs must be ordered after all "real" oneofs.
///
/// For message fields, proto3_optional doesn't create any semantic change,
/// since non-repeated message fields always track presence. However it still
/// indicates the semantic detail of whether the user wrote "optional" or not.
/// This can be useful for round-tripping the .proto file.
/// This can be useful for round-tripping the .proto file. For consistency we
/// give message fields a synthetic oneof also, even though it is not required
/// to track presence. This is especially important because the parser can't
/// tell if a field is a message or an enum, so it must always create a
/// synthetic oneof.
///
/// Proto2 optional fields do not set this flag, because they already indicate
/// optional with `LABEL_OPTIONAL`.

@ -58,6 +58,12 @@ namespace Google.Protobuf.Reflection
/// </summary>
public OneofDescriptor ContainingOneof { get; }
/// <summary>
/// Returns the oneof containing this field if it's a "real" oneof, or <c>null</c> if either this
/// field is not part of a oneof, or the oneof is synthetic.
/// </summary>
public OneofDescriptor RealContainingOneof => ContainingOneof?.IsSynthetic == false ? ContainingOneof : null;
/// <summary>
/// The effective JSON name for this field. This is usually the lower-camel-cased form of the field name,
/// but can be overridden using the <c>json_name</c> option in the .proto file.

@ -59,7 +59,8 @@ namespace Google.Protobuf.Reflection
object GetValue(IMessage message);
/// <summary>
/// Indicates whether the field in the specified message is set. For proto3 fields, this throws an <see cref="InvalidOperationException"/>
/// Indicates whether the field in the specified message is set.
/// For proto3 fields that aren't explicitly optional, this throws an <see cref="InvalidOperationException"/>
/// </summary>
bool HasValue(IMessage message);

@ -80,6 +80,20 @@ namespace Google.Protobuf.Reflection
(oneof, index) =>
new OneofDescriptor(oneof, file, this, index, generatedCodeInfo?.OneofNames[index]));
int syntheticOneofCount = 0;
foreach (var oneof in Oneofs)
{
if (oneof.IsSynthetic)
{
syntheticOneofCount++;
}
else if (syntheticOneofCount != 0)
{
throw new ArgumentException("All synthetic oneofs should come after real oneofs");
}
}
RealOneofCount = Oneofs.Count - syntheticOneofCount;
NestedTypes = DescriptorUtil.ConvertAndMakeReadOnly(
proto.NestedType,
(type, index) =>
@ -234,9 +248,19 @@ namespace Google.Protobuf.Reflection
/// <value>
/// An unmodifiable list of the "oneof" field collections in this message type.
/// All "real" oneofs (where <see cref="OneofDescriptor.IsSynthetic"/> returns false)
/// come before synthetic ones.
/// </value>
public IList<OneofDescriptor> Oneofs { get; }
/// <summary>
/// The number of real "oneof" descriptors in this message type. Every element in <see cref="Oneofs"/>
/// with an index less than this will have a <see cref="OneofDescriptor.IsSynthetic"/> property value
/// of <c>false</c>; every element with an index greater than or equal to this will have a
/// <see cref="OneofDescriptor.IsSynthetic"/> property value of <c>true</c>.
/// </summary>
public int RealOneofCount { get; }
/// <summary>
/// Finds a field by field name.
/// </summary>

@ -43,19 +43,31 @@ namespace Google.Protobuf.Reflection
{
private readonly Func<IMessage, int> caseDelegate;
private readonly Action<IMessage> clearDelegate;
private OneofDescriptor descriptor;
internal OneofAccessor(PropertyInfo caseProperty, MethodInfo clearMethod, OneofDescriptor descriptor)
private OneofAccessor(OneofDescriptor descriptor, Func<IMessage, int> caseDelegate, Action<IMessage> clearDelegate)
{
if (!caseProperty.CanRead)
{
throw new ArgumentException("Cannot read from property");
}
this.descriptor = descriptor;
caseDelegate = ReflectionUtil.CreateFuncIMessageInt32(caseProperty.GetGetMethod());
Descriptor = descriptor;
this.caseDelegate = caseDelegate;
this.clearDelegate = clearDelegate;
}
internal static OneofAccessor ForRegularOneof(
OneofDescriptor descriptor,
PropertyInfo caseProperty,
MethodInfo clearMethod) =>
new OneofAccessor(
descriptor,
ReflectionUtil.CreateFuncIMessageInt32(caseProperty.GetGetMethod()),
ReflectionUtil.CreateActionIMessage(clearMethod));
this.descriptor = descriptor;
clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod);
internal static OneofAccessor ForSyntheticOneof(OneofDescriptor descriptor)
{
// Note: descriptor.Fields will be null when this method is called, because we haven't
// cross-linked yet. But by the time the delgates are called by user code, all will be
// well. (That's why we capture the descriptor itself rather than a field.)
return new OneofAccessor(descriptor,
message => descriptor.Fields[0].Accessor.HasValue(message) ? descriptor.Fields[0].FieldNumber : 0,
message => descriptor.Fields[0].Accessor.Clear(message));
}
/// <summary>
@ -64,15 +76,12 @@ namespace Google.Protobuf.Reflection
/// <value>
/// The descriptor of the oneof.
/// </value>
public OneofDescriptor Descriptor { get { return descriptor; } }
public OneofDescriptor Descriptor { get; }
/// <summary>
/// Clears the oneof in the specified message.
/// </summary>
public void Clear(IMessage message)
{
clearDelegate(message);
}
public void Clear(IMessage message) => clearDelegate(message);
/// <summary>
/// Indicates which field in the oneof is set for specified message
@ -80,11 +89,9 @@ namespace Google.Protobuf.Reflection
public FieldDescriptor GetCaseFieldDescriptor(IMessage message)
{
int fieldNumber = caseDelegate(message);
if (fieldNumber > 0)
{
return descriptor.ContainingType.FindFieldByNumber(fieldNumber);
}
return null;
return fieldNumber > 0
? Descriptor.ContainingType.FindFieldByNumber(fieldNumber)
: null;
}
}
}

@ -33,6 +33,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Google.Protobuf.Collections;
using Google.Protobuf.Compatibility;
@ -54,8 +55,13 @@ namespace Google.Protobuf.Reflection
{
this.proto = proto;
containingType = parent;
file.DescriptorPool.AddSymbol(this);
// It's useful to determine whether or not this is a synthetic oneof before cross-linking. That means
// diving into the proto directly rather than using FieldDescriptor, but that's okay.
var firstFieldInOneof = parent.Proto.Field.FirstOrDefault(fieldProto => fieldProto.OneofIndex == index);
IsSynthetic = firstFieldInOneof?.Proto3Optional ?? false;
accessor = CreateAccessor(clrName);
}
@ -83,6 +89,12 @@ namespace Google.Protobuf.Reflection
/// </value>
public IList<FieldDescriptor> Fields { get { return fields; } }
/// <summary>
/// Returns <c>true</c> if this oneof is a synthetic oneof containing a proto3 optional field;
/// <c>false</c> otherwise.
/// </summary>
public bool IsSynthetic { get; }
/// <summary>
/// Gets an accessor for reflective access to the values associated with the oneof
/// in a particular message.
@ -146,18 +158,28 @@ namespace Google.Protobuf.Reflection
{
return null;
}
var caseProperty = containingType.ClrType.GetProperty(clrName + "Case");
if (caseProperty == null)
if (IsSynthetic)
{
throw new DescriptorValidationException(this, $"Property {clrName}Case not found in {containingType.ClrType}");
return OneofAccessor.ForSyntheticOneof(this);
}
var clearMethod = containingType.ClrType.GetMethod("Clear" + clrName);
if (clearMethod == null)
else
{
throw new DescriptorValidationException(this, $"Method Clear{clrName} not found in {containingType.ClrType}");
var caseProperty = containingType.ClrType.GetProperty(clrName + "Case");
if (caseProperty == null)
{
throw new DescriptorValidationException(this, $"Property {clrName}Case not found in {containingType.ClrType}");
}
if (!caseProperty.CanRead)
{
throw new ArgumentException($"Cannot read from property {clrName}Case in {containingType.ClrType}");
}
var clearMethod = containingType.ClrType.GetMethod("Clear" + clrName);
if (clearMethod == null)
{
throw new DescriptorValidationException(this, $"Method Clear{clrName} not found in {containingType.ClrType}");
}
return OneofAccessor.ForRegularOneof(this, caseProperty, clearMethod);
}
return new OneofAccessor(caseProperty, clearMethod, this);
}
}
}

@ -57,10 +57,11 @@ namespace Google.Protobuf.Reflection
throw new ArgumentException("Not all required properties/methods available");
}
setValueDelegate = ReflectionUtil.CreateActionIMessageObject(property.GetSetMethod());
if (descriptor.File.Syntax == Syntax.Proto3)
if (descriptor.File.Syntax == Syntax.Proto3 && !descriptor.Proto.Proto3Optional)
{
hasDelegate = message => {
throw new InvalidOperationException("HasValue is not implemented for proto3 fields");
hasDelegate = message =>
{
throw new InvalidOperationException("HasValue is not implemented for non-optional proto3 fields");
};
var clrType = property.PropertyType;
@ -74,16 +75,29 @@ namespace Google.Protobuf.Reflection
}
else
{
MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod;
if (hasMethod == null) {
throw new ArgumentException("Not all required properties/methods are available");
// For message fields, just compare with null and set to null.
// For primitive fields, use the Has/Clear methods.
if (descriptor.FieldType == FieldType.Message)
{
hasDelegate = message => GetValue(message) != null;
clearDelegate = message => SetValue(message, null);
}
hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod);
MethodInfo clearMethod = property.DeclaringType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes);
if (clearMethod == null) {
throw new ArgumentException("Not all required properties/methods are available");
else
{
MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod;
if (hasMethod == null)
{
throw new ArgumentException("Not all required properties/methods are available");
}
hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod);
MethodInfo clearMethod = property.DeclaringType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes);
if (clearMethod == null)
{
throw new ArgumentException("Not all required properties/methods are available");
}
clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod);
}
clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod);
}
}

@ -0,0 +1,476 @@
# Application note: Field presence
This application note explains the various presence tracking disciplies for protobuf fields. It also explains how to enable experimental support for explicit presence tracking for singular proto3 fields with basic types.
## Background
_Field presence_ is the notion of whether a protobuf field has a value. There are two different manifestations of presence for protobufs: _no presence_, where the generated message API stores field values (only), and _explicit presence_, where the API also stores whether or not a field has been set.
Historically, proto2 has mostly followed _explicit presence_, while proto3 exposes only _no presence_ semantics. Singular proto3 fields of basic types (numeric, string, bytes, and enums) which are defined with the `optional` label have _explicit presence_, like proto2 (this is an experimental feature added as of release 3.12, and must be enabled by passing a flag to `protoc`).
### Presence disciplines
_Presence disciplines_ define the semantics for translating between the _API representation_ and the _serialized representation_. The _no presence_ discipline relies upon the field value itself to make decisions at (de)serialization time, while the _explicit presence_ discipline relies upon the explicit tracking state instead.
### Presence in _tag-value stream_ (wire format) serialization
The wire format is a stream of tagged, _self-delimiting_ values. By definition, the wire format represents a sequence of _present_ values. In other words, every value found within a serialization represents a _present_ field; furthermore, the serialization contains no information about not-present values.
The generated API for a proto message includes (de)serialization definitions which translate between API types and a stream of definitionally _present_ (tag, value) pairs. This translation is designed to be forward- and backward-compatibile across changes to the message definition; however, this compatibility introduces some (perhaps surprising) considerations when deserializing wire-formatted messages:
- When serializing, fields with _no presence_ are not serialized if they contain their default value.
- For numeric types, the default is 0.
- For enums, the default is the zero-valued enumerator.
- For strings, bytes, and repeated fields, the default is the zero-length value.
- For messages, the default is the language-specific null value.
- "Empty" length-delimited values (such as empty strings) can be validly represented in serialized values: the field is "present," in the sense that it appears in the wire format. However, if the generated API does not track presence, then these values may not be re-serialized; i.e., the empty field may be "not present" after a serialization round-trip.
- When deserializing, duplicate field values may be handled in different ways depending on the field definition.
- Duplicate `repeated` fields are typically appended to the field's API representation. (Note that serializing a _packed_ repeated field produces only one, length-delimited value in the tag stream.)
- Duplicate `optional` field values follow the rule that "the last one wins."
- `oneof` fields expose the API-level invariant that only one field is set at a time. However, the wire format may include multiple (tag, value) pairs which notionally belong to the `oneof`. Similar to `optional` fields, the generated API follows the "last one wins" rule.
- Out-of-range values are not returned for enum fields in generated proto2 APIs. However, out-of-range values may be stored as _unknown fields_ in the API, even though the wire-format tag was recognized.
### Presence in _named-field mapping_ formats
Protobufs can be represented in human-readable, textual forms. Two notable formats are TextFormat (the output format produced by generated message `DebugString` methods) and JSON.
These formats have correctness requirements of their own, and are generally stricter than _tagged-value stream_ formats. However, TextFormat more closely mimics the semantics of the wire format, and does, in certain cases, provide similar semantics (for example, appending repeated name-value mappings to a repeated field). In particular, similar to the wire format, TextFormat only includes fields which are present.
JSON is a much stricter format, however, and cannot validly represent some semantics of the wire format or TextFormat.
- Notably, JSON _elements_ are semantically unordered, and each member must have a unique name. This is different from TextFormat rules for repeated fields.
- JSON may include fields that are "not present," unlike the _no presence_ discipline for other formats:
- JSON defines a `null` value, which may be used to represent a _defined but not-present field_.
- Repeated field values may be included in the formatted output, even if they are equal to the default (an empty list).
- Because JSON elements are unordered, there is no way to unambiguously interpret the "last one wins" rule.
- In most cases, this is fine: JSON elements must have unique names: repeated field values are not valid JSON, so they do not need to be resolved as they are for TextFormat.
- However, this means that it may not be possible to interpret `oneof` fields unambiguously: if multiple cases are present, they are unordered.
In theory, JSON _can_ represent presence in a semantic-preserving fashion. In practice, however, presence correctness can vary depending upon implementation choices, especially if JSON was chosen as a means to interoperate with clients not using protobufs.
### Presence in proto2 APIs
This table outlines whether presence is tracked for fields in proto2 APIs (both for generated APIs and using dynamic reflection):
Field type | Explicit Presence
-------------------------------------------- | -----------------
Singular numeric (integer or floating point) | ✔
Singular enum | ✔
Singular string or bytes | ✔
Singular message | ✔
Repeated |
Oneofs | ✔
Maps |
Singular fields (of all types) track presence explicitly in the generated API. The generated message interface includes methods to query presence of fields. For example, the field `foo` has a corresponding `has_foo` method. (The specific name follows the same language-specific naming convention as the field accessors.) These methods are sometimes referred to as "hazzers" within the protobuf implementation.
Similar to singular fields, `oneof` fields explicitly track which one of the members, if any, contains a value. For example, consider this example `oneof`:
```
oneof foo {
int32 a = 1;
float b = 2;
}
```
Depending on the target language, the generated API would generally include several methods:
- A hazzer for the oneof: `has_foo`
- A _oneof case_ method: `foo`
- Hazzers for the members: `has_a`, `has_b`
- Getters for the members: `a`, `b`
Repeated fields and maps do not track presence: there is no distinction between an _empty_ and a _not-present_ repeated field.
### Presence in proto3 APIs
This table outlines whether presence is tracked for fields in proto3 APIs (both for generated APIs and using dynamic reflection):
Field type | `optional` | Explicit Presence
-------------------------------------------- | ---------- | -----------------
Singular numeric (integer or floating point) | No |
Singular enum | No |
Singular string or bytes | No |
Singular numeric (integer or floating point) | Yes | ✔
Singular enum | Yes | ✔
Singular string or bytes | Yes | ✔
Singular message | Yes | ✔
Singular message | No | ✔
Repeated | N/A |
Oneofs | N/A | ✔
Maps | N/A |
Similar to proto2 APIs, proto3 does not track presence explicitly for repeated fields. Without the `optional` label, proto3 APIs do not track presence for basic types (numeric, string, bytes, and enums), either. (Note that `optional` for proto3 fields is only experimentally available as of release 3.12.) Oneof fields affirmatively expose presence, although the same set of hazzer methods may not generated as in proto2 APIs.
Under the _no presence_ discipline, the default value is synonymous with "not present" for purposes of serialization. To notionally "clear" a field (so it won't be serialized), an API user would set it to the default value.
The default value for enum-typed fields under _no presence_ is the corresponding 0-valued enumerator. Under proto3 syntax rules, all enum types are required to have an enumerator value which maps to 0. By convention, this is an `UNKNOWN` or similarly-named enumerator. If the zero value is notionally outside the domain of valid values for the application, this behavior can be thought of as tantamount to _explicit presence_.
## Semantic differences
The _no presence_ serialization discipline results in visible differences from the _explicit presence_ tracking discipline, when the default value is set. For a singular field with numeric, enum, or string type:
- _No presence_ discipline:
- Default values are not serialized.
- Default values are _not_ merged-from.
- To "clear" a field, it is set to its default value.
- The default value may mean:
- the field was explicitly set to its default value, which is valid in the application-specific domain of values;
- the field was notionally "cleared" by setting its default; or
- the field was never set.
- _Explicit presence_ discipline:
- Explicitly set values are always serialized, including default values.
- Un-set fields are never merged-from.
- Explicitly set fields -- including default values -- _are_ merged-from.
- A generated `has_foo` method indicates whether or not the field `foo` has been set (and not cleared).
- A generated `clear_foo` method must be used to clear (i.e., un-set) the value.
### Considerations for merging
Under the _no presence_ rules, it is effectively impossible for a target field to merge-from its default value (using the protobuf's API merging functions). This is because default values are skipped, simliar to the _no presence_ serialization discipline. Merging only updates the target (merged-to) message using the non-skipped values from the update (merged-from) message.
The difference in merging behavior has further implications for protocols which rely on partial "patch" updates. If field presence is not tracked, then an update patch alone cannot represent an update to the default value, because only non-default values are merged-from.
Updating to set a default value in this case requires some external mechanism, such as `FieldMask`. However, if presence _is_ tracked, then all explicitly-set values -- even default values -- will be merged into the target.
### Considerations for change-compatibility
Changing a field between _explicit presence_ and _no presence_ is a binary-compatible change for serialized values in wire format. However, the serialized representation of the message may differ, depending on which version of the message definition was used for serialization. Specifically, when a "sender" explicitly sets a field to its default value:
- The serialized value following _no presence_ discipline does not contain the default value, even though it was explicitly set.
- The serialized value following _explicit presence_ discipline contains every "present" field, even if it contains the default value.
This change may or may not be safe, depending on the application's semantics. For example, consider two clients with different versions of a message definition.
Client A uses this definition of the message, which follows the _explicit presence_ serialization discipline for field `foo`:
```
syntax = "proto3";
message Msg {
optional int32 foo = 1;
}
```
Client B uses a definition of the same message, except that it follows the _no presence_ discipline:
```
syntax = "proto3";
message Msg {
int32 foo = 1;
}
```
Now, consider a scenario where client A observes `foo`'s presence as the clients repeatedly exchange the "same" message by deserializing and reserializing:
```
// Client A:
Msg m_a;
m_a.set_foo(1); // non-default value
assert(m_a.has_foo()); // OK
Send(m_a.SerializeAsString()); // to client B
// Client B:
Msg m_b;
m_b.ParseFromString(Receive()); // from client A
assert(m_b.foo() == 1); // OK
Send(m_b.SerializeAsString()); // to client A
// Client A:
m_a.ParseFromString(Receive()); // from client B
assert(m_a.foo() == 1); // OK
assert(m_a.has_foo()); // OK
m_a.set_foo(0); // default value
Send(m_a.SerializeAsString()); // to client B
// Client B:
Msg m_b;
m_b.ParseFromString(Receive()); // from client A
assert(m_b.foo() == 0); // OK
Send(m_b.SerializeAsString()); // to client A
// Client A:
m_a.ParseFromString(Receive()); // from client B
assert(m_a.foo() == 0); // OK
assert(m_a.has_foo()); // FAIL
```
If client A depends on _explicit presence_ for `foo`, then a "round trip" through client B will be lossy from the perspective of client A. In the example, this is not a safe change: client A requires (by `assert`) that the field is present; even without any modifications through the API, that requirement fails in a value- and peer-dependent case.
## How to enable _explicit presence_ in proto3
These are the general steps to use the experimental field tracking support for proto3:
1. Add an `optional` field to a `.proto` file.
1. Run `protoc` (from release 3.12 or later) with an extra flag to recognize `optional` (i.e,. explicit presence) in proto3 files.
1. Use the generated "hazzer" methods and "clear" methods in application code, instead of comparing or setting default values.
### `.proto` file changes
This is an example of a proto3 message with fields which follow both _no presence_ and _explicit presence_ semantics:
```
syntax = "proto3";
package example;
message MyMessage {
// No presence:
int32 not_tracked = 1;
// Explicit presence:
optional int32 tracked = 2;
}
```
### `protoc` invocation
To enable presence tracking for proto3 messages, pass the `--experimental_allow_proto3_optional` flag to protoc. Without this flag, the `optional` label is an error in files using proto3 syntax. This flag is available in protobuf release 3.12 or later (or at HEAD, if you are reading this application note from Git).
### Using the generated code
The generated code for proto3 fields with _explicit presence_ (the `optional` label) will be the same as it would be in a proto2 file.
This is the definition used in the "no presence" examples below:
```
syntax = "proto3";
package example;
message Msg {
int32 foo = 1;
}
```
This is the definition used in the "explicit presence" examples below:
```
syntax = "proto3";
package example;
message Msg {
optional int32 foo = 1;
}
```
In the examples, a function `GetProto` constructs and returns a message of type `Msg` with unspecified contents.
#### C++ example
No presence:
```
Msg m = GetProto();
if (m.foo() != 0) {
// "Clear" the field:
m.set_foo(0);
} else {
// Default value: field may not have been present.
m.set_foo(1);
}
```
Explicit presence:
```
Msg m = GetProto();
if (m.has_foo()) {
// Clear the field:
m.clear_foo();
} else {
// Field is not present, so set it.
m.set_foo(1);
}
```
#### C# example
No presence:
```
var m = GetProto();
if (m.Foo != 0) {
// "Clear" the field:
m.Foo = 0;
} else {
// Default value: field may not have been present.
m.Foo = 1;
}
```
Explicit presence:
```
var m = GetProto();
if (m.HasFoo) {
// Clear the field:
m.ClearFoo();
} else {
// Field is not present, so set it.
m.Foo = 1;
}
```
#### Go example
No presence:
```
m := GetProto()
if (m.GetFoo() != 0) {
// "Clear" the field:
m.Foo = 0;
} else {
// Default value: field may not have been present.
m.Foo = 1;
}
```
Explicit presence:
```
m := GetProto()
if (m.HasFoo()) {
// Clear the field:
m.Foo = nil
} else {
// Field is not present, so set it.
m.Foo = proto.Int32(1);
}
```
#### Java example
These examples use a `Builder` to demonstrate clearing. Simply checking presence and getting values from a `Builder` follows the same API as the message type.
No presence:
```
Msg.Builder m = GetProto().toBuilder();
if (m.getFoo() != 0) {
// "Clear" the field:
m.setFoo(0);
} else {
// Default value: field may not have been present.
m.setFoo(1);
}
```
Explicit presence:
```
Msg.Builder m = GetProto().toBuilder();
if (m.hasFoo()) {
// Clear the field:
m.clearFoo()
} else {
// Field is not present, so set it.
m.setFoo(1);
}
```
#### Python example
No presence:
```
m = example.Msg()
if m.foo != 0:
// "Clear" the field:
m.foo = 0
else:
// Default value: field may not have been present.
m.foo = 1
```
Explicit presence:
```
m = example.Msg()
if m.HasField('foo'):
// Clear the field:
m.ClearField('foo')
else:
// Field is not present, so set it.
m.foo = 1
```
#### Ruby example
No presence:
```
m = Msg.new
if m.foo != 0
// "Clear" the field:
m.foo = 0
else
// Default value: field may not have been present.
m.foo = 1
end
```
Explicit presence:
```
m = Msg.new
if m.has_foo?
// Clear the field:
m.clear_foo
else
// Field is not present, so set it.
m.foo = 1
end
```
#### Javascript example
No presence:
```
var m = new Msg();
if (m.getFoo() != 0) {
// "Clear" the field:
m.setFoo(0);
} else {
// Default value: field may not have been present.
m.setFoo(1);
}
```
Explicit presence:
```
var m = new Msg();
if (m.hasFoo()) {
// Clear the field:
m.clearFoo()
} else {
// Field is not present, so set it.
m.setFoo(1);
}
```
#### Objective C example
No presence:
```
Msg *m = [[Msg alloc] init];
if (m.foo != 0) {
// "Clear" the field:
m.foo = 0;
} else {
// Default value: field may not have been present.
m.foo = 1;
}
```
Explicit presence:
```
Msg *m = [[Msg alloc] init];
if (m.hasFoo()) {
// Clear the field:
[m clearFoo];
} else {
// Field is not present, so set it.
[m setFoo:1];
}
```

@ -0,0 +1,350 @@
# How To Implement Field Presence for Proto3
Protobuf release 3.12 adds experimental support for `optional` fields in
proto3. Proto3 optional fields track presence like in proto2. For background
information about what presence tracking means, please see
[docs/field_presence](field_presence.md).
This document is targeted at developers who own or maintain protobuf code
generators. All code generators will need to be updated to support proto3
optional fields. First-party code generators developed by Google are being
updated already. However third-party code generators will need to be updated
independently by their authors. This includes:
- implementations of Protocol Buffers for other languges.
- alternate implementations of Protocol Buffers that target specialized use
cases.
- code generators that implement some utility code on top of protobuf generated
classes.
While this document speaks in terms of "code generators", these same principles
apply to implementations that dynamically generate a protocol buffer API "on the
fly", directly from a descriptor, in languages that support this kind of usage.
## Updating a Code Generator
When a user adds an `optional` field to proto3, this is internally rewritten as
a one-field oneof, for backward-compatibility with reflection-based algorithms:
```protobuf
syntax = "proto3";
message Foo {
// Experimental feature, not generally supported yet!
optional int32 foo = 1;
// Internally rewritten to:
// oneof _foo {
// int32 foo = 1 [proto3_optional=true];
// }
//
// We call _foo a "synthetic" oneof, since it was not created by the user.
}
```
As a result, the main two goals when updating a code generator are:
1. Give `optional` fields like `foo` normal field presence, as described in
[docs/field_presence](field_presence.md) If your implementation already
supports proto2, a proto3 `optional` field should use exactly the same API
and internal implementation as proto2 `optional`.
2. Avoid generating any oneof-based accessors for the synthetic oneof. Its only
purpose is to make reflection-based algorithms work properly if they are
not aware of proto3 presence. The synthetic oneof should not appear anywhere
in the generated API.
### Satisfying the Experimental Check
If you try to run `protoc` on a file with proto3 `optional` fields, you will get
an error because the feature is still experimental:
```
$ cat test.proto
syntax = "proto3";
message Foo {
// Experimental feature, not generally supported yet!
optional int32 a = 1;
}
$ protoc --cpp_out=. test.proto
test.proto: This file contains proto3 optional fields, but --experimental_allow_proto3_optional was not set.
```
There are two options for getting around this error:
1. Pass `--experimental_allow_proto3_optional` to protoc.
2. Make your filename (or a directory name) contain the string
`test_proto3_optional`. This indicates that the proto file is specifically
for testing proto3 optional support, so the check is suppressed.
These options are demonstrated below:
```
# One option:
$ ./src/protoc test.proto --cpp_out=. --experimental_allow_proto3_optional
# Another option:
$ cp test.proto test_proto3_optional.proto
$ ./src/protoc test_proto3_optional.proto --cpp_out=.
$
```
The experimental check will be removed in a future release, once we are ready
to make this feature generally available. Ideally this will happen for the 3.13
release of protobuf, sometime in mid-2020, but there is not a specific date set
for this yet. Some of the timing will depend on feedback we get from the
community, so if you have questions or concerns please get in touch via a
GitHub issue.
### Signaling That Your Code Generator Supports Proto3 Optional
If you now try to invoke your own code generator with the test proto, you will
run into a different error:
```
$ ./src/protoc test_proto3_optional.proto --my_codegen_out=.
test_proto3_optional.proto: is a proto3 file that contains optional fields, but
code generator --my_codegen_out hasn't been updated to support optional fields in
proto3. Please ask the owner of this code generator to support proto3 optional.
```
This check exists to make sure that code generators get a chance to update
before they are used with proto3 `optional` fields. Without this check an old
code generator might emit obsolete generated APIs (like accessors for a
synthetic oneof) and users could start depending on these. That would create
a legacy migration burden once a code generator actually implements the feature.
To signal that your code generator supports `optional` fields in proto3, you
need to tell `protoc` what features you support. The method for doing this
depends on whether you are using the C++
`google::protobuf::compiler::CodeGenerator`
framework or not.
If you are using the CodeGenerator framework:
```c++
class MyCodeGenerator : public google::protobuf::compiler::CodeGenerator {
// Add this method.
uint64_t GetSupportedFeatures() const override {
// Indicate that this code generator supports proto3 optional fields.
// (Note: don't release your code generator with this flag set until you
// have actually added and tested your proto3 support!)
return FEATURE_PROTO3_OPTIONAL;
}
}
```
If you are generating code using raw `CodeGeneratorRequest` and
`CodeGeneratorResponse` messages from `plugin.proto`, the change will be very
similar:
```c++
void GenerateResponse() {
CodeGeneratorResponse response;
response.set_supported_features(CodeGeneratorResponse::FEATURE_PROTO3_OPTIONAL);
// Generate code...
}
```
Once you have added this, you should now be able to successfully use your code
generator to generate a file containing proto3 optional fields:
```
$ ./src/protoc test_proto3_optional.proto --my_codegen_out=.
```
### Updating Your Code Generator
Now to actually add support for proto3 optional to your code generator. The goal
is to recognize proto3 optional fields as optional, and suppress any output from
synthetic oneofs.
If your code generator does not currently support proto2, you will need to
design an API and implementation for supporting presence in scalar fields.
Generally this means:
- allocating a bit inside the generated class to represent whether a given field
is present or not.
- exposing a `has_foo()` method for each field to return the value of this bit.
- make the parser set this bit when a value is parsed from the wire.
- make the serializer test this bit to decide whether to serialize.
If your code generator already supports proto2, then most of your work is
already done. All you need to do is make sure that proto3 optional fields have
exactly the same API and behave in exactly the same way as proto2 optional
fields.
From experience updating several of Google's code generators, most of the
updates that are required fall into one of several patterns. Here we will show
the patterns in terms of the C++ CodeGenerator framework. If you are using
`CodeGeneratorRequest` and `CodeGeneratorReply` directly, you can translate the
C++ examples to your own language, referencing the C++ implementation of these
methods where required.
#### To test whether a field should have presence
Old:
```c++
bool MessageHasPresence(const google::protobuf::Descriptor* message) {
return message->file()->syntax() ==
google::protobuf::FileDescriptor::SYNTAX_PROTO2;
}
```
New:
```c++
// Presence is no longer a property of a message, it's a property of individual
// fields.
bool FieldHasPresence(const google::protobuf::FieldDescriptor* field) {
return field->has_presence();
// Note, the above will return true for fields in a oneof.
// If you want to filter out oneof fields, write this instead:
// return field->has_presence && !field->real_containing_oneof()
}
```
#### To test whether a field is a member of a oneof
Old:
```c++
bool FieldIsInOneof(const google::protobuf::FielDescriptor* field) {
return field->containing_oneof() != nullptr;
}
```
New:
```c++
bool FieldIsInOneof(const google::protobuf::FielDescriptor* field) {
// real_containing_oneof() returns nullptr for synthetic oneofs.
return field->real_containing_oneof() != nullptr;
}
```
#### To iterate over all oneofs
Old:
```c++
bool IterateOverOneofs(const google::protobuf::Descriptor* message) {
for (int i = 0; i < message->oneof_decl_count(); i++) {
const google::protobuf::OneofDescriptor* oneof = message->oneof(i);
// ...
}
}
```
New:
```c++
bool IterateOverOneofs(const google::protobuf::Descriptor* message) {
// Real oneofs are always first, and real_oneof_decl_count() will return the
// total number of oneofs, excluding synthetic oneofs.
for (int i = 0; i < message->real_oneof_decl_count(); i++) {
const google::protobuf::OneofDescriptor* oneof = message->oneof(i);
// ...
}
}
```
## Updating Reflection
If your implementation offers reflection, there are a few other changes to make:
### API Changes
The API for reflecting over fields and oneofs should make the following changes.
These match the changes implemented in C++ reflection.
1. Add a `FieldDescriptor::has_presence()` method returning `bool`
(adjusted to your language's naming convention). This should return true
for all fields that have explicit presence, as documented in
[docs/field_presence](field_presence.md). In particular, this includes
fields in a oneof, proto2 scalar fields, and proto3 `optional` fields.
This accessor will allow users to query what fields have presence without
thinking about the difference between proto2 and proto3.
2. As a corollary of (1), please do *not* expose an accessor for the
`FieldDescriptorProto.proto3_optional` field. We want to avoid having
users implement any proto2/proto3-specific logic. Users should use the
`has_presence()` function instead.
3. You may also wish to add a `FieldDescriptor::has_optional_keyword()` method
returning `bool`, which indicates whether the `optional` keyword is present.
Message fields will always return `true` for `has_presence()`, so this method
can allow a user to know whether the user wrote `optional` or not. It can
occasionally be useful to have this information, even though it does not
change the presence semantics of the field.
4. If your reflection API may be used for a code generator, you may wish to
implement methods to help users tell the difference between real and
synthetic oneofs. In particular:
- `OneofDescriptor::is_synthetic()`: returns true if this is a synthetic
oneof.
- `FieldDescriptor::real_containing_oneof()`: like `containing_oneof()`,
but returns `nullptr` if the oneof is synthetic.
- `Descriptor::real_oneof_decl_count()`: like `oneof_decl_count()`, but
returns the number of real oneofs only.
### Implementation Changes
Proto3 `optional` fields and synthetic oneofs must work correctly when
reflected on. Specifically:
1. Reflection for synthetic oneofs should work properly. Even though synthetic
oneofs do not really exist in the message, you can still make reflection work
as if they did. In particular, you can make a method like
`Reflection::HasOneof()` or `Reflection::GetOneofFieldDescriptor()` look at
the hasbit to determine if the oneof is present or not.
2. Reflection for proto3 optional fields should work properly. For example, a
method like `Reflection::HasField()` should know to look for the hasbit for a
proto3 `optional` field. It should not be fooled by the synthetic oneof into
thinking that there is a `case` member for the oneof.
Once you have updated reflection to work properly with proto3 `optional` and
synthetic oneofs, any code that *uses* your reflection interface should work
properly with no changes. This is the benefit of using synthetic oneofs.
In particular, if you have a reflection-based implementation of protobuf text
format or JSON, it should properly support proto3 optional fields without any
changes to the code. The fields will look like they all belong to a one-field
oneof, and existing proto3 reflection code should know how to test presence for
fields in a oneof.
So the best way to test your reflection changes is to try round-tripping a
message through text format, JSON, or some other reflection-based parser and
serializer, if you have one.
### Validating Descriptors
If your reflection implementation supports loading descriptors at runtime,
you must verify that all synthetic oneofs are ordered after all "real" oneofs.
Here is the code that implements this validation step in C++, for inspiration:
```c++
// Validation that runs for each message.
// Synthetic oneofs must be last.
int first_synthetic = -1;
for (int i = 0; i < message->oneof_decl_count(); i++) {
const OneofDescriptor* oneof = message->oneof_decl(i);
if (oneof->is_synthetic()) {
if (first_synthetic == -1) {
first_synthetic = i;
}
} else {
if (first_synthetic != -1) {
AddError(message->full_name(), proto.oneof_decl(i),
DescriptorPool::ErrorCollector::OTHER,
"Synthetic oneofs must be after all other oneofs");
}
}
}
if (first_synthetic == -1) {
message->real_oneof_decl_count_ = message->oneof_decl_count_;
} else {
message->real_oneof_decl_count_ = first_synthetic;
}
```

@ -82,6 +82,7 @@ These are projects we know about implementing Protocol Buffers for other program
* Prolog: http://www.swi-prolog.org/pldoc/package/protobufs.html
* Python: https://github.com/google/protobuf (Google-official implementation)
* Python: https://github.com/eigenein/protobuf
* Python: https://github.com/danielgtaylor/python-betterproto
* R: http://cran.r-project.org/package=RProtoBuf
* Ruby: http://code.google.com/p/ruby-protobuf/
* Ruby: http://github.com/mozy/ruby-protocol-buffers

@ -93,12 +93,12 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.2-android</version>
<version>29.0-android</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava-testlib</artifactId>
<version>28.2-android</version>
<version>29.0-android</version>
<scope>test</scope>
</dependency>
<dependency>

@ -8,7 +8,7 @@ cd kokoro/linux/dockerfile
DOCKERHUB_ORGANIZATION=protobuftesting
for DOCKERFILE_DIR in test/* release/*
for DOCKERFILE_DIR in test/*
do
# Generate image name based on Dockerfile checksum. That works well as long
# as can count on dockerfiles being written in a way that changing the logical

@ -1,3 +0,0 @@
FROM grpctesting/rake-compiler-dock_53c22085d091183c528303791e7771359f699bcf
RUN /bin/bash -l -c "gem update --system '2.7.9' && gem install bundler"

@ -0,0 +1,23 @@
FROM python:2.7-buster
# Install dependencies. We start with the basic ones require to build protoc
# and the C++ build
RUN apt-get update && apt-get install -y \
autoconf \
autotools-dev \
build-essential \
bzip2 \
ccache \
curl \
gcc \
git \
libc6 \
libc6-dbg \
libc6-dev \
libgtest-dev \
libtool \
make \
parallel \
time \
wget \
&& apt-get clean

@ -0,0 +1,23 @@
FROM python:3.5-buster
# Install dependencies. We start with the basic ones require to build protoc
# and the C++ build
RUN apt-get update && apt-get install -y \
autoconf \
autotools-dev \
build-essential \
bzip2 \
ccache \
curl \
gcc \
git \
libc6 \
libc6-dbg \
libc6-dev \
libgtest-dev \
libtool \
make \
parallel \
time \
wget \
&& apt-get clean

@ -0,0 +1,23 @@
FROM python:3.6-buster
# Install dependencies. We start with the basic ones require to build protoc
# and the C++ build
RUN apt-get update && apt-get install -y \
autoconf \
autotools-dev \
build-essential \
bzip2 \
ccache \
curl \
gcc \
git \
libc6 \
libc6-dbg \
libc6-dev \
libgtest-dev \
libtool \
make \
parallel \
time \
wget \
&& apt-get clean

@ -0,0 +1,23 @@
FROM python:3.7-buster
# Install dependencies. We start with the basic ones require to build protoc
# and the C++ build
RUN apt-get update && apt-get install -y \
autoconf \
autotools-dev \
build-essential \
bzip2 \
ccache \
curl \
gcc \
git \
libc6 \
libc6-dbg \
libc6-dev \
libgtest-dev \
libtool \
make \
parallel \
time \
wget \
&& apt-get clean

@ -0,0 +1,23 @@
FROM python:3.8-buster
# Install dependencies. We start with the basic ones require to build protoc
# and the C++ build
RUN apt-get update && apt-get install -y \
autoconf \
autotools-dev \
build-essential \
bzip2 \
ccache \
curl \
gcc \
git \
libc6 \
libc6-dbg \
libc6-dev \
libgtest-dev \
libtool \
make \
parallel \
time \
wget \
&& apt-get clean

@ -1,39 +0,0 @@
FROM debian:jessie
# Install dependencies. We start with the basic ones require to build protoc
# and the C++ build
RUN apt-get update && apt-get install -y \
autoconf \
autotools-dev \
build-essential \
bzip2 \
ccache \
curl \
gcc \
git \
libc6 \
libc6-dbg \
libc6-dev \
libgtest-dev \
libtool \
make \
parallel \
time \
wget \
&& apt-get clean
# Install python dependencies
RUN apt-get update && apt-get install -y \
python-setuptools \
python-all-dev \
python3-all-dev \
python-pip
# Install Python packages from PyPI
RUN pip install --upgrade pip==10.0.1
RUN pip install virtualenv
RUN pip install six==1.10.0 twisted==17.5.0
# Install pip and virtualenv for Python 3.4
RUN curl https://bootstrap.pypa.io/get-pip.py | python3.4
RUN python3.4 -m pip install virtualenv

@ -1,49 +0,0 @@
FROM debian:stretch
# Install dependencies. We start with the basic ones require to build protoc
# and the C++ build
RUN apt-get update && apt-get install -y \
autoconf \
autotools-dev \
build-essential \
bzip2 \
ccache \
curl \
gcc \
git \
libc6 \
libc6-dbg \
libc6-dev \
libgtest-dev \
libtool \
make \
parallel \
time \
wget \
&& apt-get clean
# Install Python 2.7
RUN apt-get update && apt-get install -y python2.7 python-all-dev
RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7
# Install python dependencies
RUN apt-get update && apt-get install -y \
python-setuptools \
python-pip
# Add Debian 'testing' repository
RUN echo 'deb http://ftp.de.debian.org/debian testing main' >> /etc/apt/sources.list
RUN echo 'APT::Default-Release "stable";' | tee -a /etc/apt/apt.conf.d/00local
# Install Python3
RUN apt-get update && apt-get -t testing install -y \
python3.5 \
python3.6 \
python3.7 \
python3.8 \
python3-all-dev
RUN curl https://bootstrap.pypa.io/get-pip.py | python3.5
RUN curl https://bootstrap.pypa.io/get-pip.py | python3.6
RUN curl https://bootstrap.pypa.io/get-pip.py | python3.7
RUN curl https://bootstrap.pypa.io/get-pip.py | python3.8

@ -32,6 +32,7 @@ RUN /bin/bash -l -c "rvm install 2.3.8"
RUN /bin/bash -l -c "rvm install 2.4.5"
RUN /bin/bash -l -c "rvm install 2.5.1"
RUN /bin/bash -l -c "rvm install 2.6.0"
RUN /bin/bash -l -c "rvm install 2.7.0"
RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"

@ -11,7 +11,7 @@
cd $(dirname $0)/../../..
export DOCKERHUB_ORGANIZATION=protobuftesting
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_jessie
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python27
export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
export OUTPUT_DIR=testoutput
export TEST_SET="python27"

@ -11,7 +11,7 @@
cd $(dirname $0)/../../..
export DOCKERHUB_ORGANIZATION=protobuftesting
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_jessie
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python27
export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
export OUTPUT_DIR=testoutput
export TEST_SET="python27_cpp"

@ -1,18 +0,0 @@
#!/bin/bash
#
# This is the top-level script we give to Kokoro as the entry point for
# running the "pull request" project:
#
# This script selects a specific Dockerfile (for building a Docker image) and
# a script to run inside that image. Then we delegate to the general
# build_and_run_docker.sh script.
# Change to repo root
cd $(dirname $0)/../../..
export DOCKERHUB_ORGANIZATION=protobuftesting
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_jessie
export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
export OUTPUT_DIR=testoutput
export TEST_SET="python33"
./kokoro/linux/build_and_run_docker.sh

@ -1,11 +0,0 @@
# Config file for running tests in Kokoro
# Location of the build script in repository
build_file: "protobuf/kokoro/linux/python/build.sh"
timeout_mins: 120
action {
define_artifacts {
regex: "**/sponge_log.xml"
}
}

@ -1,11 +0,0 @@
# Config file for running tests in Kokoro
# Location of the build script in repository
build_file: "protobuf/kokoro/linux/python/build.sh"
timeout_mins: 120
action {
define_artifacts {
regex: "**/sponge_log.xml"
}
}

@ -1,18 +0,0 @@
#!/bin/bash
#
# This is the top-level script we give to Kokoro as the entry point for
# running the "pull request" project:
#
# This script selects a specific Dockerfile (for building a Docker image) and
# a script to run inside that image. Then we delegate to the general
# build_and_run_docker.sh script.
# Change to repo root
cd $(dirname $0)/../../..
export DOCKERHUB_ORGANIZATION=protobuftesting
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_jessie
export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
export OUTPUT_DIR=testoutput
export TEST_SET="python33_cpp"
./kokoro/linux/build_and_run_docker.sh

@ -1,11 +0,0 @@
# Config file for running tests in Kokoro
# Location of the build script in repository
build_file: "protobuf/kokoro/linux/python_cpp/build.sh"
timeout_mins: 120
action {
define_artifacts {
regex: "**/sponge_log.xml"
}
}

@ -1,11 +0,0 @@
# Config file for running tests in Kokoro
# Location of the build script in repository
build_file: "protobuf/kokoro/linux/python_cpp/build.sh"
timeout_mins: 120
action {
define_artifacts {
regex: "**/sponge_log.xml"
}
}

@ -1,18 +0,0 @@
#!/bin/bash
#
# This is the top-level script we give to Kokoro as the entry point for
# running the "pull request" project:
#
# This script selects a specific Dockerfile (for building a Docker image) and
# a script to run inside that image. Then we delegate to the general
# build_and_run_docker.sh script.
# Change to repo root
cd $(dirname $0)/../../..
export DOCKERHUB_ORGANIZATION=protobuftesting
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_jessie
export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
export OUTPUT_DIR=testoutput
export TEST_SET="python34_cpp"
./kokoro/linux/build_and_run_docker.sh

@ -1,11 +0,0 @@
# Config file for running tests in Kokoro
# Location of the build script in repository
build_file: "protobuf/kokoro/linux/python_cpp/build.sh"
timeout_mins: 120
action {
define_artifacts {
regex: "**/sponge_log.xml"
}
}

@ -1,11 +0,0 @@
# Config file for running tests in Kokoro
# Location of the build script in repository
build_file: "protobuf/kokoro/linux/python_cpp/build.sh"
timeout_mins: 120
action {
define_artifacts {
regex: "**/sponge_log.xml"
}
}

@ -11,7 +11,7 @@
cd $(dirname $0)/../../..
export DOCKERHUB_ORGANIZATION=protobuftesting
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_stretch
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python35
export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
export OUTPUT_DIR=testoutput
export TEST_SET="python35"

@ -11,7 +11,7 @@
cd $(dirname $0)/../../..
export DOCKERHUB_ORGANIZATION=protobuftesting
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_stretch
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python35
export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
export OUTPUT_DIR=testoutput
export TEST_SET="python35_cpp"

@ -11,7 +11,7 @@
cd $(dirname $0)/../../..
export DOCKERHUB_ORGANIZATION=protobuftesting
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_stretch
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python36
export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
export OUTPUT_DIR=testoutput
export TEST_SET="python36"

@ -11,7 +11,7 @@
cd $(dirname $0)/../../..
export DOCKERHUB_ORGANIZATION=protobuftesting
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_stretch
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python36
export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
export OUTPUT_DIR=testoutput
export TEST_SET="python36_cpp"

@ -11,7 +11,7 @@
cd $(dirname $0)/../../..
export DOCKERHUB_ORGANIZATION=protobuftesting
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_stretch
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python37
export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
export OUTPUT_DIR=testoutput
export TEST_SET="python37"

@ -11,7 +11,7 @@
cd $(dirname $0)/../../..
export DOCKERHUB_ORGANIZATION=protobuftesting
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_stretch
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python37
export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
export OUTPUT_DIR=testoutput
export TEST_SET="python37_cpp"

@ -11,7 +11,7 @@
cd $(dirname $0)/../../..
export DOCKERHUB_ORGANIZATION=protobuftesting
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_stretch
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python38
export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
export OUTPUT_DIR=testoutput
export TEST_SET="python38"

@ -11,7 +11,7 @@
cd $(dirname $0)/../../..
export DOCKERHUB_ORGANIZATION=protobuftesting
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_stretch
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python38
export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
export OUTPUT_DIR=testoutput
export TEST_SET="python38_cpp"

@ -11,8 +11,8 @@
cd $(dirname $0)/../../..
export DOCKERHUB_ORGANIZATION=protobuftesting
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_jessie
export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/ruby
export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
export OUTPUT_DIR=testoutput
export TEST_SET="python34"
export TEST_SET="ruby27"
./kokoro/linux/build_and_run_docker.sh

@ -1,7 +1,7 @@
# Config file for running tests in Kokoro
# Location of the build script in repository
build_file: "protobuf/kokoro/linux/python/build.sh"
build_file: "protobuf/kokoro/linux/ruby27/build.sh"
timeout_mins: 120
action {

@ -1,7 +1,7 @@
# Config file for running tests in Kokoro
# Location of the build script in repository
build_file: "protobuf/kokoro/linux/python/build.sh"
build_file: "protobuf/kokoro/linux/ruby27/build.sh"
timeout_mins: 120
action {

@ -0,0 +1,11 @@
#!/bin/bash
#
# Build file to set up and run tests
# Change to repo root
cd $(dirname $0)/../../..
# Prepare worker environment to run tests
source kokoro/macos/prepare_build_macos_rc
./tests.sh ruby27

@ -0,0 +1,5 @@
# Config file for running tests in Kokoro
# Location of the build script in repository
build_file: "protobuf/kokoro/macos/ruby27/build.sh"
timeout_mins: 1440

@ -0,0 +1,5 @@
# Config file for running tests in Kokoro
# Location of the build script in repository
build_file: "protobuf/kokoro/macos/ruby27/build.sh"
timeout_mins: 1440

@ -7,12 +7,6 @@ echo 'DOCKER_OPTS="${DOCKER_OPTS} --graph=/tmpfs/docker"' | sudo tee --append /e
echo 'DOCKER_OPTS="${DOCKER_OPTS} --registry-mirror=https://mirror.gcr.io"' | sudo tee --append /etc/default/docker
sudo service docker restart
# Download Docker images from DockerHub
DOCKERHUB_ORGANIZATION=protobuftesting
DOCKERFILE_DIR=kokoro/linux/dockerfile/release/ruby_rake_compiler
DOCKERFILE_PREFIX=$(basename $DOCKERFILE_DIR)
export RAKE_COMPILER_DOCK_IMAGE=${DOCKERHUB_ORGANIZATION}/${DOCKERFILE_PREFIX}_$(sha1sum $DOCKERFILE_DIR/Dockerfile | cut -f1 -d\ )
# All artifacts come here
mkdir artifacts
export ARTIFACT_DIR=$(pwd)/artifacts

@ -11,6 +11,7 @@ fi
umask 0022
pushd ruby
gem install bundler -v 2.1.4
bundle install && bundle exec rake gem:native
ls pkg
mv pkg/* $ARTIFACT_DIR

@ -6,7 +6,11 @@ set +ex # rvm script is very verbose and exits with errorcode
source $HOME/.rvm/scripts/rvm
set -e # rvm commands are very verbose
time rvm install 2.5.0
rvm use 2.5.0 --default
rvm use 2.5.0
gem install rake-compiler --no-document
gem install bundler --no-document
time rvm install 2.7.0
rvm use 2.7.0 --default
gem install rake-compiler --no-document
gem install bundler --no-document
rvm osx-ssl-certs status all
@ -17,13 +21,13 @@ rm -rf ~/.rake-compiler
CROSS_RUBY=$(mktemp tmpfile.XXXXXXXX)
curl https://raw.githubusercontent.com/rake-compiler/rake-compiler/v1.0.3/tasks/bin/cross-ruby.rake > "$CROSS_RUBY"
curl https://raw.githubusercontent.com/rake-compiler/rake-compiler/v1.1.0/tasks/bin/cross-ruby.rake > "$CROSS_RUBY"
# See https://github.com/grpc/grpc/issues/12161 for verconf.h patch details
patch "$CROSS_RUBY" << EOF
--- cross-ruby.rake 2018-04-10 11:32:16.000000000 -0700
+++ patched 2018-04-10 11:40:25.000000000 -0700
@@ -133,8 +133,10 @@
@@ -141,8 +141,10 @@
"--host=#{MINGW_HOST}",
"--target=#{MINGW_TARGET}",
"--build=#{RUBY_BUILD}",
@ -35,9 +39,9 @@ patch "$CROSS_RUBY" << EOF
'--with-ext='
]
@@ -151,6 +153,7 @@
@@ -159,6 +161,7 @@
# make
file "#{USER_HOME}/builds/#{MINGW_HOST}/#{RUBY_CC_VERSION}/ruby.exe" => ["#{USER_HOME}/builds/#{MINGW_HOST}/#{RUBY_CC_VERSION}/Makefile"] do |t|
file "#{build_dir}/ruby.exe" => ["#{build_dir}/Makefile"] do |t|
chdir File.dirname(t.prerequisites.first) do
+ sh "test -s verconf.h || rm -f verconf.h" # if verconf.h has size 0, make sure it gets re-built by make
sh MAKE
@ -47,10 +51,25 @@ EOF
MAKE="make -j8"
set +x # rvm commands are very verbose
rvm use 2.7.0
set -x
ruby --version | grep 'ruby 2.7.0'
for v in 2.7.0 ; do
ccache -c
rake -f "$CROSS_RUBY" cross-ruby VERSION="$v" HOST=x86_64-darwin11 MAKE="$MAKE"
done
set +x
rvm use 2.5.0
set -x
ruby --version | grep 'ruby 2.5.0'
for v in 2.6.0 2.5.1 2.4.0 2.3.0 ; do
ccache -c
rake -f "$CROSS_RUBY" cross-ruby VERSION="$v" HOST=x86_64-darwin11 MAKE="$MAKE"
done
set +x
rvm use 2.7.0
set -x
sed 's/x86_64-darwin-11/universal-darwin/' ~/.rake-compiler/config.yml > "$CROSS_RUBY"
mv "$CROSS_RUBY" ~/.rake-compiler/config.yml

@ -158,6 +158,7 @@ compile_protos() {
--objc_out="${OUTPUT_DIR}/google/protobuf" \
--proto_path=src/google/protobuf/ \
--proto_path=src \
--experimental_allow_proto3_optional \
"$@"
}

@ -290,12 +290,9 @@ if [[ "${DO_XCODE_IOS_TESTS}" == "yes" ]] ; then
)
;;
11.*)
# Dropped 32bit as Apple doesn't seem support the simulators either.
XCODEBUILD_TEST_BASE_IOS+=(
-destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit
-destination "platform=iOS Simulator,name=iPhone 8,OS=latest" # 64bit
# 10.x also seems to often fail running destinations in parallel (with
# 32bit one include atleast)
-disable-concurrent-destination-testing
)
;;
* )

@ -17,10 +17,10 @@
#import "GPBRootObject.h"
#endif
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
#endif

@ -72,7 +72,7 @@ typedef struct GPBAny__storage_ {
.number = GPBAny_FieldNumber_TypeURL,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBAny__storage_, typeURL),
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom),
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeString,
},
{
@ -81,7 +81,7 @@ typedef struct GPBAny__storage_ {
.number = GPBAny_FieldNumber_Value,
.hasIndex = 1,
.offset = (uint32_t)offsetof(GPBAny__storage_, value),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeBytes,
},
};
@ -92,7 +92,7 @@ typedef struct GPBAny__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBAny__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
static const char *extraTextFormatInfo =
"\001\001\004\241!!\000";

@ -17,10 +17,10 @@
#import "GPBRootObject.h"
#endif
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
#endif

@ -96,7 +96,7 @@ typedef struct GPBApi__storage_ {
.number = GPBApi_FieldNumber_Name,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBApi__storage_, name),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeString,
},
{
@ -123,7 +123,7 @@ typedef struct GPBApi__storage_ {
.number = GPBApi_FieldNumber_Version,
.hasIndex = 1,
.offset = (uint32_t)offsetof(GPBApi__storage_, version),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeString,
},
{
@ -150,7 +150,7 @@ typedef struct GPBApi__storage_ {
.number = GPBApi_FieldNumber_Syntax,
.hasIndex = 3,
.offset = (uint32_t)offsetof(GPBApi__storage_, syntax),
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor),
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeEnum,
},
};
@ -161,7 +161,7 @@ typedef struct GPBApi__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBApi__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
@ -175,13 +175,13 @@ typedef struct GPBApi__storage_ {
int32_t GPBApi_Syntax_RawValue(GPBApi *message) {
GPBDescriptor *descriptor = [GPBApi descriptor];
GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBApi_FieldNumber_Syntax];
return GPBGetMessageInt32Field(message, field);
return GPBGetMessageRawEnumField(message, field);
}
void SetGPBApi_Syntax_RawValue(GPBApi *message, int32_t value) {
GPBDescriptor *descriptor = [GPBApi descriptor];
GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBApi_FieldNumber_Syntax];
GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
GPBSetMessageRawEnumField(message, field, value);
}
#pragma mark - GPBMethod
@ -217,7 +217,7 @@ typedef struct GPBMethod__storage_ {
.number = GPBMethod_FieldNumber_Name,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBMethod__storage_, name),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeString,
},
{
@ -226,7 +226,7 @@ typedef struct GPBMethod__storage_ {
.number = GPBMethod_FieldNumber_RequestTypeURL,
.hasIndex = 1,
.offset = (uint32_t)offsetof(GPBMethod__storage_, requestTypeURL),
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom),
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeString,
},
{
@ -235,7 +235,7 @@ typedef struct GPBMethod__storage_ {
.number = GPBMethod_FieldNumber_RequestStreaming,
.hasIndex = 2,
.offset = 3, // Stored in _has_storage_ to save space.
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeBool,
},
{
@ -244,7 +244,7 @@ typedef struct GPBMethod__storage_ {
.number = GPBMethod_FieldNumber_ResponseTypeURL,
.hasIndex = 4,
.offset = (uint32_t)offsetof(GPBMethod__storage_, responseTypeURL),
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom),
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeString,
},
{
@ -253,7 +253,7 @@ typedef struct GPBMethod__storage_ {
.number = GPBMethod_FieldNumber_ResponseStreaming,
.hasIndex = 5,
.offset = 6, // Stored in _has_storage_ to save space.
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeBool,
},
{
@ -271,7 +271,7 @@ typedef struct GPBMethod__storage_ {
.number = GPBMethod_FieldNumber_Syntax,
.hasIndex = 7,
.offset = (uint32_t)offsetof(GPBMethod__storage_, syntax),
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor),
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeEnum,
},
};
@ -282,7 +282,7 @@ typedef struct GPBMethod__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBMethod__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
static const char *extraTextFormatInfo =
"\002\002\007\244\241!!\000\004\010\244\241!!\000";
@ -301,13 +301,13 @@ typedef struct GPBMethod__storage_ {
int32_t GPBMethod_Syntax_RawValue(GPBMethod *message) {
GPBDescriptor *descriptor = [GPBMethod descriptor];
GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBMethod_FieldNumber_Syntax];
return GPBGetMessageInt32Field(message, field);
return GPBGetMessageRawEnumField(message, field);
}
void SetGPBMethod_Syntax_RawValue(GPBMethod *message, int32_t value) {
GPBDescriptor *descriptor = [GPBMethod descriptor];
GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBMethod_FieldNumber_Syntax];
GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
GPBSetMessageRawEnumField(message, field, value);
}
#pragma mark - GPBMixin
@ -335,7 +335,7 @@ typedef struct GPBMixin__storage_ {
.number = GPBMixin_FieldNumber_Name,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBMixin__storage_, name),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeString,
},
{
@ -344,7 +344,7 @@ typedef struct GPBMixin__storage_ {
.number = GPBMixin_FieldNumber_Root,
.hasIndex = 1,
.offset = (uint32_t)offsetof(GPBMixin__storage_, root),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeString,
},
};
@ -355,7 +355,7 @@ typedef struct GPBMixin__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBMixin__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG

@ -132,7 +132,7 @@
// Current library runtime version.
// - Gets bumped when the runtime makes changes to the interfaces between the
// generated code and runtime (things added/removed, etc).
#define GOOGLE_PROTOBUF_OBJC_VERSION 30003
#define GOOGLE_PROTOBUF_OBJC_VERSION 30004
// Minimum runtime version supported for compiling/running against.
// - Gets changed when support for the older generated code is dropped.

@ -128,6 +128,8 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex,
(flags & GPBDescriptorInitializationFlag_FieldsWithDefault) != 0;
BOOL usesClassRefs =
(flags & GPBDescriptorInitializationFlag_UsesClassRefs) != 0;
BOOL proto3OptionalKnown =
(flags & GPBDescriptorInitializationFlag_Proto3OptionalKnown) != 0;
void *desc;
for (uint32_t i = 0; i < fieldCount; ++i) {
@ -146,6 +148,7 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex,
[[GPBFieldDescriptor alloc] initWithFieldDescription:desc
includesDefault:fieldsIncludeDefault
usesClassRefs:usesClassRefs
proto3OptionalKnown:proto3OptionalKnown
syntax:syntax];
[fields addObject:fieldDescriptor];
[fieldDescriptor release];
@ -488,6 +491,7 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) {
- (instancetype)initWithFieldDescription:(void *)description
includesDefault:(BOOL)includesDefault
usesClassRefs:(BOOL)usesClassRefs
proto3OptionalKnown:(BOOL)proto3OptionalKnown
syntax:(GPBFileSyntax)syntax {
if ((self = [super init])) {
GPBMessageFieldDescription *coreDesc;
@ -504,20 +508,34 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) {
BOOL isMessage = GPBDataTypeIsMessage(dataType);
BOOL isMapOrArray = GPBFieldIsMapOrArray(self);
// If proto3 optionals weren't known (i.e. generated code from an
// older version), compute the flag for the rest of the runtime.
if (!proto3OptionalKnown) {
// If it was...
// - proto3 syntax
// - not repeated/map
// - not in a oneof (negative has index)
// - not a message (the flag doesn't make sense for messages)
BOOL clearOnZero = ((syntax == GPBFileSyntaxProto3) &&
!isMapOrArray &&
(coreDesc->hasIndex >= 0) &&
!isMessage);
if (clearOnZero) {
coreDesc->flags |= GPBFieldClearHasIvarOnZero;
}
}
if (isMapOrArray) {
// map<>/repeated fields get a *Count property (inplace of a has*) to
// support checking if there are any entries without triggering
// autocreation.
hasOrCountSel_ = SelFromStrings(NULL, coreDesc->name, "_Count", NO);
} else {
// If there is a positive hasIndex, then:
// - All fields types for proto2 messages get has* selectors.
// - Only message fields for proto3 messages get has* selectors.
// Note: the positive check is to handle oneOfs, we can't check
// containingOneof_ because it isn't set until after initialization.
// It is a single field; it gets has/setHas selectors if...
// - not in a oneof (negative has index)
// - not clearing on zero
if ((coreDesc->hasIndex >= 0) &&
(coreDesc->hasIndex != GPBNoHasBit) &&
((syntax != GPBFileSyntaxProto3) || isMessage)) {
((coreDesc->flags & GPBFieldClearHasIvarOnZero) == 0)) {
hasOrCountSel_ = SelFromStrings("has", coreDesc->name, NULL, NO);
setHasSel_ = SelFromStrings("setHas", coreDesc->name, NULL, YES);
}
@ -567,15 +585,6 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) {
return self;
}
- (instancetype)initWithFieldDescription:(void *)description
includesDefault:(BOOL)includesDefault
syntax:(GPBFileSyntax)syntax {
return [self initWithFieldDescription:description
includesDefault:includesDefault
usesClassRefs:NO
syntax:syntax];
}
- (void)dealloc {
if (description_->dataType == GPBDataTypeBytes &&
!(description_->flags & GPBFieldRepeated)) {

@ -45,6 +45,10 @@ typedef NS_OPTIONS(uint16_t, GPBFieldFlags) {
GPBFieldOptional = 1 << 3,
GPBFieldHasDefaultValue = 1 << 4,
// Indicate that the field should "clear" when set to zero value. This is the
// proto3 non optional behavior for singular data (ints, data, string, enum)
// fields.
GPBFieldClearHasIvarOnZero = 1 << 5,
// Indicates the field needs custom handling for the TextFormat name, if not
// set, the name can be derived from the ObjC name.
GPBFieldTextFormatNameCustom = 1 << 6,
@ -149,7 +153,13 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) {
// This is used as a stopgap as we move from using class names to class
// references. The runtime needs to support both until we allow a
// breaking change in the runtime.
GPBDescriptorInitializationFlag_UsesClassRefs = 1 << 2,
GPBDescriptorInitializationFlag_UsesClassRefs = 1 << 2,
// This flag is used to indicate that the generated sources already contain
// the `GPBFieldClearHasIvarOnZero` flag and it doesn't have to be computed
// at startup. This allows older generated code to still work with the
// current runtime library.
GPBDescriptorInitializationFlag_Proto3OptionalKnown = 1 << 3,
};
@interface GPBDescriptor () {
@ -225,14 +235,9 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) {
- (instancetype)initWithFieldDescription:(void *)description
includesDefault:(BOOL)includesDefault
usesClassRefs:(BOOL)usesClassRefs
proto3OptionalKnown:(BOOL)proto3OptionalKnown
syntax:(GPBFileSyntax)syntax;
// Deprecated. Equivalent to calling above with `usesClassRefs = NO`.
- (instancetype)initWithFieldDescription:(void *)description
includesDefault:(BOOL)includesDefault
syntax:(GPBFileSyntax)syntax;
@end
@interface GPBEnumDescriptor ()

@ -17,10 +17,10 @@
#import "GPBRootObject.h"
#endif
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
#endif

@ -72,7 +72,7 @@ typedef struct GPBDuration__storage_ {
.number = GPBDuration_FieldNumber_Seconds,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBDuration__storage_, seconds),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeInt64,
},
{
@ -81,7 +81,7 @@ typedef struct GPBDuration__storage_ {
.number = GPBDuration_FieldNumber_Nanos,
.hasIndex = 1,
.offset = (uint32_t)offsetof(GPBDuration__storage_, nanos),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeInt32,
},
};
@ -92,7 +92,7 @@ typedef struct GPBDuration__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBDuration__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG

@ -17,10 +17,10 @@
#import "GPBRootObject.h"
#endif
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
#endif

@ -68,7 +68,7 @@ typedef struct GPBEmpty__storage_ {
fields:NULL
fieldCount:0
storageSize:sizeof(GPBEmpty__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG

@ -17,10 +17,10 @@
#import "GPBRootObject.h"
#endif
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
#endif

@ -81,7 +81,7 @@ typedef struct GPBFieldMask__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBFieldMask__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG

@ -99,15 +99,13 @@ static id CreateArrayForField(GPBFieldDescriptor *field,
GPBMessage *autocreator)
__attribute__((ns_returns_retained));
static id GetOrCreateArrayIvarWithField(GPBMessage *self,
GPBFieldDescriptor *field,
GPBFileSyntax syntax);
GPBFieldDescriptor *field);
static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
static id CreateMapForField(GPBFieldDescriptor *field,
GPBMessage *autocreator)
__attribute__((ns_returns_retained));
static id GetOrCreateMapIvarWithField(GPBMessage *self,
GPBFieldDescriptor *field,
GPBFileSyntax syntax);
GPBFieldDescriptor *field);
static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap,
NSZone *zone)
@ -560,10 +558,10 @@ static id CreateMapForField(GPBFieldDescriptor *field,
#if !defined(__clang_analyzer__)
// These functions are blocked from the analyzer because the analyzer sees the
// GPBSetRetainedObjectIvarWithFieldInternal() call as consuming the array/map,
// GPBSetRetainedObjectIvarWithFieldPrivate() call as consuming the array/map,
// so use of the array/map after the call returns is flagged as a use after
// free.
// But GPBSetRetainedObjectIvarWithFieldInternal() is "consuming" the retain
// But GPBSetRetainedObjectIvarWithFieldPrivate() is "consuming" the retain
// count be holding onto the object (it is transferring it), the object is
// still valid after returning from the call. The other way to avoid this
// would be to add a -retain/-autorelease, but that would force every
@ -571,14 +569,13 @@ static id CreateMapForField(GPBFieldDescriptor *field,
// and performance hit.
static id GetOrCreateArrayIvarWithField(GPBMessage *self,
GPBFieldDescriptor *field,
GPBFileSyntax syntax) {
GPBFieldDescriptor *field) {
id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
if (!array) {
// No lock needed, this is called from places expecting to mutate
// so no threading protection is needed.
array = CreateArrayForField(field, nil);
GPBSetRetainedObjectIvarWithFieldInternal(self, field, array, syntax);
GPBSetRetainedObjectIvarWithFieldPrivate(self, field, array);
}
return array;
}
@ -602,14 +599,13 @@ static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
}
static id GetOrCreateMapIvarWithField(GPBMessage *self,
GPBFieldDescriptor *field,
GPBFileSyntax syntax) {
GPBFieldDescriptor *field) {
id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
if (!dict) {
// No lock needed, this is called from places expecting to mutate
// so no threading protection is needed.
dict = CreateMapForField(field, nil);
GPBSetRetainedObjectIvarWithFieldInternal(self, field, dict, syntax);
GPBSetRetainedObjectIvarWithFieldPrivate(self, field, dict);
}
return dict;
}
@ -668,9 +664,8 @@ void GPBBecomeVisibleToAutocreator(GPBMessage *self) {
// This will recursively make all parent messages visible until it reaches a
// super-creator that's visible.
if (self->autocreatorField_) {
GPBFileSyntax syntax = [self->autocreator_ descriptor].file.syntax;
GPBSetObjectIvarWithFieldInternal(self->autocreator_,
self->autocreatorField_, self, syntax);
GPBSetObjectIvarWithFieldPrivate(self->autocreator_,
self->autocreatorField_, self);
} else {
[self->autocreator_ setExtension:self->autocreatorExtension_ value:self];
}
@ -936,8 +931,6 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
// Copy all the storage...
memcpy(message->messageStorage_, messageStorage_, descriptor->storageSize_);
GPBFileSyntax syntax = descriptor.file.syntax;
// Loop over the fields doing fixup...
for (GPBFieldDescriptor *field in descriptor->fields_) {
if (GPBFieldIsMapOrArray(field)) {
@ -1005,8 +998,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
// We retain here because the memcpy picked up the pointer value and
// the next call to SetRetainedObject... will release the current value.
[value retain];
GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue,
syntax);
GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue);
}
} else if (GPBFieldDataTypeIsMessage(field)) {
// For object types, if we have a value, copy it. If we don't,
@ -1018,8 +1010,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
// We retain here because the memcpy picked up the pointer value and
// the next call to SetRetainedObject... will release the current value.
[value retain];
GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue,
syntax);
GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue);
} else {
uint8_t *storage = (uint8_t *)message->messageStorage_;
id *typePtr = (id *)&storage[field->description_->offset];
@ -1033,8 +1024,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
// We retain here because the memcpy picked up the pointer value and
// the next call to SetRetainedObject... will release the current value.
[value retain];
GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue,
syntax);
GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue);
} else {
// memcpy took care of the rest of the primitive fields if they were set.
}
@ -2161,13 +2151,13 @@ static void MergeSingleFieldFromCodedInputStream(
#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE) \
case GPBDataType##NAME: { \
TYPE val = GPBCodedInputStreamRead##NAME(&input->state_); \
GPBSet##FUNC_TYPE##IvarWithFieldInternal(self, field, val, syntax); \
GPBSet##FUNC_TYPE##IvarWithFieldPrivate(self, field, val); \
break; \
}
#define CASE_SINGLE_OBJECT(NAME) \
case GPBDataType##NAME: { \
id val = GPBCodedInputStreamReadRetained##NAME(&input->state_); \
GPBSetRetainedObjectIvarWithFieldInternal(self, field, val, syntax); \
GPBSetRetainedObjectIvarWithFieldPrivate(self, field, val); \
break; \
}
CASE_SINGLE_POD(Bool, BOOL, Bool)
@ -2198,7 +2188,7 @@ static void MergeSingleFieldFromCodedInputStream(
} else {
GPBMessage *message = [[field.msgClass alloc] init];
[input readMessage:message extensionRegistry:extensionRegistry];
GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax);
GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message);
}
break;
}
@ -2217,7 +2207,7 @@ static void MergeSingleFieldFromCodedInputStream(
[input readGroup:GPBFieldNumber(field)
message:message
extensionRegistry:extensionRegistry];
GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax);
GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message);
}
break;
}
@ -2226,7 +2216,7 @@ static void MergeSingleFieldFromCodedInputStream(
int32_t val = GPBCodedInputStreamReadEnum(&input->state_);
if (GPBHasPreservingUnknownEnumSemantics(syntax) ||
[field isValidEnumValue:val]) {
GPBSetInt32IvarWithFieldInternal(self, field, val, syntax);
GPBSetInt32IvarWithFieldPrivate(self, field, val);
} else {
GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
[unknownFields mergeVarintField:GPBFieldNumber(field) value:val];
@ -2240,7 +2230,7 @@ static void MergeRepeatedPackedFieldFromCodedInputStream(
GPBCodedInputStream *input) {
GPBDataType fieldDataType = GPBGetFieldDataType(field);
GPBCodedInputStreamState *state = &input->state_;
id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax);
id genericArray = GetOrCreateArrayIvarWithField(self, field);
int32_t length = GPBCodedInputStreamReadInt32(state);
size_t limit = GPBCodedInputStreamPushLimit(state, length);
while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
@ -2293,7 +2283,7 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream(
GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax,
GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) {
GPBCodedInputStreamState *state = &input->state_;
id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax);
id genericArray = GetOrCreateArrayIvarWithField(self, field);
switch (GPBGetFieldDataType(field)) {
#define CASE_REPEATED_NOT_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \
case GPBDataType##NAME: { \
@ -2395,7 +2385,7 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream(
} else { // fieldType == GPBFieldTypeMap
// GPB*Dictionary or NSDictionary, exact type doesn't matter at this
// point.
id map = GetOrCreateMapIvarWithField(self, fieldDescriptor, syntax);
id map = GetOrCreateMapIvarWithField(self, fieldDescriptor);
[input readMapEntry:map
extensionRegistry:extensionRegistry
field:fieldDescriptor
@ -2469,7 +2459,6 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream(
GPBBecomeVisibleToAutocreator(self);
GPBDescriptor *descriptor = [[self class] descriptor];
GPBFileSyntax syntax = descriptor.file.syntax;
for (GPBFieldDescriptor *field in descriptor->fields_) {
GPBFieldType fieldType = field.fieldType;
@ -2483,44 +2472,44 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream(
GPBDataType fieldDataType = GPBGetFieldDataType(field);
switch (fieldDataType) {
case GPBDataTypeBool:
GPBSetBoolIvarWithFieldInternal(
self, field, GPBGetMessageBoolField(other, field), syntax);
GPBSetBoolIvarWithFieldPrivate(
self, field, GPBGetMessageBoolField(other, field));
break;
case GPBDataTypeSFixed32:
case GPBDataTypeEnum:
case GPBDataTypeInt32:
case GPBDataTypeSInt32:
GPBSetInt32IvarWithFieldInternal(
self, field, GPBGetMessageInt32Field(other, field), syntax);
GPBSetInt32IvarWithFieldPrivate(
self, field, GPBGetMessageInt32Field(other, field));
break;
case GPBDataTypeFixed32:
case GPBDataTypeUInt32:
GPBSetUInt32IvarWithFieldInternal(
self, field, GPBGetMessageUInt32Field(other, field), syntax);
GPBSetUInt32IvarWithFieldPrivate(
self, field, GPBGetMessageUInt32Field(other, field));
break;
case GPBDataTypeSFixed64:
case GPBDataTypeInt64:
case GPBDataTypeSInt64:
GPBSetInt64IvarWithFieldInternal(
self, field, GPBGetMessageInt64Field(other, field), syntax);
GPBSetInt64IvarWithFieldPrivate(
self, field, GPBGetMessageInt64Field(other, field));
break;
case GPBDataTypeFixed64:
case GPBDataTypeUInt64:
GPBSetUInt64IvarWithFieldInternal(
self, field, GPBGetMessageUInt64Field(other, field), syntax);
GPBSetUInt64IvarWithFieldPrivate(
self, field, GPBGetMessageUInt64Field(other, field));
break;
case GPBDataTypeFloat:
GPBSetFloatIvarWithFieldInternal(
self, field, GPBGetMessageFloatField(other, field), syntax);
GPBSetFloatIvarWithFieldPrivate(
self, field, GPBGetMessageFloatField(other, field));
break;
case GPBDataTypeDouble:
GPBSetDoubleIvarWithFieldInternal(
self, field, GPBGetMessageDoubleField(other, field), syntax);
GPBSetDoubleIvarWithFieldPrivate(
self, field, GPBGetMessageDoubleField(other, field));
break;
case GPBDataTypeBytes:
case GPBDataTypeString: {
id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field);
GPBSetObjectIvarWithFieldInternal(self, field, otherVal, syntax);
GPBSetObjectIvarWithFieldPrivate(self, field, otherVal);
break;
}
case GPBDataTypeMessage:
@ -2532,8 +2521,7 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream(
[message mergeFrom:otherVal];
} else {
GPBMessage *message = [otherVal copy];
GPBSetRetainedObjectIvarWithFieldInternal(self, field, message,
syntax);
GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message);
}
break;
}
@ -2547,17 +2535,17 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream(
GPBDataType fieldDataType = field->description_->dataType;
if (GPBDataTypeIsObject(fieldDataType)) {
NSMutableArray *resultArray =
GetOrCreateArrayIvarWithField(self, field, syntax);
GetOrCreateArrayIvarWithField(self, field);
[resultArray addObjectsFromArray:otherArray];
} else if (fieldDataType == GPBDataTypeEnum) {
GPBEnumArray *resultArray =
GetOrCreateArrayIvarWithField(self, field, syntax);
GetOrCreateArrayIvarWithField(self, field);
[resultArray addRawValuesFromArray:otherArray];
} else {
// The array type doesn't matter, that all implement
// -addValuesFromArray:.
GPBInt32Array *resultArray =
GetOrCreateArrayIvarWithField(self, field, syntax);
GetOrCreateArrayIvarWithField(self, field);
[resultArray addValuesFromArray:otherArray];
}
}
@ -2571,19 +2559,19 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream(
if (GPBDataTypeIsObject(keyDataType) &&
GPBDataTypeIsObject(valueDataType)) {
NSMutableDictionary *resultDict =
GetOrCreateMapIvarWithField(self, field, syntax);
GetOrCreateMapIvarWithField(self, field);
[resultDict addEntriesFromDictionary:otherDict];
} else if (valueDataType == GPBDataTypeEnum) {
// The exact type doesn't matter, just need to know it is a
// GPB*EnumDictionary.
GPBInt32EnumDictionary *resultDict =
GetOrCreateMapIvarWithField(self, field, syntax);
GetOrCreateMapIvarWithField(self, field);
[resultDict addRawEntriesFromDictionary:otherDict];
} else {
// The exact type doesn't matter, they all implement
// -addEntriesFromDictionary:.
GPBInt32Int32Dictionary *resultDict =
GetOrCreateMapIvarWithField(self, field, syntax);
GetOrCreateMapIvarWithField(self, field);
[resultDict addEntriesFromDictionary:otherDict];
}
}
@ -3115,14 +3103,13 @@ static void ResolveIvarGet(__unsafe_unretained GPBFieldDescriptor *field,
// See comment about __unsafe_unretained on ResolveIvarGet.
static void ResolveIvarSet(__unsafe_unretained GPBFieldDescriptor *field,
GPBFileSyntax syntax,
ResolveIvarAccessorMethodResult *result) {
GPBDataType fieldDataType = GPBGetFieldDataType(field);
switch (fieldDataType) {
#define CASE_SET(NAME, TYPE, TRUE_NAME) \
case GPBDataType##NAME: { \
result->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) { \
return GPBSet##TRUE_NAME##IvarWithFieldInternal(obj, field, value, syntax); \
return GPBSet##TRUE_NAME##IvarWithFieldPrivate(obj, field, value); \
}); \
result->encodingSelector = @selector(set##NAME:); \
break; \
@ -3130,7 +3117,7 @@ static void ResolveIvarSet(__unsafe_unretained GPBFieldDescriptor *field,
#define CASE_SET_COPY(NAME) \
case GPBDataType##NAME: { \
result->impToAdd = imp_implementationWithBlock(^(id obj, id value) { \
return GPBSetRetainedObjectIvarWithFieldInternal(obj, field, [value copy], syntax); \
return GPBSetRetainedObjectIvarWithFieldPrivate(obj, field, [value copy]); \
}); \
result->encodingSelector = @selector(set##NAME:); \
break; \
@ -3177,7 +3164,7 @@ static void ResolveIvarSet(__unsafe_unretained GPBFieldDescriptor *field,
ResolveIvarGet(field, &result);
break;
} else if (sel == field->setSel_) {
ResolveIvarSet(field, descriptor.file.syntax, &result);
ResolveIvarSet(field, &result);
break;
} else if (sel == field->hasOrCountSel_) {
int32_t index = GPBFieldHasIndex(field);
@ -3227,9 +3214,8 @@ static void ResolveIvarSet(__unsafe_unretained GPBFieldDescriptor *field,
} else if (sel == field->setSel_) {
// Local for syntax so the block can directly capture it and not the
// full lookup.
const GPBFileSyntax syntax = descriptor.file.syntax;
result.impToAdd = imp_implementationWithBlock(^(id obj, id value) {
GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax);
GPBSetObjectIvarWithFieldPrivate(obj, field, value);
});
result.encodingSelector = @selector(setArray:);
break;
@ -3334,9 +3320,7 @@ id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field) {
[self class], field.name];
}
#endif
GPBDescriptor *descriptor = [[self class] descriptor];
GPBFileSyntax syntax = descriptor.file.syntax;
return GetOrCreateArrayIvarWithField(self, field, syntax);
return GetOrCreateArrayIvarWithField(self, field);
}
// Only exists for public api, no core code should use this.
@ -3348,9 +3332,7 @@ id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field) {
[self class], field.name];
}
#endif
GPBDescriptor *descriptor = [[self class] descriptor];
GPBFileSyntax syntax = descriptor.file.syntax;
return GetOrCreateMapIvarWithField(self, field, syntax);
return GetOrCreateMapIvarWithField(self, field);
}
id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {

@ -17,10 +17,10 @@
#import "GPBRootObject.h"
#endif
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
#endif

@ -70,7 +70,7 @@ typedef struct GPBSourceContext__storage_ {
.number = GPBSourceContext_FieldNumber_FileName,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBSourceContext__storage_, fileName),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeString,
},
};
@ -81,7 +81,7 @@ typedef struct GPBSourceContext__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBSourceContext__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG

@ -17,10 +17,10 @@
#import "GPBRootObject.h"
#endif
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
#endif

@ -126,7 +126,7 @@ typedef struct GPBStruct__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBStruct__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
@ -226,7 +226,7 @@ typedef struct GPBValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBValue__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
static const char *oneofs[] = {
"kind",
};
@ -246,19 +246,19 @@ typedef struct GPBValue__storage_ {
int32_t GPBValue_NullValue_RawValue(GPBValue *message) {
GPBDescriptor *descriptor = [GPBValue descriptor];
GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue];
return GPBGetMessageInt32Field(message, field);
return GPBGetMessageRawEnumField(message, field);
}
void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value) {
GPBDescriptor *descriptor = [GPBValue descriptor];
GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue];
GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
GPBSetMessageRawEnumField(message, field, value);
}
void GPBValue_ClearKindOneOfCase(GPBValue *message) {
GPBDescriptor *descriptor = [message descriptor];
GPBDescriptor *descriptor = [GPBValue descriptor];
GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:0];
GPBMaybeClearOneof(message, oneof, -1, 0);
GPBClearOneof(message, oneof);
}
#pragma mark - GPBListValue
@ -294,7 +294,7 @@ typedef struct GPBListValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBListValue__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG

@ -17,10 +17,10 @@
#import "GPBRootObject.h"
#endif
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
#endif

@ -72,7 +72,7 @@ typedef struct GPBTimestamp__storage_ {
.number = GPBTimestamp_FieldNumber_Seconds,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBTimestamp__storage_, seconds),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeInt64,
},
{
@ -81,7 +81,7 @@ typedef struct GPBTimestamp__storage_ {
.number = GPBTimestamp_FieldNumber_Nanos,
.hasIndex = 1,
.offset = (uint32_t)offsetof(GPBTimestamp__storage_, nanos),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeInt32,
},
};
@ -92,7 +92,7 @@ typedef struct GPBTimestamp__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBTimestamp__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG

@ -17,10 +17,10 @@
#import "GPBRootObject.h"
#endif
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
#endif

@ -132,7 +132,7 @@ typedef struct GPBType__storage_ {
.number = GPBType_FieldNumber_Name,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBType__storage_, name),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeString,
},
{
@ -177,7 +177,7 @@ typedef struct GPBType__storage_ {
.number = GPBType_FieldNumber_Syntax,
.hasIndex = 2,
.offset = (uint32_t)offsetof(GPBType__storage_, syntax),
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor),
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeEnum,
},
};
@ -188,7 +188,7 @@ typedef struct GPBType__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBType__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
@ -202,13 +202,13 @@ typedef struct GPBType__storage_ {
int32_t GPBType_Syntax_RawValue(GPBType *message) {
GPBDescriptor *descriptor = [GPBType descriptor];
GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBType_FieldNumber_Syntax];
return GPBGetMessageInt32Field(message, field);
return GPBGetMessageRawEnumField(message, field);
}
void SetGPBType_Syntax_RawValue(GPBType *message, int32_t value) {
GPBDescriptor *descriptor = [GPBType descriptor];
GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBType_FieldNumber_Syntax];
GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
GPBSetMessageRawEnumField(message, field, value);
}
#pragma mark - GPBField
@ -251,7 +251,7 @@ typedef struct GPBField__storage_ {
.number = GPBField_FieldNumber_Kind,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBField__storage_, kind),
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor),
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeEnum,
},
{
@ -260,7 +260,7 @@ typedef struct GPBField__storage_ {
.number = GPBField_FieldNumber_Cardinality,
.hasIndex = 1,
.offset = (uint32_t)offsetof(GPBField__storage_, cardinality),
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor),
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeEnum,
},
{
@ -269,7 +269,7 @@ typedef struct GPBField__storage_ {
.number = GPBField_FieldNumber_Number,
.hasIndex = 2,
.offset = (uint32_t)offsetof(GPBField__storage_, number),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeInt32,
},
{
@ -278,7 +278,7 @@ typedef struct GPBField__storage_ {
.number = GPBField_FieldNumber_Name,
.hasIndex = 3,
.offset = (uint32_t)offsetof(GPBField__storage_, name),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeString,
},
{
@ -287,7 +287,7 @@ typedef struct GPBField__storage_ {
.number = GPBField_FieldNumber_TypeURL,
.hasIndex = 4,
.offset = (uint32_t)offsetof(GPBField__storage_, typeURL),
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom),
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeString,
},
{
@ -296,7 +296,7 @@ typedef struct GPBField__storage_ {
.number = GPBField_FieldNumber_OneofIndex,
.hasIndex = 5,
.offset = (uint32_t)offsetof(GPBField__storage_, oneofIndex),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeInt32,
},
{
@ -305,7 +305,7 @@ typedef struct GPBField__storage_ {
.number = GPBField_FieldNumber_Packed,
.hasIndex = 6,
.offset = 7, // Stored in _has_storage_ to save space.
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeBool,
},
{
@ -323,7 +323,7 @@ typedef struct GPBField__storage_ {
.number = GPBField_FieldNumber_JsonName,
.hasIndex = 8,
.offset = (uint32_t)offsetof(GPBField__storage_, jsonName),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeString,
},
{
@ -332,7 +332,7 @@ typedef struct GPBField__storage_ {
.number = GPBField_FieldNumber_DefaultValue,
.hasIndex = 9,
.offset = (uint32_t)offsetof(GPBField__storage_, defaultValue),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeString,
},
};
@ -343,7 +343,7 @@ typedef struct GPBField__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBField__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
static const char *extraTextFormatInfo =
"\001\006\004\241!!\000";
@ -362,25 +362,25 @@ typedef struct GPBField__storage_ {
int32_t GPBField_Kind_RawValue(GPBField *message) {
GPBDescriptor *descriptor = [GPBField descriptor];
GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind];
return GPBGetMessageInt32Field(message, field);
return GPBGetMessageRawEnumField(message, field);
}
void SetGPBField_Kind_RawValue(GPBField *message, int32_t value) {
GPBDescriptor *descriptor = [GPBField descriptor];
GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind];
GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
GPBSetMessageRawEnumField(message, field, value);
}
int32_t GPBField_Cardinality_RawValue(GPBField *message) {
GPBDescriptor *descriptor = [GPBField descriptor];
GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality];
return GPBGetMessageInt32Field(message, field);
return GPBGetMessageRawEnumField(message, field);
}
void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value) {
GPBDescriptor *descriptor = [GPBField descriptor];
GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality];
GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
GPBSetMessageRawEnumField(message, field, value);
}
#pragma mark - Enum GPBField_Kind
@ -528,7 +528,7 @@ typedef struct GPBEnum__storage_ {
.number = GPBEnum_FieldNumber_Name,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBEnum__storage_, name),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeString,
},
{
@ -564,7 +564,7 @@ typedef struct GPBEnum__storage_ {
.number = GPBEnum_FieldNumber_Syntax,
.hasIndex = 2,
.offset = (uint32_t)offsetof(GPBEnum__storage_, syntax),
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor),
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeEnum,
},
};
@ -575,7 +575,7 @@ typedef struct GPBEnum__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBEnum__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
@ -589,13 +589,13 @@ typedef struct GPBEnum__storage_ {
int32_t GPBEnum_Syntax_RawValue(GPBEnum *message) {
GPBDescriptor *descriptor = [GPBEnum descriptor];
GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBEnum_FieldNumber_Syntax];
return GPBGetMessageInt32Field(message, field);
return GPBGetMessageRawEnumField(message, field);
}
void SetGPBEnum_Syntax_RawValue(GPBEnum *message, int32_t value) {
GPBDescriptor *descriptor = [GPBEnum descriptor];
GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBEnum_FieldNumber_Syntax];
GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);
GPBSetMessageRawEnumField(message, field, value);
}
#pragma mark - GPBEnumValue
@ -625,7 +625,7 @@ typedef struct GPBEnumValue__storage_ {
.number = GPBEnumValue_FieldNumber_Name,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBEnumValue__storage_, name),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeString,
},
{
@ -634,7 +634,7 @@ typedef struct GPBEnumValue__storage_ {
.number = GPBEnumValue_FieldNumber_Number,
.hasIndex = 1,
.offset = (uint32_t)offsetof(GPBEnumValue__storage_, number),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeInt32,
},
{
@ -654,7 +654,7 @@ typedef struct GPBEnumValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBEnumValue__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
@ -690,7 +690,7 @@ typedef struct GPBOption__storage_ {
.number = GPBOption_FieldNumber_Name,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBOption__storage_, name),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeString,
},
{
@ -710,7 +710,7 @@ typedef struct GPBOption__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBOption__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG

@ -34,6 +34,8 @@
#import "GPBMessage.h"
#import "GPBRuntimeTypes.h"
@class GPBOneofDescriptor;
CF_EXTERN_C_BEGIN
NS_ASSUME_NONNULL_BEGIN
@ -92,6 +94,14 @@ BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field);
**/
void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field);
/**
* Clears the given oneof field for the given message.
*
* @param self The message for which to clear the field.
* @param oneof The oneof to clear.
**/
void GPBClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof);
//%PDDM-EXPAND GPB_ACCESSORS()
// This block of code is generated, do not edit it directly.
// clang-format off

@ -62,6 +62,12 @@ static GPBDataType BaseDataType(GPBDataType type) __attribute__ ((unused));
// Marked unused because currently only called from asserts/debug.
static NSString *TypeToString(GPBDataType dataType) __attribute__ ((unused));
// Helper for clearing oneofs.
static void GPBMaybeClearOneofPrivate(GPBMessage *self,
GPBOneofDescriptor *oneof,
int32_t oneofHasIndex,
uint32_t fieldNumberNotToClear);
NSData *GPBEmptyNSData(void) {
static dispatch_once_t onceToken;
static NSData *defaultNSData = nil;
@ -267,17 +273,28 @@ void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field) {
return;
}
GPBMessageFieldDescription *fieldDesc = field->description_;
if (GPBFieldStoresObject(field)) {
// Object types are handled slightly differently, they need to be released.
uint8_t *storage = (uint8_t *)self->messageStorage_;
id *typePtr = (id *)&storage[field->description_->offset];
id *typePtr = (id *)&storage[fieldDesc->offset];
[*typePtr release];
*typePtr = nil;
} else {
// POD types just need to clear the has bit as the Get* method will
// fetch the default when needed.
}
GPBSetHasIvarField(self, field, NO);
GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, NO);
}
void GPBClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof) {
#if defined(DEBUG) && DEBUG
NSCAssert([[self descriptor] oneofWithName:oneof.name] == oneof,
@"OneofDescriptor %@ doesn't appear to be for %@ messages.",
oneof.name, [self class]);
#endif
GPBFieldDescriptor *firstField = oneof->fields_[0];
GPBMaybeClearOneofPrivate(self, oneof, firstField->description_->hasIndex, 0);
}
BOOL GPBGetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber) {
@ -324,8 +341,10 @@ void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber,
}
}
void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
int32_t oneofHasIndex, uint32_t fieldNumberNotToClear) {
static void GPBMaybeClearOneofPrivate(GPBMessage *self,
GPBOneofDescriptor *oneof,
int32_t oneofHasIndex,
uint32_t fieldNumberNotToClear) {
uint32_t fieldNumberSet = GPBGetHasOneof(self, oneofHasIndex);
if ((fieldNumberSet == fieldNumberNotToClear) || (fieldNumberSet == 0)) {
// Do nothing/nothing set in the oneof.
@ -356,6 +375,9 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
//%TYPE GPBGetMessage##NAME##Field(GPBMessage *self,
//% TYPE$S NAME$S GPBFieldDescriptor *field) {
//%#if defined(DEBUG) && DEBUG
//% NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
//% @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
//% field.name, [self class]);
//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
//% GPBDataType##NAME),
//% @"Attempting to get value of TYPE from field %@ "
@ -377,15 +399,10 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
//% NAME$S GPBFieldDescriptor *field,
//% NAME$S TYPE value) {
//% if (self == nil || field == nil) return;
//% GPBFileSyntax syntax = [self descriptor].file.syntax;
//% GPBSet##NAME##IvarWithFieldInternal(self, field, value, syntax);
//%}
//%
//%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self,
//% NAME$S GPBFieldDescriptor *field,
//% NAME$S TYPE value,
//% NAME$S GPBFileSyntax syntax) {
//%#if defined(DEBUG) && DEBUG
//% NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
//% @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
//% field.name, [self class]);
//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
//% GPBDataType##NAME),
//% @"Attempting to set field %@ of %@ which is of type %@ with "
@ -393,10 +410,16 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
//% [self class], field.name,
//% TypeToString(GPBGetFieldDataType(field)));
//%#endif
//% GPBSet##NAME##IvarWithFieldPrivate(self, field, value);
//%}
//%
//%void GPBSet##NAME##IvarWithFieldPrivate(GPBMessage *self,
//% NAME$S GPBFieldDescriptor *field,
//% NAME$S TYPE value) {
//% GPBOneofDescriptor *oneof = field->containingOneof_;
//% GPBMessageFieldDescription *fieldDesc = field->description_;
//% if (oneof) {
//% GPBMessageFieldDescription *fieldDesc = field->description_;
//% GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
//% GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
//% }
//%#if defined(DEBUG) && DEBUG
//% NSCAssert(self->messageStorage_ != NULL,
@ -407,14 +430,13 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
//% if (self->messageStorage_ == NULL) return;
//%#endif
//% uint8_t *storage = (uint8_t *)self->messageStorage_;
//% TYPE *typePtr = (TYPE *)&storage[field->description_->offset];
//% TYPE *typePtr = (TYPE *)&storage[fieldDesc->offset];
//% *typePtr = value;
//% // proto2: any value counts as having been set; proto3, it
//% // has to be a non zero value or be in a oneof.
//% BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
//% || (value != (TYPE)0)
//% || (field->containingOneof_ != NULL));
//% GPBSetHasIvarField(self, field, hasValue);
//% // If the value is zero, then we only count the field as "set" if the field
//% // shouldn't auto clear on zero.
//% BOOL hasValue = ((value != (TYPE)0)
//% || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
//% GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
//% GPBBecomeVisibleToAutocreator(self);
//%}
//%
@ -508,16 +530,14 @@ void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self,
static void GPBSetObjectIvarWithField(GPBMessage *self,
GPBFieldDescriptor *field, id value) {
if (self == nil || field == nil) return;
GPBFileSyntax syntax = [self descriptor].file.syntax;
GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain],
syntax);
GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value retain]);
}
static void GPBSetCopyObjectIvarWithField(GPBMessage *self,
GPBFieldDescriptor *field, id value);
// GPBSetCopyObjectIvarWithField is blocked from the analyzer because it flags
// a leak for the -copy even though GPBSetRetainedObjectIvarWithFieldInternal
// a leak for the -copy even though GPBSetRetainedObjectIvarWithFieldPrivate
// is marked as consuming the value. Note: For some reason this doesn't happen
// with the -retain in GPBSetObjectIvarWithField.
#if !defined(__clang_analyzer__)
@ -525,22 +545,18 @@ static void GPBSetCopyObjectIvarWithField(GPBMessage *self,
static void GPBSetCopyObjectIvarWithField(GPBMessage *self,
GPBFieldDescriptor *field, id value) {
if (self == nil || field == nil) return;
GPBFileSyntax syntax = [self descriptor].file.syntax;
GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value copy],
syntax);
GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value copy]);
}
#endif // !defined(__clang_analyzer__)
void GPBSetObjectIvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field, id value,
GPBFileSyntax syntax) {
GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain],
syntax);
void GPBSetObjectIvarWithFieldPrivate(GPBMessage *self,
GPBFieldDescriptor *field, id value) {
GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value retain]);
}
void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
id value, GPBFileSyntax syntax) {
void GPBSetRetainedObjectIvarWithFieldPrivate(GPBMessage *self,
GPBFieldDescriptor *field,
id value) {
NSCAssert(self->messageStorage_ != NULL,
@"%@: All messages should have storage (from init)",
[self class]);
@ -579,39 +595,30 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self,
// valueData/valueMessage.
}
#endif // DEBUG
GPBMessageFieldDescription *fieldDesc = field->description_;
if (!isMapOrArray) {
// Non repeated/map can be in an oneof, clear any existing value from the
// oneof.
GPBOneofDescriptor *oneof = field->containingOneof_;
if (oneof) {
GPBMessageFieldDescription *fieldDesc = field->description_;
GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
}
// Clear "has" if they are being set to nil.
BOOL setHasValue = (value != nil);
// Under proto3, Bytes & String fields get cleared by resetting them to
// their default (empty) values, so if they are set to something of length
// zero, they are being cleared.
if ((syntax == GPBFileSyntaxProto3) && !fieldIsMessage &&
// If the field should clear on a "zero" value, then check if the string/data
// was zero length, and clear instead.
if (((fieldDesc->flags & GPBFieldClearHasIvarOnZero) != 0) &&
([value length] == 0)) {
// Except, if the field was in a oneof, then it still gets recorded as
// having been set so the state of the oneof can be serialized back out.
if (!oneof) {
setHasValue = NO;
}
if (setHasValue) {
NSCAssert(value != nil, @"Should never be setting has for nil");
} else {
// The value passed in was retained, it must be released since we
// aren't saving anything in the field.
[value release];
value = nil;
}
setHasValue = NO;
// The value passed in was retained, it must be released since we
// aren't saving anything in the field.
[value release];
value = nil;
}
GPBSetHasIvarField(self, field, setHasValue);
GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, setHasValue);
}
uint8_t *storage = (uint8_t *)self->messageStorage_;
id *typePtr = (id *)&storage[field->description_->offset];
id *typePtr = (id *)&storage[fieldDesc->offset];
id oldValue = *typePtr;
@ -678,23 +685,22 @@ id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self,
// Only exists for public api, no core code should use this.
int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field) {
GPBFileSyntax syntax = [self descriptor].file.syntax;
return GPBGetEnumIvarWithFieldInternal(self, field, syntax);
}
#if defined(DEBUG) && DEBUG
NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
@"FieldDescriptor %@ doesn't appear to be for %@ messages.",
field.name, [self class]);
NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum,
@"Attempting to get value of type Enum from field %@ "
@"of %@ which is of type %@.",
[self class], field.name,
TypeToString(GPBGetFieldDataType(field)));
#endif
int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
GPBFileSyntax syntax) {
#if defined(DEBUG) && DEBUG
NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum,
@"Attempting to get value of type Enum from field %@ "
@"of %@ which is of type %@.",
[self class], field.name,
TypeToString(GPBGetFieldDataType(field)));
#endif
int32_t result = GPBGetMessageInt32Field(self, field);
// If this is presevering unknown enums, make sure the value is valid before
// returning it.
GPBFileSyntax syntax = [self descriptor].file.syntax;
if (GPBHasPreservingUnknownEnumSemantics(syntax) &&
![field isValidEnumValue:result]) {
result = kGPBUnrecognizedEnumeratorValue;
@ -705,27 +711,28 @@ int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self,
// Only exists for public api, no core code should use this.
void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field,
int32_t value) {
GPBFileSyntax syntax = [self descriptor].file.syntax;
GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
}
void GPBSetEnumIvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field, int32_t value,
GPBFileSyntax syntax) {
#if defined(DEBUG) && DEBUG
NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum,
@"Attempting to set field %@ of %@ which is of type %@ with "
@"value of type Enum.",
[self class], field.name,
TypeToString(GPBGetFieldDataType(field)));
#endif
#if defined(DEBUG) && DEBUG
NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
@"FieldDescriptor %@ doesn't appear to be for %@ messages.",
field.name, [self class]);
NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum,
@"Attempting to set field %@ of %@ which is of type %@ with "
@"value of type Enum.",
[self class], field.name,
TypeToString(GPBGetFieldDataType(field)));
#endif
GPBSetEnumIvarWithFieldPrivate(self, field, value);
}
void GPBSetEnumIvarWithFieldPrivate(GPBMessage *self,
GPBFieldDescriptor *field, int32_t value) {
// Don't allow in unknown values. Proto3 can use the Raw method.
if (![field isValidEnumValue:value]) {
[NSException raise:NSInvalidArgumentException
format:@"%@.%@: Attempt to set an unknown enum value (%d)",
[self class], field.name, value];
}
GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
GPBSetInt32IvarWithFieldPrivate(self, field, value);
}
// Only exists for public api, no core code should use this.
@ -738,13 +745,15 @@ int32_t GPBGetMessageRawEnumField(GPBMessage *self,
// Only exists for public api, no core code should use this.
void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field,
int32_t value) {
GPBFileSyntax syntax = [self descriptor].file.syntax;
GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
GPBSetInt32IvarWithFieldPrivate(self, field, value);
}
BOOL GPBGetMessageBoolField(GPBMessage *self,
GPBFieldDescriptor *field) {
#if defined(DEBUG) && DEBUG
NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
@"FieldDescriptor %@ doesn't appear to be for %@ messages.",
field.name, [self class]);
NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool),
@"Attempting to get value of type bool from field %@ "
@"of %@ which is of type %@.",
@ -768,25 +777,26 @@ void GPBSetMessageBoolField(GPBMessage *self,
GPBFieldDescriptor *field,
BOOL value) {
if (self == nil || field == nil) return;
GPBFileSyntax syntax = [self descriptor].file.syntax;
GPBSetBoolIvarWithFieldInternal(self, field, value, syntax);
}
void GPBSetBoolIvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
BOOL value,
GPBFileSyntax syntax) {
#if defined(DEBUG) && DEBUG
NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool),
@"Attempting to set field %@ of %@ which is of type %@ with "
@"value of type bool.",
[self class], field.name,
TypeToString(GPBGetFieldDataType(field)));
#endif
#if defined(DEBUG) && DEBUG
NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
@"FieldDescriptor %@ doesn't appear to be for %@ messages.",
field.name, [self class]);
NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool),
@"Attempting to set field %@ of %@ which is of type %@ with "
@"value of type bool.",
[self class], field.name,
TypeToString(GPBGetFieldDataType(field)));
#endif
GPBSetBoolIvarWithFieldPrivate(self, field, value);
}
void GPBSetBoolIvarWithFieldPrivate(GPBMessage *self,
GPBFieldDescriptor *field,
BOOL value) {
GPBMessageFieldDescription *fieldDesc = field->description_;
GPBOneofDescriptor *oneof = field->containingOneof_;
if (oneof) {
GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
}
// Bools are stored in the has bits to avoid needing explicit space in the
@ -795,12 +805,11 @@ void GPBSetBoolIvarWithFieldInternal(GPBMessage *self,
// the offset is never negative)
GPBSetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number, value);
// proto2: any value counts as having been set; proto3, it
// has to be a non zero value or be in a oneof.
BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
|| (value != (BOOL)0)
|| (field->containingOneof_ != NULL));
GPBSetHasIvarField(self, field, hasValue);
// If the value is zero, then we only count the field as "set" if the field
// shouldn't auto clear on zero.
BOOL hasValue = ((value != (BOOL)0)
|| ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
GPBBecomeVisibleToAutocreator(self);
}
@ -811,6 +820,9 @@ void GPBSetBoolIvarWithFieldInternal(GPBMessage *self,
int32_t GPBGetMessageInt32Field(GPBMessage *self,
GPBFieldDescriptor *field) {
#if defined(DEBUG) && DEBUG
NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
@"FieldDescriptor %@ doesn't appear to be for %@ messages.",
field.name, [self class]);
NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
GPBDataTypeInt32),
@"Attempting to get value of int32_t from field %@ "
@ -832,15 +844,10 @@ void GPBSetMessageInt32Field(GPBMessage *self,
GPBFieldDescriptor *field,
int32_t value) {
if (self == nil || field == nil) return;
GPBFileSyntax syntax = [self descriptor].file.syntax;
GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
}
void GPBSetInt32IvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
int32_t value,
GPBFileSyntax syntax) {
#if defined(DEBUG) && DEBUG
NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
@"FieldDescriptor %@ doesn't appear to be for %@ messages.",
field.name, [self class]);
NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
GPBDataTypeInt32),
@"Attempting to set field %@ of %@ which is of type %@ with "
@ -848,10 +855,16 @@ void GPBSetInt32IvarWithFieldInternal(GPBMessage *self,
[self class], field.name,
TypeToString(GPBGetFieldDataType(field)));
#endif
GPBSetInt32IvarWithFieldPrivate(self, field, value);
}
void GPBSetInt32IvarWithFieldPrivate(GPBMessage *self,
GPBFieldDescriptor *field,
int32_t value) {
GPBOneofDescriptor *oneof = field->containingOneof_;
GPBMessageFieldDescription *fieldDesc = field->description_;
if (oneof) {
GPBMessageFieldDescription *fieldDesc = field->description_;
GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
}
#if defined(DEBUG) && DEBUG
NSCAssert(self->messageStorage_ != NULL,
@ -862,14 +875,13 @@ void GPBSetInt32IvarWithFieldInternal(GPBMessage *self,
if (self->messageStorage_ == NULL) return;
#endif
uint8_t *storage = (uint8_t *)self->messageStorage_;
int32_t *typePtr = (int32_t *)&storage[field->description_->offset];
int32_t *typePtr = (int32_t *)&storage[fieldDesc->offset];
*typePtr = value;
// proto2: any value counts as having been set; proto3, it
// has to be a non zero value or be in a oneof.
BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
|| (value != (int32_t)0)
|| (field->containingOneof_ != NULL));
GPBSetHasIvarField(self, field, hasValue);
// If the value is zero, then we only count the field as "set" if the field
// shouldn't auto clear on zero.
BOOL hasValue = ((value != (int32_t)0)
|| ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
GPBBecomeVisibleToAutocreator(self);
}
@ -881,6 +893,9 @@ void GPBSetInt32IvarWithFieldInternal(GPBMessage *self,
uint32_t GPBGetMessageUInt32Field(GPBMessage *self,
GPBFieldDescriptor *field) {
#if defined(DEBUG) && DEBUG
NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
@"FieldDescriptor %@ doesn't appear to be for %@ messages.",
field.name, [self class]);
NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
GPBDataTypeUInt32),
@"Attempting to get value of uint32_t from field %@ "
@ -902,15 +917,10 @@ void GPBSetMessageUInt32Field(GPBMessage *self,
GPBFieldDescriptor *field,
uint32_t value) {
if (self == nil || field == nil) return;
GPBFileSyntax syntax = [self descriptor].file.syntax;
GPBSetUInt32IvarWithFieldInternal(self, field, value, syntax);
}
void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
uint32_t value,
GPBFileSyntax syntax) {
#if defined(DEBUG) && DEBUG
NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
@"FieldDescriptor %@ doesn't appear to be for %@ messages.",
field.name, [self class]);
NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
GPBDataTypeUInt32),
@"Attempting to set field %@ of %@ which is of type %@ with "
@ -918,10 +928,16 @@ void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self,
[self class], field.name,
TypeToString(GPBGetFieldDataType(field)));
#endif
GPBSetUInt32IvarWithFieldPrivate(self, field, value);
}
void GPBSetUInt32IvarWithFieldPrivate(GPBMessage *self,
GPBFieldDescriptor *field,
uint32_t value) {
GPBOneofDescriptor *oneof = field->containingOneof_;
GPBMessageFieldDescription *fieldDesc = field->description_;
if (oneof) {
GPBMessageFieldDescription *fieldDesc = field->description_;
GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
}
#if defined(DEBUG) && DEBUG
NSCAssert(self->messageStorage_ != NULL,
@ -932,14 +948,13 @@ void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self,
if (self->messageStorage_ == NULL) return;
#endif
uint8_t *storage = (uint8_t *)self->messageStorage_;
uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset];
uint32_t *typePtr = (uint32_t *)&storage[fieldDesc->offset];
*typePtr = value;
// proto2: any value counts as having been set; proto3, it
// has to be a non zero value or be in a oneof.
BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
|| (value != (uint32_t)0)
|| (field->containingOneof_ != NULL));
GPBSetHasIvarField(self, field, hasValue);
// If the value is zero, then we only count the field as "set" if the field
// shouldn't auto clear on zero.
BOOL hasValue = ((value != (uint32_t)0)
|| ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
GPBBecomeVisibleToAutocreator(self);
}
@ -951,6 +966,9 @@ void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self,
int64_t GPBGetMessageInt64Field(GPBMessage *self,
GPBFieldDescriptor *field) {
#if defined(DEBUG) && DEBUG
NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
@"FieldDescriptor %@ doesn't appear to be for %@ messages.",
field.name, [self class]);
NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
GPBDataTypeInt64),
@"Attempting to get value of int64_t from field %@ "
@ -972,15 +990,10 @@ void GPBSetMessageInt64Field(GPBMessage *self,
GPBFieldDescriptor *field,
int64_t value) {
if (self == nil || field == nil) return;
GPBFileSyntax syntax = [self descriptor].file.syntax;
GPBSetInt64IvarWithFieldInternal(self, field, value, syntax);
}
void GPBSetInt64IvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
int64_t value,
GPBFileSyntax syntax) {
#if defined(DEBUG) && DEBUG
NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
@"FieldDescriptor %@ doesn't appear to be for %@ messages.",
field.name, [self class]);
NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
GPBDataTypeInt64),
@"Attempting to set field %@ of %@ which is of type %@ with "
@ -988,10 +1001,16 @@ void GPBSetInt64IvarWithFieldInternal(GPBMessage *self,
[self class], field.name,
TypeToString(GPBGetFieldDataType(field)));
#endif
GPBSetInt64IvarWithFieldPrivate(self, field, value);
}
void GPBSetInt64IvarWithFieldPrivate(GPBMessage *self,
GPBFieldDescriptor *field,
int64_t value) {
GPBOneofDescriptor *oneof = field->containingOneof_;
GPBMessageFieldDescription *fieldDesc = field->description_;
if (oneof) {
GPBMessageFieldDescription *fieldDesc = field->description_;
GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
}
#if defined(DEBUG) && DEBUG
NSCAssert(self->messageStorage_ != NULL,
@ -1002,14 +1021,13 @@ void GPBSetInt64IvarWithFieldInternal(GPBMessage *self,
if (self->messageStorage_ == NULL) return;
#endif
uint8_t *storage = (uint8_t *)self->messageStorage_;
int64_t *typePtr = (int64_t *)&storage[field->description_->offset];
int64_t *typePtr = (int64_t *)&storage[fieldDesc->offset];
*typePtr = value;
// proto2: any value counts as having been set; proto3, it
// has to be a non zero value or be in a oneof.
BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
|| (value != (int64_t)0)
|| (field->containingOneof_ != NULL));
GPBSetHasIvarField(self, field, hasValue);
// If the value is zero, then we only count the field as "set" if the field
// shouldn't auto clear on zero.
BOOL hasValue = ((value != (int64_t)0)
|| ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
GPBBecomeVisibleToAutocreator(self);
}
@ -1021,6 +1039,9 @@ void GPBSetInt64IvarWithFieldInternal(GPBMessage *self,
uint64_t GPBGetMessageUInt64Field(GPBMessage *self,
GPBFieldDescriptor *field) {
#if defined(DEBUG) && DEBUG
NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
@"FieldDescriptor %@ doesn't appear to be for %@ messages.",
field.name, [self class]);
NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
GPBDataTypeUInt64),
@"Attempting to get value of uint64_t from field %@ "
@ -1042,15 +1063,10 @@ void GPBSetMessageUInt64Field(GPBMessage *self,
GPBFieldDescriptor *field,
uint64_t value) {
if (self == nil || field == nil) return;
GPBFileSyntax syntax = [self descriptor].file.syntax;
GPBSetUInt64IvarWithFieldInternal(self, field, value, syntax);
}
void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
uint64_t value,
GPBFileSyntax syntax) {
#if defined(DEBUG) && DEBUG
NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
@"FieldDescriptor %@ doesn't appear to be for %@ messages.",
field.name, [self class]);
NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
GPBDataTypeUInt64),
@"Attempting to set field %@ of %@ which is of type %@ with "
@ -1058,10 +1074,16 @@ void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self,
[self class], field.name,
TypeToString(GPBGetFieldDataType(field)));
#endif
GPBSetUInt64IvarWithFieldPrivate(self, field, value);
}
void GPBSetUInt64IvarWithFieldPrivate(GPBMessage *self,
GPBFieldDescriptor *field,
uint64_t value) {
GPBOneofDescriptor *oneof = field->containingOneof_;
GPBMessageFieldDescription *fieldDesc = field->description_;
if (oneof) {
GPBMessageFieldDescription *fieldDesc = field->description_;
GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
}
#if defined(DEBUG) && DEBUG
NSCAssert(self->messageStorage_ != NULL,
@ -1072,14 +1094,13 @@ void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self,
if (self->messageStorage_ == NULL) return;
#endif
uint8_t *storage = (uint8_t *)self->messageStorage_;
uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset];
uint64_t *typePtr = (uint64_t *)&storage[fieldDesc->offset];
*typePtr = value;
// proto2: any value counts as having been set; proto3, it
// has to be a non zero value or be in a oneof.
BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
|| (value != (uint64_t)0)
|| (field->containingOneof_ != NULL));
GPBSetHasIvarField(self, field, hasValue);
// If the value is zero, then we only count the field as "set" if the field
// shouldn't auto clear on zero.
BOOL hasValue = ((value != (uint64_t)0)
|| ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
GPBBecomeVisibleToAutocreator(self);
}
@ -1091,6 +1112,9 @@ void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self,
float GPBGetMessageFloatField(GPBMessage *self,
GPBFieldDescriptor *field) {
#if defined(DEBUG) && DEBUG
NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
@"FieldDescriptor %@ doesn't appear to be for %@ messages.",
field.name, [self class]);
NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
GPBDataTypeFloat),
@"Attempting to get value of float from field %@ "
@ -1112,15 +1136,10 @@ void GPBSetMessageFloatField(GPBMessage *self,
GPBFieldDescriptor *field,
float value) {
if (self == nil || field == nil) return;
GPBFileSyntax syntax = [self descriptor].file.syntax;
GPBSetFloatIvarWithFieldInternal(self, field, value, syntax);
}
void GPBSetFloatIvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
float value,
GPBFileSyntax syntax) {
#if defined(DEBUG) && DEBUG
NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
@"FieldDescriptor %@ doesn't appear to be for %@ messages.",
field.name, [self class]);
NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
GPBDataTypeFloat),
@"Attempting to set field %@ of %@ which is of type %@ with "
@ -1128,10 +1147,16 @@ void GPBSetFloatIvarWithFieldInternal(GPBMessage *self,
[self class], field.name,
TypeToString(GPBGetFieldDataType(field)));
#endif
GPBSetFloatIvarWithFieldPrivate(self, field, value);
}
void GPBSetFloatIvarWithFieldPrivate(GPBMessage *self,
GPBFieldDescriptor *field,
float value) {
GPBOneofDescriptor *oneof = field->containingOneof_;
GPBMessageFieldDescription *fieldDesc = field->description_;
if (oneof) {
GPBMessageFieldDescription *fieldDesc = field->description_;
GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
}
#if defined(DEBUG) && DEBUG
NSCAssert(self->messageStorage_ != NULL,
@ -1142,14 +1167,13 @@ void GPBSetFloatIvarWithFieldInternal(GPBMessage *self,
if (self->messageStorage_ == NULL) return;
#endif
uint8_t *storage = (uint8_t *)self->messageStorage_;
float *typePtr = (float *)&storage[field->description_->offset];
float *typePtr = (float *)&storage[fieldDesc->offset];
*typePtr = value;
// proto2: any value counts as having been set; proto3, it
// has to be a non zero value or be in a oneof.
BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
|| (value != (float)0)
|| (field->containingOneof_ != NULL));
GPBSetHasIvarField(self, field, hasValue);
// If the value is zero, then we only count the field as "set" if the field
// shouldn't auto clear on zero.
BOOL hasValue = ((value != (float)0)
|| ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
GPBBecomeVisibleToAutocreator(self);
}
@ -1161,6 +1185,9 @@ void GPBSetFloatIvarWithFieldInternal(GPBMessage *self,
double GPBGetMessageDoubleField(GPBMessage *self,
GPBFieldDescriptor *field) {
#if defined(DEBUG) && DEBUG
NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
@"FieldDescriptor %@ doesn't appear to be for %@ messages.",
field.name, [self class]);
NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
GPBDataTypeDouble),
@"Attempting to get value of double from field %@ "
@ -1182,15 +1209,10 @@ void GPBSetMessageDoubleField(GPBMessage *self,
GPBFieldDescriptor *field,
double value) {
if (self == nil || field == nil) return;
GPBFileSyntax syntax = [self descriptor].file.syntax;
GPBSetDoubleIvarWithFieldInternal(self, field, value, syntax);
}
void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
double value,
GPBFileSyntax syntax) {
#if defined(DEBUG) && DEBUG
NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
@"FieldDescriptor %@ doesn't appear to be for %@ messages.",
field.name, [self class]);
NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
GPBDataTypeDouble),
@"Attempting to set field %@ of %@ which is of type %@ with "
@ -1198,10 +1220,16 @@ void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self,
[self class], field.name,
TypeToString(GPBGetFieldDataType(field)));
#endif
GPBSetDoubleIvarWithFieldPrivate(self, field, value);
}
void GPBSetDoubleIvarWithFieldPrivate(GPBMessage *self,
GPBFieldDescriptor *field,
double value) {
GPBOneofDescriptor *oneof = field->containingOneof_;
GPBMessageFieldDescription *fieldDesc = field->description_;
if (oneof) {
GPBMessageFieldDescription *fieldDesc = field->description_;
GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
}
#if defined(DEBUG) && DEBUG
NSCAssert(self->messageStorage_ != NULL,
@ -1212,14 +1240,13 @@ void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self,
if (self->messageStorage_ == NULL) return;
#endif
uint8_t *storage = (uint8_t *)self->messageStorage_;
double *typePtr = (double *)&storage[field->description_->offset];
double *typePtr = (double *)&storage[fieldDesc->offset];
*typePtr = value;
// proto2: any value counts as having been set; proto3, it
// has to be a non zero value or be in a oneof.
BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
|| (value != (double)0)
|| (field->containingOneof_ != NULL));
GPBSetHasIvarField(self, field, hasValue);
// If the value is zero, then we only count the field as "set" if the field
// shouldn't auto clear on zero.
BOOL hasValue = ((value != (double)0)
|| ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
GPBBecomeVisibleToAutocreator(self);
}
@ -2212,8 +2239,36 @@ NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key,
return result;
}
#pragma mark Legacy methods old generated code calls
// Shim from the older generated code into the runtime.
void GPBSetInt32IvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
int32_t value,
GPBFileSyntax syntax) {
#pragma unused(syntax)
GPBSetMessageInt32Field(self, field, value);
}
void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
int32_t oneofHasIndex, uint32_t fieldNumberNotToClear) {
#pragma unused(fieldNumberNotToClear)
#if defined(DEBUG) && DEBUG
NSCAssert([[self descriptor] oneofWithName:oneof.name] == oneof,
@"OneofDescriptor %@ doesn't appear to be for %@ messages.",
oneof.name, [self class]);
GPBFieldDescriptor *firstField = oneof->fields_[0];
NSCAssert(firstField->description_->hasIndex == oneofHasIndex,
@"Internal error, oneofHasIndex (%d) doesn't match (%d).",
firstField->description_->hasIndex, oneofHasIndex);
#endif
GPBMaybeClearOneofPrivate(self, oneof, oneofHasIndex, 0);
}
#pragma clang diagnostic pop
#pragma mark Misc Helpers
BOOL GPBClassHasSel(Class aClass, SEL sel) {
// NOTE: We have to use class_copyMethodList, all other runtime method
// lookups actually also resolve the method implementation and this

@ -206,110 +206,83 @@ GPBGetHasIvarField(GPBMessage *self, GPBFieldDescriptor *field) {
GPBMessageFieldDescription *fieldDesc = field->description_;
return GPBGetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number);
}
GPB_INLINE void GPBSetHasIvarField(GPBMessage *self, GPBFieldDescriptor *field,
BOOL value) {
GPBMessageFieldDescription *fieldDesc = field->description_;
GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, value);
}
void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
int32_t oneofHasIndex, uint32_t fieldNumberNotToClear);
#pragma clang diagnostic pop
//%PDDM-DEFINE GPB_IVAR_SET_DECL(NAME, TYPE)
//%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self,
//% NAME$S GPBFieldDescriptor *field,
//% NAME$S TYPE value,
//% NAME$S GPBFileSyntax syntax);
//%void GPBSet##NAME##IvarWithFieldPrivate(GPBMessage *self,
//% NAME$S GPBFieldDescriptor *field,
//% NAME$S TYPE value);
//%PDDM-EXPAND GPB_IVAR_SET_DECL(Bool, BOOL)
// This block of code is generated, do not edit it directly.
// clang-format off
void GPBSetBoolIvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
BOOL value,
GPBFileSyntax syntax);
void GPBSetBoolIvarWithFieldPrivate(GPBMessage *self,
GPBFieldDescriptor *field,
BOOL value);
// clang-format on
//%PDDM-EXPAND GPB_IVAR_SET_DECL(Int32, int32_t)
// This block of code is generated, do not edit it directly.
// clang-format off
void GPBSetInt32IvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
int32_t value,
GPBFileSyntax syntax);
void GPBSetInt32IvarWithFieldPrivate(GPBMessage *self,
GPBFieldDescriptor *field,
int32_t value);
// clang-format on
//%PDDM-EXPAND GPB_IVAR_SET_DECL(UInt32, uint32_t)
// This block of code is generated, do not edit it directly.
// clang-format off
void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
uint32_t value,
GPBFileSyntax syntax);
void GPBSetUInt32IvarWithFieldPrivate(GPBMessage *self,
GPBFieldDescriptor *field,
uint32_t value);
// clang-format on
//%PDDM-EXPAND GPB_IVAR_SET_DECL(Int64, int64_t)
// This block of code is generated, do not edit it directly.
// clang-format off
void GPBSetInt64IvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
int64_t value,
GPBFileSyntax syntax);
void GPBSetInt64IvarWithFieldPrivate(GPBMessage *self,
GPBFieldDescriptor *field,
int64_t value);
// clang-format on
//%PDDM-EXPAND GPB_IVAR_SET_DECL(UInt64, uint64_t)
// This block of code is generated, do not edit it directly.
// clang-format off
void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
uint64_t value,
GPBFileSyntax syntax);
void GPBSetUInt64IvarWithFieldPrivate(GPBMessage *self,
GPBFieldDescriptor *field,
uint64_t value);
// clang-format on
//%PDDM-EXPAND GPB_IVAR_SET_DECL(Float, float)
// This block of code is generated, do not edit it directly.
// clang-format off
void GPBSetFloatIvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
float value,
GPBFileSyntax syntax);
void GPBSetFloatIvarWithFieldPrivate(GPBMessage *self,
GPBFieldDescriptor *field,
float value);
// clang-format on
//%PDDM-EXPAND GPB_IVAR_SET_DECL(Double, double)
// This block of code is generated, do not edit it directly.
// clang-format off
void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
double value,
GPBFileSyntax syntax);
// clang-format on
//%PDDM-EXPAND GPB_IVAR_SET_DECL(Enum, int32_t)
// This block of code is generated, do not edit it directly.
// clang-format off
void GPBSetEnumIvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
int32_t value,
GPBFileSyntax syntax);
void GPBSetDoubleIvarWithFieldPrivate(GPBMessage *self,
GPBFieldDescriptor *field,
double value);
// clang-format on
//%PDDM-EXPAND-END (8 expansions)
//%PDDM-EXPAND-END (7 expansions)
int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
GPBFileSyntax syntax);
void GPBSetEnumIvarWithFieldPrivate(GPBMessage *self,
GPBFieldDescriptor *field,
int32_t value);
id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
void GPBSetObjectIvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field, id value,
GPBFileSyntax syntax);
void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
id __attribute__((ns_consumed))
value,
GPBFileSyntax syntax);
void GPBSetObjectIvarWithFieldPrivate(GPBMessage *self,
GPBFieldDescriptor *field, id value);
void GPBSetRetainedObjectIvarWithFieldPrivate(GPBMessage *self,
GPBFieldDescriptor *field,
id __attribute__((ns_consumed))
value);
// GPBGetObjectIvarWithField will automatically create the field (message) if
// it doesn't exist. GPBGetObjectIvarWithFieldNoAutocreate will return nil.
@ -336,6 +309,15 @@ const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel);
NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key,
NSString *inputString);
// Shims from the older generated code into the runtime.
void GPBSetInt32IvarWithFieldInternal(GPBMessage *self,
GPBFieldDescriptor *field,
int32_t value,
GPBFileSyntax syntax);
void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
int32_t oneofHasIndex, uint32_t fieldNumberNotToClear);
// A series of selectors that are used solely to get @encoding values
// for them by the dynamic protobuf runtime code. See
// GPBMessageEncodingForSelector for details. GPBRootObject conforms to

@ -17,10 +17,10 @@
#import "GPBRootObject.h"
#endif
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
#endif
#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.
#endif

@ -70,7 +70,7 @@ typedef struct GPBDoubleValue__storage_ {
.number = GPBDoubleValue_FieldNumber_Value,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBDoubleValue__storage_, value),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeDouble,
},
};
@ -81,7 +81,7 @@ typedef struct GPBDoubleValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBDoubleValue__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
@ -115,7 +115,7 @@ typedef struct GPBFloatValue__storage_ {
.number = GPBFloatValue_FieldNumber_Value,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBFloatValue__storage_, value),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeFloat,
},
};
@ -126,7 +126,7 @@ typedef struct GPBFloatValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBFloatValue__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
@ -160,7 +160,7 @@ typedef struct GPBInt64Value__storage_ {
.number = GPBInt64Value_FieldNumber_Value,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBInt64Value__storage_, value),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeInt64,
},
};
@ -171,7 +171,7 @@ typedef struct GPBInt64Value__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBInt64Value__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
@ -205,7 +205,7 @@ typedef struct GPBUInt64Value__storage_ {
.number = GPBUInt64Value_FieldNumber_Value,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBUInt64Value__storage_, value),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeUInt64,
},
};
@ -216,7 +216,7 @@ typedef struct GPBUInt64Value__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBUInt64Value__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
@ -250,7 +250,7 @@ typedef struct GPBInt32Value__storage_ {
.number = GPBInt32Value_FieldNumber_Value,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBInt32Value__storage_, value),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeInt32,
},
};
@ -261,7 +261,7 @@ typedef struct GPBInt32Value__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBInt32Value__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
@ -295,7 +295,7 @@ typedef struct GPBUInt32Value__storage_ {
.number = GPBUInt32Value_FieldNumber_Value,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBUInt32Value__storage_, value),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeUInt32,
},
};
@ -306,7 +306,7 @@ typedef struct GPBUInt32Value__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBUInt32Value__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
@ -339,7 +339,7 @@ typedef struct GPBBoolValue__storage_ {
.number = GPBBoolValue_FieldNumber_Value,
.hasIndex = 0,
.offset = 1, // Stored in _has_storage_ to save space.
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeBool,
},
};
@ -350,7 +350,7 @@ typedef struct GPBBoolValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBBoolValue__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
@ -384,7 +384,7 @@ typedef struct GPBStringValue__storage_ {
.number = GPBStringValue_FieldNumber_Value,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBStringValue__storage_, value),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeString,
},
};
@ -395,7 +395,7 @@ typedef struct GPBStringValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBStringValue__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
@ -429,7 +429,7 @@ typedef struct GPBBytesValue__storage_ {
.number = GPBBytesValue_FieldNumber_Value,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBBytesValue__storage_, value),
.flags = GPBFieldOptional,
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero),
.dataType = GPBDataTypeBytes,
},
};
@ -440,7 +440,7 @@ typedef struct GPBBytesValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBBytesValue__storage_)
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG

@ -252,7 +252,7 @@
// build the selector, i.e. - repeatedInt32Array_Count
SEL countSel = NSSelectorFromString(
[NSString stringWithFormat:@"repeated%@Array_Count", name]);
XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@",
XCTAssertTrue([Message3 instancesRespondToSelector:countSel], @"field: %@",
name);
}
@ -264,12 +264,29 @@
NSSelectorFromString([NSString stringWithFormat:@"hasOneof%@", name]);
SEL setHasSel = NSSelectorFromString(
[NSString stringWithFormat:@"setHasOneof%@:", name]);
XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@",
XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@",
name);
XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel],
@"field: %@", name);
}
// Single Optional fields
// - has*/setHas* thanks to the optional keyword in proto3, they exist
// for primitive types.
// - has*/setHas* valid for Message.
for (NSString *name in names) {
// build the selector, i.e. - hasOptionalInt32/setHasOptionalInt32:
SEL hasSel = NSSelectorFromString(
[NSString stringWithFormat:@"hasOptional%@", name]);
SEL setHasSel = NSSelectorFromString(
[NSString stringWithFormat:@"setHasOptional%@:", name]);
XCTAssertTrue([Message3Optional instancesRespondToSelector:hasSel], @"field: %@",
name);
XCTAssertTrue([Message3Optional instancesRespondToSelector:setHasSel],
@"field: %@", name);
}
// map<> fields
// - no has*/setHas*
// - *Count
@ -302,14 +319,14 @@
[NSString stringWithFormat:@"hasMap%@", name]);
SEL setHasSel = NSSelectorFromString(
[NSString stringWithFormat:@"setHasMap%@:", name]);
XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@",
XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@",
name);
XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel],
@"field: %@", name);
// build the selector, i.e. - mapInt32Int32Count
SEL countSel = NSSelectorFromString(
[NSString stringWithFormat:@"map%@_Count", name]);
XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@",
XCTAssertTrue([Message3 instancesRespondToSelector:countSel], @"field: %@",
name);
}
}
@ -1002,6 +1019,249 @@
//%PDDM-EXPAND-END PROTO3_TEST_HAS_FIELDS()
}
- (void)testProto3SingleOptionalFieldHasBehavior {
//
// Setting to any value including the default (0) should result in true.
//
//%PDDM-DEFINE PROTO3_TEST_OPTIONAL_HAS_FIELD(FIELD, NON_ZERO_VALUE, ZERO_VALUE)
//% { // optional##FIELD
//% Message3Optional *msg = [[Message3Optional alloc] init];
//% XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_Optional##FIELD));
//% msg.optional##FIELD = NON_ZERO_VALUE;
//% XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_Optional##FIELD));
//% msg.hasOptional##FIELD = NO;
//% XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_Optional##FIELD));
//% msg.optional##FIELD = ZERO_VALUE;
//% XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_Optional##FIELD));
//% [msg release];
//% }
//%
//%PDDM-DEFINE PROTO3_TEST_OPTIONAL_HAS_FIELDS()
//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Int32, 1, 0)
//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Int64, 1, 0)
//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Uint32, 1, 0)
//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Uint64, 1, 0)
//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Sint32, 1, 0)
//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Sint64, 1, 0)
//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Fixed32, 1, 0)
//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Fixed64, 1, 0)
//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Sfixed32, 1, 0)
//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Sfixed64, 1, 0)
//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Float, 1.0f, 0.0f)
//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Double, 1.0, 0.0)
//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Bool, YES, NO)
//%PROTO3_TEST_OPTIONAL_HAS_FIELD(String, @"foo", @"")
//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Bytes, [@"foo" dataUsingEncoding:NSUTF8StringEncoding], [NSData data])
//% //
//% // Test doesn't apply to optionalMessage (no groups in proto3).
//% //
//%
//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Enum, Message3Optional_Enum_Bar, Message3Optional_Enum_Foo)
//%PDDM-EXPAND PROTO3_TEST_OPTIONAL_HAS_FIELDS()
// This block of code is generated, do not edit it directly.
// clang-format off
{ // optionalInt32
Message3Optional *msg = [[Message3Optional alloc] init];
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt32));
msg.optionalInt32 = 1;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt32));
msg.hasOptionalInt32 = NO;
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt32));
msg.optionalInt32 = 0;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt32));
[msg release];
}
{ // optionalInt64
Message3Optional *msg = [[Message3Optional alloc] init];
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt64));
msg.optionalInt64 = 1;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt64));
msg.hasOptionalInt64 = NO;
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt64));
msg.optionalInt64 = 0;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt64));
[msg release];
}
{ // optionalUint32
Message3Optional *msg = [[Message3Optional alloc] init];
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint32));
msg.optionalUint32 = 1;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint32));
msg.hasOptionalUint32 = NO;
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint32));
msg.optionalUint32 = 0;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint32));
[msg release];
}
{ // optionalUint64
Message3Optional *msg = [[Message3Optional alloc] init];
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint64));
msg.optionalUint64 = 1;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint64));
msg.hasOptionalUint64 = NO;
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint64));
msg.optionalUint64 = 0;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint64));
[msg release];
}
{ // optionalSint32
Message3Optional *msg = [[Message3Optional alloc] init];
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint32));
msg.optionalSint32 = 1;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint32));
msg.hasOptionalSint32 = NO;
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint32));
msg.optionalSint32 = 0;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint32));
[msg release];
}
{ // optionalSint64
Message3Optional *msg = [[Message3Optional alloc] init];
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint64));
msg.optionalSint64 = 1;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint64));
msg.hasOptionalSint64 = NO;
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint64));
msg.optionalSint64 = 0;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint64));
[msg release];
}
{ // optionalFixed32
Message3Optional *msg = [[Message3Optional alloc] init];
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed32));
msg.optionalFixed32 = 1;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed32));
msg.hasOptionalFixed32 = NO;
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed32));
msg.optionalFixed32 = 0;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed32));
[msg release];
}
{ // optionalFixed64
Message3Optional *msg = [[Message3Optional alloc] init];
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed64));
msg.optionalFixed64 = 1;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed64));
msg.hasOptionalFixed64 = NO;
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed64));
msg.optionalFixed64 = 0;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed64));
[msg release];
}
{ // optionalSfixed32
Message3Optional *msg = [[Message3Optional alloc] init];
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed32));
msg.optionalSfixed32 = 1;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed32));
msg.hasOptionalSfixed32 = NO;
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed32));
msg.optionalSfixed32 = 0;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed32));
[msg release];
}
{ // optionalSfixed64
Message3Optional *msg = [[Message3Optional alloc] init];
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed64));
msg.optionalSfixed64 = 1;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed64));
msg.hasOptionalSfixed64 = NO;
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed64));
msg.optionalSfixed64 = 0;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed64));
[msg release];
}
{ // optionalFloat
Message3Optional *msg = [[Message3Optional alloc] init];
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFloat));
msg.optionalFloat = 1.0f;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFloat));
msg.hasOptionalFloat = NO;
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFloat));
msg.optionalFloat = 0.0f;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFloat));
[msg release];
}
{ // optionalDouble
Message3Optional *msg = [[Message3Optional alloc] init];
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalDouble));
msg.optionalDouble = 1.0;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalDouble));
msg.hasOptionalDouble = NO;
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalDouble));
msg.optionalDouble = 0.0;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalDouble));
[msg release];
}
{ // optionalBool
Message3Optional *msg = [[Message3Optional alloc] init];
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBool));
msg.optionalBool = YES;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBool));
msg.hasOptionalBool = NO;
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBool));
msg.optionalBool = NO;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBool));
[msg release];
}
{ // optionalString
Message3Optional *msg = [[Message3Optional alloc] init];
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalString));
msg.optionalString = @"foo";
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalString));
msg.hasOptionalString = NO;
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalString));
msg.optionalString = @"";
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalString));
[msg release];
}
{ // optionalBytes
Message3Optional *msg = [[Message3Optional alloc] init];
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBytes));
msg.optionalBytes = [@"foo" dataUsingEncoding:NSUTF8StringEncoding];
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBytes));
msg.hasOptionalBytes = NO;
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBytes));
msg.optionalBytes = [NSData data];
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBytes));
[msg release];
}
//
// Test doesn't apply to optionalMessage (no groups in proto3).
//
{ // optionalEnum
Message3Optional *msg = [[Message3Optional alloc] init];
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalEnum));
msg.optionalEnum = Message3Optional_Enum_Bar;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalEnum));
msg.hasOptionalEnum = NO;
XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalEnum));
msg.optionalEnum = Message3Optional_Enum_Foo;
XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalEnum));
[msg release];
}
// clang-format on
//%PDDM-EXPAND-END PROTO3_TEST_OPTIONAL_HAS_FIELDS()
}
- (void)testAccessingProto2UnknownEnumValues {
Message2 *msg = [[Message2 alloc] init];

@ -109,6 +109,317 @@
[msg release];
}
- (void)testProto3SerializationHandlingOptionals {
//
// Proto3 optionals should be just like proto2, zero values also get serialized.
//
//%PDDM-DEFINE PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(FIELD, ZERO_VALUE, EXPECTED_LEN)
//% { // optional##FIELD
//% Message3Optional *msg = [[Message3Optional alloc] init];
//% NSData *data = [msg data];
//% XCTAssertEqual([data length], 0U);
//% msg.optional##FIELD = ZERO_VALUE;
//% data = [msg data];
//% XCTAssertEqual(data.length, EXPECTED_LEN);
//% NSError *err = nil;
//% Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
//% XCTAssertNotNil(msg2);
//% XCTAssertNil(err);
//% XCTAssertTrue(msg2.hasOptional##FIELD);
//% XCTAssertEqualObjects(msg, msg2);
//% [msg release];
//% }
//%
//%PDDM-DEFINE PROTO3_TEST_SERIALIZE_OPTIONAL_FIELDS()
//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Int32, 0, 2)
//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Int64, 0, 2)
//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Uint32, 0, 2)
//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Uint64, 0, 2)
//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Sint32, 0, 2)
//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Sint64, 0, 2)
//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Fixed32, 0, 5)
//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Fixed64, 0, 9)
//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Sfixed32, 0, 5)
//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Sfixed64, 0, 9)
//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Float, 0.0f, 5)
//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Double, 0.0, 9)
//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Bool, NO, 2)
//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(String, @"", 2)
//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Bytes, [NSData data], 2)
//% //
//% // Test doesn't apply to optionalMessage (no groups in proto3).
//% //
//%
//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Enum, Message3Optional_Enum_Foo, 3)
//%PDDM-EXPAND PROTO3_TEST_SERIALIZE_OPTIONAL_FIELDS()
// This block of code is generated, do not edit it directly.
// clang-format off
{ // optionalInt32
Message3Optional *msg = [[Message3Optional alloc] init];
NSData *data = [msg data];
XCTAssertEqual([data length], 0U);
msg.optionalInt32 = 0;
data = [msg data];
XCTAssertEqual(data.length, 2);
NSError *err = nil;
Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
XCTAssertNotNil(msg2);
XCTAssertNil(err);
XCTAssertTrue(msg2.hasOptionalInt32);
XCTAssertEqualObjects(msg, msg2);
[msg release];
}
{ // optionalInt64
Message3Optional *msg = [[Message3Optional alloc] init];
NSData *data = [msg data];
XCTAssertEqual([data length], 0U);
msg.optionalInt64 = 0;
data = [msg data];
XCTAssertEqual(data.length, 2);
NSError *err = nil;
Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
XCTAssertNotNil(msg2);
XCTAssertNil(err);
XCTAssertTrue(msg2.hasOptionalInt64);
XCTAssertEqualObjects(msg, msg2);
[msg release];
}
{ // optionalUint32
Message3Optional *msg = [[Message3Optional alloc] init];
NSData *data = [msg data];
XCTAssertEqual([data length], 0U);
msg.optionalUint32 = 0;
data = [msg data];
XCTAssertEqual(data.length, 2);
NSError *err = nil;
Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
XCTAssertNotNil(msg2);
XCTAssertNil(err);
XCTAssertTrue(msg2.hasOptionalUint32);
XCTAssertEqualObjects(msg, msg2);
[msg release];
}
{ // optionalUint64
Message3Optional *msg = [[Message3Optional alloc] init];
NSData *data = [msg data];
XCTAssertEqual([data length], 0U);
msg.optionalUint64 = 0;
data = [msg data];
XCTAssertEqual(data.length, 2);
NSError *err = nil;
Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
XCTAssertNotNil(msg2);
XCTAssertNil(err);
XCTAssertTrue(msg2.hasOptionalUint64);
XCTAssertEqualObjects(msg, msg2);
[msg release];
}
{ // optionalSint32
Message3Optional *msg = [[Message3Optional alloc] init];
NSData *data = [msg data];
XCTAssertEqual([data length], 0U);
msg.optionalSint32 = 0;
data = [msg data];
XCTAssertEqual(data.length, 2);
NSError *err = nil;
Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
XCTAssertNotNil(msg2);
XCTAssertNil(err);
XCTAssertTrue(msg2.hasOptionalSint32);
XCTAssertEqualObjects(msg, msg2);
[msg release];
}
{ // optionalSint64
Message3Optional *msg = [[Message3Optional alloc] init];
NSData *data = [msg data];
XCTAssertEqual([data length], 0U);
msg.optionalSint64 = 0;
data = [msg data];
XCTAssertEqual(data.length, 2);
NSError *err = nil;
Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
XCTAssertNotNil(msg2);
XCTAssertNil(err);
XCTAssertTrue(msg2.hasOptionalSint64);
XCTAssertEqualObjects(msg, msg2);
[msg release];
}
{ // optionalFixed32
Message3Optional *msg = [[Message3Optional alloc] init];
NSData *data = [msg data];
XCTAssertEqual([data length], 0U);
msg.optionalFixed32 = 0;
data = [msg data];
XCTAssertEqual(data.length, 5);
NSError *err = nil;
Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
XCTAssertNotNil(msg2);
XCTAssertNil(err);
XCTAssertTrue(msg2.hasOptionalFixed32);
XCTAssertEqualObjects(msg, msg2);
[msg release];
}
{ // optionalFixed64
Message3Optional *msg = [[Message3Optional alloc] init];
NSData *data = [msg data];
XCTAssertEqual([data length], 0U);
msg.optionalFixed64 = 0;
data = [msg data];
XCTAssertEqual(data.length, 9);
NSError *err = nil;
Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
XCTAssertNotNil(msg2);
XCTAssertNil(err);
XCTAssertTrue(msg2.hasOptionalFixed64);
XCTAssertEqualObjects(msg, msg2);
[msg release];
}
{ // optionalSfixed32
Message3Optional *msg = [[Message3Optional alloc] init];
NSData *data = [msg data];
XCTAssertEqual([data length], 0U);
msg.optionalSfixed32 = 0;
data = [msg data];
XCTAssertEqual(data.length, 5);
NSError *err = nil;
Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
XCTAssertNotNil(msg2);
XCTAssertNil(err);
XCTAssertTrue(msg2.hasOptionalSfixed32);
XCTAssertEqualObjects(msg, msg2);
[msg release];
}
{ // optionalSfixed64
Message3Optional *msg = [[Message3Optional alloc] init];
NSData *data = [msg data];
XCTAssertEqual([data length], 0U);
msg.optionalSfixed64 = 0;
data = [msg data];
XCTAssertEqual(data.length, 9);
NSError *err = nil;
Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
XCTAssertNotNil(msg2);
XCTAssertNil(err);
XCTAssertTrue(msg2.hasOptionalSfixed64);
XCTAssertEqualObjects(msg, msg2);
[msg release];
}
{ // optionalFloat
Message3Optional *msg = [[Message3Optional alloc] init];
NSData *data = [msg data];
XCTAssertEqual([data length], 0U);
msg.optionalFloat = 0.0f;
data = [msg data];
XCTAssertEqual(data.length, 5);
NSError *err = nil;
Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
XCTAssertNotNil(msg2);
XCTAssertNil(err);
XCTAssertTrue(msg2.hasOptionalFloat);
XCTAssertEqualObjects(msg, msg2);
[msg release];
}
{ // optionalDouble
Message3Optional *msg = [[Message3Optional alloc] init];
NSData *data = [msg data];
XCTAssertEqual([data length], 0U);
msg.optionalDouble = 0.0;
data = [msg data];
XCTAssertEqual(data.length, 9);
NSError *err = nil;
Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
XCTAssertNotNil(msg2);
XCTAssertNil(err);
XCTAssertTrue(msg2.hasOptionalDouble);
XCTAssertEqualObjects(msg, msg2);
[msg release];
}
{ // optionalBool
Message3Optional *msg = [[Message3Optional alloc] init];
NSData *data = [msg data];
XCTAssertEqual([data length], 0U);
msg.optionalBool = NO;
data = [msg data];
XCTAssertEqual(data.length, 2);
NSError *err = nil;
Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
XCTAssertNotNil(msg2);
XCTAssertNil(err);
XCTAssertTrue(msg2.hasOptionalBool);
XCTAssertEqualObjects(msg, msg2);
[msg release];
}
{ // optionalString
Message3Optional *msg = [[Message3Optional alloc] init];
NSData *data = [msg data];
XCTAssertEqual([data length], 0U);
msg.optionalString = @"";
data = [msg data];
XCTAssertEqual(data.length, 2);
NSError *err = nil;
Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
XCTAssertNotNil(msg2);
XCTAssertNil(err);
XCTAssertTrue(msg2.hasOptionalString);
XCTAssertEqualObjects(msg, msg2);
[msg release];
}
{ // optionalBytes
Message3Optional *msg = [[Message3Optional alloc] init];
NSData *data = [msg data];
XCTAssertEqual([data length], 0U);
msg.optionalBytes = [NSData data];
data = [msg data];
XCTAssertEqual(data.length, 2);
NSError *err = nil;
Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
XCTAssertNotNil(msg2);
XCTAssertNil(err);
XCTAssertTrue(msg2.hasOptionalBytes);
XCTAssertEqualObjects(msg, msg2);
[msg release];
}
//
// Test doesn't apply to optionalMessage (no groups in proto3).
//
{ // optionalEnum
Message3Optional *msg = [[Message3Optional alloc] init];
NSData *data = [msg data];
XCTAssertEqual([data length], 0U);
msg.optionalEnum = Message3Optional_Enum_Foo;
data = [msg data];
XCTAssertEqual(data.length, 3);
NSError *err = nil;
Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err];
XCTAssertNotNil(msg2);
XCTAssertNil(err);
XCTAssertTrue(msg2.hasOptionalEnum);
XCTAssertEqualObjects(msg, msg2);
[msg release];
}
// clang-format on
//%PDDM-EXPAND-END PROTO3_TEST_SERIALIZE_OPTIONAL_FIELDS()
}
- (void)testProto2UnknownEnumToUnknownField {
Message3 *orig = [[Message3 alloc] init];

@ -355,7 +355,7 @@ class GPBBridgeTests: XCTestCase {
msg.oneof = nil
XCTAssertEqual(msg.oneof.optionalInt32, Int32(0)) // Default
XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.gpbUnsetOneOfCase)
}
}
func testProto3OneOfSupport() {
let msg = Message3()

@ -119,3 +119,31 @@ message Message3 {
map<int32 , Enum > map_int32_enum = 87;
map<int32 , Message3> map_int32_message = 88;
}
message Message3Optional {
enum Enum {
FOO = 0;
BAR = 1;
BAZ = 2;
EXTRA_3 = 30;
}
optional int32 optional_int32 = 1;
optional int64 optional_int64 = 2;
optional uint32 optional_uint32 = 3;
optional uint64 optional_uint64 = 4;
optional sint32 optional_sint32 = 5;
optional sint64 optional_sint64 = 6;
optional fixed32 optional_fixed32 = 7;
optional fixed64 optional_fixed64 = 8;
optional sfixed32 optional_sfixed32 = 9;
optional sfixed64 optional_sfixed64 = 10;
optional float optional_float = 11;
optional double optional_double = 12;
optional bool optional_bool = 13;
optional string optional_string = 14;
optional bytes optional_bytes = 15;
// No 'group' in proto3.
optional Message3 optional_message = 18;
optional Enum optional_enum = 19;
}

@ -96,10 +96,20 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
/**
* If true, this is a proto3 "optional". When a proto3 field is optional, it
* tracks presence regardless of field type.
* For message fields this doesn't create any semantic change, since
* non-repeated message fields always track presence. However it still
* When proto3_optional is true, this field must be belong to a oneof to
* signal to old proto3 clients that presence is tracked for this field. This
* oneof is known as a "synthetic" oneof, and this field must be its sole
* member (each proto3 optional field gets its own synthetic oneof). Synthetic
* oneofs exist in the descriptor only, and do not generate any API. Synthetic
* oneofs must be ordered after all "real" oneofs.
* For message fields, proto3_optional doesn't create any semantic change,
* since non-repeated message fields always track presence. However it still
* indicates the semantic detail of whether the user wrote "optional" or not.
* This can be useful for round-tripping the .proto file.
* This can be useful for round-tripping the .proto file. For consistency we
* give message fields a synthetic oneof also, even though it is not required
* to track presence. This is especially important because the parser can't
* tell if a field is a message or an enum, so it must always create a
* synthetic oneof.
* Proto2 optional fields do not set this flag, because they already indicate
* optional with `LABEL_OPTIONAL`.
*
@ -147,10 +157,20 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
* @type bool $proto3_optional
* If true, this is a proto3 "optional". When a proto3 field is optional, it
* tracks presence regardless of field type.
* For message fields this doesn't create any semantic change, since
* non-repeated message fields always track presence. However it still
* When proto3_optional is true, this field must be belong to a oneof to
* signal to old proto3 clients that presence is tracked for this field. This
* oneof is known as a "synthetic" oneof, and this field must be its sole
* member (each proto3 optional field gets its own synthetic oneof). Synthetic
* oneofs exist in the descriptor only, and do not generate any API. Synthetic
* oneofs must be ordered after all "real" oneofs.
* For message fields, proto3_optional doesn't create any semantic change,
* since non-repeated message fields always track presence. However it still
* indicates the semantic detail of whether the user wrote "optional" or not.
* This can be useful for round-tripping the .proto file.
* This can be useful for round-tripping the .proto file. For consistency we
* give message fields a synthetic oneof also, even though it is not required
* to track presence. This is especially important because the parser can't
* tell if a field is a message or an enum, so it must always create a
* synthetic oneof.
* Proto2 optional fields do not set this flag, because they already indicate
* optional with `LABEL_OPTIONAL`.
* }
@ -495,10 +515,20 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
/**
* If true, this is a proto3 "optional". When a proto3 field is optional, it
* tracks presence regardless of field type.
* For message fields this doesn't create any semantic change, since
* non-repeated message fields always track presence. However it still
* When proto3_optional is true, this field must be belong to a oneof to
* signal to old proto3 clients that presence is tracked for this field. This
* oneof is known as a "synthetic" oneof, and this field must be its sole
* member (each proto3 optional field gets its own synthetic oneof). Synthetic
* oneofs exist in the descriptor only, and do not generate any API. Synthetic
* oneofs must be ordered after all "real" oneofs.
* For message fields, proto3_optional doesn't create any semantic change,
* since non-repeated message fields always track presence. However it still
* indicates the semantic detail of whether the user wrote "optional" or not.
* This can be useful for round-tripping the .proto file.
* This can be useful for round-tripping the .proto file. For consistency we
* give message fields a synthetic oneof also, even though it is not required
* to track presence. This is especially important because the parser can't
* tell if a field is a message or an enum, so it must always create a
* synthetic oneof.
* Proto2 optional fields do not set this flag, because they already indicate
* optional with `LABEL_OPTIONAL`.
*
@ -513,10 +543,20 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
/**
* If true, this is a proto3 "optional". When a proto3 field is optional, it
* tracks presence regardless of field type.
* For message fields this doesn't create any semantic change, since
* non-repeated message fields always track presence. However it still
* When proto3_optional is true, this field must be belong to a oneof to
* signal to old proto3 clients that presence is tracked for this field. This
* oneof is known as a "synthetic" oneof, and this field must be its sole
* member (each proto3 optional field gets its own synthetic oneof). Synthetic
* oneofs exist in the descriptor only, and do not generate any API. Synthetic
* oneofs must be ordered after all "real" oneofs.
* For message fields, proto3_optional doesn't create any semantic change,
* since non-repeated message fields always track presence. However it still
* indicates the semantic detail of whether the user wrote "optional" or not.
* This can be useful for round-tripping the .proto file.
* This can be useful for round-tripping the .proto file. For consistency we
* give message fields a synthetic oneof also, even though it is not required
* to track presence. This is especially important because the parser can't
* tell if a field is a message or an enum, so it must always create a
* synthetic oneof.
* Proto2 optional fields do not set this flag, because they already indicate
* optional with `LABEL_OPTIONAL`.
*

@ -67,12 +67,22 @@ DOCS_DIR = pathlib.Path(__file__).parent.resolve()
PYTHON_DIR = DOCS_DIR.parent
SOURCE_DIR = PYTHON_DIR / "google" / "protobuf"
SOURCE_POSIX = SOURCE_DIR.as_posix()
# Modules which are always included:
INCLUDED_MODULES = (
"google.protobuf.internal.containers",
)
# Packages to ignore, including all modules (unless in INCLUDED_MODULES):
IGNORED_PACKAGES = (
"compiler",
"docs",
"internal",
"pyext",
"util",
)
# Ignored module stems in all packages (unless in INCLUDED_MODULES):
IGNORED_MODULES = (
"any_test_pb2",
"api_pb2",
@ -81,6 +91,7 @@ IGNORED_MODULES = (
"test_messages_proto3_pb2",
"test_messages_proto2",
)
TOC_REGEX = re.compile(
r"\.\. START REFTOC.*\.\. END REFTOC\.\n",
flags=re.DOTALL,
@ -120,20 +131,28 @@ AUTOMODULE_TEMPLATE = """.. DO NOT EDIT, generated by generate_docs.py.
def find_modules():
modules = []
for module_path in SOURCE_DIR.glob("**/*.py"):
package_posix = module_path.parent.as_posix()
if any(ignored in package_posix for ignored in IGNORED_PACKAGES):
# Determine the (dotted) relative package and module names.
package_path = module_path.parent.relative_to(PYTHON_DIR)
if package_path == SOURCE_DIR:
package_name = ""
module_name = module_path.stem
else:
package_name = package_path.as_posix().replace("/", ".")
module_name = package_name + "." + module_path.stem
# Filter: first, accept anything in the whitelist; then, reject anything
# at package level, then module name level.
if any(include == module_name for include in INCLUDED_MODULES):
pass
elif any(ignored in package_name for ignored in IGNORED_PACKAGES):
continue
if any(ignored in module_path.stem for ignored in IGNORED_MODULES):
elif any(ignored in module_path.stem for ignored in IGNORED_MODULES):
continue
package_name = "google.protobuf{}".format(
package_posix[len(SOURCE_POSIX) :].replace("/", ".")
)
if module_path.name == "__init__.py":
modules.append(package_name)
else:
module_name = module_path.stem
modules.append("{}.{}".format(package_name, module_name))
modules.append(module_name)
return modules

@ -0,0 +1,21 @@
.. DO NOT EDIT, generated by generate_docs.py.
.. ifconfig:: build_env == 'readthedocs'
.. warning::
You are reading the documentation for the `latest committed changes
<https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
the `Protocol Buffers package for Python
<https://developers.google.com/protocol-buffers/docs/pythontutorial>`_.
Some features may not yet be released. Read the documentation for the
latest released package at `googleapis.dev
<https://googleapis.dev/python/protobuf/latest/>`_.
google.protobuf.internal.containers
===================================
.. automodule:: google.protobuf.internal.containers
:members:
:inherited-members:
:undoc-members:

@ -38,6 +38,7 @@ Modules and Packages
google/protobuf/duration_pb2
google/protobuf/empty_pb2
google/protobuf/field_mask_pb2
google/protobuf/internal/containers
google/protobuf/json_format
google/protobuf/message
google/protobuf/message_factory

@ -33,11 +33,14 @@
#include <google/protobuf/pyext/message.h>
#include <structmember.h> // A Python header file.
#include <map>
#include <memory>
#include <string>
#include <vector>
#include <structmember.h> // A Python header file.
#include <google/protobuf/stubs/strutil.h>
#ifndef PyVarObject_HEAD_INIT
#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
@ -456,7 +459,7 @@ static PyObject* GetClassAttribute(CMessageClass *self, PyObject* name) {
Py_ssize_t attr_size;
static const char kSuffix[] = "_FIELD_NUMBER";
if (PyString_AsStringAndSize(name, &attr, &attr_size) >= 0 &&
strings::EndsWith(StringPiece(attr, attr_size), kSuffix)) {
HasSuffixString(StringPiece(attr, attr_size), kSuffix)) {
std::string field_name(attr, attr_size - sizeof(kSuffix) + 1);
LowerString(&field_name);
@ -1424,8 +1427,7 @@ bool CheckHasPresence(const FieldDescriptor* field_descriptor, bool in_oneof) {
return false;
}
if (field_descriptor->containing_oneof() == NULL &&
!field_descriptor->is_singular_with_presence()) {
if (!field_descriptor->has_presence()) {
PyErr_Format(PyExc_ValueError,
"Can't test non-optional, non-submessage field \"%s.%s\" for "
"presence in proto3.",
@ -2168,19 +2170,21 @@ static PyObject* RichCompare(CMessage* self, PyObject* other, int opid) {
// If other is not a message, it cannot be equal.
if (!PyObject_TypeCheck(other, CMessage_Type)) {
equals = false;
}
const google::protobuf::Message* other_message =
reinterpret_cast<CMessage*>(other)->message;
// If messages don't have the same descriptors, they are not equal.
if (equals &&
self->message->GetDescriptor() != other_message->GetDescriptor()) {
equals = false;
}
// Check the message contents.
if (equals && !google::protobuf::util::MessageDifferencer::Equals(
*self->message,
*reinterpret_cast<CMessage*>(other)->message)) {
equals = false;
} else {
// Otherwise, we have a CMessage whose message we can inspect.
const google::protobuf::Message* other_message =
reinterpret_cast<CMessage*>(other)->message;
// If messages don't have the same descriptors, they are not equal.
if (equals &&
self->message->GetDescriptor() != other_message->GetDescriptor()) {
equals = false;
}
// Check the message contents.
if (equals &&
!google::protobuf::util::MessageDifferencer::Equals(
*self->message, *reinterpret_cast<CMessage*>(other)->message)) {
equals = false;
}
}
if (equals ^ (opid == Py_EQ)) {

@ -120,20 +120,21 @@ class TextWriter(object):
return self._writer.getvalue()
def MessageToString(message,
as_utf8=False,
as_one_line=False,
use_short_repeated_primitives=False,
pointy_brackets=False,
use_index_order=False,
float_format=None,
double_format=None,
use_field_number=False,
descriptor_pool=None,
indent=0,
message_formatter=None,
print_unknown_fields=False,
force_colon=False):
def MessageToString(
message,
as_utf8=False,
as_one_line=False,
use_short_repeated_primitives=False,
pointy_brackets=False,
use_index_order=False,
float_format=None,
double_format=None,
use_field_number=False,
descriptor_pool=None,
indent=0,
message_formatter=None,
print_unknown_fields=False,
force_colon=False):
# type: (...) -> str
"""Convert protobuf message to text format.
@ -329,21 +330,22 @@ WIRETYPE_START_GROUP = 3
class _Printer(object):
"""Text format printer for protocol message."""
def __init__(self,
out,
indent=0,
as_utf8=False,
as_one_line=False,
use_short_repeated_primitives=False,
pointy_brackets=False,
use_index_order=False,
float_format=None,
double_format=None,
use_field_number=False,
descriptor_pool=None,
message_formatter=None,
print_unknown_fields=False,
force_colon=False):
def __init__(
self,
out,
indent=0,
as_utf8=False,
as_one_line=False,
use_short_repeated_primitives=False,
pointy_brackets=False,
use_index_order=False,
float_format=None,
double_format=None,
use_field_number=False,
descriptor_pool=None,
message_formatter=None,
print_unknown_fields=False,
force_colon=False):
"""Initialize the Printer.
Double values can be formatted compactly with 15 digits of precision

@ -70,13 +70,18 @@ else
task 'gem:windows' do
require 'rake_compiler_dock'
RakeCompilerDock.sh "bundle && IN_DOCKER=true rake cross native gem RUBY_CC_VERSION=2.6.0:2.5.0:2.4.0:2.3.0"
['x86-mingw32', 'x64-mingw32', 'x86_64-linux', 'x86-linux'].each do |plat|
RakeCompilerDock.sh <<-"EOT", platform: plat
bundle && \
IN_DOCKER=true rake native:#{plat} pkg/#{spec.full_name}-#{plat}.gem RUBY_CC_VERSION=2.7.0:2.6.0:2.5.0:2.4.0:2.3.0
EOT
end
end
if RUBY_PLATFORM =~ /darwin/
task 'gem:native' do
system "rake genproto"
system "rake cross native gem RUBY_CC_VERSION=2.6.0:2.5.1:2.4.0:2.3.0"
system "rake cross native gem RUBY_CC_VERSION=2.7.0:2.6.0:2.5.1:2.4.0:2.3.0"
end
else
task 'gem:native' => [:genproto, 'gem:windows']
@ -119,7 +124,7 @@ file "tests/test_ruby_package_proto2.rb" => "tests/test_ruby_package_proto2.prot
end
file "tests/basic_test.rb" => "tests/basic_test.proto" do |file_task|
sh "../src/protoc -I../src -I. --ruby_out=. tests/basic_test.proto"
sh "../src/protoc --experimental_allow_proto3_optional -I../src -I. --ruby_out=. tests/basic_test.proto"
end
file "tests/basic_test_proto2.rb" => "tests/basic_test_proto2.proto" do |file_task|

@ -20,6 +20,7 @@ class RepeatedFieldTest < Test::Unit::TestCase
:iter_for_each_with_index, :dimensions, :copy_data, :copy_data_simple,
:nitems, :iter_for_reverse_each, :indexes, :append, :prepend]
arr_methods -= [:union, :difference, :filter!]
arr_methods -= [:intersection, :deconstruct] # ruby 2.7 methods we can ignore
arr_methods.each do |method_name|
assert m.repeated_string.respond_to?(method_name) == true, "does not respond to #{method_name}"
end

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save