PROTOBUF_SYNC_PIPER
pull/8262/head
Joshua Haberman 4 years ago
commit 51daaba638
  1. 26
      CHANGES.txt
  2. 14
      Makefile.am
  3. 1
      cmake/libprotoc.cmake
  4. 6
      conformance/Makefile.am
  5. 810
      conformance/failure_list_jruby.txt
  6. 8
      conformance/text_format_failure_list_jruby.txt
  7. 24
      csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
  8. 26
      csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs
  9. 17
      csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs
  10. 20
      csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs
  11. 123
      csharp/src/Google.Protobuf/Collections/MapField.cs
  12. 2
      csharp/src/Google.Protobuf/ExtensionValue.cs
  13. 6
      csharp/src/Google.Protobuf/FieldCodec.cs
  14. 63
      csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs
  15. 19
      csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
  16. 56
      csharp/src/Google.Protobuf/WritingPrimitives.cs
  17. 11
      java/core/src/main/java/com/google/protobuf/Android.java
  18. 6
      java/core/src/main/java/com/google/protobuf/RawMessageInfo.java
  19. 5
      java/lite/proguard.pgcfg
  20. 209
      js/binary/reader_test.js
  21. 87
      js/binary/writer_test.js
  22. 208
      js/compatibility_tests/v3.1.0/binary/reader_test.js
  23. 86
      js/compatibility_tests/v3.1.0/binary/writer_test.js
  24. 75
      js/compatibility_tests/v3.1.0/maps_test.js
  25. 299
      js/compatibility_tests/v3.1.0/message_test.js
  26. 143
      js/maps_test.js
  27. 5
      js/message_test.js
  28. 27
      js/proto3_test.js
  29. 6
      kokoro/README.md
  30. 20
      kokoro/linux/dockerfile/test/php/Dockerfile
  31. 19
      kokoro/linux/dockerfile/test/php_32bit/Dockerfile
  32. 31
      kokoro/linux/dockerfile/test/python39/Dockerfile
  33. 18
      kokoro/linux/python39/build.sh
  34. 11
      kokoro/linux/python39/continuous.cfg
  35. 11
      kokoro/linux/python39/presubmit.cfg
  36. 18
      kokoro/linux/python39_cpp/build.sh
  37. 11
      kokoro/linux/python39_cpp/continuous.cfg
  38. 11
      kokoro/linux/python39_cpp/presubmit.cfg
  39. 3
      kokoro/release/csharp/windows/build_nuget.bat
  40. 1
      kokoro/release/python/linux/build_artifacts.sh
  41. 1
      kokoro/release/python/macos/build_artifacts.sh
  42. 10
      kokoro/release/python/windows/build_artifacts.bat
  43. 8
      kokoro/release/python/windows/build_single_artifact.bat
  44. 3
      kokoro/windows/csharp/build.bat
  45. 4
      php/composer.json
  46. 76
      php/ext/google/protobuf/array.c
  47. 19
      php/ext/google/protobuf/array.h
  48. 31
      php/ext/google/protobuf/convert.c
  49. 11
      php/ext/google/protobuf/convert.h
  50. 23
      php/ext/google/protobuf/def.h
  51. 120
      php/ext/google/protobuf/map.c
  52. 15
      php/ext/google/protobuf/map.h
  53. 143
      php/ext/google/protobuf/message.c
  54. 3
      php/ext/google/protobuf/message.h
  55. 2096
      php/ext/google/protobuf/php-upb.c
  56. 876
      php/ext/google/protobuf/php-upb.h
  57. 4
      php/ext/google/protobuf/protobuf.h
  58. 7
      php/src/Google/Protobuf/Internal/FileOptions.php
  59. 4
      php/src/Google/Protobuf/Internal/GPBWire.php
  60. 5
      php/src/Google/Protobuf/Internal/Message.php
  61. 12
      php/tests/ArrayTest.php
  62. 10
      php/tests/EncodeDecodeTest.php
  63. 66
      php/tests/GeneratedClassTest.php
  64. 7
      php/tests/GeneratedPhpdocTest.php
  65. 18
      php/tests/MapFieldTest.php
  66. 7
      php/tests/proto/test.proto
  67. 6
      python/release/wheel/Dockerfile
  68. 17
      python/release/wheel/README.md
  69. 27
      python/release/wheel/build_wheel_manylinux.sh
  70. 66
      python/release/wheel/protobuf_optimized_pip.sh
  71. 4
      python/setup.py
  72. 2
      python/tox.ini
  73. 10
      ruby/ext/google/protobuf_c/ruby-upb.c
  74. 2
      ruby/ext/google/protobuf_c/ruby-upb.h
  75. 1
      src/Makefile.am
  76. 2
      src/google/protobuf/arena.h
  77. 16
      src/google/protobuf/compiler/command_line_interface.cc
  78. 42
      src/google/protobuf/compiler/command_line_interface_unittest.cc
  79. 2
      src/google/protobuf/compiler/cpp/cpp_field.h
  80. 5
      src/google/protobuf/compiler/cpp/cpp_file.cc
  81. 11
      src/google/protobuf/compiler/java/java_helpers.cc
  82. 1
      src/google/protobuf/compiler/java/java_message_field.cc
  83. 83
      src/google/protobuf/compiler/js/js_generator.cc
  84. 42
      src/google/protobuf/compiler/php/php_generator.cc
  85. 38
      src/google/protobuf/dynamic_message.cc
  86. 6
      src/google/protobuf/generated_message_table_driven_lite.h
  87. 17
      src/google/protobuf/message_lite.cc
  88. 2
      src/google/protobuf/message_lite.h
  89. 28
      src/google/protobuf/message_unittest.inc
  90. 29
      src/google/protobuf/metadata_lite.h
  91. 4
      src/google/protobuf/repeated_field.h
  92. 1
      src/google/protobuf/util/internal/default_value_objectwriter.cc
  93. 1
      src/google/protobuf/util/internal/json_stream_parser.cc
  94. 2
      src/google/protobuf/util/internal/json_stream_parser_test.cc
  95. 1
      src/google/protobuf/util/internal/proto_writer.cc
  96. 2
      src/google/protobuf/util/internal/protostream_objectsource.cc
  97. 60
      src/google/protobuf/util/internal/protostream_objectsource.h
  98. 12
      src/google/protobuf/util/internal/protostream_objectsource_test.cc
  99. 5
      src/google/protobuf/util/internal/type_info_test_helper.cc
  100. 5
      src/google/protobuf/util/internal/type_info_test_helper.h
  101. Some files were not shown because too many files have changed in this diff Show More

@ -12,6 +12,22 @@ Unreleased Changes (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
implementation detail users must not rely on. It should not be used in implementation detail users must not rely on. It should not be used in
unit tests. unit tests.
* Change the signature of Any::PackFrom() to return false on error. * Change the signature of Any::PackFrom() to return false on error.
* Add fast reflection getter API for strings.
* Constant initialize the global message instances
* Avoid potential for missed wakeup in UnknownFieldSet
* Now Proto3 Oneof fields have "has" methods for checking their presence in
C++.
* Bugfix for NVCC
* Return early in _InternalSerialize for empty maps.
* Adding functionality for outputting map key values in proto path logging
output (does not affect comparison logic) and stop printing 'value' in the
path. The modified print functionality is in the
MessageDifferencer::StreamReporter.
* Fixes https://github.com/protocolbuffers/protobuf/issues/8129
* Ensure that null char symbol, package and file names do not result in a
crash.
* Constant initialize the global message instances
* Pretty print 'max' instead of numeric values in reserved ranges.
Java Java
* Avoid possible UnsupportedOperationException when using CodedInputSteam * Avoid possible UnsupportedOperationException when using CodedInputSteam
@ -19,10 +35,20 @@ Unreleased Changes (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
* Make Durations.comparator() and Timestamps.comparator() Serializable. * Make Durations.comparator() and Timestamps.comparator() Serializable.
* Add more detailed error information for dynamic message field type * Add more detailed error information for dynamic message field type
validation failure validation failure
* Removed declarations of functions declared in java_names.h from
java_helpers.h.
* Now Proto3 Oneof fields have "has" methods for checking their presence in
Java.
* Annotates Java proto generated *_FIELD_NUMBER constants.
Python Python
* Provided an override for the reverse() method that will reverse the internal * Provided an override for the reverse() method that will reverse the internal
collection directly instead of using the other methods of the BaseContainer. collection directly instead of using the other methods of the BaseContainer.
* MessageFactory.CreateProtoype can be overridden to customize class creation.
Javascript
* Generate `getDescriptor` methods with `*` as their `this` type.
* Enforce `let/const` for generated messages.
2020-11-11 version 3.14.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) 2020-11-11 version 3.14.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)

@ -1094,17 +1094,21 @@ ruby_EXTRA_DIST= \
ruby/compatibility_tests/v3.0.0/test.sh \ ruby/compatibility_tests/v3.0.0/test.sh \
ruby/compatibility_tests/v3.0.0/Rakefile \ ruby/compatibility_tests/v3.0.0/Rakefile \
ruby/compatibility_tests/v3.0.0/README.md \ ruby/compatibility_tests/v3.0.0/README.md \
ruby/ext/google/protobuf_c/convert.c \
ruby/ext/google/protobuf_c/convert.h \
ruby/ext/google/protobuf_c/defs.c \ ruby/ext/google/protobuf_c/defs.c \
ruby/ext/google/protobuf_c/encode_decode.c \ ruby/ext/google/protobuf_c/defs.h \
ruby/ext/google/protobuf_c/extconf.rb \ ruby/ext/google/protobuf_c/extconf.rb \
ruby/ext/google/protobuf_c/map.c \ ruby/ext/google/protobuf_c/map.c \
ruby/ext/google/protobuf_c/map.h \
ruby/ext/google/protobuf_c/message.c \ ruby/ext/google/protobuf_c/message.c \
ruby/ext/google/protobuf_c/message.h \
ruby/ext/google/protobuf_c/protobuf.c \ ruby/ext/google/protobuf_c/protobuf.c \
ruby/ext/google/protobuf_c/protobuf.h \ ruby/ext/google/protobuf_c/protobuf.h \
ruby/ext/google/protobuf_c/repeated_field.c \ ruby/ext/google/protobuf_c/repeated_field.c \
ruby/ext/google/protobuf_c/storage.c \ ruby/ext/google/protobuf_c/repeated_field.h \
ruby/ext/google/protobuf_c/upb.c \ ruby/ext/google/protobuf_c/ruby-upb.c \
ruby/ext/google/protobuf_c/upb.h \ ruby/ext/google/protobuf_c/ruby-upb.h \
ruby/ext/google/protobuf_c/wrap_memcpy.c \ ruby/ext/google/protobuf_c/wrap_memcpy.c \
ruby/google-protobuf.gemspec \ ruby/google-protobuf.gemspec \
ruby/lib/google/protobuf/message_exts.rb \ ruby/lib/google/protobuf/message_exts.rb \
@ -1144,6 +1148,8 @@ ruby_EXTRA_DIST= \
ruby/tests/generated_code_proto2_test.rb \ ruby/tests/generated_code_proto2_test.rb \
ruby/tests/generated_code_proto2.proto \ ruby/tests/generated_code_proto2.proto \
ruby/tests/generated_code.proto \ ruby/tests/generated_code.proto \
ruby/tests/multi_level_nesting_test.proto \
ruby/tests/multi_level_nesting_test.rb \
ruby/tests/test_import_proto2.proto \ ruby/tests/test_import_proto2.proto \
ruby/tests/test_import.proto \ ruby/tests/test_import.proto \
ruby/tests/test_ruby_package_proto2.proto \ ruby/tests/test_ruby_package_proto2.proto \

@ -93,6 +93,7 @@ set(libprotoc_headers
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message.h ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message.h
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message_field.h ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message_field.h
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_names.h
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_options.h ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_options.h
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_primitive_field.h ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_primitive_field.h

@ -5,7 +5,7 @@ conformance_protoc_inputs = \
$(top_srcdir)/src/google/protobuf/test_messages_proto3.proto $(top_srcdir)/src/google/protobuf/test_messages_proto3.proto
# proto2 input files, should be separated with proto3, as we # proto2 input files, should be separated with proto3, as we
# can't generate proto2 files for ruby, php and objc # can't generate proto2 files for php.
conformance_proto2_protoc_inputs = \ conformance_proto2_protoc_inputs = \
$(top_srcdir)/src/google/protobuf/test_messages_proto2.proto $(top_srcdir)/src/google/protobuf/test_messages_proto2.proto
@ -261,7 +261,7 @@ if USE_EXTERNAL_PROTOC
# Some implementations include pre-generated versions of well-known types. # Some implementations include pre-generated versions of well-known types.
protoc_middleman: $(conformance_protoc_inputs) $(conformance_proto2_protoc_inputs) $(well_known_type_protoc_inputs) google-protobuf protoc_middleman: $(conformance_protoc_inputs) $(conformance_proto2_protoc_inputs) $(well_known_type_protoc_inputs) google-protobuf
$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --objc_out=. --python_out=. --php_out=. --js_out=import_style=commonjs,binary:. $(conformance_protoc_inputs) $(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --objc_out=. --python_out=. --php_out=. --js_out=import_style=commonjs,binary:. $(conformance_protoc_inputs)
$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --objc_out=. --python_out=. --js_out=import_style=commonjs,binary:. $(conformance_proto2_protoc_inputs) $(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --objc_out=. --python_out=. --js_out=import_style=commonjs,binary:. $(conformance_proto2_protoc_inputs)
$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --python_out=. --js_out=import_style=commonjs,binary:google-protobuf $(well_known_type_protoc_inputs) $(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --python_out=. --js_out=import_style=commonjs,binary:google-protobuf $(well_known_type_protoc_inputs)
## $(PROTOC) -I$(srcdir) -I$(top_srcdir) --java_out=lite:lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs) ## $(PROTOC) -I$(srcdir) -I$(top_srcdir) --java_out=lite:lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs)
touch protoc_middleman touch protoc_middleman
@ -273,7 +273,7 @@ else
# building out-of-tree. # building out-of-tree.
protoc_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(conformance_protoc_inputs) $(conformance_proto2_protoc_inputs) $(well_known_type_protoc_inputs) google-protobuf protoc_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(conformance_protoc_inputs) $(conformance_proto2_protoc_inputs) $(well_known_type_protoc_inputs) google-protobuf
oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --objc_out=$$oldpwd --python_out=$$oldpwd --php_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd $(conformance_protoc_inputs) ) oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --objc_out=$$oldpwd --python_out=$$oldpwd --php_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd $(conformance_protoc_inputs) )
oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --objc_out=. --python_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd $(conformance_proto2_protoc_inputs) ) oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --objc_out=$$oldpwd --python_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd $(conformance_proto2_protoc_inputs) )
oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --python_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd/google-protobuf $(well_known_type_protoc_inputs) ) oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --python_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd/google-protobuf $(well_known_type_protoc_inputs) )
## @mkdir -p lite ## @mkdir -p lite
## oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --java_out=lite:$$oldpwd/lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs) ) ## oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --java_out=lite:$$oldpwd/lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs) )

@ -0,0 +1,810 @@
Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
Recommended.FieldMaskTooManyUnderscore.JsonOutput
Recommended.Proto2.JsonInput.FieldNameExtension.Validator
Recommended.Proto3.JsonInput.BoolFieldAllCapitalFalse
Recommended.Proto3.JsonInput.BoolFieldAllCapitalTrue
Recommended.Proto3.JsonInput.BoolFieldCamelCaseFalse
Recommended.Proto3.JsonInput.BoolFieldCamelCaseTrue
Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedFalse
Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedTrue
Recommended.Proto3.JsonInput.BoolMapFieldKeyNotQuoted
Recommended.Proto3.JsonInput.DoubleFieldInfinityNotQuoted
Recommended.Proto3.JsonInput.DoubleFieldNanNotQuoted
Recommended.Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted
Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
Recommended.Proto3.JsonInput.FieldNameDuplicate
Recommended.Proto3.JsonInput.FieldNameNotQuoted
Recommended.Proto3.JsonInput.FloatFieldInfinityNotQuoted
Recommended.Proto3.JsonInput.FloatFieldNanNotQuoted
Recommended.Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted
Recommended.Proto3.JsonInput.Int32MapFieldKeyNotQuoted
Recommended.Proto3.JsonInput.Int64MapFieldKeyNotQuoted
Recommended.Proto3.JsonInput.JsonWithComments
Recommended.Proto3.JsonInput.StringFieldSingleQuoteBoth
Recommended.Proto3.JsonInput.StringFieldSingleQuoteKey
Recommended.Proto3.JsonInput.StringFieldSingleQuoteValue
Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder
Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate
Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
Recommended.Proto3.JsonInput.Uint32MapFieldKeyNotQuoted
Recommended.Proto3.JsonInput.Uint64MapFieldKeyNotQuoted
Recommended.Proto3.ProtobufInput.OneofZeroBool.JsonOutput
Recommended.Proto3.ProtobufInput.OneofZeroBool.ProtobufOutput
Recommended.Proto3.ProtobufInput.OneofZeroBytes.JsonOutput
Recommended.Proto3.ProtobufInput.OneofZeroBytes.ProtobufOutput
Recommended.Proto3.ProtobufInput.OneofZeroDouble.JsonOutput
Recommended.Proto3.ProtobufInput.OneofZeroDouble.ProtobufOutput
Recommended.Proto3.ProtobufInput.OneofZeroEnum.JsonOutput
Recommended.Proto3.ProtobufInput.OneofZeroEnum.ProtobufOutput
Recommended.Proto3.ProtobufInput.OneofZeroFloat.JsonOutput
Recommended.Proto3.ProtobufInput.OneofZeroFloat.ProtobufOutput
Recommended.Proto3.ProtobufInput.OneofZeroMessage.JsonOutput
Recommended.Proto3.ProtobufInput.OneofZeroMessage.ProtobufOutput
Recommended.Proto3.ProtobufInput.OneofZeroMessageSetTwice.JsonOutput
Recommended.Proto3.ProtobufInput.OneofZeroMessageSetTwice.ProtobufOutput
Recommended.Proto3.ProtobufInput.OneofZeroString.JsonOutput
Recommended.Proto3.ProtobufInput.OneofZeroString.ProtobufOutput
Recommended.Proto3.ProtobufInput.OneofZeroUint32.JsonOutput
Recommended.Proto3.ProtobufInput.OneofZeroUint32.ProtobufOutput
Recommended.Proto3.ProtobufInput.OneofZeroUint64.JsonOutput
Recommended.Proto3.ProtobufInput.OneofZeroUint64.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BOOL.DefaultValue.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BOOL.MultipleValuesForDifferentField.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BOOL.MultipleValuesForSameField.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BOOL.NonDefaultValue.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BYTES.DefaultValue.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BYTES.MultipleValuesForDifferentField.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BYTES.MultipleValuesForSameField.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BYTES.NonDefaultValue.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.DOUBLE.DefaultValue.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.DOUBLE.MultipleValuesForDifferentField.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.DOUBLE.MultipleValuesForSameField.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.DOUBLE.NonDefaultValue.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.ENUM.DefaultValue.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.ENUM.MultipleValuesForDifferentField.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.ENUM.MultipleValuesForSameField.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.ENUM.NonDefaultValue.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.FLOAT.DefaultValue.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.FLOAT.MultipleValuesForDifferentField.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.FLOAT.MultipleValuesForSameField.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.FLOAT.NonDefaultValue.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.DefaultValue.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.MultipleValuesForDifferentField.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.MultipleValuesForSameField.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.NonDefaultValue.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.STRING.DefaultValue.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.STRING.MultipleValuesForDifferentField.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.STRING.MultipleValuesForSameField.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.STRING.NonDefaultValue.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT32.DefaultValue.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT32.MultipleValuesForDifferentField.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT32.MultipleValuesForSameField.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT32.NonDefaultValue.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT64.DefaultValue.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT64.MultipleValuesForDifferentField.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT64.MultipleValuesForSameField.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT64.NonDefaultValue.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[2].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[3].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[4].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[5].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[6].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BYTES[3].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.DOUBLE[1].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.DOUBLE[2].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[0].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[1].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[2].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[3].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[4].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[5].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FIXED32[2].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FIXED64[2].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FLOAT[1].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FLOAT[2].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FLOAT[3].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FLOAT[4].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[1].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[2].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[3].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[4].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[5].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[6].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[7].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[8].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[9].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT64[1].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT64[2].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT64[3].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.MESSAGE[0].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.MESSAGE[1].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SFIXED32[2].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SFIXED32[3].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SFIXED64[2].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SFIXED64[3].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT32[1].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT32[2].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT32[3].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT32[4].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT64[1].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT64[2].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT64[3].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.STRING[3].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.STRING[4].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.STRING[5].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.STRING[6].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[1].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[2].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[3].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[4].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[5].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[6].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[7].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[8].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[9].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT64[1].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT64[2].ProtobufOutput
Required.DurationProtoInputTooLarge.JsonOutput
Required.DurationProtoInputTooSmall.JsonOutput
Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator
Required.Proto3.JsonInput.Any.JsonOutput
Required.Proto3.JsonInput.Any.ProtobufOutput
Required.Proto3.JsonInput.AnyNested.JsonOutput
Required.Proto3.JsonInput.AnyNested.ProtobufOutput
Required.Proto3.JsonInput.AnyUnorderedTypeTag.JsonOutput
Required.Proto3.JsonInput.AnyUnorderedTypeTag.ProtobufOutput
Required.Proto3.JsonInput.AnyWithDuration.JsonOutput
Required.Proto3.JsonInput.AnyWithDuration.ProtobufOutput
Required.Proto3.JsonInput.AnyWithFieldMask.JsonOutput
Required.Proto3.JsonInput.AnyWithFieldMask.ProtobufOutput
Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.JsonOutput
Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput
Required.Proto3.JsonInput.AnyWithStruct.JsonOutput
Required.Proto3.JsonInput.AnyWithStruct.ProtobufOutput
Required.Proto3.JsonInput.AnyWithTimestamp.JsonOutput
Required.Proto3.JsonInput.AnyWithTimestamp.ProtobufOutput
Required.Proto3.JsonInput.AnyWithValueForInteger.JsonOutput
Required.Proto3.JsonInput.AnyWithValueForInteger.ProtobufOutput
Required.Proto3.JsonInput.AnyWithValueForJsonObject.JsonOutput
Required.Proto3.JsonInput.AnyWithValueForJsonObject.ProtobufOutput
Required.Proto3.JsonInput.EnumFieldNotQuoted
Required.Proto3.JsonInput.IgnoreUnknownJsonFalse.ProtobufOutput
Required.Proto3.JsonInput.IgnoreUnknownJsonNull.ProtobufOutput
Required.Proto3.JsonInput.IgnoreUnknownJsonNumber.ProtobufOutput
Required.Proto3.JsonInput.IgnoreUnknownJsonObject.ProtobufOutput
Required.Proto3.JsonInput.IgnoreUnknownJsonString.ProtobufOutput
Required.Proto3.JsonInput.IgnoreUnknownJsonTrue.ProtobufOutput
Required.Proto3.JsonInput.Int32FieldLeadingZero
Required.Proto3.JsonInput.Int32FieldNegativeWithLeadingZero
Required.Proto3.JsonInput.Int32FieldPlusSign
Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
Required.Proto3.JsonInput.StringFieldNotAString
Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.BOOL
Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.INT32
Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.INT64
Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.SINT32
Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.SINT64
Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.UINT32
Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.UINT64
Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.JsonOutput
Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.ProtobufOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.BOOL.JsonOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.BOOL.ProtobufOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.BYTES.JsonOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.BYTES.ProtobufOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.ENUM.JsonOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.ENUM.ProtobufOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.JsonOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.ProtobufOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.JsonOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.ProtobufOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FLOAT.JsonOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FLOAT.ProtobufOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.INT32.JsonOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.INT32.ProtobufOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.INT64.JsonOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.INT64.ProtobufOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SFIXED32.JsonOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SFIXED32.ProtobufOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SFIXED64.JsonOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SFIXED64.ProtobufOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SINT32.JsonOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SINT32.ProtobufOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SINT64.JsonOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SINT64.ProtobufOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.STRING.JsonOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.STRING.ProtobufOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.UINT32.JsonOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.UINT32.ProtobufOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.UINT64.JsonOutput
Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.UINT64.ProtobufOutput
Required.Proto3.ProtobufInput.UnknownVarint.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.Default.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.Default.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateKey.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateKey.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateKeyInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateKeyInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateValueInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateValueInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.MissingDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.MissingDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.NonDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.NonDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.Unordered.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.Unordered.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.Default.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.Default.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateKey.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateKey.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateKeyInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateKeyInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateValueInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateValueInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.MissingDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.MissingDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.NonDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.NonDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.Unordered.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.Unordered.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.Default.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.Default.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateKey.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateKey.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateKeyInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateKeyInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateValueInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateValueInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.MissingDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.MissingDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.NonDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.NonDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.Unordered.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.Unordered.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.Default.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.Default.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateKey.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateKey.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateKeyInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateKeyInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateValueInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateValueInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.MissingDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.MissingDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.NonDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.NonDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.Unordered.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.Unordered.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.Default.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.Default.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateKey.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateKey.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateKeyInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateKeyInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateValueInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateValueInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.MissingDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.MissingDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.NonDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.NonDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.Unordered.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.Unordered.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.Default.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.Default.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateKey.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateKey.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateKeyInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateKeyInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateValueInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateValueInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.MissingDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.MissingDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.NonDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.NonDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.Unordered.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.Unordered.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.Default.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.Default.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateKey.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateKey.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateKeyInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateKeyInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateValueInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateValueInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.MissingDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.MissingDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.NonDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.NonDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.Unordered.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.Unordered.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.Default.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.Default.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateKey.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateKey.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateKeyInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateKeyInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateValueInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateValueInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.MissingDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.MissingDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.NonDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.NonDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.Unordered.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.Unordered.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.Default.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.Default.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateKey.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateKey.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateKeyInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateKeyInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateValueInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateValueInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.MissingDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.MissingDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.NonDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.NonDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.Unordered.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.Unordered.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.Default.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.Default.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateKey.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateKey.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateKeyInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateKeyInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateValueInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateValueInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.MissingDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.MissingDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.NonDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.NonDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.Unordered.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.Unordered.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.Default.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.Default.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateKey.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateKey.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateKeyInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateKeyInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateValueInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateValueInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.MissingDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.MissingDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.NonDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.NonDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.Unordered.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.Unordered.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.Default.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.Default.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateKey.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateKey.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateKeyInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateKeyInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateValueInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateValueInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.MissingDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.MissingDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.NonDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.NonDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.Unordered.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.Unordered.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.Default.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.Default.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateKey.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateKey.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateKeyInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateKeyInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateValueInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateValueInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.MissingDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.MissingDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.NonDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.NonDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.Unordered.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.Unordered.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.Default.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.Default.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateKey.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateKey.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateKeyInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateKeyInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateValueInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateValueInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.MergeValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.MergeValue.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.MissingDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.MissingDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.NonDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.NonDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.Unordered.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.Unordered.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.Default.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.Default.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateKey.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateKey.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateKeyInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateKeyInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateValueInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateValueInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.MissingDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.MissingDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.NonDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.NonDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.Unordered.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.Unordered.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.Default.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.Default.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateKey.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateKey.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateKeyInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateKeyInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateValueInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateValueInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.MissingDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.MissingDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.NonDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.NonDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.Unordered.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.Unordered.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.Default.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.Default.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateKey.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateKey.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateKeyInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateKeyInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateValueInMapEntry.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateValueInMapEntry.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.MissingDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.MissingDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.NonDefault.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.NonDefault.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.Unordered.JsonOutput
Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.Unordered.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.DefaultValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.DefaultValue.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.MultipleValuesForDifferentField.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.MultipleValuesForDifferentField.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.MultipleValuesForSameField.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.MultipleValuesForSameField.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.NonDefaultValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.NonDefaultValue.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.DefaultValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.DefaultValue.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.MultipleValuesForDifferentField.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.MultipleValuesForDifferentField.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.MultipleValuesForSameField.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.MultipleValuesForSameField.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.NonDefaultValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.NonDefaultValue.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.DefaultValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.DefaultValue.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.MultipleValuesForDifferentField.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.MultipleValuesForDifferentField.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.MultipleValuesForSameField.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.MultipleValuesForSameField.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.NonDefaultValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.NonDefaultValue.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.DefaultValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.DefaultValue.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.MultipleValuesForDifferentField.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.MultipleValuesForDifferentField.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.MultipleValuesForSameField.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.MultipleValuesForSameField.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.NonDefaultValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.NonDefaultValue.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.DefaultValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.DefaultValue.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.MultipleValuesForDifferentField.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.MultipleValuesForDifferentField.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.MultipleValuesForSameField.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.MultipleValuesForSameField.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.NonDefaultValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.NonDefaultValue.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.DefaultValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.DefaultValue.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.Merge.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.Merge.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.MultipleValuesForDifferentField.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.MultipleValuesForDifferentField.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.MultipleValuesForSameField.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.MultipleValuesForSameField.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.NonDefaultValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.NonDefaultValue.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.STRING.DefaultValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.STRING.DefaultValue.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.STRING.MultipleValuesForDifferentField.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.STRING.MultipleValuesForDifferentField.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.STRING.MultipleValuesForSameField.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.STRING.MultipleValuesForSameField.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.STRING.NonDefaultValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.STRING.NonDefaultValue.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.DefaultValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.DefaultValue.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.MultipleValuesForDifferentField.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.MultipleValuesForDifferentField.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.MultipleValuesForSameField.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.MultipleValuesForSameField.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.NonDefaultValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.NonDefaultValue.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.DefaultValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.DefaultValue.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.MultipleValuesForDifferentField.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.MultipleValuesForDifferentField.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.MultipleValuesForSameField.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.MultipleValuesForSameField.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.NonDefaultValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.NonDefaultValue.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.MESSAGE.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.MESSAGE.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[2].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[2].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[3].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[3].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[4].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[4].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[5].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[5].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[6].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[6].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.BYTES[3].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.BYTES[3].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.DOUBLE[1].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.DOUBLE[1].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.DOUBLE[2].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.DOUBLE[2].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[0].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[0].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[1].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[1].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[2].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[2].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[3].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[3].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[4].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[4].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[5].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[5].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.FIXED32[2].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.FIXED32[2].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.FIXED64[2].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.FIXED64[2].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[1].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[1].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[3].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[3].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[4].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[4].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT32[1].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT32[1].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT32[2].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT32[2].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT32[3].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT32[3].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT32[4].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT32[4].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT32[5].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT32[5].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT32[6].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT32[6].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT32[7].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT32[7].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT32[8].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT32[8].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT32[9].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT32[9].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT64[1].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT64[1].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT64[2].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT64[2].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT64[3].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.INT64[3].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.MESSAGE[0].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.MESSAGE[0].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.MESSAGE[1].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.MESSAGE[1].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED32[2].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED32[2].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED32[3].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED32[3].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED64[2].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED64[2].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED64[3].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED64[3].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[1].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[1].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[2].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[2].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[3].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[3].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[4].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[4].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[1].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[1].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[2].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[2].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[3].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[3].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.STRING[3].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.STRING[3].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.STRING[4].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.STRING[4].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.STRING[5].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.STRING[5].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.STRING[6].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.STRING[6].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[1].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[1].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[2].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[2].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[3].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[3].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[4].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[4].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[5].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[5].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[6].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[6].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[7].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[7].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[8].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[8].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[9].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[9].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT64[1].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT64[1].ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT64[2].JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.UINT64[2].ProtobufOutput
Required.TimestampProtoInputTooLarge.JsonOutput
Required.TimestampProtoInputTooSmall.JsonOutput

@ -0,0 +1,8 @@
Recommended.Proto3.ProtobufInput.GroupUnknownFields_Drop.TextFormatOutput
Recommended.Proto3.ProtobufInput.GroupUnknownFields_Print.TextFormatOutput
Recommended.Proto3.ProtobufInput.MessageUnknownFields_Drop.TextFormatOutput
Recommended.Proto3.ProtobufInput.MessageUnknownFields_Print.TextFormatOutput
Recommended.Proto3.ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput
Recommended.Proto3.ProtobufInput.RepeatedUnknownFields_Print.TextFormatOutput
Recommended.Proto3.ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput
Recommended.Proto3.ProtobufInput.ScalarUnknownFields_Print.TextFormatOutput

@ -35,6 +35,7 @@ using System.IO;
using Google.Protobuf.TestProtos; using Google.Protobuf.TestProtos;
using Google.Protobuf.Buffers; using Google.Protobuf.Buffers;
using NUnit.Framework; using NUnit.Framework;
using System.Text;
namespace Google.Protobuf namespace Google.Protobuf
{ {
@ -516,5 +517,28 @@ namespace Google.Protobuf
var stream = new CodedOutputStream(new byte[10]); var stream = new CodedOutputStream(new byte[10]);
stream.Dispose(); stream.Dispose();
} }
[Test]
public void WriteStringsOfDifferentSizes()
{
for (int i = 1; i <= 1024; i++)
{
var buffer = new byte[4096];
var output = new CodedOutputStream(buffer);
var sb = new StringBuilder();
for (int j = 0; j < i; j++)
{
sb.Append((j % 10).ToString()); // incrementing numbers, repeating
}
var s = sb.ToString();
output.WriteString(s);
output.Flush();
// Verify written content
var input = new CodedInputStream(buffer);
Assert.AreEqual(s, input.ReadString());
}
}
} }
} }

@ -611,6 +611,32 @@ namespace Google.Protobuf.Collections
Assert.IsTrue(input.IsAtEnd); Assert.IsTrue(input.IsAtEnd);
} }
[Test]
public void AddEntriesFrom_CodedInputStream_MissingKey()
{
// map will have string key and string value
var keyTag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
var valueTag = WireFormat.MakeTag(2, WireFormat.WireType.LengthDelimited);
var memoryStream = new MemoryStream();
var output = new CodedOutputStream(memoryStream);
output.WriteLength(11); // total of valueTag + value
output.WriteTag(valueTag);
output.WriteString("the_value");
output.Flush();
Console.WriteLine(BitConverter.ToString(memoryStream.ToArray()));
var field = new MapField<string, string>();
var mapCodec = new MapField<string, string>.Codec(FieldCodec.ForString(keyTag, ""), FieldCodec.ForString(valueTag, ""), 10);
var input = new CodedInputStream(memoryStream.ToArray());
field.AddEntriesFrom(input, mapCodec);
CollectionAssert.AreEquivalent(new[] { "" }, field.Keys);
CollectionAssert.AreEquivalent(new[] { "the_value" }, field.Values);
Assert.IsTrue(input.IsAtEnd);
}
#if !NET35 #if !NET35
[Test] [Test]
public void IDictionaryKeys_Equals_IReadOnlyDictionaryKeys() public void IDictionaryKeys_Equals_IReadOnlyDictionaryKeys()

@ -116,7 +116,22 @@ namespace Google.Protobuf
var other = message.Clone(); var other = message.Clone();
Assert.AreEqual(message, other); Assert.AreEqual(message, other);
Assert.AreEqual(message.CalculateSize(), message.CalculateSize()); Assert.AreEqual(message.CalculateSize(), other.CalculateSize());
}
[Test]
public void TestDefaultValueRoundTrip()
{
var message = new TestAllExtensions();
message.SetExtension(OptionalBoolExtension, false);
Assert.IsFalse(message.GetExtension(OptionalBoolExtension));
Assert.IsTrue(message.HasExtension(OptionalBoolExtension));
var bytes = message.ToByteArray();
var registry = new ExtensionRegistry { OptionalBoolExtension };
var parsed = TestAllExtensions.Parser.WithExtensionRegistry(registry).ParseFrom(bytes);
Assert.IsFalse(parsed.GetExtension(OptionalBoolExtension));
Assert.IsTrue(parsed.HasExtension(OptionalBoolExtension));
} }
} }
} }

@ -35,7 +35,9 @@ using NUnit.Framework;
using ProtobufUnittest; using ProtobufUnittest;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using UnitTest.Issues.TestProtos;
namespace Google.Protobuf.Reflection namespace Google.Protobuf.Reflection
{ {
@ -70,6 +72,24 @@ namespace Google.Protobuf.Reflection
TestFileDescriptor(converted[2], converted[1], converted[0]); TestFileDescriptor(converted[2], converted[1], converted[0]);
} }
[Test]
public void FileDescriptor_BuildFromByteStrings_WithExtensionRegistry()
{
var extension = UnittestCustomOptionsProto3Extensions.MessageOpt1;
var byteStrings = new[]
{
DescriptorReflection.Descriptor.Proto.ToByteString(),
UnittestCustomOptionsProto3Reflection.Descriptor.Proto.ToByteString()
};
var registry = new ExtensionRegistry { extension };
var descriptor = FileDescriptor.BuildFromByteStrings(byteStrings, registry).Last();
var message = descriptor.MessageTypes.Single(t => t.Name == nameof(TestMessageWithCustomOptions));
var extensionValue = message.GetOptions().GetExtension(extension);
Assert.AreEqual(-56, extensionValue);
}
private void TestFileDescriptor(FileDescriptor file, FileDescriptor importedFile, FileDescriptor importedPublicFile) private void TestFileDescriptor(FileDescriptor file, FileDescriptor importedFile, FileDescriptor importedPublicFile)
{ {
Assert.AreEqual("unittest_proto3.proto", file.Name); Assert.AreEqual("unittest_proto3.proto", file.Name);

@ -448,12 +448,10 @@ namespace Google.Protobuf.Collections
[SecuritySafeCritical] [SecuritySafeCritical]
public void AddEntriesFrom(ref ParseContext ctx, Codec codec) public void AddEntriesFrom(ref ParseContext ctx, Codec codec)
{ {
var adapter = new Codec.MessageAdapter(codec);
do do
{ {
adapter.Reset(); KeyValuePair<TKey, TValue> entry = ParsingPrimitivesMessages.ReadMapEntry(ref ctx, codec);
ctx.ReadMessage(adapter); this[entry.Key] = entry.Value;
this[adapter.Key] = adapter.Value;
} while (ParsingPrimitives.MaybeConsumeTag(ref ctx.buffer, ref ctx.state, codec.MapTag)); } while (ParsingPrimitives.MaybeConsumeTag(ref ctx.buffer, ref ctx.state, codec.MapTag));
} }
@ -485,13 +483,13 @@ namespace Google.Protobuf.Collections
[SecuritySafeCritical] [SecuritySafeCritical]
public void WriteTo(ref WriteContext ctx, Codec codec) public void WriteTo(ref WriteContext ctx, Codec codec)
{ {
var message = new Codec.MessageAdapter(codec);
foreach (var entry in list) foreach (var entry in list)
{ {
message.Key = entry.Key;
message.Value = entry.Value;
ctx.WriteTag(codec.MapTag); ctx.WriteTag(codec.MapTag);
ctx.WriteMessage(message);
WritingPrimitives.WriteLength(ref ctx.buffer, ref ctx.state, CalculateEntrySize(codec, entry));
codec.KeyCodec.WriteTagAndValue(ref ctx, entry.Key);
codec.ValueCodec.WriteTagAndValue(ref ctx, entry.Value);
} }
} }
@ -506,18 +504,22 @@ namespace Google.Protobuf.Collections
{ {
return 0; return 0;
} }
var message = new Codec.MessageAdapter(codec);
int size = 0; int size = 0;
foreach (var entry in list) foreach (var entry in list)
{ {
message.Key = entry.Key; int entrySize = CalculateEntrySize(codec, entry);
message.Value = entry.Value;
size += CodedOutputStream.ComputeRawVarint32Size(codec.MapTag); size += CodedOutputStream.ComputeRawVarint32Size(codec.MapTag);
size += CodedOutputStream.ComputeMessageSize(message); size += CodedOutputStream.ComputeLengthSize(entrySize) + entrySize;
} }
return size; return size;
} }
private static int CalculateEntrySize(Codec codec, KeyValuePair<TKey, TValue> entry)
{
return codec.KeyCodec.CalculateSizeWithTag(entry.Key) + codec.ValueCodec.CalculateSizeWithTag(entry.Value);
}
/// <summary> /// <summary>
/// Returns a string representation of this repeated field, in the same /// Returns a string representation of this repeated field, in the same
/// way as it would be represented by the default JSON formatter. /// way as it would be represented by the default JSON formatter.
@ -655,100 +657,19 @@ namespace Google.Protobuf.Collections
} }
/// <summary> /// <summary>
/// The tag used in the enclosing message to indicate map entries. /// The key codec.
/// </summary> /// </summary>
internal uint MapTag { get { return mapTag; } } internal FieldCodec<TKey> KeyCodec => keyCodec;
/// <summary> /// <summary>
/// A mutable message class, used for parsing and serializing. This /// The value codec.
/// delegates the work to a codec, but implements the <see cref="IMessage"/> interface
/// for interop with <see cref="CodedInputStream"/> and <see cref="CodedOutputStream"/>.
/// This is nested inside Codec as it's tightly coupled to the associated codec,
/// and it's simpler if it has direct access to all its fields.
/// </summary> /// </summary>
internal class MessageAdapter : IMessage, IBufferMessage internal FieldCodec<TValue> ValueCodec => valueCodec;
{
private static readonly byte[] ZeroLengthMessageStreamData = new byte[] { 0 };
private readonly Codec codec;
internal TKey Key { get; set; }
internal TValue Value { get; set; }
internal MessageAdapter(Codec codec)
{
this.codec = codec;
}
internal void Reset()
{
Key = codec.keyCodec.DefaultValue;
Value = codec.valueCodec.DefaultValue;
}
public void MergeFrom(CodedInputStream input)
{
// Message adapter is an internal class and we know that all the parsing will happen via InternalMergeFrom.
throw new NotImplementedException();
}
[SecuritySafeCritical]
public void InternalMergeFrom(ref ParseContext ctx)
{
uint tag;
while ((tag = ctx.ReadTag()) != 0)
{
if (tag == codec.keyCodec.Tag)
{
Key = codec.keyCodec.Read(ref ctx);
}
else if (tag == codec.valueCodec.Tag)
{
Value = codec.valueCodec.Read(ref ctx);
}
else
{
ParsingPrimitivesMessages.SkipLastField(ref ctx.buffer, ref ctx.state);
}
}
// Corner case: a map entry with a key but no value, where the value type is a message.
// Read it as if we'd seen input with no data (i.e. create a "default" message).
if (Value == null)
{
if (ctx.state.CodedInputStream != null)
{
// the decoded message might not support parsing from ParseContext, so
// we need to allow fallback to the legacy MergeFrom(CodedInputStream) parsing.
Value = codec.valueCodec.Read(new CodedInputStream(ZeroLengthMessageStreamData));
}
else
{
ParseContext.Initialize(new ReadOnlySequence<byte>(ZeroLengthMessageStreamData), out ParseContext zeroLengthCtx);
Value = codec.valueCodec.Read(ref zeroLengthCtx);
}
}
}
public void WriteTo(CodedOutputStream output)
{
// Message adapter is an internal class and we know that all the writing will happen via InternalWriteTo.
throw new NotImplementedException();
}
[SecuritySafeCritical] /// <summary>
public void InternalWriteTo(ref WriteContext ctx) /// The tag used in the enclosing message to indicate map entries.
{ /// </summary>
codec.keyCodec.WriteTagAndValue(ref ctx, Key); internal uint MapTag => mapTag;
codec.valueCodec.WriteTagAndValue(ref ctx, Value);
}
public int CalculateSize()
{
return codec.keyCodec.CalculateSizeWithTag(Key) + codec.valueCodec.CalculateSizeWithTag(Value);
}
MessageDescriptor IMessage.Descriptor { get { return null; } }
}
} }
private class MapView<T> : ICollection<T>, ICollection private class MapView<T> : ICollection<T>, ICollection

@ -59,7 +59,7 @@ namespace Google.Protobuf
public int CalculateSize() public int CalculateSize()
{ {
return codec.CalculateSizeWithTag(field); return codec.CalculateUnconditionalSizeWithTag(field);
} }
public IExtensionValue Clone() public IExtensionValue Clone()

@ -876,6 +876,12 @@ namespace Google.Protobuf
/// </summary> /// </summary>
public int CalculateSizeWithTag(T value) => IsDefault(value) ? 0 : ValueSizeCalculator(value) + tagSize; public int CalculateSizeWithTag(T value) => IsDefault(value) ? 0 : ValueSizeCalculator(value) + tagSize;
/// <summary>
/// Calculates the size required to write the given value, with a tag, even
/// if the value is the default.
/// </summary>
internal int CalculateUnconditionalSizeWithTag(T value) => ValueSizeCalculator(value) + tagSize;
private bool IsDefault(T value) => EqualityComparer.Equals(value, DefaultValue); private bool IsDefault(T value) => EqualityComparer.Equals(value, DefaultValue);
} }
} }

@ -32,9 +32,11 @@
using System; using System;
using System.Buffers; using System.Buffers;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Security; using System.Security;
using Google.Protobuf.Collections;
namespace Google.Protobuf namespace Google.Protobuf
{ {
@ -44,6 +46,8 @@ namespace Google.Protobuf
[SecuritySafeCritical] [SecuritySafeCritical]
internal static class ParsingPrimitivesMessages internal static class ParsingPrimitivesMessages
{ {
private static readonly byte[] ZeroLengthMessageStreamData = new byte[] { 0 };
public static void SkipLastField(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state) public static void SkipLastField(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
{ {
if (state.lastTag == 0) if (state.lastTag == 0)
@ -134,6 +138,65 @@ namespace Google.Protobuf
SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit); SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit);
} }
public static KeyValuePair<TKey, TValue> ReadMapEntry<TKey, TValue>(ref ParseContext ctx, MapField<TKey, TValue>.Codec codec)
{
int length = ParsingPrimitives.ParseLength(ref ctx.buffer, ref ctx.state);
if (ctx.state.recursionDepth >= ctx.state.recursionLimit)
{
throw InvalidProtocolBufferException.RecursionLimitExceeded();
}
int oldLimit = SegmentedBufferHelper.PushLimit(ref ctx.state, length);
++ctx.state.recursionDepth;
TKey key = codec.KeyCodec.DefaultValue;
TValue value = codec.ValueCodec.DefaultValue;
uint tag;
while ((tag = ctx.ReadTag()) != 0)
{
if (tag == codec.KeyCodec.Tag)
{
key = codec.KeyCodec.Read(ref ctx);
}
else if (tag == codec.ValueCodec.Tag)
{
value = codec.ValueCodec.Read(ref ctx);
}
else
{
SkipLastField(ref ctx.buffer, ref ctx.state);
}
}
// Corner case: a map entry with a key but no value, where the value type is a message.
// Read it as if we'd seen input with no data (i.e. create a "default" message).
if (value == null)
{
if (ctx.state.CodedInputStream != null)
{
// the decoded message might not support parsing from ParseContext, so
// we need to allow fallback to the legacy MergeFrom(CodedInputStream) parsing.
value = codec.ValueCodec.Read(new CodedInputStream(ZeroLengthMessageStreamData));
}
else
{
ParseContext.Initialize(new ReadOnlySequence<byte>(ZeroLengthMessageStreamData), out ParseContext zeroLengthCtx);
value = codec.ValueCodec.Read(ref zeroLengthCtx);
}
}
CheckReadEndOfStreamTag(ref ctx.state);
// Check that we've read exactly as much data as expected.
if (!SegmentedBufferHelper.IsReachedLimit(ref ctx.state))
{
throw InvalidProtocolBufferException.TruncatedMessage();
}
--ctx.state.recursionDepth;
SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit);
return new KeyValuePair<TKey, TValue>(key, value);
}
public static void ReadGroup(ref ParseContext ctx, IMessage message) public static void ReadGroup(ref ParseContext ctx, IMessage message)
{ {
if (ctx.state.recursionDepth >= ctx.state.recursionLimit) if (ctx.state.recursionDepth >= ctx.state.recursionLimit)

@ -481,18 +481,21 @@ namespace Google.Protobuf.Reflection
/// dependencies must come before the descriptor which depends on them. (If A depends on B, and B /// dependencies must come before the descriptor which depends on them. (If A depends on B, and B
/// depends on C, then the descriptors must be presented in the order C, B, A.) This is compatible /// depends on C, then the descriptors must be presented in the order C, B, A.) This is compatible
/// with the order in which protoc provides descriptors to plugins.</param> /// with the order in which protoc provides descriptors to plugins.</param>
/// <param name="registry">The extension registry to use when parsing, or null if no extensions are required.</param>
/// <returns>The file descriptors corresponding to <paramref name="descriptorData"/>.</returns> /// <returns>The file descriptors corresponding to <paramref name="descriptorData"/>.</returns>
public static IReadOnlyList<FileDescriptor> BuildFromByteStrings(IEnumerable<ByteString> descriptorData) public static IReadOnlyList<FileDescriptor> BuildFromByteStrings(IEnumerable<ByteString> descriptorData, ExtensionRegistry registry)
{ {
ProtoPreconditions.CheckNotNull(descriptorData, nameof(descriptorData)); ProtoPreconditions.CheckNotNull(descriptorData, nameof(descriptorData));
var parser = FileDescriptorProto.Parser.WithExtensionRegistry(registry);
// TODO: See if we can build a single DescriptorPool instead of building lots of them. // TODO: See if we can build a single DescriptorPool instead of building lots of them.
// This will all behave correctly, but it's less efficient than we'd like. // This will all behave correctly, but it's less efficient than we'd like.
var descriptors = new List<FileDescriptor>(); var descriptors = new List<FileDescriptor>();
var descriptorsByName = new Dictionary<string, FileDescriptor>(); var descriptorsByName = new Dictionary<string, FileDescriptor>();
foreach (var data in descriptorData) foreach (var data in descriptorData)
{ {
var proto = FileDescriptorProto.Parser.ParseFrom(data); var proto = parser.ParseFrom(data);
var dependencies = new List<FileDescriptor>(); var dependencies = new List<FileDescriptor>();
foreach (var dependencyName in proto.Dependency) foreach (var dependencyName in proto.Dependency)
{ {
@ -518,6 +521,18 @@ namespace Google.Protobuf.Reflection
return new ReadOnlyCollection<FileDescriptor>(descriptors); return new ReadOnlyCollection<FileDescriptor>(descriptors);
} }
/// <summary>
/// Converts the given descriptor binary data into FileDescriptor objects.
/// Note: reflection using the returned FileDescriptors is not currently supported.
/// </summary>
/// <param name="descriptorData">The binary file descriptor proto data. Must not be null, and any
/// dependencies must come before the descriptor which depends on them. (If A depends on B, and B
/// depends on C, then the descriptors must be presented in the order C, B, A.) This is compatible
/// with the order in which protoc provides descriptors to plugins.</param>
/// <returns>The file descriptors corresponding to <paramref name="descriptorData"/>.</returns>
public static IReadOnlyList<FileDescriptor> BuildFromByteStrings(IEnumerable<ByteString> descriptorData) =>
BuildFromByteStrings(descriptorData, null);
/// <summary> /// <summary>
/// Returns a <see cref="System.String" /> that represents this instance. /// Returns a <see cref="System.String" /> that represents this instance.
/// </summary> /// </summary>

@ -163,10 +163,25 @@ namespace Google.Protobuf
/// </summary> /// </summary>
public static void WriteString(ref Span<byte> buffer, ref WriterInternalState state, string value) public static void WriteString(ref Span<byte> buffer, ref WriterInternalState state, string value)
{ {
// Optimise the case where we have enough space to write const int MaxBytesPerChar = 3;
// the string directly to the buffer, which should be common. const int MaxSmallStringLength = 128 / MaxBytesPerChar;
// The string is small enough that the length will always be a 1 byte varint.
// Also there is enough space to write length + bytes to buffer.
// Write string directly to the buffer, and then write length.
// This saves calling GetByteCount on the string. We get the string length from GetBytes.
if (value.Length <= MaxSmallStringLength && buffer.Length - state.position - 1 >= value.Length * MaxBytesPerChar)
{
int indexOfLengthDelimiter = state.position++;
buffer[indexOfLengthDelimiter] = (byte)WriteStringToBuffer(buffer, ref state, value);
return;
}
int length = Utf8Encoding.GetByteCount(value); int length = Utf8Encoding.GetByteCount(value);
WriteLength(ref buffer, ref state, length); WriteLength(ref buffer, ref state, length);
// Optimise the case where we have enough space to write
// the string directly to the buffer, which should be common.
if (buffer.Length - state.position >= length) if (buffer.Length - state.position >= length)
{ {
if (length == value.Length) // Must be all ASCII... if (length == value.Length) // Must be all ASCII...
@ -179,35 +194,46 @@ namespace Google.Protobuf
} }
else else
{ {
WriteStringToBuffer(buffer, ref state, value);
}
}
else
{
// Opportunity for future optimization:
// Large strings that don't fit into the current buffer segment
// can probably be optimized by using Utf8Encoding.GetEncoder()
// but more benchmarks would need to be added as evidence.
byte[] bytes = Utf8Encoding.GetBytes(value);
WriteRawBytes(ref buffer, ref state, bytes);
}
}
private static int WriteStringToBuffer(Span<byte> buffer, ref WriterInternalState state, string value)
{
#if NETSTANDARD1_1 #if NETSTANDARD1_1
// slowpath when Encoding.GetBytes(Char*, Int32, Byte*, Int32) is not available // slowpath when Encoding.GetBytes(Char*, Int32, Byte*, Int32) is not available
byte[] bytes = Utf8Encoding.GetBytes(value); byte[] bytes = Utf8Encoding.GetBytes(value);
WriteRawBytes(ref buffer, ref state, bytes); WriteRawBytes(ref buffer, ref state, bytes);
return bytes.Length;
#else #else
ReadOnlySpan<char> source = value.AsSpan(); ReadOnlySpan<char> source = value.AsSpan();
int bytesUsed; int bytesUsed;
unsafe unsafe
{ {
fixed (char* sourceChars = &MemoryMarshal.GetReference(source)) fixed (char* sourceChars = &MemoryMarshal.GetReference(source))
fixed (byte* destinationBytes = &MemoryMarshal.GetReference(buffer.Slice(state.position))) fixed (byte* destinationBytes = &MemoryMarshal.GetReference(buffer))
{ {
bytesUsed = Utf8Encoding.GetBytes(sourceChars, source.Length, destinationBytes, buffer.Length); bytesUsed = Utf8Encoding.GetBytes(
sourceChars,
source.Length,
destinationBytes + state.position,
buffer.Length - state.position);
} }
} }
state.position += bytesUsed; state.position += bytesUsed;
return bytesUsed;
#endif #endif
} }
}
else
{
// Opportunity for future optimization:
// Large strings that don't fit into the current buffer segment
// can probably be optimized by using Utf8Encoding.GetEncoder()
// but more benchmarks would need to be added as evidence.
byte[] bytes = Utf8Encoding.GetBytes(value);
WriteRawBytes(ref buffer, ref state, bytes);
}
}
/// <summary> /// <summary>
/// Write a byte string, without a tag, to the stream. /// Write a byte string, without a tag, to the stream.

@ -31,14 +31,21 @@
package com.google.protobuf; package com.google.protobuf;
final class Android { final class Android {
private Android() {
}
// Set to true in lite_proguard_android.pgcfg.
@SuppressWarnings("ConstantField")
private static boolean ASSUME_ANDROID;
private static final Class<?> MEMORY_CLASS = getClassForName("libcore.io.Memory"); private static final Class<?> MEMORY_CLASS = getClassForName("libcore.io.Memory");
private static final boolean IS_ROBOLECTRIC = private static final boolean IS_ROBOLECTRIC =
getClassForName("org.robolectric.Robolectric") != null; !ASSUME_ANDROID && getClassForName("org.robolectric.Robolectric") != null;
/** Returns {@code true} if running on an Android device. */ /** Returns {@code true} if running on an Android device. */
static boolean isOnAndroidDevice() { static boolean isOnAndroidDevice() {
return MEMORY_CLASS != null && !IS_ROBOLECTRIC; return ASSUME_ANDROID || (MEMORY_CLASS != null && !IS_ROBOLECTRIC);
} }
/** Returns the memory class or {@code null} if not on Android device. */ /** Returns the memory class or {@code null} if not on Android device. */

@ -184,20 +184,20 @@ final class RawMessageInfo implements MessageInfo {
int value; int value;
try { try {
value = (int) info.charAt(0); value = (int) info.charAt(0);
} catch (ArrayIndexOutOfBoundsException e) { } catch (StringIndexOutOfBoundsException e) {
// This is a fix for issues // This is a fix for issues
// that error out on a subset of phones on charAt(0) with an index out of bounds exception. // that error out on a subset of phones on charAt(0) with an index out of bounds exception.
char[] infoChars = info.toCharArray(); char[] infoChars = info.toCharArray();
info = new String(infoChars); info = new String(infoChars);
try { try {
value = (int) info.charAt(0); value = (int) info.charAt(0);
} catch (ArrayIndexOutOfBoundsException e2) { } catch (StringIndexOutOfBoundsException e2) {
try { try {
char[] infoChars2 = new char[info.length()]; char[] infoChars2 = new char[info.length()];
info.getChars(0, info.length(), infoChars2, 0); info.getChars(0, info.length(), infoChars2, 0);
info = new String(infoChars2); info = new String(infoChars2);
value = (int) info.charAt(0); value = (int) info.charAt(0);
} catch (ArrayIndexOutOfBoundsException e3) { } catch (StringIndexOutOfBoundsException | ArrayIndexOutOfBoundsException e3) {
throw new IllegalStateException( throw new IllegalStateException(
String.format( String.format(
"Failed parsing '%s' with charArray.length of %d", info, infoChars.length), "Failed parsing '%s' with charArray.length of %d", info, infoChars.length),

@ -1,3 +1,8 @@
# Skip runtime check for isOnAndroidDevice().
# One line to make it easy to remove with sed.
-assumevalues class com.google.protobuf.Android { static boolean ASSUME_ANDROID return true; }
-keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite { -keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite {
<fields>; <fields>;
} }

@ -46,7 +46,8 @@ goog.require('jspb.BinaryConstants');
goog.require('jspb.BinaryDecoder'); goog.require('jspb.BinaryDecoder');
goog.require('jspb.BinaryReader'); goog.require('jspb.BinaryReader');
goog.require('jspb.BinaryWriter'); goog.require('jspb.BinaryWriter');
goog.require('jspb.utils');
goog.requireType('jspb.BinaryMessage');
describe('binaryReaderTest', function() { describe('binaryReaderTest', function() {
@ -144,47 +145,91 @@ describe('binaryReaderTest', function() {
// Reading past the end of the stream should trigger an assertion. // Reading past the end of the stream should trigger an assertion.
reader = jspb.BinaryReader.alloc([9, 1]); reader = jspb.BinaryReader.alloc([9, 1]);
reader.nextField(); reader.nextField();
assertThrows(function() {reader.readFixed64()}); assertThrows(function() {
reader.readFixed64()
});
// Reading past the end of a submessage should trigger an assertion. // Reading past the end of a submessage should trigger an assertion.
reader = jspb.BinaryReader.alloc([10, 4, 13, 1, 1, 1]); reader = jspb.BinaryReader.alloc([10, 4, 13, 1, 1, 1]);
reader.nextField(); reader.nextField();
reader.readMessage(dummyMessage, function() { reader.readMessage(dummyMessage, function() {
reader.nextField(); reader.nextField();
assertThrows(function() {reader.readFixed32()}); assertThrows(function() {
reader.readFixed32()
});
}); });
// Skipping an invalid field should trigger an assertion. // Skipping an invalid field should trigger an assertion.
reader = jspb.BinaryReader.alloc([12, 1]); reader = jspb.BinaryReader.alloc([12, 1]);
reader.nextWireType_ = 1000; reader.nextWireType_ = 1000;
assertThrows(function() {reader.skipField()}); assertThrows(function() {
reader.skipField()
});
// Reading fields with the wrong wire type should assert. // Reading fields with the wrong wire type should assert.
reader = jspb.BinaryReader.alloc([9, 0, 0, 0, 0, 0, 0, 0, 0]); reader = jspb.BinaryReader.alloc([9, 0, 0, 0, 0, 0, 0, 0, 0]);
reader.nextField(); reader.nextField();
assertThrows(function() {reader.readInt32()}); assertThrows(function() {
assertThrows(function() {reader.readInt32String()}); reader.readInt32()
assertThrows(function() {reader.readInt64()}); });
assertThrows(function() {reader.readInt64String()}); assertThrows(function() {
assertThrows(function() {reader.readUint32()}); reader.readInt32String()
assertThrows(function() {reader.readUint32String()}); });
assertThrows(function() {reader.readUint64()}); assertThrows(function() {
assertThrows(function() {reader.readUint64String()}); reader.readInt64()
assertThrows(function() {reader.readSint32()}); });
assertThrows(function() {reader.readBool()}); assertThrows(function() {
assertThrows(function() {reader.readEnum()}); reader.readInt64String()
});
assertThrows(function() {
reader.readUint32()
});
assertThrows(function() {
reader.readUint32String()
});
assertThrows(function() {
reader.readUint64()
});
assertThrows(function() {
reader.readUint64String()
});
assertThrows(function() {
reader.readSint32()
});
assertThrows(function() {
reader.readBool()
});
assertThrows(function() {
reader.readEnum()
});
reader = jspb.BinaryReader.alloc([8, 1]); reader = jspb.BinaryReader.alloc([8, 1]);
reader.nextField(); reader.nextField();
assertThrows(function() {reader.readFixed32()}); assertThrows(function() {
assertThrows(function() {reader.readFixed64()}); reader.readFixed32()
assertThrows(function() {reader.readSfixed32()}); });
assertThrows(function() {reader.readSfixed64()}); assertThrows(function() {
assertThrows(function() {reader.readFloat()}); reader.readFixed64()
assertThrows(function() {reader.readDouble()}); });
assertThrows(function() {
reader.readSfixed32()
});
assertThrows(function() {
reader.readSfixed64()
});
assertThrows(function() {
reader.readFloat()
});
assertThrows(function() {
reader.readDouble()
});
assertThrows(function() {reader.readString()}); assertThrows(function() {
assertThrows(function() {reader.readBytes()}); reader.readString()
});
assertThrows(function() {
reader.readBytes()
});
}); });
@ -198,8 +243,8 @@ describe('binaryReaderTest', function() {
* @private * @private
* @suppress {missingProperties} * @suppress {missingProperties}
*/ */
var doTestUnsignedField_ = function(readField, var doTestUnsignedField_ = function(
writeField, epsilon, upperLimit, filter) { readField, writeField, epsilon, upperLimit, filter) {
assertNotNull(readField); assertNotNull(readField);
assertNotNull(writeField); assertNotNull(writeField);
@ -250,8 +295,8 @@ describe('binaryReaderTest', function() {
* @private * @private
* @suppress {missingProperties} * @suppress {missingProperties}
*/ */
var doTestSignedField_ = function(readField, var doTestSignedField_ = function(
writeField, epsilon, lowerLimit, upperLimit, filter) { readField, writeField, epsilon, lowerLimit, upperLimit, filter) {
var writer = new jspb.BinaryWriter(); var writer = new jspb.BinaryWriter();
// Encode zero and limits. // Encode zero and limits.
@ -267,20 +312,14 @@ describe('binaryReaderTest', function() {
for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) { for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) {
var val = filter(cursor); var val = filter(cursor);
writeField.call(writer, 6, val); writeField.call(writer, 6, val);
inputValues.push({ inputValues.push({fieldNumber: 6, value: val});
fieldNumber: 6,
value: val
});
} }
// Encode positive values. // Encode positive values.
for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) { for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
var val = filter(cursor); var val = filter(cursor);
writeField.call(writer, 7, val); writeField.call(writer, 7, val);
inputValues.push({ inputValues.push({fieldNumber: 7, value: val});
fieldNumber: 7,
value: val
});
} }
var reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
@ -327,33 +366,34 @@ describe('binaryReaderTest', function() {
assertNotUndefined(jspb.BinaryWriter.prototype.writeBool); assertNotUndefined(jspb.BinaryWriter.prototype.writeBool);
doTestUnsignedField_( doTestUnsignedField_(
jspb.BinaryReader.prototype.readUint32, jspb.BinaryReader.prototype.readUint32,
jspb.BinaryWriter.prototype.writeUint32, jspb.BinaryWriter.prototype.writeUint32, 1, Math.pow(2, 32) - 1,
1, Math.pow(2, 32) - 1, Math.round); Math.round);
doTestUnsignedField_( doTestUnsignedField_(
jspb.BinaryReader.prototype.readUint64, jspb.BinaryReader.prototype.readUint64,
jspb.BinaryWriter.prototype.writeUint64, jspb.BinaryWriter.prototype.writeUint64, 1, Math.pow(2, 64) - 1025,
1, Math.pow(2, 64) - 1025, Math.round); Math.round);
doTestSignedField_( doTestSignedField_(
jspb.BinaryReader.prototype.readInt32, jspb.BinaryReader.prototype.readInt32,
jspb.BinaryWriter.prototype.writeInt32, jspb.BinaryWriter.prototype.writeInt32, 1, -Math.pow(2, 31),
1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); Math.pow(2, 31) - 1, Math.round);
doTestSignedField_( doTestSignedField_(
jspb.BinaryReader.prototype.readInt64, jspb.BinaryReader.prototype.readInt64,
jspb.BinaryWriter.prototype.writeInt64, jspb.BinaryWriter.prototype.writeInt64, 1, -Math.pow(2, 63),
1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round); Math.pow(2, 63) - 513, Math.round);
doTestSignedField_( doTestSignedField_(
jspb.BinaryReader.prototype.readEnum, jspb.BinaryReader.prototype.readEnum,
jspb.BinaryWriter.prototype.writeEnum, jspb.BinaryWriter.prototype.writeEnum, 1, -Math.pow(2, 31),
1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); Math.pow(2, 31) - 1, Math.round);
doTestUnsignedField_( doTestUnsignedField_(
jspb.BinaryReader.prototype.readBool, jspb.BinaryReader.prototype.readBool,
jspb.BinaryWriter.prototype.writeBool, jspb.BinaryWriter.prototype.writeBool, 1, 1, function(x) {
1, 1, function(x) { return !!x; }); return !!x;
});
}); });
@ -387,24 +427,22 @@ describe('binaryReaderTest', function() {
// uint32 and sint32 take no more than 5 bytes // uint32 and sint32 take no more than 5 bytes
// 08 - field prefix (type = 0 means varint) // 08 - field prefix (type = 0 means varint)
doTestHexStringVarint_( doTestHexStringVarint_(
jspb.BinaryReader.prototype.readUint32, jspb.BinaryReader.prototype.readUint32, 12, '08 8C 80 80 80 00');
12, '08 8C 80 80 80 00');
// 11 stands for -6 in zigzag encoding // 11 stands for -6 in zigzag encoding
doTestHexStringVarint_( doTestHexStringVarint_(
jspb.BinaryReader.prototype.readSint32, jspb.BinaryReader.prototype.readSint32, -6, '08 8B 80 80 80 00');
-6, '08 8B 80 80 80 00');
// uint64 and sint64 take no more than 10 bytes // uint64 and sint64 take no more than 10 bytes
// 08 - field prefix (type = 0 means varint) // 08 - field prefix (type = 0 means varint)
doTestHexStringVarint_( doTestHexStringVarint_(
jspb.BinaryReader.prototype.readUint64, jspb.BinaryReader.prototype.readUint64, 12,
12, '08 8C 80 80 80 80 80 80 80 80 00'); '08 8C 80 80 80 80 80 80 80 80 00');
// 11 stands for -6 in zigzag encoding // 11 stands for -6 in zigzag encoding
doTestHexStringVarint_( doTestHexStringVarint_(
jspb.BinaryReader.prototype.readSint64, jspb.BinaryReader.prototype.readSint64, -6,
-6, '08 8B 80 80 80 80 80 80 80 80 00'); '08 8B 80 80 80 80 80 80 80 80 00');
}); });
/** /**
@ -440,27 +478,15 @@ describe('binaryReaderTest', function() {
var writer = new jspb.BinaryWriter(); var writer = new jspb.BinaryWriter();
var testSignedData = [ var testSignedData = [
'2730538252207801776', '2730538252207801776', '-2688470994844604560', '3398529779486536359',
'-2688470994844604560', '3568577411627971000', '272477188847484900', '-6649058714086158188',
'3398529779486536359', '-7695254765712060806', '-4525541438037104029', '-4993706538836508568',
'3568577411627971000',
'272477188847484900',
'-6649058714086158188',
'-7695254765712060806',
'-4525541438037104029',
'-4993706538836508568',
'4990160321893729138' '4990160321893729138'
]; ];
var testUnsignedData = [ var testUnsignedData = [
'7822732630241694882', '7822732630241694882', '6753602971916687352', '2399935075244442116',
'6753602971916687352', '8724292567325338867', '16948784802625696584', '4136275908516066934',
'2399935075244442116', '3575388346793700364', '5167142028379259461', '1557573948689737699',
'8724292567325338867',
'16948784802625696584',
'4136275908516066934',
'3575388346793700364',
'5167142028379259461',
'1557573948689737699',
'17100725280812548567' '17100725280812548567'
]; ];
@ -488,13 +514,13 @@ describe('binaryReaderTest', function() {
it('testZigzagFields', function() { it('testZigzagFields', function() {
doTestSignedField_( doTestSignedField_(
jspb.BinaryReader.prototype.readSint32, jspb.BinaryReader.prototype.readSint32,
jspb.BinaryWriter.prototype.writeSint32, jspb.BinaryWriter.prototype.writeSint32, 1, -Math.pow(2, 31),
1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); Math.pow(2, 31) - 1, Math.round);
doTestSignedField_( doTestSignedField_(
jspb.BinaryReader.prototype.readSint64, jspb.BinaryReader.prototype.readSint64,
jspb.BinaryWriter.prototype.writeSint64, jspb.BinaryWriter.prototype.writeSint64, 1, -Math.pow(2, 63),
1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round); Math.pow(2, 63) - 513, Math.round);
doTestSignedField_( doTestSignedField_(
jspb.BinaryReader.prototype.readSintHash64, jspb.BinaryReader.prototype.readSintHash64,
@ -509,23 +535,23 @@ describe('binaryReaderTest', function() {
it('testFixedFields', function() { it('testFixedFields', function() {
doTestUnsignedField_( doTestUnsignedField_(
jspb.BinaryReader.prototype.readFixed32, jspb.BinaryReader.prototype.readFixed32,
jspb.BinaryWriter.prototype.writeFixed32, jspb.BinaryWriter.prototype.writeFixed32, 1, Math.pow(2, 32) - 1,
1, Math.pow(2, 32) - 1, Math.round); Math.round);
doTestUnsignedField_( doTestUnsignedField_(
jspb.BinaryReader.prototype.readFixed64, jspb.BinaryReader.prototype.readFixed64,
jspb.BinaryWriter.prototype.writeFixed64, jspb.BinaryWriter.prototype.writeFixed64, 1, Math.pow(2, 64) - 1025,
1, Math.pow(2, 64) - 1025, Math.round); Math.round);
doTestSignedField_( doTestSignedField_(
jspb.BinaryReader.prototype.readSfixed32, jspb.BinaryReader.prototype.readSfixed32,
jspb.BinaryWriter.prototype.writeSfixed32, jspb.BinaryWriter.prototype.writeSfixed32, 1, -Math.pow(2, 31),
1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); Math.pow(2, 31) - 1, Math.round);
doTestSignedField_( doTestSignedField_(
jspb.BinaryReader.prototype.readSfixed64, jspb.BinaryReader.prototype.readSfixed64,
jspb.BinaryWriter.prototype.writeSfixed64, jspb.BinaryWriter.prototype.writeSfixed64, 1, -Math.pow(2, 63),
1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round); Math.pow(2, 63) - 513, Math.round);
}); });
@ -536,18 +562,17 @@ describe('binaryReaderTest', function() {
doTestSignedField_( doTestSignedField_(
jspb.BinaryReader.prototype.readFloat, jspb.BinaryReader.prototype.readFloat,
jspb.BinaryWriter.prototype.writeFloat, jspb.BinaryWriter.prototype.writeFloat,
jspb.BinaryConstants.FLOAT32_MIN, jspb.BinaryConstants.FLOAT32_MIN, -jspb.BinaryConstants.FLOAT32_MAX,
-jspb.BinaryConstants.FLOAT32_MAX, jspb.BinaryConstants.FLOAT32_MAX, truncate);
jspb.BinaryConstants.FLOAT32_MAX,
truncate);
doTestSignedField_( doTestSignedField_(
jspb.BinaryReader.prototype.readDouble, jspb.BinaryReader.prototype.readDouble,
jspb.BinaryWriter.prototype.writeDouble, jspb.BinaryWriter.prototype.writeDouble,
jspb.BinaryConstants.FLOAT64_EPS * 10, jspb.BinaryConstants.FLOAT64_EPS * 10,
-jspb.BinaryConstants.FLOAT64_MIN, -jspb.BinaryConstants.FLOAT64_MIN, jspb.BinaryConstants.FLOAT64_MIN,
jspb.BinaryConstants.FLOAT64_MIN, function(x) {
function(x) { return x; }); return x;
});
}); });

@ -44,7 +44,8 @@ goog.require('jspb.BinaryConstants');
goog.require('jspb.BinaryReader'); goog.require('jspb.BinaryReader');
goog.require('jspb.BinaryWriter'); goog.require('jspb.BinaryWriter');
goog.require('jspb.utils'); goog.require('jspb.utils');
goog.require('goog.crypt.base64');
goog.requireType('jspb.BinaryMessage');
/** /**
* @param {function()} func This function should throw an error when run. * @param {function()} func This function should throw an error when run.
@ -69,40 +70,82 @@ describe('binaryWriterTest', function() {
// Writing invalid field indices should assert. // Writing invalid field indices should assert.
writer = new jspb.BinaryWriter(); writer = new jspb.BinaryWriter();
assertFails(function() {writer.writeUint64(-1, 1);}); assertFails(function() {
writer.writeUint64(-1, 1);
});
// Writing out-of-range field values should assert. // Writing out-of-range field values should assert.
writer = new jspb.BinaryWriter(); writer = new jspb.BinaryWriter();
assertFails(function() {writer.writeInt32(1, -Infinity);}); assertFails(function() {
assertFails(function() {writer.writeInt32(1, Infinity);}); writer.writeInt32(1, -Infinity);
});
assertFails(function() {
writer.writeInt32(1, Infinity);
});
assertFails(function() {writer.writeInt64(1, -Infinity);}); assertFails(function() {
assertFails(function() {writer.writeInt64(1, Infinity);}); writer.writeInt64(1, -Infinity);
});
assertFails(function() {
writer.writeInt64(1, Infinity);
});
assertFails(function() {writer.writeUint32(1, -1);}); assertFails(function() {
assertFails(function() {writer.writeUint32(1, Infinity);}); writer.writeUint32(1, -1);
});
assertFails(function() {
writer.writeUint32(1, Infinity);
});
assertFails(function() {writer.writeUint64(1, -1);}); assertFails(function() {
assertFails(function() {writer.writeUint64(1, Infinity);}); writer.writeUint64(1, -1);
});
assertFails(function() {
writer.writeUint64(1, Infinity);
});
assertFails(function() {writer.writeSint32(1, -Infinity);}); assertFails(function() {
assertFails(function() {writer.writeSint32(1, Infinity);}); writer.writeSint32(1, -Infinity);
});
assertFails(function() {
writer.writeSint32(1, Infinity);
});
assertFails(function() {writer.writeSint64(1, -Infinity);}); assertFails(function() {
assertFails(function() {writer.writeSint64(1, Infinity);}); writer.writeSint64(1, -Infinity);
});
assertFails(function() {
writer.writeSint64(1, Infinity);
});
assertFails(function() {writer.writeFixed32(1, -1);}); assertFails(function() {
assertFails(function() {writer.writeFixed32(1, Infinity);}); writer.writeFixed32(1, -1);
});
assertFails(function() {
writer.writeFixed32(1, Infinity);
});
assertFails(function() {writer.writeFixed64(1, -1);}); assertFails(function() {
assertFails(function() {writer.writeFixed64(1, Infinity);}); writer.writeFixed64(1, -1);
});
assertFails(function() {
writer.writeFixed64(1, Infinity);
});
assertFails(function() {writer.writeSfixed32(1, -Infinity);}); assertFails(function() {
assertFails(function() {writer.writeSfixed32(1, Infinity);}); writer.writeSfixed32(1, -Infinity);
});
assertFails(function() {
writer.writeSfixed32(1, Infinity);
});
assertFails(function() {writer.writeSfixed64(1, -Infinity);}); assertFails(function() {
assertFails(function() {writer.writeSfixed64(1, Infinity);}); writer.writeSfixed64(1, -Infinity);
});
assertFails(function() {
writer.writeSfixed64(1, Infinity);
});
}); });

@ -46,7 +46,7 @@ goog.require('jspb.BinaryConstants');
goog.require('jspb.BinaryDecoder'); goog.require('jspb.BinaryDecoder');
goog.require('jspb.BinaryReader'); goog.require('jspb.BinaryReader');
goog.require('jspb.BinaryWriter'); goog.require('jspb.BinaryWriter');
goog.requireType('jspb.BinaryMessage');
describe('binaryReaderTest', function() { describe('binaryReaderTest', function() {
@ -144,47 +144,91 @@ describe('binaryReaderTest', function() {
// Reading past the end of the stream should trigger an assertion. // Reading past the end of the stream should trigger an assertion.
reader = jspb.BinaryReader.alloc([9, 1]); reader = jspb.BinaryReader.alloc([9, 1]);
reader.nextField(); reader.nextField();
assertThrows(function() {reader.readFixed64()}); assertThrows(function() {
reader.readFixed64()
});
// Reading past the end of a submessage should trigger an assertion. // Reading past the end of a submessage should trigger an assertion.
reader = jspb.BinaryReader.alloc([10, 4, 13, 1, 1, 1]); reader = jspb.BinaryReader.alloc([10, 4, 13, 1, 1, 1]);
reader.nextField(); reader.nextField();
reader.readMessage(dummyMessage, function() { reader.readMessage(dummyMessage, function() {
reader.nextField(); reader.nextField();
assertThrows(function() {reader.readFixed32()}); assertThrows(function() {
reader.readFixed32()
});
}); });
// Skipping an invalid field should trigger an assertion. // Skipping an invalid field should trigger an assertion.
reader = jspb.BinaryReader.alloc([12, 1]); reader = jspb.BinaryReader.alloc([12, 1]);
reader.nextWireType_ = 1000; reader.nextWireType_ = 1000;
assertThrows(function() {reader.skipField()}); assertThrows(function() {
reader.skipField()
});
// Reading fields with the wrong wire type should assert. // Reading fields with the wrong wire type should assert.
reader = jspb.BinaryReader.alloc([9, 0, 0, 0, 0, 0, 0, 0, 0]); reader = jspb.BinaryReader.alloc([9, 0, 0, 0, 0, 0, 0, 0, 0]);
reader.nextField(); reader.nextField();
assertThrows(function() {reader.readInt32()}); assertThrows(function() {
assertThrows(function() {reader.readInt32String()}); reader.readInt32()
assertThrows(function() {reader.readInt64()}); });
assertThrows(function() {reader.readInt64String()}); assertThrows(function() {
assertThrows(function() {reader.readUint32()}); reader.readInt32String()
assertThrows(function() {reader.readUint32String()}); });
assertThrows(function() {reader.readUint64()}); assertThrows(function() {
assertThrows(function() {reader.readUint64String()}); reader.readInt64()
assertThrows(function() {reader.readSint32()}); });
assertThrows(function() {reader.readBool()}); assertThrows(function() {
assertThrows(function() {reader.readEnum()}); reader.readInt64String()
});
assertThrows(function() {
reader.readUint32()
});
assertThrows(function() {
reader.readUint32String()
});
assertThrows(function() {
reader.readUint64()
});
assertThrows(function() {
reader.readUint64String()
});
assertThrows(function() {
reader.readSint32()
});
assertThrows(function() {
reader.readBool()
});
assertThrows(function() {
reader.readEnum()
});
reader = jspb.BinaryReader.alloc([8, 1]); reader = jspb.BinaryReader.alloc([8, 1]);
reader.nextField(); reader.nextField();
assertThrows(function() {reader.readFixed32()}); assertThrows(function() {
assertThrows(function() {reader.readFixed64()}); reader.readFixed32()
assertThrows(function() {reader.readSfixed32()}); });
assertThrows(function() {reader.readSfixed64()}); assertThrows(function() {
assertThrows(function() {reader.readFloat()}); reader.readFixed64()
assertThrows(function() {reader.readDouble()}); });
assertThrows(function() {
reader.readSfixed32()
});
assertThrows(function() {
reader.readSfixed64()
});
assertThrows(function() {
reader.readFloat()
});
assertThrows(function() {
reader.readDouble()
});
assertThrows(function() {reader.readString()}); assertThrows(function() {
assertThrows(function() {reader.readBytes()}); reader.readString()
});
assertThrows(function() {
reader.readBytes()
});
}); });
@ -198,8 +242,8 @@ describe('binaryReaderTest', function() {
* @private * @private
* @suppress {missingProperties} * @suppress {missingProperties}
*/ */
var doTestUnsignedField_ = function(readField, var doTestUnsignedField_ = function(
writeField, epsilon, upperLimit, filter) { readField, writeField, epsilon, upperLimit, filter) {
assertNotNull(readField); assertNotNull(readField);
assertNotNull(writeField); assertNotNull(writeField);
@ -250,8 +294,8 @@ describe('binaryReaderTest', function() {
* @private * @private
* @suppress {missingProperties} * @suppress {missingProperties}
*/ */
var doTestSignedField_ = function(readField, var doTestSignedField_ = function(
writeField, epsilon, lowerLimit, upperLimit, filter) { readField, writeField, epsilon, lowerLimit, upperLimit, filter) {
var writer = new jspb.BinaryWriter(); var writer = new jspb.BinaryWriter();
// Encode zero and limits. // Encode zero and limits.
@ -267,20 +311,14 @@ describe('binaryReaderTest', function() {
for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) { for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) {
var val = filter(cursor); var val = filter(cursor);
writeField.call(writer, 6, val); writeField.call(writer, 6, val);
inputValues.push({ inputValues.push({fieldNumber: 6, value: val});
fieldNumber: 6,
value: val
});
} }
// Encode positive values. // Encode positive values.
for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) { for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
var val = filter(cursor); var val = filter(cursor);
writeField.call(writer, 7, val); writeField.call(writer, 7, val);
inputValues.push({ inputValues.push({fieldNumber: 7, value: val});
fieldNumber: 7,
value: val
});
} }
var reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
@ -327,33 +365,34 @@ describe('binaryReaderTest', function() {
assertNotUndefined(jspb.BinaryWriter.prototype.writeBool); assertNotUndefined(jspb.BinaryWriter.prototype.writeBool);
doTestUnsignedField_( doTestUnsignedField_(
jspb.BinaryReader.prototype.readUint32, jspb.BinaryReader.prototype.readUint32,
jspb.BinaryWriter.prototype.writeUint32, jspb.BinaryWriter.prototype.writeUint32, 1, Math.pow(2, 32) - 1,
1, Math.pow(2, 32) - 1, Math.round); Math.round);
doTestUnsignedField_( doTestUnsignedField_(
jspb.BinaryReader.prototype.readUint64, jspb.BinaryReader.prototype.readUint64,
jspb.BinaryWriter.prototype.writeUint64, jspb.BinaryWriter.prototype.writeUint64, 1, Math.pow(2, 64) - 1025,
1, Math.pow(2, 64) - 1025, Math.round); Math.round);
doTestSignedField_( doTestSignedField_(
jspb.BinaryReader.prototype.readInt32, jspb.BinaryReader.prototype.readInt32,
jspb.BinaryWriter.prototype.writeInt32, jspb.BinaryWriter.prototype.writeInt32, 1, -Math.pow(2, 31),
1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); Math.pow(2, 31) - 1, Math.round);
doTestSignedField_( doTestSignedField_(
jspb.BinaryReader.prototype.readInt64, jspb.BinaryReader.prototype.readInt64,
jspb.BinaryWriter.prototype.writeInt64, jspb.BinaryWriter.prototype.writeInt64, 1, -Math.pow(2, 63),
1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round); Math.pow(2, 63) - 513, Math.round);
doTestSignedField_( doTestSignedField_(
jspb.BinaryReader.prototype.readEnum, jspb.BinaryReader.prototype.readEnum,
jspb.BinaryWriter.prototype.writeEnum, jspb.BinaryWriter.prototype.writeEnum, 1, -Math.pow(2, 31),
1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); Math.pow(2, 31) - 1, Math.round);
doTestUnsignedField_( doTestUnsignedField_(
jspb.BinaryReader.prototype.readBool, jspb.BinaryReader.prototype.readBool,
jspb.BinaryWriter.prototype.writeBool, jspb.BinaryWriter.prototype.writeBool, 1, 1, function(x) {
1, 1, function(x) { return !!x; }); return !!x;
});
}); });
@ -387,24 +426,22 @@ describe('binaryReaderTest', function() {
// uint32 and sint32 take no more than 5 bytes // uint32 and sint32 take no more than 5 bytes
// 08 - field prefix (type = 0 means varint) // 08 - field prefix (type = 0 means varint)
doTestHexStringVarint_( doTestHexStringVarint_(
jspb.BinaryReader.prototype.readUint32, jspb.BinaryReader.prototype.readUint32, 12, '08 8C 80 80 80 00');
12, '08 8C 80 80 80 00');
// 11 stands for -6 in zigzag encoding // 11 stands for -6 in zigzag encoding
doTestHexStringVarint_( doTestHexStringVarint_(
jspb.BinaryReader.prototype.readSint32, jspb.BinaryReader.prototype.readSint32, -6, '08 8B 80 80 80 00');
-6, '08 8B 80 80 80 00');
// uint64 and sint64 take no more than 10 bytes // uint64 and sint64 take no more than 10 bytes
// 08 - field prefix (type = 0 means varint) // 08 - field prefix (type = 0 means varint)
doTestHexStringVarint_( doTestHexStringVarint_(
jspb.BinaryReader.prototype.readUint64, jspb.BinaryReader.prototype.readUint64, 12,
12, '08 8C 80 80 80 80 80 80 80 80 00'); '08 8C 80 80 80 80 80 80 80 80 00');
// 11 stands for -6 in zigzag encoding // 11 stands for -6 in zigzag encoding
doTestHexStringVarint_( doTestHexStringVarint_(
jspb.BinaryReader.prototype.readSint64, jspb.BinaryReader.prototype.readSint64, -6,
-6, '08 8B 80 80 80 80 80 80 80 80 00'); '08 8B 80 80 80 80 80 80 80 80 00');
}); });
@ -415,27 +452,15 @@ describe('binaryReaderTest', function() {
var writer = new jspb.BinaryWriter(); var writer = new jspb.BinaryWriter();
var testSignedData = [ var testSignedData = [
'2730538252207801776', '2730538252207801776', '-2688470994844604560', '3398529779486536359',
'-2688470994844604560', '3568577411627971000', '272477188847484900', '-6649058714086158188',
'3398529779486536359', '-7695254765712060806', '-4525541438037104029', '-4993706538836508568',
'3568577411627971000',
'272477188847484900',
'-6649058714086158188',
'-7695254765712060806',
'-4525541438037104029',
'-4993706538836508568',
'4990160321893729138' '4990160321893729138'
]; ];
var testUnsignedData = [ var testUnsignedData = [
'7822732630241694882', '7822732630241694882', '6753602971916687352', '2399935075244442116',
'6753602971916687352', '8724292567325338867', '16948784802625696584', '4136275908516066934',
'2399935075244442116', '3575388346793700364', '5167142028379259461', '1557573948689737699',
'8724292567325338867',
'16948784802625696584',
'4136275908516066934',
'3575388346793700364',
'5167142028379259461',
'1557573948689737699',
'17100725280812548567' '17100725280812548567'
]; ];
@ -463,13 +488,13 @@ describe('binaryReaderTest', function() {
it('testZigzagFields', function() { it('testZigzagFields', function() {
doTestSignedField_( doTestSignedField_(
jspb.BinaryReader.prototype.readSint32, jspb.BinaryReader.prototype.readSint32,
jspb.BinaryWriter.prototype.writeSint32, jspb.BinaryWriter.prototype.writeSint32, 1, -Math.pow(2, 31),
1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); Math.pow(2, 31) - 1, Math.round);
doTestSignedField_( doTestSignedField_(
jspb.BinaryReader.prototype.readSint64, jspb.BinaryReader.prototype.readSint64,
jspb.BinaryWriter.prototype.writeSint64, jspb.BinaryWriter.prototype.writeSint64, 1, -Math.pow(2, 63),
1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round); Math.pow(2, 63) - 513, Math.round);
}); });
@ -479,23 +504,23 @@ describe('binaryReaderTest', function() {
it('testFixedFields', function() { it('testFixedFields', function() {
doTestUnsignedField_( doTestUnsignedField_(
jspb.BinaryReader.prototype.readFixed32, jspb.BinaryReader.prototype.readFixed32,
jspb.BinaryWriter.prototype.writeFixed32, jspb.BinaryWriter.prototype.writeFixed32, 1, Math.pow(2, 32) - 1,
1, Math.pow(2, 32) - 1, Math.round); Math.round);
doTestUnsignedField_( doTestUnsignedField_(
jspb.BinaryReader.prototype.readFixed64, jspb.BinaryReader.prototype.readFixed64,
jspb.BinaryWriter.prototype.writeFixed64, jspb.BinaryWriter.prototype.writeFixed64, 1, Math.pow(2, 64) - 1025,
1, Math.pow(2, 64) - 1025, Math.round); Math.round);
doTestSignedField_( doTestSignedField_(
jspb.BinaryReader.prototype.readSfixed32, jspb.BinaryReader.prototype.readSfixed32,
jspb.BinaryWriter.prototype.writeSfixed32, jspb.BinaryWriter.prototype.writeSfixed32, 1, -Math.pow(2, 31),
1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); Math.pow(2, 31) - 1, Math.round);
doTestSignedField_( doTestSignedField_(
jspb.BinaryReader.prototype.readSfixed64, jspb.BinaryReader.prototype.readSfixed64,
jspb.BinaryWriter.prototype.writeSfixed64, jspb.BinaryWriter.prototype.writeSfixed64, 1, -Math.pow(2, 63),
1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round); Math.pow(2, 63) - 513, Math.round);
}); });
@ -506,18 +531,17 @@ describe('binaryReaderTest', function() {
doTestSignedField_( doTestSignedField_(
jspb.BinaryReader.prototype.readFloat, jspb.BinaryReader.prototype.readFloat,
jspb.BinaryWriter.prototype.writeFloat, jspb.BinaryWriter.prototype.writeFloat,
jspb.BinaryConstants.FLOAT32_MIN, jspb.BinaryConstants.FLOAT32_MIN, -jspb.BinaryConstants.FLOAT32_MAX,
-jspb.BinaryConstants.FLOAT32_MAX, jspb.BinaryConstants.FLOAT32_MAX, truncate);
jspb.BinaryConstants.FLOAT32_MAX,
truncate);
doTestSignedField_( doTestSignedField_(
jspb.BinaryReader.prototype.readDouble, jspb.BinaryReader.prototype.readDouble,
jspb.BinaryWriter.prototype.writeDouble, jspb.BinaryWriter.prototype.writeDouble,
jspb.BinaryConstants.FLOAT64_EPS * 10, jspb.BinaryConstants.FLOAT64_EPS * 10,
-jspb.BinaryConstants.FLOAT64_MIN, -jspb.BinaryConstants.FLOAT64_MIN, jspb.BinaryConstants.FLOAT64_MIN,
jspb.BinaryConstants.FLOAT64_MIN, function(x) {
function(x) { return x; }); return x;
});
}); });

@ -41,7 +41,7 @@
goog.require('goog.crypt'); goog.require('goog.crypt');
goog.require('goog.testing.asserts'); goog.require('goog.testing.asserts');
goog.require('jspb.BinaryWriter'); goog.require('jspb.BinaryWriter');
goog.requireType('jspb.BinaryMessage');
/** /**
* @param {function()} func This function should throw an error when run. * @param {function()} func This function should throw an error when run.
@ -67,40 +67,82 @@ describe('binaryWriterTest', function() {
// Writing invalid field indices should assert. // Writing invalid field indices should assert.
writer = new jspb.BinaryWriter(); writer = new jspb.BinaryWriter();
assertFails(function() {writer.writeUint64(-1, 1);}); assertFails(function() {
writer.writeUint64(-1, 1);
});
// Writing out-of-range field values should assert. // Writing out-of-range field values should assert.
writer = new jspb.BinaryWriter(); writer = new jspb.BinaryWriter();
assertFails(function() {writer.writeInt32(1, -Infinity);}); assertFails(function() {
assertFails(function() {writer.writeInt32(1, Infinity);}); writer.writeInt32(1, -Infinity);
});
assertFails(function() {
writer.writeInt32(1, Infinity);
});
assertFails(function() {writer.writeInt64(1, -Infinity);}); assertFails(function() {
assertFails(function() {writer.writeInt64(1, Infinity);}); writer.writeInt64(1, -Infinity);
});
assertFails(function() {
writer.writeInt64(1, Infinity);
});
assertFails(function() {writer.writeUint32(1, -1);}); assertFails(function() {
assertFails(function() {writer.writeUint32(1, Infinity);}); writer.writeUint32(1, -1);
});
assertFails(function() {
writer.writeUint32(1, Infinity);
});
assertFails(function() {writer.writeUint64(1, -1);}); assertFails(function() {
assertFails(function() {writer.writeUint64(1, Infinity);}); writer.writeUint64(1, -1);
});
assertFails(function() {
writer.writeUint64(1, Infinity);
});
assertFails(function() {writer.writeSint32(1, -Infinity);}); assertFails(function() {
assertFails(function() {writer.writeSint32(1, Infinity);}); writer.writeSint32(1, -Infinity);
});
assertFails(function() {
writer.writeSint32(1, Infinity);
});
assertFails(function() {writer.writeSint64(1, -Infinity);}); assertFails(function() {
assertFails(function() {writer.writeSint64(1, Infinity);}); writer.writeSint64(1, -Infinity);
});
assertFails(function() {
writer.writeSint64(1, Infinity);
});
assertFails(function() {writer.writeFixed32(1, -1);}); assertFails(function() {
assertFails(function() {writer.writeFixed32(1, Infinity);}); writer.writeFixed32(1, -1);
});
assertFails(function() {
writer.writeFixed32(1, Infinity);
});
assertFails(function() {writer.writeFixed64(1, -1);}); assertFails(function() {
assertFails(function() {writer.writeFixed64(1, Infinity);}); writer.writeFixed64(1, -1);
});
assertFails(function() {
writer.writeFixed64(1, Infinity);
});
assertFails(function() {writer.writeSfixed32(1, -Infinity);}); assertFails(function() {
assertFails(function() {writer.writeSfixed32(1, Infinity);}); writer.writeSfixed32(1, -Infinity);
});
assertFails(function() {
writer.writeSfixed32(1, Infinity);
});
assertFails(function() {writer.writeSfixed64(1, -Infinity);}); assertFails(function() {
assertFails(function() {writer.writeSfixed64(1, Infinity);}); writer.writeSfixed64(1, -Infinity);
});
assertFails(function() {
writer.writeSfixed64(1, Infinity);
});
}); });

@ -40,6 +40,8 @@ goog.require('proto.jspb.test.TestMapFields');
goog.require('proto.jspb.test.MapValueMessageNoBinary'); goog.require('proto.jspb.test.MapValueMessageNoBinary');
goog.require('proto.jspb.test.TestMapFieldsNoBinary'); goog.require('proto.jspb.test.TestMapFieldsNoBinary');
goog.requireType('jspb.Map');
/** /**
* Helper: check that the given map has exactly this set of (sorted) entries. * Helper: check that the given map has exactly this set of (sorted) entries.
* @param {!jspb.Map} map * @param {!jspb.Map} map
@ -98,7 +100,9 @@ function makeTests(msgInfo, submessageCtor, suffix) {
msg.getMapStringMsgMap().get('k').setFoo(42); msg.getMapStringMsgMap().get('k').setFoo(42);
msg.getMapStringMsgMap().get('l').setFoo(84); msg.getMapStringMsgMap().get('l').setFoo(84);
msg.getMapInt32StringMap().set(-1, 'a').set(42, 'b'); msg.getMapInt32StringMap().set(-1, 'a').set(42, 'b');
msg.getMapInt64StringMap().set(0x123456789abc, 'c').set(0xcba987654321, 'd'); msg.getMapInt64StringMap()
.set(0x123456789abc, 'c')
.set(0xcba987654321, 'd');
msg.getMapBoolStringMap().set(false, 'e').set(true, 'f'); msg.getMapBoolStringMap().set(false, 'e').set(true, 'f');
}; };
@ -107,42 +111,24 @@ function makeTests(msgInfo, submessageCtor, suffix) {
* @param {?} msg * @param {?} msg
*/ */
var checkMapFields = function(msg) { var checkMapFields = function(msg) {
checkMapEquals(msg.getMapStringStringMap(), [ checkMapEquals(
['asdf', 'jkl;'], msg.getMapStringStringMap(),
['key 2', 'hello world'] [['asdf', 'jkl;'], ['key 2', 'hello world']]);
]); checkMapEquals(msg.getMapStringInt32Map(), [['a', 1], ['b', -2]]);
checkMapEquals(msg.getMapStringInt32Map(), [ checkMapEquals(
['a', 1], msg.getMapStringInt64Map(), [['c', 0x100000000], ['d', 0x200000000]]);
['b', -2] checkMapEquals(msg.getMapStringBoolMap(), [['e', true], ['f', false]]);
]); checkMapEquals(
checkMapEquals(msg.getMapStringInt64Map(), [ msg.getMapStringDoubleMap(), [['g', 3.14159], ['h', 2.71828]]);
['c', 0x100000000],
['d', 0x200000000]
]);
checkMapEquals(msg.getMapStringBoolMap(), [
['e', true],
['f', false]
]);
checkMapEquals(msg.getMapStringDoubleMap(), [
['g', 3.14159],
['h', 2.71828]
]);
checkMapEquals(msg.getMapStringEnumMap(), [ checkMapEquals(msg.getMapStringEnumMap(), [
['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR], ['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR],
['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ] ['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ]
]); ]);
checkMapEquals(msg.getMapInt32StringMap(), [ checkMapEquals(msg.getMapInt32StringMap(), [[-1, 'a'], [42, 'b']]);
[-1, 'a'], checkMapEquals(
[42, 'b'] msg.getMapInt64StringMap(),
]); [[0x123456789abc, 'c'], [0xcba987654321, 'd']]);
checkMapEquals(msg.getMapInt64StringMap(), [ checkMapEquals(msg.getMapBoolStringMap(), [[false, 'e'], [true, 'f']]);
[0x123456789abc, 'c'],
[0xcba987654321, 'd']
]);
checkMapEquals(msg.getMapBoolStringMap(), [
[false, 'e'],
[true, 'f']
]);
assertEquals(msg.getMapStringMsgMap().getLength(), 2); assertEquals(msg.getMapStringMsgMap().getLength(), 2);
assertEquals(msg.getMapStringMsgMap().get('k').getFoo(), 42); assertEquals(msg.getMapStringMsgMap().get('k').getFoo(), 42);
@ -187,10 +173,7 @@ function makeTests(msgInfo, submessageCtor, suffix) {
assertElementsEquals(it.next().value, ['asdf', 'hello world']); assertElementsEquals(it.next().value, ['asdf', 'hello world']);
assertElementsEquals(it.next().value, ['jkl;', 'key 2']); assertElementsEquals(it.next().value, ['jkl;', 'key 2']);
assertEquals(it.next().done, true); assertEquals(it.next().done, true);
checkMapEquals(m, [ checkMapEquals(m, [['asdf', 'hello world'], ['jkl;', 'key 2']]);
['asdf', 'hello world'],
['jkl;', 'key 2']
]);
m.del('jkl;'); m.del('jkl;');
assertEquals(m.has('jkl;'), false); assertEquals(m.has('jkl;'), false);
assertEquals(m.get('jkl;'), undefined); assertEquals(m.get('jkl;'), undefined);
@ -267,11 +250,7 @@ function makeTests(msgInfo, submessageCtor, suffix) {
*/ */
it('testLazyMapSync' + suffix, function() { it('testLazyMapSync' + suffix, function() {
// Start with a JSPB array containing a few map entries. // Start with a JSPB array containing a few map entries.
var entries = [ var entries = [['a', 'entry 1'], ['c', 'entry 2'], ['b', 'entry 3']];
['a', 'entry 1'],
['c', 'entry 2'],
['b', 'entry 3']
];
var msg = new msgInfo.constructor([entries]); var msg = new msgInfo.constructor([entries]);
assertEquals(entries.length, 3); assertEquals(entries.length, 3);
assertEquals(entries[0][0], 'a'); assertEquals(entries[0][0], 'a');
@ -290,12 +269,16 @@ function makeTests(msgInfo, submessageCtor, suffix) {
} }
describe('mapsTest', function() { describe('mapsTest', function() {
makeTests({ makeTests(
{
constructor: proto.jspb.test.TestMapFields, constructor: proto.jspb.test.TestMapFields,
deserializeBinary: proto.jspb.test.TestMapFields.deserializeBinary deserializeBinary: proto.jspb.test.TestMapFields.deserializeBinary
}, proto.jspb.test.MapValueMessage, "_Binary"); },
makeTests({ proto.jspb.test.MapValueMessage, '_Binary');
makeTests(
{
constructor: proto.jspb.test.TestMapFieldsNoBinary, constructor: proto.jspb.test.TestMapFieldsNoBinary,
deserializeBinary: null deserializeBinary: null
}, proto.jspb.test.MapValueMessageNoBinary, "_NoBinary"); },
proto.jspb.test.MapValueMessageNoBinary, '_NoBinary');
}); });

@ -67,7 +67,6 @@ goog.require('proto.jspb.test.Simple1');
goog.require('proto.jspb.test.Simple2'); goog.require('proto.jspb.test.Simple2');
goog.require('proto.jspb.test.SpecialCases'); goog.require('proto.jspb.test.SpecialCases');
goog.require('proto.jspb.test.TestClone'); goog.require('proto.jspb.test.TestClone');
goog.require('proto.jspb.test.TestEndsWithBytes');
goog.require('proto.jspb.test.TestGroup'); goog.require('proto.jspb.test.TestGroup');
goog.require('proto.jspb.test.TestGroup1'); goog.require('proto.jspb.test.TestGroup1');
goog.require('proto.jspb.test.TestMessageWithOneof'); goog.require('proto.jspb.test.TestMessageWithOneof');
@ -77,7 +76,7 @@ goog.require('proto.jspb.test.TestReservedNamesExtension');
// CommonJS-LoadFromFile: test2_pb proto.jspb.test // CommonJS-LoadFromFile: test2_pb proto.jspb.test
goog.require('proto.jspb.test.ExtensionMessage'); goog.require('proto.jspb.test.ExtensionMessage');
goog.require('proto.jspb.test.TestExtensionsMessage'); goog.require('proto.jspb.test.TestExtensionsMessage');
goog.require('proto.jspb.test.simple1');
@ -107,54 +106,54 @@ describe('Message test suite', function() {
var foo = new proto.jspb.test.Complex(data1); var foo = new proto.jspb.test.Complex(data1);
var bar = new proto.jspb.test.Complex(data2); var bar = new proto.jspb.test.Complex(data2);
var result = foo.toObject(); var result = foo.toObject();
assertObjectEquals({ assertObjectEquals(
{
aString: 'a', aString: 'a',
anOutOfOrderBool: true, anOutOfOrderBool: true,
aNestedMessage: { aNestedMessage: {anInt: 11},
anInt: 11
},
aRepeatedMessageList: [{anInt: 22}, {anInt: 33}], aRepeatedMessageList: [{anInt: 22}, {anInt: 33}],
aRepeatedStringList: ['s1', 's2'] aRepeatedStringList: ['s1', 's2']
}, result); },
result);
// Now test with the jspb instances included. // Now test with the jspb instances included.
result = foo.toObject(true /* opt_includeInstance */); result = foo.toObject(true /* opt_includeInstance */);
assertObjectEquals({ assertObjectEquals(
{
aString: 'a', aString: 'a',
anOutOfOrderBool: true, anOutOfOrderBool: true,
aNestedMessage: { aNestedMessage:
anInt: 11, {anInt: 11, $jspbMessageInstance: foo.getANestedMessage()},
$jspbMessageInstance: foo.getANestedMessage()
},
aRepeatedMessageList: [ aRepeatedMessageList: [
{anInt: 22, $jspbMessageInstance: foo.getARepeatedMessageList()[0]}, {anInt: 22, $jspbMessageInstance: foo.getARepeatedMessageList()[0]},
{anInt: 33, $jspbMessageInstance: foo.getARepeatedMessageList()[1]} {anInt: 33, $jspbMessageInstance: foo.getARepeatedMessageList()[1]}
], ],
aRepeatedStringList: ['s1', 's2'], aRepeatedStringList: ['s1', 's2'],
$jspbMessageInstance: foo $jspbMessageInstance: foo
}, result); },
result);
}); });
it('testMissingFields', function() { it('testMissingFields', function() {
var foo = new proto.jspb.test.Complex([ var foo = new proto.jspb.test.Complex([
undefined, undefined, undefined, [], undefined, undefined, undefined, [], undefined, undefined, undefined,
undefined, undefined, undefined, undefined]); undefined
]);
var bar = new proto.jspb.test.Complex([ var bar = new proto.jspb.test.Complex([
undefined, undefined, undefined, [], undefined, undefined, undefined, [], undefined, undefined, undefined,
undefined, undefined, undefined, undefined]); undefined
]);
var result = foo.toObject(); var result = foo.toObject();
assertObjectEquals({ assertObjectEquals(
{
aString: undefined, aString: undefined,
anOutOfOrderBool: undefined, anOutOfOrderBool: undefined,
aNestedMessage: { aNestedMessage: {anInt: undefined},
anInt: undefined
},
// Note: JsPb converts undefined repeated fields to empty arrays. // Note: JsPb converts undefined repeated fields to empty arrays.
aRepeatedMessageList: [], aRepeatedMessageList: [],
aRepeatedStringList: [] aRepeatedStringList: []
}, result); },
result);
}); });
it('testNestedComplexMessage', function() { it('testNestedComplexMessage', function() {
@ -167,20 +166,21 @@ describe('Message test suite', function() {
it('testSpecialCases', function() { it('testSpecialCases', function() {
// Note: Some property names are reserved in JavaScript. // Note: Some property names are reserved in JavaScript.
// These names are converted to the Js property named pb_<reserved_name>. // These names are converted to the Js property named pb_<reserved_name>.
var special = var special = new proto.jspb.test.SpecialCases(
new proto.jspb.test.SpecialCases(['normal', 'default', 'function', ['normal', 'default', 'function', 'var']);
'var']);
var result = special.toObject(); var result = special.toObject();
assertObjectEquals({ assertObjectEquals(
{
normal: 'normal', normal: 'normal',
pb_default: 'default', pb_default: 'default',
pb_function: 'function', pb_function: 'function',
pb_var: 'var' pb_var: 'var'
}, result); },
result);
}); });
it('testDefaultValues', function() { it('testDefaultValues', function() {
var defaultString = "default<>\'\"abc"; var defaultString = 'default<>\'"abc';
var response = new proto.jspb.test.DefaultValues(); var response = new proto.jspb.test.DefaultValues();
// Test toObject // Test toObject
@ -244,8 +244,10 @@ describe('Message test suite', function() {
// Test that clearing the values reverts them to the default state. // Test that clearing the values reverts them to the default state.
response = makeDefault(['blah', false, 111, 77]); response = makeDefault(['blah', false, 111, 77]);
response.clearStringField(); response.clearBoolField(); response.clearStringField();
response.clearIntField(); response.clearEnumField(); response.clearBoolField();
response.clearIntField();
response.clearEnumField();
assertEquals(defaultString, response.getStringField()); assertEquals(defaultString, response.getStringField());
assertEquals(true, response.getBoolField()); assertEquals(true, response.getBoolField());
assertEquals(11, response.getIntField()); assertEquals(11, response.getIntField());
@ -257,8 +259,10 @@ describe('Message test suite', function() {
// Test that setFoo(null) clears the values. // Test that setFoo(null) clears the values.
response = makeDefault(['blah', false, 111, 77]); response = makeDefault(['blah', false, 111, 77]);
response.setStringField(null); response.setBoolField(null); response.setStringField(null);
response.setIntField(undefined); response.setEnumField(undefined); response.setBoolField(null);
response.setIntField(undefined);
response.setEnumField(undefined);
assertEquals(defaultString, response.getStringField()); assertEquals(defaultString, response.getStringField());
assertEquals(true, response.getBoolField()); assertEquals(true, response.getBoolField());
assertEquals(11, response.getIntField()); assertEquals(11, response.getIntField());
@ -295,8 +299,8 @@ describe('Message test suite', function() {
it('testDifferenceRawObject', /** @suppress {visibility} */ function() { it('testDifferenceRawObject', /** @suppress {visibility} */ function() {
var p1 = new proto.jspb.test.HasExtensions(['hi', 'diff', {}]); var p1 = new proto.jspb.test.HasExtensions(['hi', 'diff', {}]);
var p2 = new proto.jspb.test.HasExtensions(['hi', 'what', var p2 =
{1000: 'unique'}]); new proto.jspb.test.HasExtensions(['hi', 'what', {1000: 'unique'}]);
var diff = /** @type {proto.jspb.test.HasExtensions} */ var diff = /** @type {proto.jspb.test.HasExtensions} */
(jspb.Message.difference(p1, p2)); (jspb.Message.difference(p1, p2));
assertEquals('', diff.getStr1()); assertEquals('', diff.getStr1());
@ -310,13 +314,13 @@ describe('Message test suite', function() {
assertTrue(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['hi']))); assertTrue(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['hi'])));
assertFalse(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['bye']))); assertFalse(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['bye'])));
var s1b = new proto.jspb.test.Simple1(['hi', ['hello']]); var s1b = new proto.jspb.test.Simple1(['hi', ['hello']]);
assertTrue(jspb.Message.equals(s1b, assertTrue(jspb.Message.equals(
new proto.jspb.test.Simple1(['hi', ['hello']]))); s1b, new proto.jspb.test.Simple1(['hi', ['hello']])));
assertTrue(jspb.Message.equals(s1b, assertTrue(jspb.Message.equals(s1b, new proto.jspb.test.Simple1([
new proto.jspb.test.Simple1(['hi', ['hello', undefined, 'hi', ['hello', undefined, undefined, undefined]
undefined, undefined]]))); ])));
assertFalse(jspb.Message.equals(s1b, assertFalse(jspb.Message.equals(
new proto.jspb.test.Simple1(['no', ['hello']]))); s1b, new proto.jspb.test.Simple1(['no', ['hello']])));
// Test with messages of different types // Test with messages of different types
var s2 = new proto.jspb.test.Simple2(['hi']); var s2 = new proto.jspb.test.Simple2(['hi']);
assertFalse(jspb.Message.equals(s1, s2)); assertFalse(jspb.Message.equals(s1, s2));
@ -324,12 +328,12 @@ describe('Message test suite', function() {
it('testEquals_softComparison', function() { it('testEquals_softComparison', function() {
var s1 = new proto.jspb.test.Simple1(['hi', [], null]); var s1 = new proto.jspb.test.Simple1(['hi', [], null]);
assertTrue(jspb.Message.equals(s1, assertTrue(
new proto.jspb.test.Simple1(['hi', []]))); jspb.Message.equals(s1, new proto.jspb.test.Simple1(['hi', []])));
var s1b = new proto.jspb.test.Simple1(['hi', [], true]); var s1b = new proto.jspb.test.Simple1(['hi', [], true]);
assertTrue(jspb.Message.equals(s1b, assertTrue(
new proto.jspb.test.Simple1(['hi', [], 1]))); jspb.Message.equals(s1b, new proto.jspb.test.Simple1(['hi', [], 1])));
}); });
it('testEqualsComplex', function() { it('testEqualsComplex', function() {
@ -352,36 +356,28 @@ describe('Message test suite', function() {
it('testEqualsExtensionsConstructed', function() { it('testEqualsExtensionsConstructed', function() {
assertTrue(jspb.Message.equals( assertTrue(jspb.Message.equals(
new proto.jspb.test.HasExtensions([]), new proto.jspb.test.HasExtensions([]),
new proto.jspb.test.HasExtensions([{}]) new proto.jspb.test.HasExtensions([{}])));
));
assertTrue(jspb.Message.equals( assertTrue(jspb.Message.equals(
new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]), new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]),
new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]) new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}])));
));
assertFalse(jspb.Message.equals( assertFalse(jspb.Message.equals(
new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]), new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]),
new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'b'}]}]) new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'b'}]}])));
));
assertTrue(jspb.Message.equals( assertTrue(jspb.Message.equals(
new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]), new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]),
new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]) new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}])));
));
assertTrue(jspb.Message.equals( assertTrue(jspb.Message.equals(
new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]), new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]),
new proto.jspb.test.HasExtensions([,,, {100: [{200: 'a'}]}]) new proto.jspb.test.HasExtensions([, , , {100: [{200: 'a'}]}])));
));
assertTrue(jspb.Message.equals( assertTrue(jspb.Message.equals(
new proto.jspb.test.HasExtensions([, , , {100: [{200: 'a'}]}]), new proto.jspb.test.HasExtensions([, , , {100: [{200: 'a'}]}]),
new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]) new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}])));
));
assertTrue(jspb.Message.equals( assertTrue(jspb.Message.equals(
new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]), new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]),
new proto.jspb.test.HasExtensions(['hi',,, {100: [{200: 'a'}]}]) new proto.jspb.test.HasExtensions(['hi', , , {100: [{200: 'a'}]}])));
));
assertTrue(jspb.Message.equals( assertTrue(jspb.Message.equals(
new proto.jspb.test.HasExtensions(['hi', , , {100: [{200: 'a'}]}]), new proto.jspb.test.HasExtensions(['hi', , , {100: [{200: 'a'}]}]),
new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]) new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}])));
));
}); });
it('testEqualsExtensionsUnconstructed', function() { it('testEqualsExtensionsUnconstructed', function() {
@ -407,13 +403,13 @@ describe('Message test suite', function() {
it('testToMap', function() { it('testToMap', function() {
var p1 = new proto.jspb.test.Simple1(['k', ['v']]); var p1 = new proto.jspb.test.Simple1(['k', ['v']]);
var p2 = new proto.jspb.test.Simple1(['k1', ['v1', 'v2']]); var p2 = new proto.jspb.test.Simple1(['k1', ['v1', 'v2']]);
var soymap = jspb.Message.toMap([p1, p2], var soymap = jspb.Message.toMap(
proto.jspb.test.Simple1.prototype.getAString, [p1, p2], proto.jspb.test.Simple1.prototype.getAString,
proto.jspb.test.Simple1.prototype.toObject); proto.jspb.test.Simple1.prototype.toObject);
assertEquals('k', soymap['k'].aString); assertEquals('k', soymap['k'].aString);
assertArrayEquals(['v'], soymap['k'].aRepeatedStringList); assertArrayEquals(['v'], soymap['k'].aRepeatedStringList);
var protomap = jspb.Message.toMap([p1, p2], var protomap = jspb.Message.toMap(
proto.jspb.test.Simple1.prototype.getAString); [p1, p2], proto.jspb.test.Simple1.prototype.getAString);
assertEquals('k', protomap['k'].getAString()); assertEquals('k', protomap['k'].getAString());
assertArrayEquals(['v'], protomap['k'].getARepeatedStringList()); assertArrayEquals(['v'], protomap['k'].getARepeatedStringList());
}); });
@ -434,8 +430,12 @@ describe('Message test suite', function() {
extension.setExt('e1'); extension.setExt('e1');
original.setExtension(proto.jspb.test.IsExtension.extField, extension); original.setExtension(proto.jspb.test.IsExtension.extField, extension);
var clone = original.clone(); var clone = original.clone();
assertArrayEquals(['v1',, ['x1', ['y1', 'z1']],, assertArrayEquals(
[['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1,, { 100: [, 'e1'] }], [
'v1', , ['x1', ['y1', 'z1']], ,
[['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1, ,
{100: [, 'e1']}
],
clone.toArray()); clone.toArray());
clone.setStr('v2'); clone.setStr('v2');
var simple4 = new proto.jspb.test.Simple1(['a1', ['b1', 'c1']]); var simple4 = new proto.jspb.test.Simple1(['a1', ['b1', 'c1']]);
@ -452,11 +452,19 @@ describe('Message test suite', function() {
var newExtension = new proto.jspb.test.CloneExtension(); var newExtension = new proto.jspb.test.CloneExtension();
newExtension.setExt('e2'); newExtension.setExt('e2');
clone.setExtension(proto.jspb.test.CloneExtension.extField, newExtension); clone.setExtension(proto.jspb.test.CloneExtension.extField, newExtension);
assertArrayEquals(['v2',, ['a1', ['b1', 'c1']],, assertArrayEquals(
[['a2', ['b2', 'c2']], ['a3', ['b3', 'c3']]], bytes2,, { 100: [, 'e2'] }], [
'v2', , ['a1', ['b1', 'c1']], ,
[['a2', ['b2', 'c2']], ['a3', ['b3', 'c3']]], bytes2, ,
{100: [, 'e2']}
],
clone.toArray()); clone.toArray());
assertArrayEquals(['v1',, ['x1', ['y1', 'z1']],, assertArrayEquals(
[['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1,, { 100: [, 'e1'] }], [
'v1', , ['x1', ['y1', 'z1']], ,
[['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1, ,
{100: [, 'e1']}
],
original.toArray()); original.toArray());
}); });
@ -488,11 +496,12 @@ describe('Message test suite', function() {
jspb.Message.copyInto(original, dest); jspb.Message.copyInto(original, dest);
assertArrayEquals(original.toArray(), dest.toArray()); assertArrayEquals(original.toArray(), dest.toArray());
assertEquals('x1', dest.getSimple1().getAString()); assertEquals('x1', dest.getSimple1().getAString());
assertEquals('e1', assertEquals(
'e1',
dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt()); dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt());
dest.getSimple1().setAString('new value'); dest.getSimple1().setAString('new value');
assertNotEquals(dest.getSimple1().getAString(), assertNotEquals(
original.getSimple1().getAString()); dest.getSimple1().getAString(), original.getSimple1().getAString());
if (supportsUint8Array) { if (supportsUint8Array) {
dest.getBytesField()[0] = 7; dest.getBytesField()[0] = 7;
assertObjectEquals(bytes1, original.getBytesField()); assertObjectEquals(bytes1, original.getBytesField());
@ -502,12 +511,12 @@ describe('Message test suite', function() {
assertObjectEquals(bytes1, original.getBytesField()); assertObjectEquals(bytes1, original.getBytesField());
assertObjectEquals('789', dest.getBytesField()); assertObjectEquals('789', dest.getBytesField());
} }
dest.getExtension(proto.jspb.test.CloneExtension.extField). dest.getExtension(proto.jspb.test.CloneExtension.extField)
setExt('new value'); .setExt('new value');
assertNotEquals( assertNotEquals(
dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt(), dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt(),
original.getExtension( original.getExtension(proto.jspb.test.CloneExtension.extField)
proto.jspb.test.CloneExtension.extField).getExt()); .getExt());
}); });
it('testCopyInto_notSameType', function() { it('testCopyInto_notSameType', function() {
@ -525,25 +534,31 @@ describe('Message test suite', function() {
var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2']]); var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2']]);
var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']); var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']);
extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1); extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1);
extendable.setExtension(proto.jspb.test.IndirectExtension.simple, extendable.setExtension(
extension2); proto.jspb.test.IndirectExtension.simple, extension2);
extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy'); extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy');
extendable.setExtension(proto.jspb.test.IndirectExtension.repeatedStrList, extendable.setExtension(
['a', 'b']); proto.jspb.test.IndirectExtension.repeatedStrList, ['a', 'b']);
var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]); var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]);
var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2']]); var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2']]);
extendable.setExtension( extendable.setExtension(
proto.jspb.test.IndirectExtension.repeatedSimpleList, proto.jspb.test.IndirectExtension.repeatedSimpleList, [s1, s2]);
[s1, s2]); assertObjectEquals(
assertObjectEquals(extension1, extension1,
extendable.getExtension(proto.jspb.test.IsExtension.extField)); extendable.getExtension(proto.jspb.test.IsExtension.extField));
assertObjectEquals(extension2, assertObjectEquals(
extension2,
extendable.getExtension(proto.jspb.test.IndirectExtension.simple)); extendable.getExtension(proto.jspb.test.IndirectExtension.simple));
assertObjectEquals('xyzzy', assertObjectEquals(
'xyzzy',
extendable.getExtension(proto.jspb.test.IndirectExtension.str)); extendable.getExtension(proto.jspb.test.IndirectExtension.str));
assertObjectEquals(['a', 'b'], extendable.getExtension( assertObjectEquals(
['a', 'b'],
extendable.getExtension(
proto.jspb.test.IndirectExtension.repeatedStrList)); proto.jspb.test.IndirectExtension.repeatedStrList));
assertObjectEquals([s1, s2], extendable.getExtension( assertObjectEquals(
[s1, s2],
extendable.getExtension(
proto.jspb.test.IndirectExtension.repeatedSimpleList)); proto.jspb.test.IndirectExtension.repeatedSimpleList));
// Not supported yet, but it should work... // Not supported yet, but it should work...
extendable.setExtension(proto.jspb.test.IndirectExtension.simple, null); extendable.setExtension(proto.jspb.test.IndirectExtension.simple, null);
@ -563,18 +578,18 @@ describe('Message test suite', function() {
var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']); var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']);
var extension = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]); var extension = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]);
extendable.setExtension(proto.jspb.test.simple1, extension); extendable.setExtension(proto.jspb.test.simple1, extension);
assertObjectEquals(extension, assertObjectEquals(
extendable.getExtension(proto.jspb.test.simple1)); extension, extendable.getExtension(proto.jspb.test.simple1));
// From _lib mode. // From _lib mode.
extension = new proto.jspb.test.ExtensionMessage(['s1']); extension = new proto.jspb.test.ExtensionMessage(['s1']);
extendable = new proto.jspb.test.TestExtensionsMessage([16]); extendable = new proto.jspb.test.TestExtensionsMessage([16]);
extendable.setExtension(proto.jspb.test.floatingMsgField, extension); extendable.setExtension(proto.jspb.test.floatingMsgField, extension);
extendable.setExtension(proto.jspb.test.floatingStrField, 's2'); extendable.setExtension(proto.jspb.test.floatingStrField, 's2');
assertObjectEquals(extension, assertObjectEquals(
extendable.getExtension(proto.jspb.test.floatingMsgField)); extension, extendable.getExtension(proto.jspb.test.floatingMsgField));
assertObjectEquals('s2', assertObjectEquals(
extendable.getExtension(proto.jspb.test.floatingStrField)); 's2', extendable.getExtension(proto.jspb.test.floatingStrField));
assertNotUndefined(proto.jspb.exttest.floatingMsgField); assertNotUndefined(proto.jspb.exttest.floatingMsgField);
assertNotUndefined(proto.jspb.exttest.floatingMsgFieldTwo); assertNotUndefined(proto.jspb.exttest.floatingMsgFieldTwo);
assertNotUndefined(proto.jspb.exttest.beta.floatingStrField); assertNotUndefined(proto.jspb.exttest.beta.floatingStrField);
@ -585,21 +600,25 @@ describe('Message test suite', function() {
var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2'], true]); var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2'], true]);
var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']); var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']);
extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1); extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1);
extendable.setExtension(proto.jspb.test.IndirectExtension.simple, extendable.setExtension(
extension2); proto.jspb.test.IndirectExtension.simple, extension2);
extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy'); extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy');
extendable.setExtension(proto.jspb.test.IndirectExtension.repeatedStrList, extendable.setExtension(
['a', 'b']); proto.jspb.test.IndirectExtension.repeatedStrList, ['a', 'b']);
var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2'], true]); var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2'], true]);
var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2'], false]); var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2'], false]);
extendable.setExtension( extendable.setExtension(
proto.jspb.test.IndirectExtension.repeatedSimpleList, proto.jspb.test.IndirectExtension.repeatedSimpleList, [s1, s2]);
[s1, s2]); assertObjectEquals(
assertObjectEquals({ {
str1: 'v1', str2: 'v2', str3: 'v3', str1: 'v1',
str2: 'v2',
str3: 'v3',
extField: {ext1: 'ext1field'}, extField: {ext1: 'ext1field'},
simple: { simple: {
aString: 'str', aRepeatedStringList: ['s1', 's2'], aBoolean: true aString: 'str',
aRepeatedStringList: ['s1', 's2'],
aBoolean: true
}, },
str: 'xyzzy', str: 'xyzzy',
repeatedStrList: ['a', 'b'], repeatedStrList: ['a', 'b'],
@ -607,11 +626,15 @@ describe('Message test suite', function() {
{aString: 'foo', aRepeatedStringList: ['s1', 's2'], aBoolean: true}, {aString: 'foo', aRepeatedStringList: ['s1', 's2'], aBoolean: true},
{aString: 'bar', aRepeatedStringList: ['t1', 't2'], aBoolean: false} {aString: 'bar', aRepeatedStringList: ['t1', 't2'], aBoolean: false}
] ]
}, extendable.toObject()); },
extendable.toObject());
// Now, with instances included. // Now, with instances included.
assertObjectEquals({ assertObjectEquals(
str1: 'v1', str2: 'v2', str3: 'v3', {
str1: 'v1',
str2: 'v2',
str3: 'v3',
extField: { extField: {
ext1: 'ext1field', ext1: 'ext1field',
$jspbMessageInstance: $jspbMessageInstance:
@ -621,24 +644,28 @@ describe('Message test suite', function() {
aString: 'str', aString: 'str',
aRepeatedStringList: ['s1', 's2'], aRepeatedStringList: ['s1', 's2'],
aBoolean: true, aBoolean: true,
$jspbMessageInstance: $jspbMessageInstance: extendable.getExtension(
extendable.getExtension(proto.jspb.test.IndirectExtension.simple) proto.jspb.test.IndirectExtension.simple)
}, },
str: 'xyzzy', str: 'xyzzy',
repeatedStrList: ['a', 'b'], repeatedStrList: ['a', 'b'],
repeatedSimpleList: [{ repeatedSimpleList: [
{
aString: 'foo', aString: 'foo',
aRepeatedStringList: ['s1', 's2'], aRepeatedStringList: ['s1', 's2'],
aBoolean: true, aBoolean: true,
$jspbMessageInstance: s1 $jspbMessageInstance: s1
}, { },
{
aString: 'bar', aString: 'bar',
aRepeatedStringList: ['t1', 't2'], aRepeatedStringList: ['t1', 't2'],
aBoolean: false, aBoolean: false,
$jspbMessageInstance: s2 $jspbMessageInstance: s2
}], }
],
$jspbMessageInstance: extendable $jspbMessageInstance: extendable
}, extendable.toObject(true /* opt_includeInstance */)); },
extendable.toObject(true /* opt_includeInstance */));
}); });
it('testInitialization_emptyArray', function() { it('testInitialization_emptyArray', function() {
@ -690,8 +717,7 @@ describe('Message test suite', function() {
var extensionMessage = new proto.jspb.test.IsExtension(['is_extension']); var extensionMessage = new proto.jspb.test.IsExtension(['is_extension']);
data.setExtension(proto.jspb.test.IsExtension.extField, extensionMessage); data.setExtension(proto.jspb.test.IsExtension.extField, extensionMessage);
var obj = data.toObject(); var obj = data.toObject();
assertNotNull( assertNotNull(data.getExtension(proto.jspb.test.IsExtension.extField));
data.getExtension(proto.jspb.test.IsExtension.extField));
assertEquals('is_extension', obj.extField.ext1); assertEquals('is_extension', obj.extField.ext1);
}); });
@ -708,16 +734,18 @@ describe('Message test suite', function() {
var groups = group.getRepeatedGroupList(); var groups = group.getRepeatedGroupList();
assertEquals('g1', groups[0].getId()); assertEquals('g1', groups[0].getId());
assertObjectEquals([true, false], groups[0].getSomeBoolList()); assertObjectEquals([true, false], groups[0].getSomeBoolList());
assertObjectEquals({id: 'g1', someBoolList: [true, false]}, assertObjectEquals(
groups[0].toObject()); {id: 'g1', someBoolList: [true, false]}, groups[0].toObject());
assertObjectEquals({ assertObjectEquals(
{
repeatedGroupList: [{id: 'g1', someBoolList: [true, false]}], repeatedGroupList: [{id: 'g1', someBoolList: [true, false]}],
requiredGroup: {id: undefined}, requiredGroup: {id: undefined},
optionalGroup: undefined, optionalGroup: undefined,
requiredSimple: {aRepeatedStringList: [], aString: undefined}, requiredSimple: {aRepeatedStringList: [], aString: undefined},
optionalSimple: undefined, optionalSimple: undefined,
id: undefined id: undefined
}, group.toObject()); },
group.toObject());
var group1 = new proto.jspb.test.TestGroup1(); var group1 = new proto.jspb.test.TestGroup1();
group1.setGroup(someGroup); group1.setGroup(someGroup);
assertEquals(someGroup, group1.getGroup()); assertEquals(someGroup, group1.getGroup());
@ -734,20 +762,21 @@ describe('Message test suite', function() {
message.setExtension$(11); message.setExtension$(11);
message.setExtension(proto.jspb.test.TestReservedNamesExtension.foo, 12); message.setExtension(proto.jspb.test.TestReservedNamesExtension.foo, 12);
assertEquals(11, message.getExtension$()); assertEquals(11, message.getExtension$());
assertEquals(12, message.getExtension( assertEquals(
proto.jspb.test.TestReservedNamesExtension.foo)); 12,
message.getExtension(proto.jspb.test.TestReservedNamesExtension.foo));
assertObjectEquals({extension: 11, foo: 12}, message.toObject()); assertObjectEquals({extension: 11, foo: 12}, message.toObject());
}); });
it('testInitializeMessageWithUnsetOneof', function() { it('testInitializeMessageWithUnsetOneof', function() {
var message = new proto.jspb.test.TestMessageWithOneof([]); var message = new proto.jspb.test.TestMessageWithOneof([]);
assertEquals( assertEquals(
proto.jspb.test.TestMessageWithOneof.PartialOneofCase. proto.jspb.test.TestMessageWithOneof.PartialOneofCase
PARTIAL_ONEOF_NOT_SET, .PARTIAL_ONEOF_NOT_SET,
message.getPartialOneofCase()); message.getPartialOneofCase());
assertEquals( assertEquals(
proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase. proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase
RECURSIVE_ONEOF_NOT_SET, .RECURSIVE_ONEOF_NOT_SET,
message.getRecursiveOneofCase()); message.getRecursiveOneofCase());
}); });
@ -819,8 +848,8 @@ describe('Message test suite', function() {
it('testUnsetsOneofCaseWhenFieldIsCleared', function() { it('testUnsetsOneofCaseWhenFieldIsCleared', function() {
var message = new proto.jspb.test.TestMessageWithOneof; var message = new proto.jspb.test.TestMessageWithOneof;
assertEquals( assertEquals(
proto.jspb.test.TestMessageWithOneof.PartialOneofCase. proto.jspb.test.TestMessageWithOneof.PartialOneofCase
PARTIAL_ONEOF_NOT_SET, .PARTIAL_ONEOF_NOT_SET,
message.getPartialOneofCase()); message.getPartialOneofCase());
message.setPone('hi'); message.setPone('hi');
@ -830,8 +859,8 @@ describe('Message test suite', function() {
message.clearPone(); message.clearPone();
assertEquals( assertEquals(
proto.jspb.test.TestMessageWithOneof.PartialOneofCase. proto.jspb.test.TestMessageWithOneof.PartialOneofCase
PARTIAL_ONEOF_NOT_SET, .PARTIAL_ONEOF_NOT_SET,
message.getPartialOneofCase()); message.getPartialOneofCase());
}); });
@ -965,8 +994,8 @@ describe('Message test suite', function() {
it('testOneofContainingAnotherMessage', function() { it('testOneofContainingAnotherMessage', function() {
var message = new proto.jspb.test.TestMessageWithOneof; var message = new proto.jspb.test.TestMessageWithOneof;
assertEquals( assertEquals(
proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase. proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase
RECURSIVE_ONEOF_NOT_SET, .RECURSIVE_ONEOF_NOT_SET,
message.getRecursiveOneofCase()); message.getRecursiveOneofCase());
var other = new proto.jspb.test.TestMessageWithOneof; var other = new proto.jspb.test.TestMessageWithOneof;
@ -1015,8 +1044,7 @@ describe('Message test suite', function() {
}; };
var message = new proto.jspb.test.FloatingPointFields([ var message = new proto.jspb.test.FloatingPointFields([
'NaN', 'NaN', ['NaN', 'NaN'], 'NaN', 'NaN', 'NaN', ['NaN', 'NaN'], 'NaN', 'NaN', 'NaN', ['NaN', 'NaN'], 'NaN'
'NaN', 'NaN', ['NaN', 'NaN'], 'NaN'
]); ]);
assertNan(message.getOptionalFloatField()); assertNan(message.getOptionalFloatField());
assertNan(message.getRequiredFloatField()); assertNan(message.getRequiredFloatField());
@ -1029,5 +1057,4 @@ describe('Message test suite', function() {
assertNan(message.getRepeatedDoubleFieldList()[1]); assertNan(message.getRepeatedDoubleFieldList()[1]);
assertNan(message.getDefaultDoubleField()); assertNan(message.getDefaultDoubleField());
}); });
}); });

@ -53,6 +53,8 @@ goog.require('proto.jspb.test.MapEntryOptionalValuesMessageValue');
goog.require('proto.jspb.test.MapValueMessageNoBinary'); goog.require('proto.jspb.test.MapValueMessageNoBinary');
goog.require('proto.jspb.test.TestMapFieldsNoBinary'); goog.require('proto.jspb.test.TestMapFieldsNoBinary');
goog.requireType('jspb.Map');
/** /**
* Helper: check that the given map has exactly this set of (sorted) entries. * Helper: check that the given map has exactly this set of (sorted) entries.
* @param {!jspb.Map} map * @param {!jspb.Map} map
@ -116,7 +118,9 @@ function makeTests(msgInfo, submessageCtor, suffix) {
msg.getMapStringMsgMap().get('k').setFoo(42); msg.getMapStringMsgMap().get('k').setFoo(42);
msg.getMapStringMsgMap().get('l').setFoo(84); msg.getMapStringMsgMap().get('l').setFoo(84);
msg.getMapInt32StringMap().set(-1, 'a').set(42, 'b'); msg.getMapInt32StringMap().set(-1, 'a').set(42, 'b');
msg.getMapInt64StringMap().set(0x123456789abc, 'c').set(0xcba987654321, 'd'); msg.getMapInt64StringMap()
.set(0x123456789abc, 'c')
.set(0xcba987654321, 'd');
msg.getMapBoolStringMap().set(false, 'e').set(true, 'f'); msg.getMapBoolStringMap().set(false, 'e').set(true, 'f');
}; };
@ -125,42 +129,24 @@ function makeTests(msgInfo, submessageCtor, suffix) {
* @param {?} msg * @param {?} msg
*/ */
var checkMapFields = function(msg) { var checkMapFields = function(msg) {
checkMapEquals(msg.getMapStringStringMap(), [ checkMapEquals(
['asdf', 'jkl;'], msg.getMapStringStringMap(),
['key 2', 'hello world'] [['asdf', 'jkl;'], ['key 2', 'hello world']]);
]); checkMapEquals(msg.getMapStringInt32Map(), [['a', 1], ['b', -2]]);
checkMapEquals(msg.getMapStringInt32Map(), [ checkMapEquals(
['a', 1], msg.getMapStringInt64Map(), [['c', 0x100000000], ['d', 0x200000000]]);
['b', -2] checkMapEquals(msg.getMapStringBoolMap(), [['e', true], ['f', false]]);
]); checkMapEquals(
checkMapEquals(msg.getMapStringInt64Map(), [ msg.getMapStringDoubleMap(), [['g', 3.14159], ['h', 2.71828]]);
['c', 0x100000000],
['d', 0x200000000]
]);
checkMapEquals(msg.getMapStringBoolMap(), [
['e', true],
['f', false]
]);
checkMapEquals(msg.getMapStringDoubleMap(), [
['g', 3.14159],
['h', 2.71828]
]);
checkMapEquals(msg.getMapStringEnumMap(), [ checkMapEquals(msg.getMapStringEnumMap(), [
['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR], ['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR],
['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ] ['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ]
]); ]);
checkMapEquals(msg.getMapInt32StringMap(), [ checkMapEquals(msg.getMapInt32StringMap(), [[-1, 'a'], [42, 'b']]);
[-1, 'a'], checkMapEquals(
[42, 'b'] msg.getMapInt64StringMap(),
]); [[0x123456789abc, 'c'], [0xcba987654321, 'd']]);
checkMapEquals(msg.getMapInt64StringMap(), [ checkMapEquals(msg.getMapBoolStringMap(), [[false, 'e'], [true, 'f']]);
[0x123456789abc, 'c'],
[0xcba987654321, 'd']
]);
checkMapEquals(msg.getMapBoolStringMap(), [
[false, 'e'],
[true, 'f']
]);
assertEquals(msg.getMapStringMsgMap().getLength(), 2); assertEquals(msg.getMapStringMsgMap().getLength(), 2);
assertEquals(msg.getMapStringMsgMap().get('k').getFoo(), 42); assertEquals(msg.getMapStringMsgMap().get('k').getFoo(), 42);
@ -205,10 +191,7 @@ function makeTests(msgInfo, submessageCtor, suffix) {
assertElementsEquals(it.next().value, ['asdf', 'hello world']); assertElementsEquals(it.next().value, ['asdf', 'hello world']);
assertElementsEquals(it.next().value, ['jkl;', 'key 2']); assertElementsEquals(it.next().value, ['jkl;', 'key 2']);
assertEquals(it.next().done, true); assertEquals(it.next().done, true);
checkMapEquals(m, [ checkMapEquals(m, [['asdf', 'hello world'], ['jkl;', 'key 2']]);
['asdf', 'hello world'],
['jkl;', 'key 2']
]);
m.del('jkl;'); m.del('jkl;');
assertEquals(m.has('jkl;'), false); assertEquals(m.has('jkl;'), false);
assertEquals(m.get('jkl;'), undefined); assertEquals(m.get('jkl;'), undefined);
@ -284,34 +267,27 @@ function makeTests(msgInfo, submessageCtor, suffix) {
* binary format. * binary format.
*/ */
it('testMapDeserializationForUndefinedKeys', function() { it('testMapDeserializationForUndefinedKeys', function() {
var testMessageOptionalKeys = new proto.jspb.test.TestMapFieldsOptionalKeys(); var testMessageOptionalKeys =
var mapEntryStringKey = new proto.jspb.test.MapEntryOptionalKeysStringKey(); new proto.jspb.test.TestMapFieldsOptionalKeys();
mapEntryStringKey.setValue("a"); var mapEntryStringKey =
new proto.jspb.test.MapEntryOptionalKeysStringKey();
mapEntryStringKey.setValue('a');
testMessageOptionalKeys.setMapStringString(mapEntryStringKey); testMessageOptionalKeys.setMapStringString(mapEntryStringKey);
var mapEntryInt32Key = new proto.jspb.test.MapEntryOptionalKeysInt32Key(); var mapEntryInt32Key = new proto.jspb.test.MapEntryOptionalKeysInt32Key();
mapEntryInt32Key.setValue("b"); mapEntryInt32Key.setValue('b');
testMessageOptionalKeys.setMapInt32String(mapEntryInt32Key); testMessageOptionalKeys.setMapInt32String(mapEntryInt32Key);
var mapEntryInt64Key = new proto.jspb.test.MapEntryOptionalKeysInt64Key(); var mapEntryInt64Key = new proto.jspb.test.MapEntryOptionalKeysInt64Key();
mapEntryInt64Key.setValue("c"); mapEntryInt64Key.setValue('c');
testMessageOptionalKeys.setMapInt64String(mapEntryInt64Key); testMessageOptionalKeys.setMapInt64String(mapEntryInt64Key);
var mapEntryBoolKey = new proto.jspb.test.MapEntryOptionalKeysBoolKey(); var mapEntryBoolKey = new proto.jspb.test.MapEntryOptionalKeysBoolKey();
mapEntryBoolKey.setValue("d"); mapEntryBoolKey.setValue('d');
testMessageOptionalKeys.setMapBoolString(mapEntryBoolKey); testMessageOptionalKeys.setMapBoolString(mapEntryBoolKey);
var deserializedMessage = msgInfo.deserializeBinary( var deserializedMessage =
testMessageOptionalKeys.serializeBinary() msgInfo.deserializeBinary(testMessageOptionalKeys.serializeBinary());
); checkMapEquals(deserializedMessage.getMapStringStringMap(), [['', 'a']]);
checkMapEquals(deserializedMessage.getMapStringStringMap(), [ checkMapEquals(deserializedMessage.getMapInt32StringMap(), [[0, 'b']]);
['', 'a'] checkMapEquals(deserializedMessage.getMapInt64StringMap(), [[0, 'c']]);
]); checkMapEquals(deserializedMessage.getMapBoolStringMap(), [[false, 'd']]);
checkMapEquals(deserializedMessage.getMapInt32StringMap(), [
[0, 'b']
]);
checkMapEquals(deserializedMessage.getMapInt64StringMap(), [
[0, 'c']
]);
checkMapEquals(deserializedMessage.getMapBoolStringMap(), [
[false, 'd']
]);
}); });
/** /**
@ -323,56 +299,41 @@ function makeTests(msgInfo, submessageCtor, suffix) {
new proto.jspb.test.TestMapFieldsOptionalValues(); new proto.jspb.test.TestMapFieldsOptionalValues();
var mapEntryStringValue = var mapEntryStringValue =
new proto.jspb.test.MapEntryOptionalValuesStringValue(); new proto.jspb.test.MapEntryOptionalValuesStringValue();
mapEntryStringValue.setKey("a"); mapEntryStringValue.setKey('a');
testMessageOptionalValues.setMapStringString(mapEntryStringValue); testMessageOptionalValues.setMapStringString(mapEntryStringValue);
var mapEntryInt32Value = var mapEntryInt32Value =
new proto.jspb.test.MapEntryOptionalValuesInt32Value(); new proto.jspb.test.MapEntryOptionalValuesInt32Value();
mapEntryInt32Value.setKey("b"); mapEntryInt32Value.setKey('b');
testMessageOptionalValues.setMapStringInt32(mapEntryInt32Value); testMessageOptionalValues.setMapStringInt32(mapEntryInt32Value);
var mapEntryInt64Value = var mapEntryInt64Value =
new proto.jspb.test.MapEntryOptionalValuesInt64Value(); new proto.jspb.test.MapEntryOptionalValuesInt64Value();
mapEntryInt64Value.setKey("c"); mapEntryInt64Value.setKey('c');
testMessageOptionalValues.setMapStringInt64(mapEntryInt64Value); testMessageOptionalValues.setMapStringInt64(mapEntryInt64Value);
var mapEntryBoolValue = var mapEntryBoolValue =
new proto.jspb.test.MapEntryOptionalValuesBoolValue(); new proto.jspb.test.MapEntryOptionalValuesBoolValue();
mapEntryBoolValue.setKey("d"); mapEntryBoolValue.setKey('d');
testMessageOptionalValues.setMapStringBool(mapEntryBoolValue); testMessageOptionalValues.setMapStringBool(mapEntryBoolValue);
var mapEntryDoubleValue = var mapEntryDoubleValue =
new proto.jspb.test.MapEntryOptionalValuesDoubleValue(); new proto.jspb.test.MapEntryOptionalValuesDoubleValue();
mapEntryDoubleValue.setKey("e"); mapEntryDoubleValue.setKey('e');
testMessageOptionalValues.setMapStringDouble(mapEntryDoubleValue); testMessageOptionalValues.setMapStringDouble(mapEntryDoubleValue);
var mapEntryEnumValue = var mapEntryEnumValue =
new proto.jspb.test.MapEntryOptionalValuesEnumValue(); new proto.jspb.test.MapEntryOptionalValuesEnumValue();
mapEntryEnumValue.setKey("f"); mapEntryEnumValue.setKey('f');
testMessageOptionalValues.setMapStringEnum(mapEntryEnumValue); testMessageOptionalValues.setMapStringEnum(mapEntryEnumValue);
var mapEntryMessageValue = var mapEntryMessageValue =
new proto.jspb.test.MapEntryOptionalValuesMessageValue(); new proto.jspb.test.MapEntryOptionalValuesMessageValue();
mapEntryMessageValue.setKey("g"); mapEntryMessageValue.setKey('g');
testMessageOptionalValues.setMapStringMsg(mapEntryMessageValue); testMessageOptionalValues.setMapStringMsg(mapEntryMessageValue);
var deserializedMessage = msgInfo.deserializeBinary( var deserializedMessage = msgInfo.deserializeBinary(
testMessageOptionalValues.serializeBinary() testMessageOptionalValues.serializeBinary());
); checkMapEquals(deserializedMessage.getMapStringStringMap(), [['a', '']]);
checkMapEquals(deserializedMessage.getMapStringStringMap(), [ checkMapEquals(deserializedMessage.getMapStringInt32Map(), [['b', 0]]);
['a', ''] checkMapEquals(deserializedMessage.getMapStringInt64Map(), [['c', 0]]);
]); checkMapEquals(deserializedMessage.getMapStringBoolMap(), [['d', false]]);
checkMapEquals(deserializedMessage.getMapStringInt32Map(), [ checkMapEquals(deserializedMessage.getMapStringDoubleMap(), [['e', 0.0]]);
['b', 0] checkMapEquals(deserializedMessage.getMapStringEnumMap(), [['f', 0]]);
]); checkMapEquals(deserializedMessage.getMapStringMsgMap(), [['g', []]]);
checkMapEquals(deserializedMessage.getMapStringInt64Map(), [
['c', 0]
]);
checkMapEquals(deserializedMessage.getMapStringBoolMap(), [
['d', false]
]);
checkMapEquals(deserializedMessage.getMapStringDoubleMap(), [
['e', 0.0]
]);
checkMapEquals(deserializedMessage.getMapStringEnumMap(), [
['f', 0]
]);
checkMapEquals(deserializedMessage.getMapStringMsgMap(), [
['g', []]
]);
}); });
} }
@ -382,11 +343,7 @@ function makeTests(msgInfo, submessageCtor, suffix) {
*/ */
it('testLazyMapSync' + suffix, function() { it('testLazyMapSync' + suffix, function() {
// Start with a JSPB array containing a few map entries. // Start with a JSPB array containing a few map entries.
var entries = [ var entries = [['a', 'entry 1'], ['c', 'entry 2'], ['b', 'entry 3']];
['a', 'entry 1'],
['c', 'entry 2'],
['b', 'entry 3']
];
var msg = new msgInfo.constructor([entries]); var msg = new msgInfo.constructor([entries]);
assertEquals(entries.length, 3); assertEquals(entries.length, 3);
assertEquals(entries[0][0], 'a'); assertEquals(entries[0][0], 'a');

@ -121,6 +121,8 @@ goog.require('proto.jspb.test.TestAllowAliasEnum');
// CommonJS-LoadFromFile: testlargenumbers_pb proto.jspb.test // CommonJS-LoadFromFile: testlargenumbers_pb proto.jspb.test
goog.require('proto.jspb.test.MessageWithLargeFieldNumbers'); goog.require('proto.jspb.test.MessageWithLargeFieldNumbers');
goog.require('proto.jspb.test.simple1');
describe('Message test suite', function() { describe('Message test suite', function() {
var stubs = new goog.testing.PropertyReplacer(); var stubs = new goog.testing.PropertyReplacer();
@ -185,7 +187,6 @@ describe('Message test suite', function() {
$jspbMessageInstance: foo $jspbMessageInstance: foo
}, },
result); result);
}); });
it('testMissingFields', function() { it('testMissingFields', function() {
@ -209,7 +210,6 @@ describe('Message test suite', function() {
aFloatingPointField: undefined, aFloatingPointField: undefined,
}, },
result); result);
}); });
it('testNestedComplexMessage', function() { it('testNestedComplexMessage', function() {
@ -1108,5 +1108,4 @@ describe('Message test suite', function() {
message.setAInt(42); message.setAInt(42);
assertEquals(42, message.getAInt()); assertEquals(42, message.getAInt());
}); });
}); });

@ -41,7 +41,7 @@ goog.require('proto.google.protobuf.Any');
goog.require('proto.google.protobuf.Timestamp'); goog.require('proto.google.protobuf.Timestamp');
// CommonJS-LoadFromFile: google/protobuf/struct_pb proto.google.protobuf // CommonJS-LoadFromFile: google/protobuf/struct_pb proto.google.protobuf
goog.require('proto.google.protobuf.Struct'); goog.require('proto.google.protobuf.Struct');
goog.require('jspb.Message');
var BYTES = new Uint8Array([1, 2, 8, 9]); var BYTES = new Uint8Array([1, 2, 8, 9]);
var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES); var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES);
@ -70,7 +70,6 @@ function bytesCompare(arr, expected) {
describe('proto3Test', function() { describe('proto3Test', function() {
/** /**
* Test default values don't affect equality test. * Test default values don't affect equality test.
*/ */
@ -182,8 +181,8 @@ describe('proto3Test', function() {
assertEquals(msg.getOptionalBytes_asU8().length, 0); assertEquals(msg.getOptionalBytes_asU8().length, 0);
assertEquals(msg.getOptionalBytes_asB64(), ''); assertEquals(msg.getOptionalBytes_asB64(), '');
assertEquals(msg.getOptionalForeignEnum(), assertEquals(
proto.jspb.test.Proto3Enum.PROTO3_FOO); msg.getOptionalForeignEnum(), proto.jspb.test.Proto3Enum.PROTO3_FOO);
assertEquals(msg.getOptionalForeignMessage(), undefined); assertEquals(msg.getOptionalForeignMessage(), undefined);
assertEquals(msg.getOptionalForeignMessage(), undefined); assertEquals(msg.getOptionalForeignMessage(), undefined);
@ -309,7 +308,8 @@ describe('proto3Test', function() {
assertEquals(true, bytesCompare(msg.getRepeatedBytesList()[0], BYTES)); assertEquals(true, bytesCompare(msg.getRepeatedBytesList()[0], BYTES));
assertEquals(msg.getRepeatedForeignMessageList().length, 1); assertEquals(msg.getRepeatedForeignMessageList().length, 1);
assertEquals(msg.getRepeatedForeignMessageList()[0].getC(), 1000); assertEquals(msg.getRepeatedForeignMessageList()[0].getC(), 1000);
assertElementsEquals(msg.getRepeatedForeignEnumList(), assertElementsEquals(
msg.getRepeatedForeignEnumList(),
[proto.jspb.test.Proto3Enum.PROTO3_BAR]); [proto.jspb.test.Proto3Enum.PROTO3_BAR]);
assertEquals(msg.getOneofString(), 'asdf'); assertEquals(msg.getOneofString(), 'asdf');
@ -374,7 +374,8 @@ describe('proto3Test', function() {
assertEquals(msg.getOneofUint32(), 0); assertEquals(msg.getOneofUint32(), 0);
assertEquals(msg.getOneofForeignMessage(), undefined); assertEquals(msg.getOneofForeignMessage(), undefined);
assertEquals(msg.getOneofString(), ''); assertEquals(msg.getOneofString(), '');
assertEquals(msg.getOneofBytes_asB64(), assertEquals(
msg.getOneofBytes_asB64(),
goog.crypt.base64.encodeString('\u00FF\u00FF')); goog.crypt.base64.encodeString('\u00FF\u00FF'));
assertFalse(msg.hasOneofUint32()); assertFalse(msg.hasOneofUint32());
@ -454,24 +455,24 @@ describe('proto3Test', function() {
it('testStructWellKnownType', function() { it('testStructWellKnownType', function() {
var jsObj = { var jsObj = {
abc: "def", abc: 'def',
number: 12345.678, number: 12345.678,
nullKey: null, nullKey: null,
boolKey: true, boolKey: true,
listKey: [1, null, true, false, "abc"], listKey: [1, null, true, false, 'abc'],
structKey: {foo: "bar", somenum: 123}, structKey: {foo: 'bar', somenum: 123},
complicatedKey: [{xyz: {abc: [3, 4, null, false]}}, "zzz"] complicatedKey: [{xyz: {abc: [3, 4, null, false]}}, 'zzz']
}; };
var struct = proto.google.protobuf.Struct.fromJavaScript(jsObj); var struct = proto.google.protobuf.Struct.fromJavaScript(jsObj);
var jsObj2 = struct.toJavaScript(); var jsObj2 = struct.toJavaScript();
assertEquals("def", jsObj2.abc); assertEquals('def', jsObj2.abc);
assertEquals(12345.678, jsObj2.number); assertEquals(12345.678, jsObj2.number);
assertEquals(null, jsObj2.nullKey); assertEquals(null, jsObj2.nullKey);
assertEquals(true, jsObj2.boolKey); assertEquals(true, jsObj2.boolKey);
assertEquals("abc", jsObj2.listKey[4]); assertEquals('abc', jsObj2.listKey[4]);
assertEquals("bar", jsObj2.structKey.foo); assertEquals('bar', jsObj2.structKey.foo);
assertEquals(4, jsObj2.complicatedKey[0].xyz.abc[1]); assertEquals(4, jsObj2.complicatedKey[0].xyz.abc[1]);
}); });
}); });

@ -4,3 +4,9 @@ Kokoro Infrastructure
The files in this directory serve as plumbing for running Protobuf The files in this directory serve as plumbing for running Protobuf
tests under Kokoro, our internal CI. tests under Kokoro, our internal CI.
We have shared this part of our CI configuration in hopes that it is
helpful to contributors who want to better understand the details of
our test and release processes. If there are changes, please file an
issue; unfortunately, we may not be able to accept PRs (but feel free
to send one if it helps to explain the issue).

@ -55,6 +55,26 @@ RUN mv composer.phar /usr/local/bin/composer
# Download php source code # Download php source code
RUN git clone https://github.com/php/php-src RUN git clone https://github.com/php/php-src
# php 5.6
RUN cd php-src \
&& git checkout PHP-5.6.39 \
&& ./buildconf --force
RUN cd php-src \
&& ./configure \
--enable-bcmath \
--enable-mbstring \
--with-gmp \
--with-openssl \
--with-zlib \
--prefix=/usr/local/php-5.6 \
&& make \
&& make install \
&& make clean
RUN wget -O phpunit https://phar.phpunit.de/phpunit-5.phar \
&& chmod +x phpunit \
&& mv phpunit /usr/local/php-5.6/bin
# php 7.0 # php 7.0
RUN cd php-src \ RUN cd php-src \
&& git checkout PHP-7.0.33 \ && git checkout PHP-7.0.33 \

@ -53,6 +53,25 @@ RUN mv composer.phar /usr/local/bin/composer
# Download php source code # Download php source code
RUN git clone https://github.com/php/php-src RUN git clone https://github.com/php/php-src
# php 5.6
RUN cd php-src \
&& git checkout PHP-5.6.39 \
&& ./buildconf --force
RUN cd php-src \
&& ./configure \
--enable-bcmath \
--enable-mbstring \
--with-openssl \
--with-zlib \
--prefix=/usr/local/php-5.6 \
&& make \
&& make install \
&& make clean
RUN wget -O phpunit https://phar.phpunit.de/phpunit-5.phar \
&& chmod +x phpunit \
&& mv phpunit /usr/local/php-5.6/bin
# php 7.0 # php 7.0
RUN wget https://github.com/php/php-src/archive/php-7.0.33.tar.gz -O /var/local/php-7.0.33.tar.gz RUN wget https://github.com/php/php-src/archive/php-7.0.33.tar.gz -O /var/local/php-7.0.33.tar.gz

@ -0,0 +1,31 @@
FROM python:3.9-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 \
&& rm -rf /var/lib/apt/lists/*
# Install Python libraries.
RUN python -m pip install --no-cache-dir --upgrade \
pip \
setuptools \
tox \
wheel

@ -0,0 +1,18 @@
#!/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/python39
export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
export OUTPUT_DIR=testoutput
export TEST_SET="python39"
./kokoro/linux/build_and_run_docker.sh

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

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

@ -0,0 +1,18 @@
#!/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/python39
export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
export OUTPUT_DIR=testoutput
export TEST_SET="python39_cpp"
./kokoro/linux/build_and_run_docker.sh

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

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

@ -11,4 +11,7 @@ set PATH=%LOCALAPPDATA%\Microsoft\dotnet;%PATH%
set DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true set DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true
set DOTNET_CLI_TELEMETRY_OPTOUT=true set DOTNET_CLI_TELEMETRY_OPTOUT=true
@rem Work around https://github.com/dotnet/core/issues/5881
dotnet nuget locals all --clear
call build_packages.bat call build_packages.bat

@ -54,3 +54,4 @@ build_artifact_version 3.5
build_artifact_version 3.6 build_artifact_version 3.6
build_artifact_version 3.7 build_artifact_version 3.7
build_artifact_version 3.8 build_artifact_version 3.8
build_artifact_version 3.9

@ -55,6 +55,7 @@ build_artifact_version 2.7
build_artifact_version 3.6 build_artifact_version 3.6
build_artifact_version 3.7 build_artifact_version 3.7
build_artifact_version 3.8 build_artifact_version 3.8
build_artifact_version 3.9
# python OSX10.9 does not have python 3.5 # python OSX10.9 does not have python 3.5
export MB_PYTHON_OSX_VER=10.6 export MB_PYTHON_OSX_VER=10.6

@ -72,6 +72,16 @@ SET PYTHON_VERSION=3.8
SET PYTHON_ARCH=64 SET PYTHON_ARCH=64
CALL build_single_artifact.bat || goto :error CALL build_single_artifact.bat || goto :error
SET PYTHON=C:\python39_32bit
SET PYTHON_VERSION=3.9
SET PYTHON_ARCH=32
CALL build_single_artifact.bat || goto :error
SET PYTHON=C:\python39
SET PYTHON_VERSION=3.9
SET PYTHON_ARCH=64
CALL build_single_artifact.bat || goto :error
goto :EOF goto :EOF
:error :error

@ -24,10 +24,16 @@ if %PYTHON%==C:\python38_32bit set vcplatform=Win32
if %PYTHON%==C:\python38 set generator=Visual Studio 14 Win64 if %PYTHON%==C:\python38 set generator=Visual Studio 14 Win64
if %PYTHON%==C:\python38 set vcplatform=x64 if %PYTHON%==C:\python38 set vcplatform=x64
if %PYTHON%==C:\python39_32bit set generator=Visual Studio 14
if %PYTHON%==C:\python39_32bit set vcplatform=Win32
if %PYTHON%==C:\python39 set generator=Visual Studio 14 Win64
if %PYTHON%==C:\python39 set vcplatform=x64
REM Prepend newly installed Python to the PATH of this build (this cannot be REM Prepend newly installed Python to the PATH of this build (this cannot be
REM done from inside the powershell script as it would require to restart REM done from inside the powershell script as it would require to restart
REM the parent CMD process). REM the parent CMD process).
SET PATH=%PYTHON%;%PYTHON%\Scripts;%OLD_PATH% SET PATH=C:\Program Files\CMake\bin;%PYTHON%;%PYTHON%\Scripts;%OLD_PATH%
python -m pip install -U pip python -m pip install -U pip
pip install wheel pip install wheel

@ -11,4 +11,7 @@ set PATH=%LOCALAPPDATA%\Microsoft\dotnet;%PATH%
set DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true set DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true
set DOTNET_CLI_TELEMETRY_OPTOUT=true set DOTNET_CLI_TELEMETRY_OPTOUT=true
@rem Work around https://github.com/dotnet/core/issues/5881
dotnet nuget locals all --clear
call buildall.bat call buildall.bat

@ -6,10 +6,10 @@
"homepage": "https://developers.google.com/protocol-buffers/", "homepage": "https://developers.google.com/protocol-buffers/",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"require": { "require": {
"php": ">=7.0.0" "php": ">=5.5.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": ">=6.0.0" "phpunit/phpunit": ">=5.0.0"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

@ -55,8 +55,7 @@ typedef struct {
zend_object std; zend_object std;
zval arena; zval arena;
upb_array *array; upb_array *array;
upb_fieldtype_t type; TypeInfo type;
const Descriptor* desc; // When values are messages.
} RepeatedField; } RepeatedField;
zend_class_entry *RepeatedField_class_entry; zend_class_entry *RepeatedField_class_entry;
@ -76,7 +75,6 @@ static zend_object* RepeatedField_create(zend_class_entry *class_type) {
intern->std.handlers = &RepeatedField_object_handlers; intern->std.handlers = &RepeatedField_object_handlers;
Arena_Init(&intern->arena); Arena_Init(&intern->arena);
intern->array = NULL; intern->array = NULL;
intern->desc = NULL;
// Skip object_properties_init(), we don't allow derived classes. // Skip object_properties_init(), we don't allow derived classes.
return &intern->std; return &intern->std;
} }
@ -106,13 +104,35 @@ static void RepeatedField_destructor(zend_object* obj) {
static int RepeatedField_compare_objects(zval *rf1, zval *rf2) { static int RepeatedField_compare_objects(zval *rf1, zval *rf2) {
RepeatedField* intern1 = (RepeatedField*)Z_OBJ_P(rf1); RepeatedField* intern1 = (RepeatedField*)Z_OBJ_P(rf1);
RepeatedField* intern2 = (RepeatedField*)Z_OBJ_P(rf2); RepeatedField* intern2 = (RepeatedField*)Z_OBJ_P(rf2);
upb_fieldtype_t type = intern1->type;
const upb_msgdef *m = intern1->desc ? intern1->desc->msgdef : NULL;
if (type != intern2->type) return 1; return TypeInfo_Eq(intern1->type, intern2->type) &&
if (intern1->desc != intern2->desc) return 1; ArrayEq(intern1->array, intern2->array, intern1->type)
? 0
: 1;
}
/**
* RepeatedField_clone_obj()
*
* Object handler for cloning an object in PHP. Called when PHP code does:
*
* $rf2 = clone $rf1;
*/
static zend_object *RepeatedField_clone_obj(PROTO_VAL *object) {
RepeatedField* intern = PROTO_VAL_P(object);
upb_arena *arena = Arena_Get(&intern->arena);
upb_array *clone = upb_array_new(arena, intern->type.type);
size_t n = upb_array_size(intern->array);
size_t i;
for (i = 0; i < n; i++) {
upb_msgval msgval = upb_array_get(intern->array, i);
upb_array_append(clone, msgval, arena);
}
return ArrayEq(intern1->array, intern2->array, type, m) ? 0 : 1; zval ret;
RepeatedField_GetPhpWrapper(&ret, clone, intern->type, &intern->arena);
return Z_OBJ_P(&ret);
} }
static HashTable *RepeatedField_GetProperties(PROTO_VAL *object) { static HashTable *RepeatedField_GetProperties(PROTO_VAL *object) {
@ -129,8 +149,8 @@ static zval *RepeatedField_GetPropertyPtrPtr(PROTO_VAL *object,
// These are documented in the header file. // These are documented in the header file.
void RepeatedField_GetPhpWrapper(zval *val, upb_array *arr, void RepeatedField_GetPhpWrapper(zval *val, upb_array *arr, TypeInfo type,
const upb_fielddef *f, zval *arena) { zval *arena) {
if (!arr) { if (!arr) {
ZVAL_NULL(val); ZVAL_NULL(val);
return; return;
@ -142,15 +162,14 @@ void RepeatedField_GetPhpWrapper(zval *val, upb_array *arr,
intern->std.handlers = &RepeatedField_object_handlers; intern->std.handlers = &RepeatedField_object_handlers;
ZVAL_COPY(&intern->arena, arena); ZVAL_COPY(&intern->arena, arena);
intern->array = arr; intern->array = arr;
intern->type = upb_fielddef_type(f); intern->type = type;
intern->desc = Descriptor_GetFromFieldDef(f);
// Skip object_properties_init(), we don't allow derived classes. // Skip object_properties_init(), we don't allow derived classes.
ObjCache_Add(intern->array, &intern->std); ObjCache_Add(intern->array, &intern->std);
ZVAL_OBJ(val, &intern->std); ZVAL_OBJ(val, &intern->std);
} }
} }
upb_array *RepeatedField_GetUpbArray(zval *val, const upb_fielddef *f, upb_array *RepeatedField_GetUpbArray(zval *val, TypeInfo type,
upb_arena *arena) { upb_arena *arena) {
if (Z_ISREF_P(val)) { if (Z_ISREF_P(val)) {
ZVAL_DEREF(val); ZVAL_DEREF(val);
@ -158,11 +177,9 @@ upb_array *RepeatedField_GetUpbArray(zval *val, const upb_fielddef *f,
if (Z_TYPE_P(val) == IS_ARRAY) { if (Z_TYPE_P(val) == IS_ARRAY) {
// Auto-construct, eg. [1, 2, 3] -> upb_array([1, 2, 3]). // Auto-construct, eg. [1, 2, 3] -> upb_array([1, 2, 3]).
upb_array *arr = upb_array_new(arena, upb_fielddef_type(f)); upb_array *arr = upb_array_new(arena, type.type);
HashTable *table = HASH_OF(val); HashTable *table = HASH_OF(val);
HashPosition pos; HashPosition pos;
upb_fieldtype_t type = upb_fielddef_type(f);
const Descriptor *desc = Descriptor_GetFromFieldDef(f);
zend_hash_internal_pointer_reset_ex(table, &pos); zend_hash_internal_pointer_reset_ex(table, &pos);
@ -172,7 +189,7 @@ upb_array *RepeatedField_GetUpbArray(zval *val, const upb_fielddef *f,
if (!zv) return arr; if (!zv) return arr;
if (!Convert_PhpToUpbAutoWrap(zv, &val, type, desc, arena)) { if (!Convert_PhpToUpbAutoWrap(zv, &val, type, arena)) {
return NULL; return NULL;
} }
@ -183,9 +200,8 @@ upb_array *RepeatedField_GetUpbArray(zval *val, const upb_fielddef *f,
Z_OBJCE_P(val) == RepeatedField_class_entry) { Z_OBJCE_P(val) == RepeatedField_class_entry) {
// Unwrap existing RepeatedField object to get the upb_array* inside. // Unwrap existing RepeatedField object to get the upb_array* inside.
RepeatedField *intern = (RepeatedField*)Z_OBJ_P(val); RepeatedField *intern = (RepeatedField*)Z_OBJ_P(val);
const Descriptor *desc = Descriptor_GetFromFieldDef(f);
if (intern->type != upb_fielddef_type(f) || intern->desc != desc) { if (!TypeInfo_Eq(intern->type, type)) {
php_error_docref(NULL, E_USER_ERROR, php_error_docref(NULL, E_USER_ERROR,
"Wrong type for this repeated field."); "Wrong type for this repeated field.");
} }
@ -198,8 +214,7 @@ upb_array *RepeatedField_GetUpbArray(zval *val, const upb_fielddef *f,
} }
} }
bool ArrayEq(const upb_array *a1, const upb_array *a2, upb_fieldtype_t type, bool ArrayEq(const upb_array *a1, const upb_array *a2, TypeInfo type) {
const upb_msgdef *m) {
size_t i; size_t i;
size_t n; size_t n;
@ -212,7 +227,7 @@ bool ArrayEq(const upb_array *a1, const upb_array *a2, upb_fieldtype_t type,
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
upb_msgval val1 = upb_array_get(a1, i); upb_msgval val1 = upb_array_get(a1, i);
upb_msgval val2 = upb_array_get(a2, i); upb_msgval val2 = upb_array_get(a2, i);
if (!ValueEq(val1, val2, type, m)) return false; if (!ValueEq(val1, val2, type)) return false;
} }
return true; return true;
@ -238,16 +253,16 @@ PHP_METHOD(RepeatedField, __construct) {
return; return;
} }
intern->type = pbphp_dtype_to_type(type); intern->type.type = pbphp_dtype_to_type(type);
intern->desc = Descriptor_GetFromClassEntry(klass); intern->type.desc = Descriptor_GetFromClassEntry(klass);
if (intern->type == UPB_TYPE_MESSAGE && klass == NULL) { if (intern->type.type == UPB_TYPE_MESSAGE && klass == NULL) {
php_error_docref(NULL, E_USER_ERROR, php_error_docref(NULL, E_USER_ERROR,
"Message/enum type must have concrete class."); "Message/enum type must have concrete class.");
return; return;
} }
intern->array = upb_array_new(arena, intern->type); intern->array = upb_array_new(arena, intern->type.type);
ObjCache_Add(intern->array, &intern->std); ObjCache_Add(intern->array, &intern->std);
} }
@ -264,7 +279,7 @@ PHP_METHOD(RepeatedField, append) {
upb_msgval msgval; upb_msgval msgval;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &php_val) != SUCCESS || if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &php_val) != SUCCESS ||
!Convert_PhpToUpb(php_val, &msgval, intern->type, intern->desc, arena)) { !Convert_PhpToUpb(php_val, &msgval, intern->type, arena)) {
return; return;
} }
@ -321,7 +336,7 @@ PHP_METHOD(RepeatedField, offsetGet) {
} }
msgval = upb_array_get(intern->array, index); msgval = upb_array_get(intern->array, index);
Convert_UpbToPhp(msgval, &ret, intern->type, intern->desc, &intern->arena); Convert_UpbToPhp(msgval, &ret, intern->type, &intern->arena);
RETURN_ZVAL(&ret, 0, 1); RETURN_ZVAL(&ret, 0, 1);
} }
@ -357,7 +372,7 @@ PHP_METHOD(RepeatedField, offsetSet) {
return; return;
} }
if (!Convert_PhpToUpb(val, &msgval, intern->type, intern->desc, arena)) { if (!Convert_PhpToUpb(val, &msgval, intern->type, arena)) {
return; return;
} }
@ -563,7 +578,7 @@ PHP_METHOD(RepeatedFieldIter, current) {
msgval = upb_array_get(array, index); msgval = upb_array_get(array, index);
Convert_UpbToPhp(msgval, &ret, field->type, field->desc, &field->arena); Convert_UpbToPhp(msgval, &ret, field->type, &field->arena);
RETURN_ZVAL(&ret, 0, 1); RETURN_ZVAL(&ret, 0, 1);
} }
@ -638,6 +653,7 @@ void Array_ModuleInit() {
#else #else
h->compare = RepeatedField_compare_objects; h->compare = RepeatedField_compare_objects;
#endif #endif
h->clone_obj = RepeatedField_clone_obj;
h->get_properties = RepeatedField_GetProperties; h->get_properties = RepeatedField_GetProperties;
h->get_property_ptr_ptr = RepeatedField_GetPropertyPtrPtr; h->get_property_ptr_ptr = RepeatedField_GetPropertyPtrPtr;

@ -33,6 +33,7 @@
#include <php.h> #include <php.h>
#include "def.h"
#include "php-upb.h" #include "php-upb.h"
// Registers PHP classes for RepeatedField. // Registers PHP classes for RepeatedField.
@ -40,27 +41,27 @@ void Array_ModuleInit();
// Gets a upb_array* for the PHP object |val|: // Gets a upb_array* for the PHP object |val|:
// * If |val| is a RepeatedField object, we first check its type and verify // * If |val| is a RepeatedField object, we first check its type and verify
// that that the elements have the correct type for |f|. If so, we return the // that that the elements have the correct type for |type|. If so, we return
// wrapped upb_array*. We also make sure that this array's arena is fused to // the wrapped upb_array*. We also make sure that this array's arena is fused
// |arena|, so the returned upb_array is guaranteed to live as long as // to |arena|, so the returned upb_array is guaranteed to live as long as
// |arena|. // |arena|.
// * If |val| is a PHP Array, we attempt to create a new upb_array using // * If |val| is a PHP Array, we attempt to create a new upb_array using
// |arena| and add all of the PHP elements to it. // |arena| and add all of the PHP elements to it.
// //
// If an error occurs, we raise a PHP error and return NULL. // If an error occurs, we raise a PHP error and return NULL.
upb_array *RepeatedField_GetUpbArray(zval *val, const upb_fielddef *f, upb_arena *arena); upb_array *RepeatedField_GetUpbArray(zval *val, TypeInfo type,
upb_arena *arena);
// Creates a PHP RepeatedField object for the given upb_array* and |f| and // Creates a PHP RepeatedField object for the given upb_array* and |type| and
// returns it in |val|. The PHP object will keep a reference to this |arena| to // returns it in |val|. The PHP object will keep a reference to this |arena| to
// ensure the underlying array data stays alive. // ensure the underlying array data stays alive.
// //
// If |arr| is NULL, this will return a PHP null object. // If |arr| is NULL, this will return a PHP null object.
void RepeatedField_GetPhpWrapper(zval *val, upb_array *arr, void RepeatedField_GetPhpWrapper(zval *val, upb_array *arr, TypeInfo type,
const upb_fielddef *f, zval *arena); zval *arena);
// Returns true if the given arrays are equal. Both arrays must be of this // Returns true if the given arrays are equal. Both arrays must be of this
// |type| and, if the type is |UPB_TYPE_MESSAGE|, must have the same |m|. // |type| and, if the type is |UPB_TYPE_MESSAGE|, must have the same |m|.
bool ArrayEq(const upb_array *a1, const upb_array *a2, upb_fieldtype_t type, bool ArrayEq(const upb_array *a1, const upb_array *a2, TypeInfo type);
const upb_msgdef *m);
#endif // PHP_PROTOBUF_ARRAY_H_ #endif // PHP_PROTOBUF_ARRAY_H_

@ -348,15 +348,15 @@ static bool to_string(zval* from) {
} }
} }
bool Convert_PhpToUpb(zval *php_val, upb_msgval *upb_val, upb_fieldtype_t type, bool Convert_PhpToUpb(zval *php_val, upb_msgval *upb_val, TypeInfo type,
const Descriptor *desc, upb_arena *arena) { upb_arena *arena) {
int64_t i64; int64_t i64;
if (Z_ISREF_P(php_val)) { if (Z_ISREF_P(php_val)) {
ZVAL_DEREF(php_val); ZVAL_DEREF(php_val);
} }
switch (type) { switch (type.type) {
case UPB_TYPE_INT64: case UPB_TYPE_INT64:
return Convert_PhpToInt64(php_val, &upb_val->int64_val); return Convert_PhpToInt64(php_val, &upb_val->int64_val);
case UPB_TYPE_INT32: case UPB_TYPE_INT32:
@ -408,17 +408,17 @@ bool Convert_PhpToUpb(zval *php_val, upb_msgval *upb_val, upb_fieldtype_t type,
return true; return true;
} }
case UPB_TYPE_MESSAGE: case UPB_TYPE_MESSAGE:
PBPHP_ASSERT(desc); PBPHP_ASSERT(type.desc);
return Message_GetUpbMessage(php_val, desc, arena, return Message_GetUpbMessage(php_val, type.desc, arena,
(upb_msg **)&upb_val->msg_val); (upb_msg **)&upb_val->msg_val);
} }
return false; return false;
} }
void Convert_UpbToPhp(upb_msgval upb_val, zval *php_val, upb_fieldtype_t type, void Convert_UpbToPhp(upb_msgval upb_val, zval *php_val, TypeInfo type,
const Descriptor *desc, zval *arena) { zval *arena) {
switch (type) { switch (type.type) {
case UPB_TYPE_INT64: case UPB_TYPE_INT64:
#if SIZEOF_ZEND_LONG == 8 #if SIZEOF_ZEND_LONG == 8
ZVAL_LONG(php_val, upb_val.int64_val); ZVAL_LONG(php_val, upb_val.int64_val);
@ -467,25 +467,24 @@ void Convert_UpbToPhp(upb_msgval upb_val, zval *php_val, upb_fieldtype_t type,
break; break;
} }
case UPB_TYPE_MESSAGE: case UPB_TYPE_MESSAGE:
PBPHP_ASSERT(desc); PBPHP_ASSERT(type.desc);
Message_GetPhpWrapper(php_val, desc, (upb_msg*)upb_val.msg_val, arena); Message_GetPhpWrapper(php_val, type.desc, (upb_msg *)upb_val.msg_val,
arena);
break; break;
} }
} }
bool Convert_PhpToUpbAutoWrap(zval *val, upb_msgval *upb_val, bool Convert_PhpToUpbAutoWrap(zval *val, upb_msgval *upb_val, TypeInfo type,
upb_fieldtype_t type, const Descriptor *desc,
upb_arena *arena) { upb_arena *arena) {
const upb_msgdef *subm = desc ? desc->msgdef : NULL; const upb_msgdef *subm = type.desc ? type.desc->msgdef : NULL;
if (subm && upb_msgdef_iswrapper(subm) && Z_TYPE_P(val) != IS_OBJECT) { if (subm && upb_msgdef_iswrapper(subm) && Z_TYPE_P(val) != IS_OBJECT) {
// Assigning a scalar to a wrapper-typed value. We will automatically wrap // Assigning a scalar to a wrapper-typed value. We will automatically wrap
// the value, so the user doesn't need to create a FooWrapper(['value': X]) // the value, so the user doesn't need to create a FooWrapper(['value': X])
// message manually. // message manually.
upb_msg *wrapper = upb_msg_new(subm, arena); upb_msg *wrapper = upb_msg_new(subm, arena);
const upb_fielddef *val_f = upb_msgdef_itof(subm, 1); const upb_fielddef *val_f = upb_msgdef_itof(subm, 1);
upb_fieldtype_t type_f = upb_fielddef_type(val_f);
upb_msgval msgval; upb_msgval msgval;
if (!Convert_PhpToUpb(val, &msgval, type_f, NULL, arena)) return false; if (!Convert_PhpToUpb(val, &msgval, TypeInfo_Get(val_f), arena)) return false;
upb_msg_set(wrapper, val_f, msgval, arena); upb_msg_set(wrapper, val_f, msgval, arena);
upb_val->msg_val = wrapper; upb_val->msg_val = wrapper;
return true; return true;
@ -495,7 +494,7 @@ bool Convert_PhpToUpbAutoWrap(zval *val, upb_msgval *upb_val,
// ['foo_submsg': new Foo(['a' => 1])] // ['foo_submsg': new Foo(['a' => 1])]
// not: // not:
// ['foo_submsg': ['a' => 1]] // ['foo_submsg': ['a' => 1]]
return Convert_PhpToUpb(val, upb_val, type, desc, arena); return Convert_PhpToUpb(val, upb_val, type, arena);
} }
} }

@ -46,8 +46,8 @@ bool Convert_PhpToInt64(const zval *php_val, int64_t *i64);
// UPB_TYPE_MESSAGE, then |desc| must be the Descriptor for this message type. // UPB_TYPE_MESSAGE, then |desc| must be the Descriptor for this message type.
// If type is string, message, or bytes, then |arena| will be used to copy // If type is string, message, or bytes, then |arena| will be used to copy
// string data or fuse this arena to the given message's arena. // string data or fuse this arena to the given message's arena.
bool Convert_PhpToUpb(zval *php_val, upb_msgval *upb_val, upb_fieldtype_t type, bool Convert_PhpToUpb(zval *php_val, upb_msgval *upb_val, TypeInfo type,
const Descriptor *desc, upb_arena *arena); upb_arena *arena);
// Similar to Convert_PhpToUpb, but supports automatically wrapping the wrapper // Similar to Convert_PhpToUpb, but supports automatically wrapping the wrapper
// types if a primitive is specified: // types if a primitive is specified:
@ -56,16 +56,15 @@ bool Convert_PhpToUpb(zval *php_val, upb_msgval *upb_val, upb_fieldtype_t type,
// //
// We currently allow this implicit conversion in initializers, but not for // We currently allow this implicit conversion in initializers, but not for
// assignment. // assignment.
bool Convert_PhpToUpbAutoWrap(zval *val, upb_msgval *upb_val, bool Convert_PhpToUpbAutoWrap(zval *val, upb_msgval *upb_val, TypeInfo type,
upb_fieldtype_t type, const Descriptor *desc,
upb_arena *arena); upb_arena *arena);
// Converts |upb_val| to a PHP zval according to |type|. This may involve // Converts |upb_val| to a PHP zval according to |type|. This may involve
// creating a PHP wrapper object. If type == UPB_TYPE_MESSAGE, then |desc| must // creating a PHP wrapper object. If type == UPB_TYPE_MESSAGE, then |desc| must
// be the Descriptor for this message type. Any newly created wrapper object // be the Descriptor for this message type. Any newly created wrapper object
// will reference |arena|. // will reference |arena|.
void Convert_UpbToPhp(upb_msgval upb_val, zval *php_val, upb_fieldtype_t type, void Convert_UpbToPhp(upb_msgval upb_val, zval *php_val, TypeInfo type,
const Descriptor *desc, zval *arena); zval *arena);
// Registers the GPBUtil class. // Registers the GPBUtil class.
void Convert_ModuleInit(void); void Convert_ModuleInit(void);

@ -72,4 +72,27 @@ Descriptor* Descriptor_GetFromClassEntry(zend_class_entry *ce);
Descriptor* Descriptor_GetFromMessageDef(const upb_msgdef *m); Descriptor* Descriptor_GetFromMessageDef(const upb_msgdef *m);
Descriptor* Descriptor_GetFromFieldDef(const upb_fielddef *f); Descriptor* Descriptor_GetFromFieldDef(const upb_fielddef *f);
// Packages up a upb_fieldtype_t with a Descriptor, since many functions need
// both.
typedef struct {
upb_fieldtype_t type;
const Descriptor *desc; // When type == UPB_TYPE_MESSAGE.
} TypeInfo;
static inline TypeInfo TypeInfo_Get(const upb_fielddef *f) {
TypeInfo ret = {upb_fielddef_type(f), Descriptor_GetFromFieldDef(f)};
return ret;
}
static inline TypeInfo TypeInfo_FromType(upb_fieldtype_t type) {
TypeInfo ret = {type};
return ret;
}
static inline bool TypeInfo_Eq(TypeInfo a, TypeInfo b) {
if (a.type != b.type) return false;
if (a.type == UPB_TYPE_MESSAGE && a.desc != b.desc) return false;
return true;
}
#endif // PHP_PROTOBUF_DEF_H_ #endif // PHP_PROTOBUF_DEF_H_

@ -51,14 +51,31 @@ typedef struct {
zend_object std; zend_object std;
zval arena; zval arena;
upb_map *map; upb_map *map;
upb_fieldtype_t key_type; MapField_Type type;
upb_fieldtype_t val_type;
const Descriptor* desc; // When values are messages.
} MapField; } MapField;
zend_class_entry *MapField_class_entry; zend_class_entry *MapField_class_entry;
static zend_object_handlers MapField_object_handlers; static zend_object_handlers MapField_object_handlers;
static bool MapType_Eq(MapField_Type a, MapField_Type b) {
return a.key_type == b.key_type && TypeInfo_Eq(a.val_type, b.val_type);
}
static TypeInfo KeyType(MapField_Type type) {
TypeInfo ret = {type.key_type};
return ret;
}
MapField_Type MapType_Get(const upb_fielddef *f) {
const upb_msgdef *ent = upb_fielddef_msgsubdef(f);
const upb_fielddef *key_f = upb_msgdef_itof(ent, 1);
const upb_fielddef *val_f = upb_msgdef_itof(ent, 2);
MapField_Type type = {
upb_fielddef_type(key_f),
{upb_fielddef_type(val_f), Descriptor_GetFromFieldDef(val_f)}};
return type;
}
// PHP Object Handlers ///////////////////////////////////////////////////////// // PHP Object Handlers /////////////////////////////////////////////////////////
/** /**
@ -102,15 +119,36 @@ static void MapField_destructor(zend_object* obj) {
static int MapField_compare_objects(zval *map1, zval *map2) { static int MapField_compare_objects(zval *map1, zval *map2) {
MapField* intern1 = (MapField*)Z_OBJ_P(map1); MapField* intern1 = (MapField*)Z_OBJ_P(map1);
MapField* intern2 = (MapField*)Z_OBJ_P(map2); MapField* intern2 = (MapField*)Z_OBJ_P(map2);
const upb_msgdef *m = intern1->desc ? intern1->desc->msgdef : NULL;
upb_fieldtype_t key_type = intern1->key_type;
upb_fieldtype_t val_type = intern1->val_type;
if (key_type != intern2->key_type) return 1; return MapType_Eq(intern1->type, intern2->type) &&
if (val_type != intern2->val_type) return 1; MapEq(intern1->map, intern2->map, intern1->type)
if (intern1->desc != intern2->desc) return 1; ? 0
: 1;
}
return MapEq(intern1->map, intern2->map, key_type, val_type, m) ? 0 : 1; /**
* MapField_clone_obj()
*
* Object handler for cloning an object in PHP. Called when PHP code does:
*
* $map2 = clone $map1;
*/
static zend_object *MapField_clone_obj(PROTO_VAL *object) {
MapField* intern = PROTO_VAL_P(object);
upb_arena *arena = Arena_Get(&intern->arena);
upb_map *clone =
upb_map_new(arena, intern->type.key_type, intern->type.val_type.type);
size_t iter = UPB_MAP_BEGIN;
while (upb_mapiter_next(intern->map, &iter)) {
upb_msgval key = upb_mapiter_key(intern->map, iter);
upb_msgval val = upb_mapiter_value(intern->map, iter);
upb_map_set(clone, key, val, arena);
}
zval ret;
MapField_GetPhpWrapper(&ret, clone, intern->type, &intern->arena);
return Z_OBJ_P(&ret);
} }
static zval *Map_GetPropertyPtrPtr(PROTO_VAL *object, PROTO_STR *member, static zval *Map_GetPropertyPtrPtr(PROTO_VAL *object, PROTO_STR *member,
@ -126,7 +164,7 @@ static HashTable *Map_GetProperties(PROTO_VAL *object) {
// These are documented in the header file. // These are documented in the header file.
void MapField_GetPhpWrapper(zval *val, upb_map *map, const upb_fielddef *f, void MapField_GetPhpWrapper(zval *val, upb_map *map, MapField_Type type,
zval *arena) { zval *arena) {
if (!map) { if (!map) {
ZVAL_NULL(val); ZVAL_NULL(val);
@ -134,37 +172,25 @@ void MapField_GetPhpWrapper(zval *val, upb_map *map, const upb_fielddef *f,
} }
if (!ObjCache_Get(map, val)) { if (!ObjCache_Get(map, val)) {
const upb_msgdef *ent = upb_fielddef_msgsubdef(f);
const upb_fielddef *key_f = upb_msgdef_itof(ent, 1);
const upb_fielddef *val_f = upb_msgdef_itof(ent, 2);
MapField *intern = emalloc(sizeof(MapField)); MapField *intern = emalloc(sizeof(MapField));
zend_object_std_init(&intern->std, MapField_class_entry); zend_object_std_init(&intern->std, MapField_class_entry);
intern->std.handlers = &MapField_object_handlers; intern->std.handlers = &MapField_object_handlers;
ZVAL_COPY(&intern->arena, arena); ZVAL_COPY(&intern->arena, arena);
intern->map = map; intern->map = map;
intern->key_type = upb_fielddef_type(key_f); intern->type = type;
intern->val_type = upb_fielddef_type(val_f);
intern->desc = Descriptor_GetFromFieldDef(val_f);
// Skip object_properties_init(), we don't allow derived classes. // Skip object_properties_init(), we don't allow derived classes.
ObjCache_Add(intern->map, &intern->std); ObjCache_Add(intern->map, &intern->std);
ZVAL_OBJ(val, &intern->std); ZVAL_OBJ(val, &intern->std);
} }
} }
upb_map *MapField_GetUpbMap(zval *val, const upb_fielddef *f, upb_arena *arena) { upb_map *MapField_GetUpbMap(zval *val, MapField_Type type, upb_arena *arena) {
const upb_msgdef *ent = upb_fielddef_msgsubdef(f);
const upb_fielddef *key_f = upb_msgdef_itof(ent, 1);
const upb_fielddef *val_f = upb_msgdef_itof(ent, 2);
upb_fieldtype_t key_type = upb_fielddef_type(key_f);
upb_fieldtype_t val_type = upb_fielddef_type(val_f);
const Descriptor *desc = Descriptor_GetFromFieldDef(val_f);
if (Z_ISREF_P(val)) { if (Z_ISREF_P(val)) {
ZVAL_DEREF(val); ZVAL_DEREF(val);
} }
if (Z_TYPE_P(val) == IS_ARRAY) { if (Z_TYPE_P(val) == IS_ARRAY) {
upb_map *map = upb_map_new(arena, key_type, val_type); upb_map *map = upb_map_new(arena, type.key_type, type.val_type.type);
HashTable *table = HASH_OF(val); HashTable *table = HASH_OF(val);
HashPosition pos; HashPosition pos;
@ -181,8 +207,8 @@ upb_map *MapField_GetUpbMap(zval *val, const upb_fielddef *f, upb_arena *arena)
if (!php_val) return map; if (!php_val) return map;
if (!Convert_PhpToUpb(&php_key, &upb_key, key_type, NULL, arena) || if (!Convert_PhpToUpb(&php_key, &upb_key, KeyType(type), arena) ||
!Convert_PhpToUpbAutoWrap(php_val, &upb_val, val_type, desc, arena)) { !Convert_PhpToUpbAutoWrap(php_val, &upb_val, type.val_type, arena)) {
return NULL; return NULL;
} }
@ -194,8 +220,7 @@ upb_map *MapField_GetUpbMap(zval *val, const upb_fielddef *f, upb_arena *arena)
Z_OBJCE_P(val) == MapField_class_entry) { Z_OBJCE_P(val) == MapField_class_entry) {
MapField *intern = (MapField*)Z_OBJ_P(val); MapField *intern = (MapField*)Z_OBJ_P(val);
if (intern->key_type != key_type || intern->val_type != val_type || if (!MapType_Eq(intern->type, type)) {
intern->desc != desc) {
php_error_docref(NULL, E_USER_ERROR, "Wrong type for this map field."); php_error_docref(NULL, E_USER_ERROR, "Wrong type for this map field.");
return NULL; return NULL;
} }
@ -208,8 +233,7 @@ upb_map *MapField_GetUpbMap(zval *val, const upb_fielddef *f, upb_arena *arena)
} }
} }
bool MapEq(const upb_map *m1, const upb_map *m2, upb_fieldtype_t key_type, bool MapEq(const upb_map *m1, const upb_map *m2, MapField_Type type) {
upb_fieldtype_t val_type, const upb_msgdef *m) {
size_t iter = UPB_MAP_BEGIN; size_t iter = UPB_MAP_BEGIN;
if ((m1 == NULL) != (m2 == NULL)) return false; if ((m1 == NULL) != (m2 == NULL)) return false;
@ -222,7 +246,7 @@ bool MapEq(const upb_map *m1, const upb_map *m2, upb_fieldtype_t key_type,
upb_msgval val2; upb_msgval val2;
if (!upb_map_get(m2, key, &val2)) return false; if (!upb_map_get(m2, key, &val2)) return false;
if (!ValueEq(val1, val2, val_type, m)) return false; if (!ValueEq(val1, val2, type.val_type)) return false;
} }
return true; return true;
@ -250,12 +274,12 @@ PHP_METHOD(MapField, __construct) {
return; return;
} }
intern->key_type = pbphp_dtype_to_type(key_type); intern->type.key_type = pbphp_dtype_to_type(key_type);
intern->val_type = pbphp_dtype_to_type(val_type); intern->type.val_type.type = pbphp_dtype_to_type(val_type);
intern->desc = Descriptor_GetFromClassEntry(klass); intern->type.val_type.desc = Descriptor_GetFromClassEntry(klass);
// Check that the key type is an allowed type. // Check that the key type is an allowed type.
switch (intern->key_type) { switch (intern->type.key_type) {
case UPB_TYPE_INT32: case UPB_TYPE_INT32:
case UPB_TYPE_INT64: case UPB_TYPE_INT64:
case UPB_TYPE_UINT32: case UPB_TYPE_UINT32:
@ -269,13 +293,14 @@ PHP_METHOD(MapField, __construct) {
zend_error(E_USER_ERROR, "Invalid key type for map."); zend_error(E_USER_ERROR, "Invalid key type for map.");
} }
if (intern->val_type == UPB_TYPE_MESSAGE && klass == NULL) { if (intern->type.val_type.type == UPB_TYPE_MESSAGE && klass == NULL) {
php_error_docref(NULL, E_USER_ERROR, php_error_docref(NULL, E_USER_ERROR,
"Message/enum type must have concrete class."); "Message/enum type must have concrete class.");
return; return;
} }
intern->map = upb_map_new(arena, intern->key_type, intern->val_type); intern->map =
upb_map_new(arena, intern->type.key_type, intern->type.val_type.type);
ObjCache_Add(intern->map, &intern->std); ObjCache_Add(intern->map, &intern->std);
} }
@ -296,7 +321,7 @@ PHP_METHOD(MapField, offsetExists) {
upb_msgval upb_key; upb_msgval upb_key;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS || if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS ||
!Convert_PhpToUpb(key, &upb_key, intern->key_type, intern->desc, NULL)) { !Convert_PhpToUpb(key, &upb_key, KeyType(intern->type), NULL)) {
return; return;
} }
@ -322,7 +347,7 @@ PHP_METHOD(MapField, offsetGet) {
upb_msgval upb_key, upb_val; upb_msgval upb_key, upb_val;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS || if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS ||
!Convert_PhpToUpb(key, &upb_key, intern->key_type, intern->desc, NULL)) { !Convert_PhpToUpb(key, &upb_key, KeyType(intern->type), NULL)) {
return; return;
} }
@ -331,7 +356,7 @@ PHP_METHOD(MapField, offsetGet) {
return; return;
} }
Convert_UpbToPhp(upb_val, &ret, intern->val_type, intern->desc, &intern->arena); Convert_UpbToPhp(upb_val, &ret, intern->type.val_type, &intern->arena);
RETURN_ZVAL(&ret, 0, 1); RETURN_ZVAL(&ret, 0, 1);
} }
@ -355,8 +380,8 @@ PHP_METHOD(MapField, offsetSet) {
upb_msgval upb_key, upb_val; upb_msgval upb_key, upb_val;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &key, &val) != SUCCESS || if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &key, &val) != SUCCESS ||
!Convert_PhpToUpb(key, &upb_key, intern->key_type, NULL, NULL) || !Convert_PhpToUpb(key, &upb_key, KeyType(intern->type), NULL) ||
!Convert_PhpToUpb(val, &upb_val, intern->val_type, intern->desc, arena)) { !Convert_PhpToUpb(val, &upb_val, intern->type.val_type, arena)) {
return; return;
} }
@ -380,7 +405,7 @@ PHP_METHOD(MapField, offsetUnset) {
upb_msgval upb_key; upb_msgval upb_key;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS || if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS ||
!Convert_PhpToUpb(key, &upb_key, intern->key_type, NULL, NULL)) { !Convert_PhpToUpb(key, &upb_key, KeyType(intern->type), NULL)) {
return; return;
} }
@ -543,7 +568,7 @@ PHP_METHOD(MapFieldIter, current) {
MapField *field = (MapField*)Z_OBJ_P(&intern->map_field); MapField *field = (MapField*)Z_OBJ_P(&intern->map_field);
upb_msgval upb_val = upb_mapiter_value(field->map, intern->position); upb_msgval upb_val = upb_mapiter_value(field->map, intern->position);
zval ret; zval ret;
Convert_UpbToPhp(upb_val, &ret, field->val_type, field->desc, &field->arena); Convert_UpbToPhp(upb_val, &ret, field->type.val_type, &field->arena);
RETURN_ZVAL(&ret, 0, 1); RETURN_ZVAL(&ret, 0, 1);
} }
@ -557,7 +582,7 @@ PHP_METHOD(MapFieldIter, key) {
MapField *field = (MapField*)Z_OBJ_P(&intern->map_field); MapField *field = (MapField*)Z_OBJ_P(&intern->map_field);
upb_msgval upb_key = upb_mapiter_key(field->map, intern->position); upb_msgval upb_key = upb_mapiter_key(field->map, intern->position);
zval ret; zval ret;
Convert_UpbToPhp(upb_key, &ret, field->key_type, NULL, NULL); Convert_UpbToPhp(upb_key, &ret, KeyType(field->type), NULL);
RETURN_ZVAL(&ret, 0, 1); RETURN_ZVAL(&ret, 0, 1);
} }
@ -624,6 +649,7 @@ void Map_ModuleInit() {
#else #else
h->compare = MapField_compare_objects; h->compare = MapField_compare_objects;
#endif #endif
h->clone_obj = MapField_clone_obj;
h->get_properties = Map_GetProperties; h->get_properties = Map_GetProperties;
h->get_property_ptr_ptr = Map_GetPropertyPtrPtr; h->get_property_ptr_ptr = Map_GetPropertyPtrPtr;

@ -33,10 +33,18 @@
#include <php.h> #include <php.h>
#include "def.h"
#include "php-upb.h" #include "php-upb.h"
void Map_ModuleInit(); void Map_ModuleInit();
typedef struct {
upb_fieldtype_t key_type;
TypeInfo val_type;
} MapField_Type;
MapField_Type MapType_Get(const upb_fielddef *f);
// Gets a upb_map* for the PHP object |val|: // Gets a upb_map* for the PHP object |val|:
// * If |val| is a RepeatedField object, we first check its type and verify // * If |val| is a RepeatedField object, we first check its type and verify
// that that the elements have the correct type for |f|. If so, we return the // that that the elements have the correct type for |f|. If so, we return the
@ -47,17 +55,16 @@ void Map_ModuleInit();
// |arena| and add all of the PHP elements to it. // |arena| and add all of the PHP elements to it.
// //
// If an error occurs, we raise a PHP error and return NULL. // If an error occurs, we raise a PHP error and return NULL.
upb_map *MapField_GetUpbMap(zval *val, const upb_fielddef *f, upb_arena *arena); upb_map *MapField_GetUpbMap(zval *val, MapField_Type type, upb_arena *arena);
// Creates a PHP MapField object for the given upb_map* and |f| and returns it // Creates a PHP MapField object for the given upb_map* and |f| and returns it
// in |val|. The PHP object will keep a reference to this |arena| to ensure the // in |val|. The PHP object will keep a reference to this |arena| to ensure the
// underlying array data stays alive. // underlying array data stays alive.
// //
// If |map| is NULL, this will return a PHP null object. // If |map| is NULL, this will return a PHP null object.
void MapField_GetPhpWrapper(zval *val, upb_map *arr, const upb_fielddef *f, void MapField_GetPhpWrapper(zval *val, upb_map *arr, MapField_Type type,
zval *arena); zval *arena);
bool MapEq(const upb_map *m1, const upb_map *m2, upb_fieldtype_t key_type, bool MapEq(const upb_map *m1, const upb_map *m2, MapField_Type type);
upb_fieldtype_t val_type, const upb_msgdef *m);
#endif // PHP_PROTOBUF_MAP_H_ #endif // PHP_PROTOBUF_MAP_H_

@ -60,6 +60,21 @@ typedef struct {
zend_class_entry *message_ce; zend_class_entry *message_ce;
static zend_object_handlers message_object_handlers; static zend_object_handlers message_object_handlers;
static void Message_SuppressDefaultProperties(zend_class_entry *class_type) {
// We suppress all default properties, because all our properties are handled
// by our read_property handler.
//
// This also allows us to put our zend_object member at the beginning of our
// struct -- instead of putting it at the end with pointer fixups to access
// our own data, as recommended in the docs -- because Zend won't add any of
// its own storage directly after the zend_object if default_properties_count
// == 0.
//
// This is not officially supported, but since it simplifies the code, we'll
// do it for as long as it works in practice.
class_type->default_properties_count = 0;
}
// PHP Object Handlers ///////////////////////////////////////////////////////// // PHP Object Handlers /////////////////////////////////////////////////////////
/** /**
@ -69,8 +84,7 @@ static zend_object_handlers message_object_handlers;
*/ */
static zend_object* Message_create(zend_class_entry *class_type) { static zend_object* Message_create(zend_class_entry *class_type) {
Message *intern = emalloc(sizeof(Message)); Message *intern = emalloc(sizeof(Message));
// XXX(haberman): verify whether we actually want to take this route. Message_SuppressDefaultProperties(class_type);
class_type->default_properties_count = 0;
zend_object_std_init(&intern->std, class_type); zend_object_std_init(&intern->std, class_type);
intern->std.handlers = &message_object_handlers; intern->std.handlers = &message_object_handlers;
Arena_Init(&intern->arena); Arena_Init(&intern->arena);
@ -114,14 +128,14 @@ static void Message_get(Message *intern, const upb_fielddef *f, zval *rv) {
if (upb_fielddef_ismap(f)) { if (upb_fielddef_ismap(f)) {
upb_mutmsgval msgval = upb_msg_mutable(intern->msg, f, arena); upb_mutmsgval msgval = upb_msg_mutable(intern->msg, f, arena);
MapField_GetPhpWrapper(rv, msgval.map, f, &intern->arena); MapField_GetPhpWrapper(rv, msgval.map, MapType_Get(f), &intern->arena);
} else if (upb_fielddef_isseq(f)) { } else if (upb_fielddef_isseq(f)) {
upb_mutmsgval msgval = upb_msg_mutable(intern->msg, f, arena); upb_mutmsgval msgval = upb_msg_mutable(intern->msg, f, arena);
RepeatedField_GetPhpWrapper(rv, msgval.array, f, &intern->arena); RepeatedField_GetPhpWrapper(rv, msgval.array, TypeInfo_Get(f),
&intern->arena);
} else { } else {
upb_msgval msgval = upb_msg_get(intern->msg, f); upb_msgval msgval = upb_msg_get(intern->msg, f);
const Descriptor *subdesc = Descriptor_GetFromFieldDef(f); Convert_UpbToPhp(msgval, rv, TypeInfo_Get(f), &intern->arena);
Convert_UpbToPhp(msgval, rv, upb_fielddef_type(f), subdesc, &intern->arena);
} }
} }
@ -130,16 +144,13 @@ static bool Message_set(Message *intern, const upb_fielddef *f, zval *val) {
upb_msgval msgval; upb_msgval msgval;
if (upb_fielddef_ismap(f)) { if (upb_fielddef_ismap(f)) {
msgval.map_val = MapField_GetUpbMap(val, f, arena); msgval.map_val = MapField_GetUpbMap(val, MapType_Get(f), arena);
if (!msgval.map_val) return false; if (!msgval.map_val) return false;
} else if (upb_fielddef_isseq(f)) { } else if (upb_fielddef_isseq(f)) {
msgval.array_val = RepeatedField_GetUpbArray(val, f, arena); msgval.array_val = RepeatedField_GetUpbArray(val, TypeInfo_Get(f), arena);
if (!msgval.array_val) return false; if (!msgval.array_val) return false;
} else { } else {
upb_fieldtype_t type = upb_fielddef_type(f); if (!Convert_PhpToUpb(val, &msgval, TypeInfo_Get(f), arena)) return false;
const Descriptor *subdesc = Descriptor_GetFromFieldDef(f);
bool ok = Convert_PhpToUpb(val, &msgval, type, subdesc, arena);
if (!ok) return false;
} }
upb_msg_set(intern->msg, f, msgval, arena); upb_msg_set(intern->msg, f, msgval, arena);
@ -149,11 +160,10 @@ static bool Message_set(Message *intern, const upb_fielddef *f, zval *val) {
static bool MessageEq(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m); static bool MessageEq(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m);
/** /**
* ValueEq()() * ValueEq()
*/ */
bool ValueEq(upb_msgval val1, upb_msgval val2, upb_fieldtype_t type, bool ValueEq(upb_msgval val1, upb_msgval val2, TypeInfo type) {
const upb_msgdef *m) { switch (type.type) {
switch (type) {
case UPB_TYPE_BOOL: case UPB_TYPE_BOOL:
return val1.bool_val == val2.bool_val; return val1.bool_val == val2.bool_val;
case UPB_TYPE_INT32: case UPB_TYPE_INT32:
@ -172,7 +182,7 @@ bool ValueEq(upb_msgval val1, upb_msgval val2, upb_fieldtype_t type,
return val1.str_val.size == val2.str_val.size && return val1.str_val.size == val2.str_val.size &&
memcmp(val1.str_val.data, val2.str_val.data, val1.str_val.size) == 0; memcmp(val1.str_val.data, val2.str_val.data, val1.str_val.size) == 0;
case UPB_TYPE_MESSAGE: case UPB_TYPE_MESSAGE:
return MessageEq(val1.msg_val, val2.msg_val, m); return MessageEq(val1.msg_val, val2.msg_val, type.desc->msgdef);
default: default:
return false; return false;
} }
@ -190,8 +200,6 @@ static bool MessageEq(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m)
const upb_fielddef *f = upb_msg_iter_field(&i); const upb_fielddef *f = upb_msg_iter_field(&i);
upb_msgval val1 = upb_msg_get(m1, f); upb_msgval val1 = upb_msg_get(m1, f);
upb_msgval val2 = upb_msg_get(m2, f); upb_msgval val2 = upb_msg_get(m2, f);
upb_fieldtype_t type = upb_fielddef_type(f);
const upb_msgdef *sub_m = upb_fielddef_msgsubdef(f);
if (upb_fielddef_haspresence(f)) { if (upb_fielddef_haspresence(f)) {
if (upb_msg_has(m1, f) != upb_msg_has(m2, f)) { if (upb_msg_has(m1, f) != upb_msg_has(m2, f)) {
@ -201,18 +209,11 @@ static bool MessageEq(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m)
} }
if (upb_fielddef_ismap(f)) { if (upb_fielddef_ismap(f)) {
const upb_fielddef *key_f = upb_msgdef_itof(sub_m, 1); if (!MapEq(val1.map_val, val2.map_val, MapType_Get(f))) return false;
const upb_fielddef *val_f = upb_msgdef_itof(sub_m, 2);
upb_fieldtype_t key_type = upb_fielddef_type(key_f);
upb_fieldtype_t val_type = upb_fielddef_type(val_f);
const upb_msgdef *val_m = upb_fielddef_msgsubdef(val_f);
if (!MapEq(val1.map_val, val2.map_val, key_type, val_type, val_m)) {
return false;
}
} else if (upb_fielddef_isseq(f)) { } else if (upb_fielddef_isseq(f)) {
if (!ArrayEq(val1.array_val, val2.array_val, type, sub_m)) return false; if (!ArrayEq(val1.array_val, val2.array_val, TypeInfo_Get(f))) return false;
} else { } else {
if (!ValueEq(val1, val2, type, sub_m)) return false; if (!ValueEq(val1, val2, TypeInfo_Get(f))) return false;
} }
} }
@ -258,7 +259,7 @@ static int Message_compare_objects(zval *m1, zval *m2) {
static int Message_has_property(PROTO_VAL *obj, PROTO_STR *member, static int Message_has_property(PROTO_VAL *obj, PROTO_STR *member,
int has_set_exists, int has_set_exists,
void **cache_slot) { void **cache_slot) {
Message* intern = PROTO_MSG_P(obj); Message* intern = PROTO_VAL_P(obj);
const upb_fielddef *f = get_field(intern, member); const upb_fielddef *f = get_field(intern, member);
if (!f) return 0; if (!f) return 0;
@ -293,7 +294,7 @@ static int Message_has_property(PROTO_VAL *obj, PROTO_STR *member,
*/ */
static void Message_unset_property(PROTO_VAL *obj, PROTO_STR *member, static void Message_unset_property(PROTO_VAL *obj, PROTO_STR *member,
void **cache_slot) { void **cache_slot) {
Message* intern = PROTO_MSG_P(obj); Message* intern = PROTO_VAL_P(obj);
const upb_fielddef *f = get_field(intern, member); const upb_fielddef *f = get_field(intern, member);
if (!f) return; if (!f) return;
@ -330,7 +331,7 @@ static void Message_unset_property(PROTO_VAL *obj, PROTO_STR *member,
*/ */
static zval *Message_read_property(PROTO_VAL *obj, PROTO_STR *member, static zval *Message_read_property(PROTO_VAL *obj, PROTO_STR *member,
int type, void **cache_slot, zval *rv) { int type, void **cache_slot, zval *rv) {
Message* intern = PROTO_MSG_P(obj); Message* intern = PROTO_VAL_P(obj);
const upb_fielddef *f = get_field(intern, member); const upb_fielddef *f = get_field(intern, member);
if (!f) return NULL; if (!f) return NULL;
@ -361,7 +362,7 @@ static zval *Message_read_property(PROTO_VAL *obj, PROTO_STR *member,
*/ */
static PROTO_RETURN_VAL Message_write_property( static PROTO_RETURN_VAL Message_write_property(
PROTO_VAL *obj, PROTO_STR *member, zval *val, void **cache_slot) { PROTO_VAL *obj, PROTO_STR *member, zval *val, void **cache_slot) {
Message* intern = PROTO_MSG_P(obj); Message* intern = PROTO_VAL_P(obj);
const upb_fielddef *f = get_field(intern, member); const upb_fielddef *f = get_field(intern, member);
if (f && Message_set(intern, f, val)) { if (f && Message_set(intern, f, val)) {
@ -392,6 +393,25 @@ static zval *Message_get_property_ptr_ptr(PROTO_VAL *object, PROTO_STR *member,
return NULL; // We do not have a properties table. return NULL; // We do not have a properties table.
} }
/**
* Message_clone_obj()
*
* Object handler for cloning an object in PHP. Called when PHP code does:
*
* $msg2 = clone $msg;
*/
static zend_object *Message_clone_obj(PROTO_VAL *object) {
Message* intern = PROTO_VAL_P(object);
upb_msg *clone = upb_msg_new(intern->desc->msgdef, Arena_Get(&intern->arena));
// TODO: copy unknown fields?
// TODO: use official upb msg copy function
memcpy(clone, intern->msg, upb_msgdef_layout(intern->desc->msgdef)->size);
zval ret;
Message_GetPhpWrapper(&ret, intern->desc, clone, &intern->arena);
return Z_OBJ_P(&ret);
}
/** /**
* Message_get_properties() * Message_get_properties()
* *
@ -415,8 +435,7 @@ void Message_GetPhpWrapper(zval *val, const Descriptor *desc, upb_msg *msg,
if (!ObjCache_Get(msg, val)) { if (!ObjCache_Get(msg, val)) {
Message *intern = emalloc(sizeof(Message)); Message *intern = emalloc(sizeof(Message));
// XXX(haberman): verify whether we actually want to take this route. Message_SuppressDefaultProperties(desc->class_entry);
desc->class_entry->default_properties_count = 0;
zend_object_std_init(&intern->std, desc->class_entry); zend_object_std_init(&intern->std, desc->class_entry);
intern->std.handlers = &message_object_handlers; intern->std.handlers = &message_object_handlers;
ZVAL_COPY(&intern->arena, arena); ZVAL_COPY(&intern->arena, arena);
@ -521,15 +540,13 @@ bool Message_InitFromPhp(upb_msg *msg, const upb_msgdef *m, zval *init,
} }
if (upb_fielddef_ismap(f)) { if (upb_fielddef_ismap(f)) {
msgval.map_val = MapField_GetUpbMap(val, f, arena); msgval.map_val = MapField_GetUpbMap(val, MapType_Get(f), arena);
if (!msgval.map_val) return false; if (!msgval.map_val) return false;
} else if (upb_fielddef_isseq(f)) { } else if (upb_fielddef_isseq(f)) {
msgval.array_val = RepeatedField_GetUpbArray(val, f, arena); msgval.array_val = RepeatedField_GetUpbArray(val, TypeInfo_Get(f), arena);
if (!msgval.array_val) return false; if (!msgval.array_val) return false;
} else { } else {
const Descriptor *desc = Descriptor_GetFromFieldDef(f); if (!Convert_PhpToUpbAutoWrap(val, &msgval, TypeInfo_Get(f), arena)) {
upb_fieldtype_t type = upb_fielddef_type(f);
if (!Convert_PhpToUpbAutoWrap(val, &msgval, type, desc, arena)) {
return false; return false;
} }
} }
@ -554,10 +571,32 @@ static void Message_Initialize(Message *intern, const Descriptor *desc) {
*/ */
PHP_METHOD(Message, __construct) { PHP_METHOD(Message, __construct) {
Message* intern = (Message*)Z_OBJ_P(getThis()); Message* intern = (Message*)Z_OBJ_P(getThis());
const Descriptor* desc = Descriptor_GetFromClassEntry(Z_OBJCE_P(getThis())); const Descriptor* desc;
zend_class_entry *ce = Z_OBJCE_P(getThis());
upb_arena *arena = Arena_Get(&intern->arena); upb_arena *arena = Arena_Get(&intern->arena);
zval *init_arr = NULL; zval *init_arr = NULL;
// This descriptor should always be available, as the generated __construct
// method calls initOnce() to load the descriptor prior to calling us.
//
// However, if the user created their own class derived from Message, this
// will trigger an infinite construction loop and blow the stack. We
// temporarily clear create_object to break this loop (see check in
// NameMap_GetMessage()).
PBPHP_ASSERT(ce->create_object == Message_create);
ce->create_object = NULL;
desc = Descriptor_GetFromClassEntry(ce);
ce->create_object = Message_create;
if (!desc) {
zend_throw_exception_ex(
NULL, 0,
"Couldn't find descriptor. Note only generated code may derive from "
"\\Google\\Protobuf\\Internal\\Message");
return;
}
Message_Initialize(intern, desc); Message_Initialize(intern, desc);
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a!", &init_arr) == FAILURE) { if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a!", &init_arr) == FAILURE) {
@ -805,10 +844,9 @@ PHP_METHOD(Message, readWrapperValue) {
const upb_msg *wrapper = upb_msg_get(intern->msg, f).msg_val; const upb_msg *wrapper = upb_msg_get(intern->msg, f).msg_val;
const upb_msgdef *m = upb_fielddef_msgsubdef(f); const upb_msgdef *m = upb_fielddef_msgsubdef(f);
const upb_fielddef *val_f = upb_msgdef_itof(m, 1); const upb_fielddef *val_f = upb_msgdef_itof(m, 1);
const upb_fieldtype_t val_type = upb_fielddef_type(val_f);
upb_msgval msgval = upb_msg_get(wrapper, val_f); upb_msgval msgval = upb_msg_get(wrapper, val_f);
zval ret; zval ret;
Convert_UpbToPhp(msgval, &ret, val_type, NULL, &intern->arena); Convert_UpbToPhp(msgval, &ret, TypeInfo_Get(val_f), &intern->arena);
RETURN_ZVAL(&ret, 1, 0); RETURN_ZVAL(&ret, 1, 0);
} else { } else {
RETURN_NULL(); RETURN_NULL();
@ -861,10 +899,9 @@ PHP_METHOD(Message, writeWrapperValue) {
} else { } else {
const upb_msgdef *m = upb_fielddef_msgsubdef(f); const upb_msgdef *m = upb_fielddef_msgsubdef(f);
const upb_fielddef *val_f = upb_msgdef_itof(m, 1); const upb_fielddef *val_f = upb_msgdef_itof(m, 1);
upb_fieldtype_t val_type = upb_fielddef_type(val_f);
upb_msg *wrapper; upb_msg *wrapper;
if (!Convert_PhpToUpb(val, &msgval, val_type, NULL, arena)) { if (!Convert_PhpToUpb(val, &msgval, TypeInfo_Get(val_f), arena)) {
return; // Error is already set. return; // Error is already set.
} }
@ -974,9 +1011,7 @@ PHP_METHOD(Message, readOneof) {
{ {
upb_msgval msgval = upb_msg_get(intern->msg, f); upb_msgval msgval = upb_msg_get(intern->msg, f);
const Descriptor *subdesc = Descriptor_GetFromFieldDef(f); Convert_UpbToPhp(msgval, &ret, TypeInfo_Get(f), &intern->arena);
Convert_UpbToPhp(msgval, &ret, upb_fielddef_type(f), subdesc,
&intern->arena);
} }
RETURN_ZVAL(&ret, 1, 0); RETURN_ZVAL(&ret, 1, 0);
@ -1017,8 +1052,7 @@ PHP_METHOD(Message, writeOneof) {
f = upb_msgdef_itof(intern->desc->msgdef, field_num); f = upb_msgdef_itof(intern->desc->msgdef, field_num);
if (!Convert_PhpToUpb(val, &msgval, upb_fielddef_type(f), if (!Convert_PhpToUpb(val, &msgval, TypeInfo_Get(f), arena)) {
Descriptor_GetFromFieldDef(f), arena)) {
return; return;
} }
@ -1225,8 +1259,8 @@ PHP_METHOD(google_protobuf_Timestamp, fromDateTime) {
if (call_user_function(EG(function_table), NULL, &function_name, &retval, 1, if (call_user_function(EG(function_table), NULL, &function_name, &retval, 1,
datetime) == FAILURE || datetime) == FAILURE ||
!Convert_PhpToUpb(&retval, &timestamp_seconds, UPB_TYPE_INT64, NULL, !Convert_PhpToUpb(&retval, &timestamp_seconds,
NULL)) { TypeInfo_FromType(UPB_TYPE_INT64), NULL)) {
zend_error(E_ERROR, "Cannot get timestamp from DateTime."); zend_error(E_ERROR, "Cannot get timestamp from DateTime.");
return; return;
} }
@ -1251,8 +1285,8 @@ PHP_METHOD(google_protobuf_Timestamp, fromDateTime) {
if (call_user_function(EG(function_table), NULL, &function_name, &retval, 2, if (call_user_function(EG(function_table), NULL, &function_name, &retval, 2,
params) == FAILURE || params) == FAILURE ||
!Convert_PhpToUpb(&retval, &timestamp_nanos, UPB_TYPE_INT32, NULL, !Convert_PhpToUpb(&retval, &timestamp_nanos,
NULL)) { TypeInfo_FromType(UPB_TYPE_INT32), NULL)) {
zend_error(E_ERROR, "Cannot format DateTime."); zend_error(E_ERROR, "Cannot format DateTime.");
return; return;
} }
@ -1338,6 +1372,7 @@ void Message_ModuleInit() {
h->unset_property = Message_unset_property; h->unset_property = Message_unset_property;
h->get_properties = Message_get_properties; h->get_properties = Message_get_properties;
h->get_property_ptr_ptr = Message_get_property_ptr_ptr; h->get_property_ptr_ptr = Message_get_property_ptr_ptr;
h->clone_obj = Message_clone_obj;
WellKnownTypes_ModuleInit(); /* From wkt.inc. */ WellKnownTypes_ModuleInit(); /* From wkt.inc. */
} }

@ -56,7 +56,6 @@ bool Message_GetUpbMessage(zval *val, const Descriptor *desc, upb_arena *arena,
void Message_GetPhpWrapper(zval *val, const Descriptor *desc, upb_msg *msg, void Message_GetPhpWrapper(zval *val, const Descriptor *desc, upb_msg *msg,
zval *arena); zval *arena);
bool ValueEq(upb_msgval val1, upb_msgval val2, upb_fieldtype_t type, bool ValueEq(upb_msgval val1, upb_msgval val2, TypeInfo type);
const upb_msgdef *m);
#endif // PHP_PROTOBUF_MESSAGE_H_ #endif // PHP_PROTOBUF_MESSAGE_H_

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -58,13 +58,13 @@ const zval *get_generated_pool();
#if PHP_VERSION_ID < 80000 #if PHP_VERSION_ID < 80000
#define PROTO_VAL zval #define PROTO_VAL zval
#define PROTO_STR zval #define PROTO_STR zval
#define PROTO_MSG_P(obj) (Message*)Z_OBJ_P(obj) #define PROTO_VAL_P(obj) Z_OBJ_P(obj)
#define PROTO_STRVAL_P(obj) Z_STRVAL_P(obj) #define PROTO_STRVAL_P(obj) Z_STRVAL_P(obj)
#define PROTO_STRLEN_P(obj) Z_STRLEN_P(obj) #define PROTO_STRLEN_P(obj) Z_STRLEN_P(obj)
#else #else
#define PROTO_VAL zend_object #define PROTO_VAL zend_object
#define PROTO_STR zend_string #define PROTO_STR zend_string
#define PROTO_MSG_P(obj) (Message*)(obj) #define PROTO_VAL_P(obj) (void*)(obj)
#define PROTO_STRVAL_P(obj) ZSTR_VAL(obj) #define PROTO_STRVAL_P(obj) ZSTR_VAL(obj)
#define PROTO_STRLEN_P(obj) ZSTR_LEN(obj) #define PROTO_STRLEN_P(obj) ZSTR_LEN(obj)
#endif #endif

@ -49,6 +49,7 @@ class FileOptions extends \Google\Protobuf\Internal\Message
* This option does nothing. * This option does nothing.
* *
* Generated from protobuf field <code>optional bool java_generate_equals_and_hash = 20 [deprecated = true];</code> * Generated from protobuf field <code>optional bool java_generate_equals_and_hash = 20 [deprecated = true];</code>
* @deprecated
*/ */
protected $java_generate_equals_and_hash = null; protected $java_generate_equals_and_hash = null;
/** /**
@ -412,19 +413,23 @@ class FileOptions extends \Google\Protobuf\Internal\Message
* *
* Generated from protobuf field <code>optional bool java_generate_equals_and_hash = 20 [deprecated = true];</code> * Generated from protobuf field <code>optional bool java_generate_equals_and_hash = 20 [deprecated = true];</code>
* @return bool * @return bool
* @deprecated
*/ */
public function getJavaGenerateEqualsAndHash() public function getJavaGenerateEqualsAndHash()
{ {
@trigger_error('java_generate_equals_and_hash is deprecated.', E_USER_DEPRECATED);
return isset($this->java_generate_equals_and_hash) ? $this->java_generate_equals_and_hash : false; return isset($this->java_generate_equals_and_hash) ? $this->java_generate_equals_and_hash : false;
} }
public function hasJavaGenerateEqualsAndHash() public function hasJavaGenerateEqualsAndHash()
{ {
@trigger_error('java_generate_equals_and_hash is deprecated.', E_USER_DEPRECATED);
return isset($this->java_generate_equals_and_hash); return isset($this->java_generate_equals_and_hash);
} }
public function clearJavaGenerateEqualsAndHash() public function clearJavaGenerateEqualsAndHash()
{ {
@trigger_error('java_generate_equals_and_hash is deprecated.', E_USER_DEPRECATED);
unset($this->java_generate_equals_and_hash); unset($this->java_generate_equals_and_hash);
} }
@ -434,9 +439,11 @@ class FileOptions extends \Google\Protobuf\Internal\Message
* Generated from protobuf field <code>optional bool java_generate_equals_and_hash = 20 [deprecated = true];</code> * Generated from protobuf field <code>optional bool java_generate_equals_and_hash = 20 [deprecated = true];</code>
* @param bool $var * @param bool $var
* @return $this * @return $this
* @deprecated
*/ */
public function setJavaGenerateEqualsAndHash($var) public function setJavaGenerateEqualsAndHash($var)
{ {
@trigger_error('java_generate_equals_and_hash is deprecated.', E_USER_DEPRECATED);
GPBUtil::checkBool($var); GPBUtil::checkBool($var);
$this->java_generate_equals_and_hash = $var; $this->java_generate_equals_and_hash = $var;

@ -50,8 +50,8 @@ class GPBWire
public static function getTagFieldNumber($tag) public static function getTagFieldNumber($tag)
{ {
return ($tag >> self::TAG_TYPE_BITS) & // We have to mask because PHP has no arithmetic shift.
(1 << ((PHP_INT_SIZE * 8) - self::TAG_TYPE_BITS)) - 1; return ($tag >> self::TAG_TYPE_BITS) & 0x1fffffff;
} }
public static function getTagWireType($tag) public static function getTagWireType($tag)

@ -93,8 +93,9 @@ class Message
$pool = DescriptorPool::getGeneratedPool(); $pool = DescriptorPool::getGeneratedPool();
$this->desc = $pool->getDescriptorByClassName(get_class($this)); $this->desc = $pool->getDescriptorByClassName(get_class($this));
if (is_null($this->desc)) { if (is_null($this->desc)) {
user_error(get_class($this) . " is not found in descriptor pool."); throw new \InvalidArgumentException(
return; get_class($this) ." is not found in descriptor pool. " .
'Only generated classes may derive from Message.');
} }
foreach ($this->desc->getField() as $field) { foreach ($this->desc->getField() as $field) {
$setter = $field->getSetter(); $setter = $field->getSetter();

@ -624,4 +624,16 @@ class ArrayTest extends TestBase
new RepeatedField(GPBType::MESSAGE, TestMessage::class) == new RepeatedField(GPBType::MESSAGE, TestMessage::class) ==
new RepeatedField(GPBType::MESSAGE, Sub::class)); new RepeatedField(GPBType::MESSAGE, Sub::class));
} }
#########################################################
# Test clone
#########################################################
public function testClone()
{
$arr = new RepeatedField(GPBType::MESSAGE, TestMessage::class);
$arr[] = new TestMessage;
$arr2 = clone $arr;
$this->assertSame($arr[0], $arr2[0]);
}
} }

@ -14,6 +14,7 @@ use Foo\TestStringValue;
use Foo\TestBytesValue; use Foo\TestBytesValue;
use Foo\TestAny; use Foo\TestAny;
use Foo\TestEnum; use Foo\TestEnum;
use Foo\TestLargeFieldNumber;
use Foo\TestMessage; use Foo\TestMessage;
use Foo\TestMessage\Sub; use Foo\TestMessage\Sub;
use Foo\TestPackedMessage; use Foo\TestPackedMessage;
@ -529,6 +530,15 @@ class EncodeDecodeTest extends TestBase
$this->assertSame("", $data); $this->assertSame("", $data);
} }
public function testLargeFieldNumber()
{
$m = new TestLargeFieldNumber(['large_field_number' => 5]);
$data = $m->serializeToString();
$m2 = new TestLargeFieldNumber();
$m2->mergeFromString($data);
$this->assertSame(5, $m2->getLargeFieldNumber());
}
public function testDecodeInvalidInt32() public function testDecodeInvalidInt32()
{ {
$this->expectException(Exception::class); $this->expectException(Exception::class);

@ -24,6 +24,13 @@ use Foo\testLowerCaseEnum;
use PBEmpty\PBEcho\TestEmptyPackage; use PBEmpty\PBEcho\TestEmptyPackage;
use Php\Test\TestNamespace; use Php\Test\TestNamespace;
# This is not allowed, but we at least shouldn't crash.
class C extends \Google\Protobuf\Internal\Message {
public function __construct($data = null) {
parent::__construct($data);
}
}
class GeneratedClassTest extends TestBase class GeneratedClassTest extends TestBase
{ {
@ -71,6 +78,33 @@ class GeneratedClassTest extends TestBase
$this->assertSame(MIN_INT32, $m->getOptionalInt32()); $this->assertSame(MIN_INT32, $m->getOptionalInt32());
} }
#########################################################
# Test deprecated int32 field.
#########################################################
public function testDeprecatedInt32Field()
{
$m = new TestMessage();
// temporarily change error handler to capture the deprecated errors
$deprecationCount = 0;
set_error_handler(function ($errno, $errstr) use (&$deprecationCount) {
if ($errstr === 'deprecated_optional_int32 is deprecated.') {
$deprecationCount++;
}
}, E_USER_DEPRECATED);
// default test set
$m->setDeprecatedOptionalInt32(MAX_INT32);
$this->assertSame(MAX_INT32, $m->getDeprecatedOptionalInt32());
$m->setDeprecatedOptionalInt32(MIN_INT32);
$this->assertSame(MIN_INT32, $m->getDeprecatedOptionalInt32());
restore_error_handler();
$this->assertSame(4, $deprecationCount);
}
######################################################### #########################################################
# Test optional int32 field. # Test optional int32 field.
######################################################### #########################################################
@ -1491,6 +1525,28 @@ class GeneratedClassTest extends TestBase
$this->assertTrue(true); $this->assertTrue(true);
} }
#########################################################
# Test clone.
#########################################################
public function testClone()
{
$m = new TestMessage([
'optional_int32' => -42,
'optional_int64' => -43,
'optional_message' => new Sub([
'a' => 33
]),
'map_int32_message' => [1 => new Sub(['a' => 36])],
]);
$m2 = clone $m;
$this->assertEquals($m->getOptionalInt32(), $m2->getOptionalInt32());
$this->assertEquals($m->getOptionalInt64(), $m2->getOptionalInt64());
$this->assertSame($m->getOptionalMessage(), $m2->getOptionalMessage());
$this->assertSame($m->getMapInt32Message()[1], $m2->getMapInt32Message()[1]);
$this->assertEquals($m->serializeToJsonString(), $m2->serializeToJsonString());
}
######################################################### #########################################################
# Test message equals. # Test message equals.
######################################################### #########################################################
@ -1696,6 +1752,16 @@ class GeneratedClassTest extends TestBase
$this->assertFalse($m->hasOneofString()); $this->assertFalse($m->hasOneofString());
} }
#########################################################
# Test that we don't crash if users create their own messages.
#########################################################
public function testUserDefinedClass() {
# This is not allowed, but at least we shouldn't crash.
$this->expectException(Exception::class);
$p = new C();
}
######################################################### #########################################################
# Test no segfault when error happens # Test no segfault when error happens
######################################################### #########################################################

@ -340,6 +340,13 @@ class GeneratedPhpdocTest extends TestBase
], ],
'@param \NoNamespaceMessage $var' '@param \NoNamespaceMessage $var'
], ],
[
[
'setDeprecatedOptionalInt32',
'getDeprecatedOptionalInt32',
],
'@deprecated'
],
]; ];
} }
} }

@ -511,6 +511,24 @@ class MapFieldTest extends TestBase {
new MapField(GPBType::INT32, GPBType::MESSAGE, Sub::class)); new MapField(GPBType::INT32, GPBType::MESSAGE, Sub::class));
} }
#########################################################
# Test clone
#########################################################
public function testClone()
{
$map = new MapField(GPBType::INT32,
GPBType::MESSAGE, Sub::class);
// Test append.
$sub_m = new Sub();
$sub_m->setA(1);
$map[0] = $sub_m;
$map2 = clone $map;
$this->assertSame($map[0], $map2[0]);
}
######################################################### #########################################################
# Test memory leak # Test memory leak
######################################################### #########################################################

@ -147,6 +147,9 @@ message TestMessage {
map<string, google.protobuf.Any> map_string_any = 122; map<string, google.protobuf.Any> map_string_any = 122;
map<string, google.protobuf.ListValue> map_string_list = 123; map<string, google.protobuf.ListValue> map_string_list = 123;
map<string, google.protobuf.Struct> map_string_struct = 124; map<string, google.protobuf.Struct> map_string_struct = 124;
// deprecated field
int32 deprecated_optional_int32 = 125 [deprecated=true];
} }
enum TestEnum { enum TestEnum {
@ -220,6 +223,10 @@ message TestRandomFieldOrder {
string tag14 = 160; string tag14 = 160;
} }
message TestLargeFieldNumber {
int32 large_field_number = 536870911;
}
message TestReverseFieldOrder { message TestReverseFieldOrder {
repeated int32 a = 2; repeated int32 a = 2;
string b = 1; string b = 1;

@ -1,6 +0,0 @@
FROM quay.io/pypa/manylinux1_x86_64
RUN yum install -y libtool
RUN /opt/python/cp27-cp27mu/bin/pip install twine
COPY protobuf_optimized_pip.sh /

@ -1,17 +0,0 @@
Description
------------------------------
This directory is used to build released wheels according to PEP513 and upload
them to pypi.
Usage
------------------------------
For example, to release 3.3.0:
./protobuf_optimized_pip.sh 3.3.0 PYPI_USERNAME PYPI_PASSWORD
Structure
------------------------------
| Source | Source |
|--------------------------------------|---------------------------------------------------|
| protobuf_optimized_pip.sh | Entry point. Calling Dockerfile and build_wheel_manylinux.sh |
| Dockerfile | Build docker image according to PEP513. |
| build_wheel_manylinux.sh | Build wheel packages in the docker container. |

@ -1,27 +0,0 @@
#!/bin/bash
# Print usage and fail.
function usage() {
echo "Usage: protobuf_optimized_pip.sh PROTOBUF_VERSION PYPI_USERNAME PYPI_PASSWORD" >&2
exit 1 # Causes caller to exit because we use -e.
}
# Validate arguments.
if [ $0 != ./build_wheel_manylinux.sh ]; then
echo "Please run this script from the directory in which it is located." >&2
exit 1
fi
if [ $# -lt 3 ]; then
usage
exit 1
fi
PROTOBUF_VERSION=$1
PYPI_USERNAME=$2
PYPI_PASSWORD=$3
docker rmi protobuf-python-wheel
docker build . -t protobuf-python-wheel
docker run --rm protobuf-python-wheel ./protobuf_optimized_pip.sh $PROTOBUF_VERSION $PYPI_USERNAME $PYPI_PASSWORD
docker rmi protobuf-python-wheel

@ -1,66 +0,0 @@
#!/usr/bin/env bash
# DO NOT use this script manually! Called by docker.
set -ex
# Print usage and fail.
function usage() {
echo "Usage: protobuf_optimized_pip.sh PROTOBUF_VERSION" >&2
exit 1 # Causes caller to exit because we use -e.
}
# Build wheel
function build_wheel() {
PYTHON_VERSION=$1
PYTHON_BIN=/opt/python/${PYTHON_VERSION}/bin/python
$PYTHON_BIN setup.py bdist_wheel --cpp_implementation --compile_static_extension
auditwheel repair dist/protobuf-${PROTOBUF_VERSION}-${PYTHON_VERSION}-linux_x86_64.whl
}
# Validate arguments.
if [ $0 != ./protobuf_optimized_pip.sh ]; then
echo "Please run this script from the directory in which it is located." >&2
exit 1
fi
if [ $# -lt 1 ]; then
usage
exit 1
fi
PROTOBUF_VERSION=$1
PYPI_USERNAME=$2
PYPI_PASSWORD=$3
DIR=${PWD}/'protobuf-python-build'
PYTHON_VERSIONS=('cp27-cp27mu' 'cp33-cp33m' 'cp34-cp34m' 'cp35-cp35m' 'cp36-cp36m')
mkdir -p ${DIR}
cd ${DIR}
curl -SsL -O https://github.com/protocolbuffers/protobuf/archive/v${PROTOBUF_VERSION}.tar.gz
tar xzf v${PROTOBUF_VERSION}.tar.gz
cd $DIR/protobuf-${PROTOBUF_VERSION}
# Autoconf on centos 5.11 cannot recognize AC_PROG_OBJC.
sed -i '/AC_PROG_OBJC/d' configure.ac
sed -i 's/conformance\/Makefile//g' configure.ac
# Use the /usr/bin/autoconf and related tools to pick the correct aclocal macros
export PATH="/usr/bin:$PATH"
# Build protoc
./autogen.sh
CXXFLAGS="-fPIC -g -O2" ./configure
make -j8
export PROTOC=$DIR/src/protoc
cd python
for PYTHON_VERSION in "${PYTHON_VERSIONS[@]}"
do
build_wheel $PYTHON_VERSION
done
/opt/python/cp27-cp27mu/bin/twine upload wheelhouse/*

@ -207,7 +207,7 @@ if __name__ == '__main__':
# C++ projects must now migrate to libc++ and are recommended to set a # C++ projects must now migrate to libc++ and are recommended to set a
# deployment target of macOS 10.9 or later, or iOS 7 or later. # deployment target of macOS 10.9 or later, or iOS 7 or later.
if sys.platform == 'darwin': if sys.platform == 'darwin':
mac_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') mac_target = str(sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET'))
if mac_target and (pkg_resources.parse_version(mac_target) < if mac_target and (pkg_resources.parse_version(mac_target) <
pkg_resources.parse_version('10.9.0')): pkg_resources.parse_version('10.9.0')):
os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.9' os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.9'
@ -254,7 +254,7 @@ if __name__ == '__main__':
os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp' os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
# Keep this list of dependencies in sync with tox.ini. # Keep this list of dependencies in sync with tox.ini.
install_requires = ['six>=1.9', 'setuptools'] install_requires = ['six>=1.9']
if sys.version_info <= (2,7): if sys.version_info <= (2,7):
install_requires.append('ordereddict') install_requires.append('ordereddict')
install_requires.append('unittest2') install_requires.append('unittest2')

@ -1,6 +1,6 @@
[tox] [tox]
envlist = envlist =
py{27,33,34,35,36}-{cpp,python} py{27,33,34,35,36,37,38,39}-{cpp,python}
[testenv] [testenv]
usedevelop=true usedevelop=true

@ -7793,7 +7793,8 @@ static void jsondec_timestamp(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
{ {
/* [+-]08:00 or Z */ /* [+-]08:00 or Z */
int ofs = 0; int ofs_hour = 0;
int ofs_min = 0;
bool neg = false; bool neg = false;
if (ptr == end) goto malformed; if (ptr == end) goto malformed;
@ -7804,9 +7805,10 @@ static void jsondec_timestamp(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
/* fallthrough */ /* fallthrough */
case '+': case '+':
if ((end - ptr) != 5) goto malformed; if ((end - ptr) != 5) goto malformed;
ofs = jsondec_tsdigits(d, &ptr, 2, ":00"); ofs_hour = jsondec_tsdigits(d, &ptr, 2, ":");
ofs *= 60 * 60; ofs_min = jsondec_tsdigits(d, &ptr, 2, NULL);
seconds.int64_val += (neg ? ofs : -ofs); ofs_min = ((ofs_hour * 60) + ofs_min) * 60;
seconds.int64_val += (neg ? ofs_min : -ofs_min);
break; break;
case 'Z': case 'Z':
if (ptr != end) goto malformed; if (ptr != end) goto malformed;

@ -4161,7 +4161,6 @@ const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i);
const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i); const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i);
const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i); const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i);
const upb_symtab *upb_filedef_symtab(const upb_filedef *f); const upb_symtab *upb_filedef_symtab(const upb_filedef *f);
upb_arena *_upb_symtab_arena(const upb_symtab *s);
/* upb_symtab *****************************************************************/ /* upb_symtab *****************************************************************/
@ -4179,6 +4178,7 @@ const upb_filedef *upb_symtab_addfile(
upb_symtab *s, const google_protobuf_FileDescriptorProto *file, upb_symtab *s, const google_protobuf_FileDescriptorProto *file,
upb_status *status); upb_status *status);
size_t _upb_symtab_bytesloaded(const upb_symtab *s); size_t _upb_symtab_bytesloaded(const upb_symtab *s);
upb_arena *_upb_symtab_arena(const upb_symtab *s);
/* For generated code only: loads a generated descriptor. */ /* For generated code only: loads a generated descriptor. */
typedef struct upb_def_init { typedef struct upb_def_init {

@ -341,6 +341,7 @@ libprotoc_la_SOURCES = \
google/protobuf/compiler/cpp/cpp_message_field.cc \ google/protobuf/compiler/cpp/cpp_message_field.cc \
google/protobuf/compiler/cpp/cpp_message_field.h \ google/protobuf/compiler/cpp/cpp_message_field.h \
google/protobuf/compiler/cpp/cpp_message_layout_helper.h \ google/protobuf/compiler/cpp/cpp_message_layout_helper.h \
google/protobuf/compiler/cpp/cpp_names.h \
google/protobuf/compiler/cpp/cpp_options.h \ google/protobuf/compiler/cpp/cpp_options.h \
google/protobuf/compiler/cpp/cpp_padding_optimizer.cc \ google/protobuf/compiler/cpp/cpp_padding_optimizer.cc \
google/protobuf/compiler/cpp/cpp_padding_optimizer.h \ google/protobuf/compiler/cpp/cpp_padding_optimizer.h \

@ -327,7 +327,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
template <typename T> template <typename T>
PROTOBUF_NDEBUG_INLINE static T* CreateArray(Arena* arena, PROTOBUF_NDEBUG_INLINE static T* CreateArray(Arena* arena,
size_t num_elements) { size_t num_elements) {
static_assert(std::is_pod<T>::value, static_assert(std::is_trivially_default_constructible<T>::value,
"CreateArray requires a trivially constructible type"); "CreateArray requires a trivially constructible type");
static_assert(std::is_trivially_destructible<T>::value, static_assert(std::is_trivially_destructible<T>::value,
"CreateArray requires a trivially destructible type"); "CreateArray requires a trivially destructible type");

@ -1216,24 +1216,12 @@ PopulateSingleSimpleDescriptorDatabase(const std::string& descriptor_set_name) {
bool CommandLineInterface::AllowProto3Optional( bool CommandLineInterface::AllowProto3Optional(
const FileDescriptor& file) const { const FileDescriptor& file) const {
// If the --experimental_allow_proto3_optional flag was set, we allow. // Proto3 optional is enabled by default now, the experimental flag is no
if (allow_proto3_optional_) return true; // longer required.
// Whitelist all ads protos. Ads is an early adopter of this feature.
if (file.name().find("google/ads/googleads") != std::string::npos) {
return true;
}
// Whitelist all protos testing proto3 optional.
if (file.name().find("test_proto3_optional") != std::string::npos) {
return true; return true;
} }
return false;
}
bool CommandLineInterface::VerifyInputFilesInDescriptors( bool CommandLineInterface::VerifyInputFilesInDescriptors(
DescriptorDatabase* database) { DescriptorDatabase* database) {
for (const auto& input_file : input_files_) { for (const auto& input_file : input_files_) {

@ -2378,48 +2378,6 @@ TEST_F(CommandLineInterfaceTest, MissingValueAtEndError) {
ExpectErrorText("Missing value for flag: --test_out\n"); ExpectErrorText("Missing value for flag: --test_out\n");
} }
TEST_F(CommandLineInterfaceTest, Proto3OptionalDisallowed) {
CreateTempFile("google/foo.proto",
"syntax = \"proto3\";\n"
"message Foo {\n"
" optional int32 i = 1;\n"
"}\n");
Run("protocol_compiler --proto_path=$tmpdir google/foo.proto "
"-odescriptor.pb");
ExpectErrorSubstring("--experimental_allow_proto3_optional was not set");
}
TEST_F(CommandLineInterfaceTest, Proto3OptionalDisallowedDescriptor) {
CreateTempFile("google/foo.proto",
"syntax = \"proto3\";\n"
"message Foo {\n"
" optional int32 i = 1;\n"
"}\n");
Run("protocol_compiler --experimental_allow_proto3_optional "
"--proto_path=$tmpdir google/foo.proto "
" -o$tmpdir/descriptor.pb");
ExpectNoErrors();
Run("protocol_compiler --descriptor_set_in=$tmpdir/descriptor.pb"
" google/foo.proto --test_out=$tmpdir");
ExpectErrorSubstring("--experimental_allow_proto3_optional was not set");
}
TEST_F(CommandLineInterfaceTest, Proto3OptionalDisallowedGenCode) {
CreateTempFile("google/foo.proto",
"syntax = \"proto3\";\n"
"message Foo {\n"
" optional int32 i = 1;\n"
"}\n");
Run("protocol_compiler --proto_path=$tmpdir google/foo.proto "
"--test_out=$tmpdir");
ExpectErrorSubstring("--experimental_allow_proto3_optional was not set");
}
TEST_F(CommandLineInterfaceTest, Proto3OptionalDisallowedNoCodegenSupport) { TEST_F(CommandLineInterfaceTest, Proto3OptionalDisallowedNoCodegenSupport) {
CreateTempFile("google/foo.proto", CreateTempFile("google/foo.proto",

@ -165,7 +165,7 @@ class FieldGenerator {
} }
// Generate initialization code for private members declared by // Generate initialization code for private members declared by
// GeneratePrivateMembers(), specifically for the constexpr construtor. // GeneratePrivateMembers(), specifically for the constexpr constructor.
// These go into the constructor's initializer list and must follow that // These go into the constructor's initializer list and must follow that
// syntax (eg `field_(args)`). Does not include `:` or `,` separators. // syntax (eg `field_(args)`). Does not include `:` or `,` separators.
virtual void GenerateConstinitInitializer(io::Printer* printer) const {} virtual void GenerateConstinitInitializer(io::Printer* printer) const {}

@ -75,11 +75,6 @@ std::string GetSortKey<FileDescriptor>(const FileDescriptor& val) {
return val.name(); return val.name();
} }
template <>
std::string GetSortKey<SCC>(const SCC& val) {
return val.GetRepresentative()->full_name();
}
template <class T> template <class T>
bool CompareSortKeys(const T* a, const T* b) { bool CompareSortKeys(const T* a, const T* b) {
return GetSortKey(*a) < GetSortKey(*b); return GetSortKey(*a) < GetSortKey(*b);

@ -90,17 +90,6 @@ const std::unordered_set<std::string>* kReservedNames =
"transient", "try", "void", "volatile", "while", "transient", "try", "void", "volatile", "while",
}); });
// Names that should be avoided as field names in Kotlin.
// All Kotlin hard keywords are in this list.
const std::unordered_set<std::string>* kKotlinForbiddenNames =
new std::unordered_set<std::string>({
"as", "as?", "break", "class", "continue", "do", "else",
"false", "for", "fun", "if", "in", "!in", "interface",
"is", "!is", "null", "object", "package", "return", "super",
"this", "throw", "true", "try", "typealias", "typeof", "val",
"var", "when", "while",
});
bool IsForbidden(const std::string& field_name) { bool IsForbidden(const std::string& field_name) {
for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) { for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) {
if (field_name == kForbiddenWordList[i]) { if (field_name == kForbiddenWordList[i]) {

@ -49,6 +49,7 @@ namespace protobuf {
namespace compiler { namespace compiler {
namespace java { namespace java {
namespace { namespace {
void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,

@ -28,9 +28,19 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assert.h>
#include <google/protobuf/compiler/js/js_generator.h> #include <google/protobuf/compiler/js/js_generator.h>
#include <google/protobuf/compiler/js/well_known_types_embed.h>
#include <google/protobuf/compiler/scc.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/stubs/strutil.h>
#include <assert.h>
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
#include <map> #include <map>
@ -39,17 +49,6 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/compiler/scc.h>
#include <google/protobuf/compiler/js/well_known_types_embed.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
namespace google { namespace google {
namespace protobuf { namespace protobuf {
namespace compiler { namespace compiler {
@ -173,8 +172,8 @@ std::string GetNestedMessageName(const Descriptor* descriptor) {
if (descriptor == NULL) { if (descriptor == NULL) {
return ""; return "";
} }
std::string result = StripPrefixString( std::string result =
descriptor->full_name(), descriptor->file()->package()); StripPrefixString(descriptor->full_name(), descriptor->file()->package());
// Add a leading dot if one is not already present. // Add a leading dot if one is not already present.
if (!result.empty() && result[0] != '.') { if (!result.empty() && result[0] != '.') {
result = "." + result; result = "." + result;
@ -431,9 +430,7 @@ std::string GetEnumFileName(const GeneratorOptions& options,
} }
// Returns the message/response ID, if set. // Returns the message/response ID, if set.
std::string GetMessageId(const Descriptor* desc) { std::string GetMessageId(const Descriptor* desc) { return std::string(); }
return std::string();
}
bool IgnoreExtensionField(const FieldDescriptor* field) { bool IgnoreExtensionField(const FieldDescriptor* field) {
// Exclude descriptor extensions from output "to avoid clutter" (from original // Exclude descriptor extensions from output "to avoid clutter" (from original
@ -444,7 +441,6 @@ bool IgnoreExtensionField(const FieldDescriptor* field) {
file->name() == "google/protobuf/descriptor.proto"; file->name() == "google/protobuf/descriptor.proto";
} }
// Used inside Google only -- do not remove. // Used inside Google only -- do not remove.
bool IsResponse(const Descriptor* desc) { return false; } bool IsResponse(const Descriptor* desc) { return false; }
@ -452,7 +448,6 @@ bool IgnoreField(const FieldDescriptor* field) {
return IgnoreExtensionField(field); return IgnoreExtensionField(field);
} }
// Do we ignore this message type? // Do we ignore this message type?
bool IgnoreMessage(const Descriptor* d) { return d->options().map_entry(); } bool IgnoreMessage(const Descriptor* d) { return d->options().map_entry(); }
@ -537,7 +532,6 @@ std::string JSGetterName(const GeneratorOptions& options,
return name; return name;
} }
std::string JSOneofName(const OneofDescriptor* oneof) { std::string JSOneofName(const OneofDescriptor* oneof) {
return ToUpperCamel(ParseLowerUnderscore(oneof->name())); return ToUpperCamel(ParseLowerUnderscore(oneof->name()));
} }
@ -818,23 +812,19 @@ std::string JSFieldDefault(const FieldDescriptor* field) {
switch (field->cpp_type()) { switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32: case FieldDescriptor::CPPTYPE_INT32:
return MaybeNumberString(field, return MaybeNumberString(field, StrCat(field->default_value_int32()));
StrCat(field->default_value_int32()));
case FieldDescriptor::CPPTYPE_UINT32: case FieldDescriptor::CPPTYPE_UINT32:
// The original codegen is in Java, and Java protobufs store unsigned // The original codegen is in Java, and Java protobufs store unsigned
// integer values as signed integer values. In order to exactly match the // integer values as signed integer values. In order to exactly match the
// output, we need to reinterpret as base-2 signed. Ugh. // output, we need to reinterpret as base-2 signed. Ugh.
return MaybeNumberString( return MaybeNumberString(
field, field, StrCat(static_cast<int32>(field->default_value_uint32())));
StrCat(static_cast<int32>(field->default_value_uint32())));
case FieldDescriptor::CPPTYPE_INT64: case FieldDescriptor::CPPTYPE_INT64:
return MaybeNumberString(field, return MaybeNumberString(field, StrCat(field->default_value_int64()));
StrCat(field->default_value_int64()));
case FieldDescriptor::CPPTYPE_UINT64: case FieldDescriptor::CPPTYPE_UINT64:
// See above note for uint32 -- reinterpreting as signed. // See above note for uint32 -- reinterpreting as signed.
return MaybeNumberString( return MaybeNumberString(
field, field, StrCat(static_cast<int64>(field->default_value_uint64())));
StrCat(static_cast<int64>(field->default_value_uint64())));
case FieldDescriptor::CPPTYPE_ENUM: case FieldDescriptor::CPPTYPE_ENUM:
return StrCat(field->default_value_enum()->number()); return StrCat(field->default_value_enum()->number());
case FieldDescriptor::CPPTYPE_BOOL: case FieldDescriptor::CPPTYPE_BOOL:
@ -849,7 +839,8 @@ std::string JSFieldDefault(const FieldDescriptor* field) {
bool is_valid = EscapeJSString(field->default_value_string(), &out); bool is_valid = EscapeJSString(field->default_value_string(), &out);
if (!is_valid) { if (!is_valid) {
// TODO(b/115551870): Decide whether this should be a hard error. // TODO(b/115551870): Decide whether this should be a hard error.
GOOGLE_LOG(WARNING) << "The default value for field " << field->full_name() GOOGLE_LOG(WARNING)
<< "The default value for field " << field->full_name()
<< " was truncated since it contained invalid UTF-8 or" << " was truncated since it contained invalid UTF-8 or"
" codepoints outside the basic multilingual plane."; " codepoints outside the basic multilingual plane.";
} }
@ -1114,7 +1105,6 @@ std::string JSBinaryWriterMethodName(const GeneratorOptions& options,
JSBinaryReadWriteMethodName(field, /* is_writer = */ true); JSBinaryReadWriteMethodName(field, /* is_writer = */ true);
} }
std::string JSTypeTag(const FieldDescriptor* desc) { std::string JSTypeTag(const FieldDescriptor* desc) {
switch (desc->type()) { switch (desc->type()) {
case FieldDescriptor::TYPE_DOUBLE: case FieldDescriptor::TYPE_DOUBLE:
@ -1149,7 +1139,6 @@ std::string JSTypeTag(const FieldDescriptor* desc) {
return ""; return "";
} }
bool HasRepeatedFields(const GeneratorOptions& options, bool HasRepeatedFields(const GeneratorOptions& options,
const Descriptor* desc) { const Descriptor* desc) {
for (int i = 0; i < desc->field_count(); i++) { for (int i = 0; i < desc->field_count(); i++) {
@ -1638,6 +1627,8 @@ void Generator::GenerateHeader(const GeneratorOptions& options,
"/**\n" "/**\n"
" * @fileoverview\n" " * @fileoverview\n"
" * @enhanceable\n" " * @enhanceable\n"
// TODO(b/152440355): requireType/requires diverged from internal version.
" * @suppress {missingRequire} reports error on implict type usages.\n"
" * @suppress {messageConventions} JS Compiler reports an " " * @suppress {messageConventions} JS Compiler reports an "
"error if a variable or\n" "error if a variable or\n"
" * field starts with 'MSG_' and isn't a translatable " " * field starts with 'MSG_' and isn't a translatable "
@ -1902,16 +1893,13 @@ void Generator::GenerateRequiresImpl(const GeneratorOptions& options,
} }
} }
bool NamespaceOnly(const Descriptor* desc) { bool NamespaceOnly(const Descriptor* desc) { return false; }
return false;
}
void Generator::FindRequiresForMessage(const GeneratorOptions& options, void Generator::FindRequiresForMessage(const GeneratorOptions& options,
const Descriptor* desc, const Descriptor* desc,
std::set<std::string>* required, std::set<std::string>* required,
std::set<std::string>* forwards, std::set<std::string>* forwards,
bool* have_message) const { bool* have_message) const {
if (!NamespaceOnly(desc)) { if (!NamespaceOnly(desc)) {
*have_message = true; *have_message = true;
for (int i = 0; i < desc->field_count(); i++) { for (int i = 0; i < desc->field_count(); i++) {
@ -1960,7 +1948,8 @@ void Generator::FindRequiresForField(const GeneratorOptions& options,
void Generator::FindRequiresForExtension( void Generator::FindRequiresForExtension(
const GeneratorOptions& options, const FieldDescriptor* field, const GeneratorOptions& options, const FieldDescriptor* field,
std::set<std::string>* required, std::set<std::string>* forwards) const { std::set<std::string>* required, std::set<std::string>* forwards) const {
if (field->containing_type()->full_name() != "google.protobuf.bridge.MessageSet") { if (field->containing_type()->full_name() !=
"google.protobuf.bridge.MessageSet") {
required->insert(GetMessagePath(options, field->containing_type())); required->insert(GetMessagePath(options, field->containing_type()));
} }
FindRequiresForField(options, field, required, forwards); FindRequiresForField(options, field, required, forwards);
@ -2000,7 +1989,6 @@ void Generator::GenerateClass(const GeneratorOptions& options,
printer->Print("\n"); printer->Print("\n");
GenerateClassFieldInfo(options, printer, desc); GenerateClassFieldInfo(options, printer, desc);
GenerateClassToObject(options, printer, desc); GenerateClassToObject(options, printer, desc);
// These must come *before* the extension-field info generation in // These must come *before* the extension-field info generation in
// GenerateClassRegistration so that references to the binary // GenerateClassRegistration so that references to the binary
@ -2084,7 +2072,8 @@ void Generator::GenerateClassConstructorAndDeclareExtensionFieldInfo(
const Descriptor* desc) const { const Descriptor* desc) const {
if (!NamespaceOnly(desc)) { if (!NamespaceOnly(desc)) {
GenerateClassConstructor(options, printer, desc); GenerateClassConstructor(options, printer, desc);
if (IsExtendable(desc) && desc->full_name() != "google.protobuf.bridge.MessageSet") { if (IsExtendable(desc) &&
desc->full_name() != "google.protobuf.bridge.MessageSet") {
GenerateClassExtensionFieldInfo(options, printer, desc); GenerateClassExtensionFieldInfo(options, printer, desc);
} }
} }
@ -2524,7 +2513,6 @@ void Generator::GenerateClassRegistration(const GeneratorOptions& options,
GenerateExtension(options, printer, extension); GenerateExtension(options, printer, extension);
} }
} }
} }
void Generator::GenerateClassFields(const GeneratorOptions& options, void Generator::GenerateClassFields(const GeneratorOptions& options,
@ -2687,8 +2675,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
} }
} else { } else {
bool untyped = bool untyped = false;
false;
// Simple (primitive) field, either singular or repeated. // Simple (primitive) field, either singular or repeated.
@ -3037,7 +3024,6 @@ void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options,
} }
} }
void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options, void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options,
io::Printer* printer, io::Printer* printer,
const Descriptor* desc) const { const Descriptor* desc) const {
@ -3089,8 +3075,8 @@ void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options,
" $class$.prototype.setExtension);\n" " $class$.prototype.setExtension);\n"
" break;\n" " break;\n"
" }\n", " }\n",
"extobj", JSExtensionsObjectName(options, desc->file(), desc), "extobj", JSExtensionsObjectName(options, desc->file(), desc), "class",
"class", GetMessagePath(options, desc)); GetMessagePath(options, desc));
} else { } else {
printer->Print( printer->Print(
" reader.skipField();\n" " reader.skipField();\n"
@ -3381,9 +3367,8 @@ void Generator::GenerateEnum(const GeneratorOptions& options,
for (auto i : valid_index) { for (auto i : valid_index) {
const EnumValueDescriptor* value = enumdesc->value(i); const EnumValueDescriptor* value = enumdesc->value(i);
printer->Print(" $name$: $value$$comma$\n", "name", printer->Print(" $name$: $value$$comma$\n", "name",
ToEnumCase(value->name()), "value", ToEnumCase(value->name()), "value", StrCat(value->number()),
StrCat(value->number()), "comma", "comma", (i == valid_index.back()) ? "" : ",");
(i == valid_index.back()) ? "" : ",");
printer->Annotate("name", value); printer->Annotate("name", value);
} }
@ -3424,8 +3409,7 @@ void Generator::GenerateExtension(const GeneratorOptions& options,
"!Object} */ (\n" "!Object} */ (\n"
" $toObject$),\n" " $toObject$),\n"
" $repeated$);\n", " $repeated$);\n",
"index", StrCat(field->number()), "name", extension_object_name, "index", StrCat(field->number()), "name", extension_object_name, "ctor",
"ctor",
(field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
? SubmessageTypeRef(options, field) ? SubmessageTypeRef(options, field)
: std::string("null")), : std::string("null")),
@ -3732,7 +3716,6 @@ bool Generator::GenerateAll(const std::vector<const FileDescriptor*>& files,
return false; return false;
} }
if (options.output_mode() == GeneratorOptions::kEverythingInOneFile) { if (options.output_mode() == GeneratorOptions::kEverythingInOneFile) {
// All output should go in a single file. // All output should go in a single file.
std::string filename = options.output_dir + "/" + options.library + std::string filename = options.output_dir + "/" + options.library +

@ -644,43 +644,50 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options,
// Generate getter. // Generate getter.
GenerateFieldDocComment(printer, field, options, kFieldGetter); GenerateFieldDocComment(printer, field, options, kFieldGetter);
// deprecation
std::string deprecation_trigger = (field->options().deprecated()) ? "@trigger_error('" +
field->name() + " is deprecated.', E_USER_DEPRECATED);\n " : "";
if (oneof != NULL) { if (oneof != NULL) {
printer->Print( printer->Print(
"public function get^camel_name^()\n" "public function get^camel_name^()\n"
"{\n" "{\n"
" return $this->readOneof(^number^);\n" " ^deprecation_trigger^return $this->readOneof(^number^);\n"
"}\n\n" "}\n\n"
"public function has^camel_name^()\n" "public function has^camel_name^()\n"
"{\n" "{\n"
" return $this->hasOneof(^number^);\n" " ^deprecation_trigger^return $this->hasOneof(^number^);\n"
"}\n\n", "}\n\n",
"camel_name", UnderscoresToCamelCase(field->name(), true), "camel_name", UnderscoresToCamelCase(field->name(), true),
"number", IntToString(field->number())); "number", IntToString(field->number()),
"deprecation_trigger", deprecation_trigger);
} else if (field->has_presence()) { } else if (field->has_presence()) {
printer->Print( printer->Print(
"public function get^camel_name^()\n" "public function get^camel_name^()\n"
"{\n" "{\n"
" return isset($this->^name^) ? $this->^name^ : ^default_value^;\n" " ^deprecation_trigger^return isset($this->^name^) ? $this->^name^ : ^default_value^;\n"
"}\n\n" "}\n\n"
"public function has^camel_name^()\n" "public function has^camel_name^()\n"
"{\n" "{\n"
" return isset($this->^name^);\n" " ^deprecation_trigger^return isset($this->^name^);\n"
"}\n\n" "}\n\n"
"public function clear^camel_name^()\n" "public function clear^camel_name^()\n"
"{\n" "{\n"
" unset($this->^name^);\n" " ^deprecation_trigger^unset($this->^name^);\n"
"}\n\n", "}\n\n",
"camel_name", UnderscoresToCamelCase(field->name(), true), "camel_name", UnderscoresToCamelCase(field->name(), true),
"name", field->name(), "name", field->name(),
"default_value", DefaultForField(field)); "default_value", DefaultForField(field),
"deprecation_trigger", deprecation_trigger);
} else { } else {
printer->Print( printer->Print(
"public function get^camel_name^()\n" "public function get^camel_name^()\n"
"{\n" "{\n"
" return $this->^name^;\n" " ^deprecation_trigger^return $this->^name^;\n"
"}\n\n", "}\n\n",
"camel_name", UnderscoresToCamelCase(field->name(), true), "name", "camel_name", UnderscoresToCamelCase(field->name(), true),
field->name()); "name", field->name(),
"deprecation_trigger", deprecation_trigger);
} }
// For wrapper types, generate an additional getXXXUnwrapped getter // For wrapper types, generate an additional getXXXUnwrapped getter
@ -692,10 +699,11 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options,
printer->Print( printer->Print(
"public function get^camel_name^Unwrapped()\n" "public function get^camel_name^Unwrapped()\n"
"{\n" "{\n"
" return $this->readWrapperValue(\"^field_name^\");\n" " ^deprecation_trigger^return $this->readWrapperValue(\"^field_name^\");\n"
"}\n\n", "}\n\n",
"camel_name", UnderscoresToCamelCase(field->name(), true), "camel_name", UnderscoresToCamelCase(field->name(), true),
"field_name", field->name()); "field_name", field->name(),
"deprecation_trigger", deprecation_trigger);
} }
// Generate setter. // Generate setter.
@ -707,6 +715,13 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options,
Indent(printer); Indent(printer);
if (field->options().deprecated()) {
printer->Print(
"^deprecation_trigger^",
"deprecation_trigger", deprecation_trigger
);
}
// Type check. // Type check.
if (field->is_map()) { if (field->is_map()) {
const Descriptor* map_entry = field->message_type(); const Descriptor* map_entry = field->message_type();
@ -1741,6 +1756,9 @@ void GenerateFieldDocComment(io::Printer* printer, const FieldDescriptor* field,
"php_type", PhpGetterTypeName(field, options), "php_type", PhpGetterTypeName(field, options),
"maybe_null", can_return_null ? "|null" : ""); "maybe_null", can_return_null ? "|null" : "");
} }
if (field->options().deprecated()) {
printer->Print(" * @deprecated\n");
}
printer->Print(" */\n"); printer->Print(" */\n");
} }

@ -198,44 +198,6 @@ int FieldSpaceUsed(const FieldDescriptor* field) {
return 0; return 0;
} }
// Compute the byte size of in-memory representation of the oneof fields
// in default oneof instance.
int OneofFieldSpaceUsed(const FieldDescriptor* field) {
typedef FieldDescriptor FD; // avoid line wrapping
switch (field->cpp_type()) {
case FD::CPPTYPE_INT32:
return sizeof(int32);
case FD::CPPTYPE_INT64:
return sizeof(int64);
case FD::CPPTYPE_UINT32:
return sizeof(uint32);
case FD::CPPTYPE_UINT64:
return sizeof(uint64);
case FD::CPPTYPE_DOUBLE:
return sizeof(double);
case FD::CPPTYPE_FLOAT:
return sizeof(float);
case FD::CPPTYPE_BOOL:
return sizeof(bool);
case FD::CPPTYPE_ENUM:
return sizeof(int);
case FD::CPPTYPE_MESSAGE:
return sizeof(Message*);
case FD::CPPTYPE_STRING:
switch (field->options().ctype()) {
default:
case FieldOptions::STRING:
return sizeof(ArenaStringPtr);
}
break;
}
GOOGLE_LOG(DFATAL) << "Can't get here.";
return 0;
}
inline int DivideRoundingUp(int i, int j) { return (i + (j - 1)) / j; } inline int DivideRoundingUp(int i, int j) { return (i + (j - 1)) / j; }
static const int kSafeAlignment = sizeof(uint64); static const int kSafeAlignment = sizeof(uint64);

@ -87,7 +87,7 @@ inline ExtensionSet* GetExtensionSet(MessageLite* msg, int64 extension_offset) {
template <typename Type> template <typename Type>
inline Type* AddField(MessageLite* msg, int64 offset) { inline Type* AddField(MessageLite* msg, int64 offset) {
static_assert(std::is_pod<Type>::value, static_assert(std::is_trivially_copy_assignable<Type>::value,
"Do not assign"); "Do not assign");
RepeatedField<Type>* repeated = Raw<RepeatedField<Type>>(msg, offset); RepeatedField<Type>* repeated = Raw<RepeatedField<Type>>(msg, offset);
@ -104,7 +104,7 @@ inline std::string* AddField<std::string>(MessageLite* msg, int64 offset) {
template <typename Type> template <typename Type>
inline void AddField(MessageLite* msg, int64 offset, Type value) { inline void AddField(MessageLite* msg, int64 offset, Type value) {
static_assert(std::is_pod<Type>::value, static_assert(std::is_trivially_copy_assignable<Type>::value,
"Do not assign"); "Do not assign");
*AddField<Type>(msg, offset) = value; *AddField<Type>(msg, offset) = value;
} }
@ -126,7 +126,7 @@ inline Type* MutableField(MessageLite* msg, uint32* has_bits,
template <typename Type> template <typename Type>
inline void SetField(MessageLite* msg, uint32* has_bits, uint32 has_bit_index, inline void SetField(MessageLite* msg, uint32* has_bits, uint32 has_bit_index,
int64 offset, Type value) { int64 offset, Type value) {
static_assert(std::is_pod<Type>::value, static_assert(std::is_trivially_copy_assignable<Type>::value,
"Do not assign"); "Do not assign");
*MutableField<Type>(msg, has_bits, has_bit_index, offset) = value; *MutableField<Type>(msg, has_bits, has_bit_index, offset) = value;
} }

@ -529,6 +529,23 @@ void GenericTypeHandler<std::string>::Merge(const std::string& from,
*to = from; *to = from;
} }
// Non-inline variants of std::string specializations for
// various InternalMetadata routines.
template <>
void InternalMetadata::DoClear<std::string>() {
mutable_unknown_fields<std::string>()->clear();
}
template <>
void InternalMetadata::DoMergeFrom<std::string>(const std::string& other) {
mutable_unknown_fields<std::string>()->append(other);
}
template <>
void InternalMetadata::DoSwap<std::string>(std::string* other) {
mutable_unknown_fields<std::string>()->swap(*other);
}
} // namespace internal } // namespace internal

@ -146,7 +146,7 @@ class ExplicitlyConstructed {
private: private:
// Prefer c++14 aligned_storage, but for compatibility this will do. // Prefer c++14 aligned_storage, but for compatibility this will do.
union AlignedUnion { union AlignedUnion {
char space[sizeof(T)]; alignas(T) char space[sizeof(T)];
int64 align_to_int64; int64 align_to_int64;
void* align_to_ptr; void* align_to_ptr;
} union_; } union_;

@ -552,6 +552,34 @@ TEST(MESSAGE_TEST_NAME, IsInitialized) {
EXPECT_TRUE(msg.IsInitialized()); EXPECT_TRUE(msg.IsInitialized());
} }
TEST(MESSAGE_TEST_NAME, IsInitializedSplitBytestream) {
UNITTEST::TestRequired ab, c;
ab.set_a(1);
ab.set_b(2);
c.set_c(3);
// The protobuf represented by the concatenated string has all required
// fields (a,b,c) set.
std::string bytes =
ab.SerializePartialAsString() + c.SerializePartialAsString();
UNITTEST::TestRequired concatenated;
EXPECT_TRUE(concatenated.ParsePartialFromString(bytes));
EXPECT_TRUE(concatenated.IsInitialized());
UNITTEST::TestRequiredForeign fab, fc;
fab.mutable_optional_message()->set_a(1);
fab.mutable_optional_message()->set_b(2);
fc.mutable_optional_message()->set_c(3);
bytes =
fab.SerializePartialAsString() + fc.SerializePartialAsString();
UNITTEST::TestRequiredForeign fconcatenated;
EXPECT_TRUE(fconcatenated.ParsePartialFromString(bytes));
EXPECT_TRUE(fconcatenated.IsInitialized());
}
TEST(MESSAGE_FACTORY_TEST_NAME, GeneratedFactoryLookup) { TEST(MESSAGE_FACTORY_TEST_NAME, GeneratedFactoryLookup) {
EXPECT_EQ(MessageFactory::generated_factory()->GetPrototype( EXPECT_EQ(MessageFactory::generated_factory()->GetPrototype(
UNITTEST::TestAllTypes::descriptor()), UNITTEST::TestAllTypes::descriptor()),

@ -68,7 +68,7 @@ class InternalMetadata {
void Delete() { void Delete() {
// Note that Delete<> should be called not more than once. // Note that Delete<> should be called not more than once.
if (have_unknown_fields() && arena() == NULL) { if (have_unknown_fields() && arena() == NULL) {
delete PtrValue<Container<T>>(); DeleteOutOfLineHelper<T>();
} }
} }
@ -202,6 +202,11 @@ class InternalMetadata {
T unknown_fields; T unknown_fields;
}; };
template <typename T>
PROTOBUF_NOINLINE void DeleteOutOfLineHelper() {
delete PtrValue<Container<T>>();
}
template <typename T> template <typename T>
PROTOBUF_NOINLINE T* mutable_unknown_fields_slow() { PROTOBUF_NOINLINE T* mutable_unknown_fields_slow() {
Arena* my_arena = arena(); Arena* my_arena = arena();
@ -221,17 +226,17 @@ class InternalMetadata {
// Templated functions. // Templated functions.
template <typename T> template <typename T>
void DoClear() { PROTOBUF_NOINLINE void DoClear() {
mutable_unknown_fields<T>()->Clear(); mutable_unknown_fields<T>()->Clear();
} }
template <typename T> template <typename T>
void DoMergeFrom(const T& other) { PROTOBUF_NOINLINE void DoMergeFrom(const T& other) {
mutable_unknown_fields<T>()->MergeFrom(other); mutable_unknown_fields<T>()->MergeFrom(other);
} }
template <typename T> template <typename T>
void DoSwap(T* other) { PROTOBUF_NOINLINE void DoSwap(T* other) {
mutable_unknown_fields<T>()->Swap(other); mutable_unknown_fields<T>()->Swap(other);
} }
}; };
@ -239,20 +244,12 @@ class InternalMetadata {
// String Template specializations. // String Template specializations.
template <> template <>
inline void InternalMetadata::DoClear<std::string>() { PROTOBUF_EXPORT void InternalMetadata::DoClear<std::string>();
mutable_unknown_fields<std::string>()->clear();
}
template <> template <>
inline void InternalMetadata::DoMergeFrom<std::string>( PROTOBUF_EXPORT void InternalMetadata::DoMergeFrom<std::string>(
const std::string& other) { const std::string& other);
mutable_unknown_fields<std::string>()->append(other);
}
template <> template <>
inline void InternalMetadata::DoSwap<std::string>(std::string* other) { PROTOBUF_EXPORT void InternalMetadata::DoSwap<std::string>(std::string* other);
mutable_unknown_fields<std::string>()->swap(*other);
}
// This helper RAII class is needed to efficiently parse unknown fields. We // This helper RAII class is needed to efficiently parse unknown fields. We
// should only call mutable_unknown_fields if there are actual unknown fields. // should only call mutable_unknown_fields if there are actual unknown fields.

@ -438,7 +438,7 @@ class RepeatedField final {
// //
// The first version executes at 7 cycles per iteration while the second // The first version executes at 7 cycles per iteration while the second
// version near 1 or 2 cycles. // version near 1 or 2 cycles.
template <int = 0, bool = std::is_pod<Element>::value> template <int = 0, bool = std::is_trivial<Element>::value>
class FastAdderImpl { class FastAdderImpl {
public: public:
explicit FastAdderImpl(RepeatedField* rf) : repeated_field_(rf) { explicit FastAdderImpl(RepeatedField* rf) : repeated_field_(rf) {
@ -501,7 +501,7 @@ namespace internal {
// effectively. // effectively.
template <typename Element, template <typename Element,
bool HasTrivialCopy = bool HasTrivialCopy =
std::is_pod<Element>::value> std::is_trivially_copy_constructible<Element>::value>
struct ElementCopier { struct ElementCopier {
void operator()(Element* to, const Element* from, int array_size); void operator()(Element* to, const Element* from, int array_size);
}; };

@ -39,7 +39,6 @@
namespace google { namespace google {
namespace protobuf { namespace protobuf {
namespace util { namespace util {
using util::Status;
namespace converter { namespace converter {
namespace { namespace {

@ -52,7 +52,6 @@ namespace util {
// Allow these symbols to be referenced as util::Status, util::error::* in // Allow these symbols to be referenced as util::Status, util::error::* in
// this file. // this file.
using util::Status;
namespace error { namespace error {
using util::error::CANCELLED; using util::error::CANCELLED;
using util::error::INTERNAL; using util::error::INTERNAL;

@ -42,13 +42,11 @@
namespace google { namespace google {
namespace protobuf { namespace protobuf {
namespace util { namespace util {
using util::Status;
namespace error { namespace error {
using util::error::INVALID_ARGUMENT; using util::error::INVALID_ARGUMENT;
} // namespace error } // namespace error
namespace converter { namespace converter {
using util::Status;
// Tests for the JSON Stream Parser. These tests are intended to be // Tests for the JSON Stream Parser. These tests are intended to be
// comprehensive and cover the following: // comprehensive and cover the following:

@ -54,7 +54,6 @@ namespace converter {
using io::CodedOutputStream; using io::CodedOutputStream;
using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite; using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite;
using util::Status;
using util::error::INVALID_ARGUMENT; using util::error::INVALID_ARGUMENT;

@ -59,7 +59,6 @@
namespace google { namespace google {
namespace protobuf { namespace protobuf {
namespace util { namespace util {
using util::Status;
namespace error { namespace error {
using util::error::Code; using util::error::Code;
using util::error::INTERNAL; using util::error::INTERNAL;
@ -67,7 +66,6 @@ using util::error::INTERNAL;
namespace converter { namespace converter {
using ::PROTOBUF_NAMESPACE_ID::internal::WireFormat; using ::PROTOBUF_NAMESPACE_ID::internal::WireFormat;
using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite; using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite;
using util::Status;
namespace { namespace {

@ -74,32 +74,11 @@ class TypeInfo;
class PROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { class PROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
public: public:
struct RenderOptions { struct RenderOptions {
RenderOptions() {} RenderOptions() = default;
RenderOptions(const RenderOptions&) = default; RenderOptions(const RenderOptions&) = default;
// whether to render enums using lowercamelcase. // Sets whether or not to use lowerCamelCase casing for enum values. If set
bool use_lower_camel_for_enums = false; // to false, enum values are output without any case conversions.
// whether to render enums as ints always. defaults to false.
bool use_ints_for_enums = false;
// whether to preserve proto field names
bool preserve_proto_field_names = false;
};
ProtoStreamObjectSource(io::CodedInputStream* stream,
TypeResolver* type_resolver,
const google::protobuf::Type& type,
const RenderOptions& render_options = {});
~ProtoStreamObjectSource() override;
util::Status NamedWriteTo(StringPiece name,
ObjectWriter* ow) const override;
// Sets whether or not to use lowerCamelCase casing for enum values. If set to
// false, enum values are output without any case conversions.
// //
// For example, if we have an enum: // For example, if we have an enum:
// enum Type { // enum Type {
@ -122,20 +101,30 @@ class PROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
// "type": "ACTION_AND_ADVENTURE", // "type": "ACTION_AND_ADVENTURE",
// ... // ...
// } // }
void set_use_lower_camel_for_enums(bool value) { bool use_lower_camel_for_enums = false;
render_options_.use_lower_camel_for_enums = value;
}
// Sets whether to always output enums as ints, by default this is off, and // Sets whether to always output enums as ints, by default this is off, and
// enums are rendered as strings. // enums are rendered as strings.
void set_use_ints_for_enums(bool value) { bool use_ints_for_enums = false;
render_options_.use_ints_for_enums = value;
}
// Sets whether to use original proto field names // Whether to preserve proto field names
void set_preserve_proto_field_names(bool value) { bool preserve_proto_field_names = false;
render_options_.preserve_proto_field_names = value;
} };
ProtoStreamObjectSource(io::CodedInputStream* stream,
TypeResolver* type_resolver,
const google::protobuf::Type& type)
: ProtoStreamObjectSource(stream, type_resolver, type, RenderOptions()) {}
ProtoStreamObjectSource(io::CodedInputStream* stream,
TypeResolver* type_resolver,
const google::protobuf::Type& type,
const RenderOptions& render_options);
~ProtoStreamObjectSource() override;
util::Status NamedWriteTo(StringPiece name,
ObjectWriter* ow) const override;
// Sets the max recursion depth of proto message to be deserialized. Proto // Sets the max recursion depth of proto message to be deserialized. Proto
// messages over this depth will fail to be deserialized. // messages over this depth will fail to be deserialized.
@ -144,7 +133,6 @@ class PROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
max_recursion_depth_ = max_depth; max_recursion_depth_ = max_depth;
} }
protected: protected:
// Writes a proto2 Message to the ObjectWriter. When the given end_tag is // Writes a proto2 Message to the ObjectWriter. When the given end_tag is
// found this method will complete, allowing it to be used for parsing both // found this method will complete, allowing it to be used for parsing both
@ -317,7 +305,7 @@ class PROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
const google::protobuf::Type& type_; const google::protobuf::Type& type_;
RenderOptions render_options_; const RenderOptions render_options_;
// Tracks current recursion depth. // Tracks current recursion depth.
mutable int recursion_depth_; mutable int recursion_depth_;

@ -79,7 +79,6 @@ using proto_util_converter::testing::Proto3Message;
using proto_util_converter::testing::StructType; using proto_util_converter::testing::StructType;
using proto_util_converter::testing::TimestampDuration; using proto_util_converter::testing::TimestampDuration;
using ::testing::_; using ::testing::_;
using util::Status;
namespace { namespace {
@ -117,12 +116,13 @@ class ProtostreamObjectSourceTest
ArrayInputStream arr_stream(proto.data(), proto.size()); ArrayInputStream arr_stream(proto.data(), proto.size());
CodedInputStream in_stream(&arr_stream); CodedInputStream in_stream(&arr_stream);
ProtoStreamObjectSource::RenderOptions render_options;
render_options.use_lower_camel_for_enums = use_lower_camel_for_enums_;
render_options.use_ints_for_enums = use_ints_for_enums_;
render_options.preserve_proto_field_names = use_preserve_proto_field_names_;
std::unique_ptr<ProtoStreamObjectSource> os( std::unique_ptr<ProtoStreamObjectSource> os(
helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor))); helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor),
if (use_lower_camel_for_enums_) os->set_use_lower_camel_for_enums(true); render_options));
if (use_ints_for_enums_) os->set_use_ints_for_enums(true);
if (use_preserve_proto_field_names_)
os->set_preserve_proto_field_names(true);
os->set_max_recursion_depth(64); os->set_max_recursion_depth(64);
return os->WriteTo(&mock_); return os->WriteTo(&mock_);
} }

@ -86,12 +86,13 @@ void TypeInfoTestHelper::ResetTypeInfo(const Descriptor* descriptor1,
TypeInfo* TypeInfoTestHelper::GetTypeInfo() { return typeinfo_.get(); } TypeInfo* TypeInfoTestHelper::GetTypeInfo() { return typeinfo_.get(); }
ProtoStreamObjectSource* TypeInfoTestHelper::NewProtoSource( ProtoStreamObjectSource* TypeInfoTestHelper::NewProtoSource(
io::CodedInputStream* coded_input, const std::string& type_url) { io::CodedInputStream* coded_input, const std::string& type_url,
ProtoStreamObjectSource::RenderOptions render_options) {
const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url); const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url);
switch (type_) { switch (type_) {
case USE_TYPE_RESOLVER: { case USE_TYPE_RESOLVER: {
return new ProtoStreamObjectSource(coded_input, type_resolver_.get(), return new ProtoStreamObjectSource(coded_input, type_resolver_.get(),
*type); *type, render_options);
} }
} }
GOOGLE_LOG(FATAL) << "Can not reach here."; GOOGLE_LOG(FATAL) << "Can not reach here.";

@ -71,8 +71,9 @@ class TypeInfoTestHelper {
// Returns the TypeInfo created after ResetTypeInfo. // Returns the TypeInfo created after ResetTypeInfo.
TypeInfo* GetTypeInfo(); TypeInfo* GetTypeInfo();
ProtoStreamObjectSource* NewProtoSource(io::CodedInputStream* coded_input, ProtoStreamObjectSource* NewProtoSource(
const std::string& type_url); io::CodedInputStream* coded_input, const std::string& type_url,
ProtoStreamObjectSource::RenderOptions render_options = {});
ProtoStreamObjectWriter* NewProtoWriter( ProtoStreamObjectWriter* NewProtoWriter(
const std::string& type_url, strings::ByteSink* output, const std::string& type_url, strings::ByteSink* output,

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

Loading…
Cancel
Save