diff --git a/CHANGES.txt b/CHANGES.txt index b55e275deb..85e6a034b7 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -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 unit tests. * 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 * 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. * Add more detailed error information for dynamic message field type 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 * Provided an override for the reverse() method that will reverse the internal 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) diff --git a/Makefile.am b/Makefile.am index 707f7823d2..d8b9fda140 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1094,17 +1094,21 @@ ruby_EXTRA_DIST= \ ruby/compatibility_tests/v3.0.0/test.sh \ ruby/compatibility_tests/v3.0.0/Rakefile \ 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/encode_decode.c \ + ruby/ext/google/protobuf_c/defs.h \ ruby/ext/google/protobuf_c/extconf.rb \ 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.h \ ruby/ext/google/protobuf_c/protobuf.c \ ruby/ext/google/protobuf_c/protobuf.h \ ruby/ext/google/protobuf_c/repeated_field.c \ - ruby/ext/google/protobuf_c/storage.c \ - ruby/ext/google/protobuf_c/upb.c \ - ruby/ext/google/protobuf_c/upb.h \ + ruby/ext/google/protobuf_c/repeated_field.h \ + ruby/ext/google/protobuf_c/ruby-upb.c \ + ruby/ext/google/protobuf_c/ruby-upb.h \ ruby/ext/google/protobuf_c/wrap_memcpy.c \ ruby/google-protobuf.gemspec \ 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.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.proto \ ruby/tests/test_ruby_package_proto2.proto \ diff --git a/cmake/libprotoc.cmake b/cmake/libprotoc.cmake index b71f2f1ba9..ecb5a851b8 100644 --- a/cmake/libprotoc.cmake +++ b/cmake/libprotoc.cmake @@ -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_field.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_padding_optimizer.h ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_primitive_field.h diff --git a/conformance/Makefile.am b/conformance/Makefile.am index 0adfb83600..b281f9cfaa 100644 --- a/conformance/Makefile.am +++ b/conformance/Makefile.am @@ -5,7 +5,7 @@ conformance_protoc_inputs = \ $(top_srcdir)/src/google/protobuf/test_messages_proto3.proto # 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 = \ $(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. 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=. --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) --java_out=lite:lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs) touch protoc_middleman @@ -273,7 +273,7 @@ else # 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 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) ) ## @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) ) diff --git a/conformance/failure_list_jruby.txt b/conformance/failure_list_jruby.txt new file mode 100644 index 0000000000..ceaaf92a5f --- /dev/null +++ b/conformance/failure_list_jruby.txt @@ -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 diff --git a/conformance/text_format_failure_list_jruby.txt b/conformance/text_format_failure_list_jruby.txt new file mode 100644 index 0000000000..404b64a584 --- /dev/null +++ b/conformance/text_format_failure_list_jruby.txt @@ -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 diff --git a/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs index 1c77e121d3..1e5333c965 100644 --- a/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs +++ b/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs @@ -35,6 +35,7 @@ using System.IO; using Google.Protobuf.TestProtos; using Google.Protobuf.Buffers; using NUnit.Framework; +using System.Text; namespace Google.Protobuf { @@ -516,5 +517,28 @@ namespace Google.Protobuf var stream = new CodedOutputStream(new byte[10]); 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()); + } + } } } \ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs b/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs index d8cdee0f0f..d4c63dc688 100644 --- a/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs +++ b/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs @@ -611,6 +611,32 @@ namespace Google.Protobuf.Collections 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(); + var mapCodec = new MapField.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 [Test] public void IDictionaryKeys_Equals_IReadOnlyDictionaryKeys() diff --git a/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs b/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs index aceb4a68f7..951e856a59 100644 --- a/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs +++ b/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs @@ -116,7 +116,22 @@ namespace Google.Protobuf var other = message.Clone(); 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)); } } } diff --git a/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs index ebb8394d23..fab983d463 100644 --- a/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs +++ b/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs @@ -35,7 +35,9 @@ using NUnit.Framework; using ProtobufUnittest; using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using UnitTest.Issues.TestProtos; namespace Google.Protobuf.Reflection { @@ -70,6 +72,24 @@ namespace Google.Protobuf.Reflection 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) { Assert.AreEqual("unittest_proto3.proto", file.Name); diff --git a/csharp/src/Google.Protobuf/Collections/MapField.cs b/csharp/src/Google.Protobuf/Collections/MapField.cs index d60ebc5a8a..6b7d0f101a 100644 --- a/csharp/src/Google.Protobuf/Collections/MapField.cs +++ b/csharp/src/Google.Protobuf/Collections/MapField.cs @@ -448,12 +448,10 @@ namespace Google.Protobuf.Collections [SecuritySafeCritical] public void AddEntriesFrom(ref ParseContext ctx, Codec codec) { - var adapter = new Codec.MessageAdapter(codec); do { - adapter.Reset(); - ctx.ReadMessage(adapter); - this[adapter.Key] = adapter.Value; + KeyValuePair entry = ParsingPrimitivesMessages.ReadMapEntry(ref ctx, codec); + this[entry.Key] = entry.Value; } while (ParsingPrimitives.MaybeConsumeTag(ref ctx.buffer, ref ctx.state, codec.MapTag)); } @@ -485,13 +483,13 @@ namespace Google.Protobuf.Collections [SecuritySafeCritical] public void WriteTo(ref WriteContext ctx, Codec codec) { - var message = new Codec.MessageAdapter(codec); foreach (var entry in list) { - message.Key = entry.Key; - message.Value = entry.Value; 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; } - var message = new Codec.MessageAdapter(codec); int size = 0; foreach (var entry in list) { - message.Key = entry.Key; - message.Value = entry.Value; + int entrySize = CalculateEntrySize(codec, entry); + size += CodedOutputStream.ComputeRawVarint32Size(codec.MapTag); - size += CodedOutputStream.ComputeMessageSize(message); + size += CodedOutputStream.ComputeLengthSize(entrySize) + entrySize; } return size; } + private static int CalculateEntrySize(Codec codec, KeyValuePair entry) + { + return codec.KeyCodec.CalculateSizeWithTag(entry.Key) + codec.ValueCodec.CalculateSizeWithTag(entry.Value); + } + /// /// Returns a string representation of this repeated field, in the same /// way as it would be represented by the default JSON formatter. @@ -655,100 +657,19 @@ namespace Google.Protobuf.Collections } /// - /// The tag used in the enclosing message to indicate map entries. + /// The key codec. /// - internal uint MapTag { get { return mapTag; } } + internal FieldCodec KeyCodec => keyCodec; /// - /// A mutable message class, used for parsing and serializing. This - /// delegates the work to a codec, but implements the interface - /// for interop with and . - /// 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. + /// The value codec. /// - internal class MessageAdapter : IMessage, IBufferMessage - { - 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(); - } + internal FieldCodec ValueCodec => valueCodec; - [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(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] - public void InternalWriteTo(ref WriteContext ctx) - { - codec.keyCodec.WriteTagAndValue(ref ctx, Key); - codec.valueCodec.WriteTagAndValue(ref ctx, Value); - } - - public int CalculateSize() - { - return codec.keyCodec.CalculateSizeWithTag(Key) + codec.valueCodec.CalculateSizeWithTag(Value); - } - - MessageDescriptor IMessage.Descriptor { get { return null; } } - } + /// + /// The tag used in the enclosing message to indicate map entries. + /// + internal uint MapTag => mapTag; } private class MapView : ICollection, ICollection diff --git a/csharp/src/Google.Protobuf/ExtensionValue.cs b/csharp/src/Google.Protobuf/ExtensionValue.cs index ada5d79c80..5257c4c955 100644 --- a/csharp/src/Google.Protobuf/ExtensionValue.cs +++ b/csharp/src/Google.Protobuf/ExtensionValue.cs @@ -59,7 +59,7 @@ namespace Google.Protobuf public int CalculateSize() { - return codec.CalculateSizeWithTag(field); + return codec.CalculateUnconditionalSizeWithTag(field); } public IExtensionValue Clone() diff --git a/csharp/src/Google.Protobuf/FieldCodec.cs b/csharp/src/Google.Protobuf/FieldCodec.cs index 158739d50a..ee6bd6a0eb 100644 --- a/csharp/src/Google.Protobuf/FieldCodec.cs +++ b/csharp/src/Google.Protobuf/FieldCodec.cs @@ -876,6 +876,12 @@ namespace Google.Protobuf /// public int CalculateSizeWithTag(T value) => IsDefault(value) ? 0 : ValueSizeCalculator(value) + tagSize; + /// + /// Calculates the size required to write the given value, with a tag, even + /// if the value is the default. + /// + internal int CalculateUnconditionalSizeWithTag(T value) => ValueSizeCalculator(value) + tagSize; + private bool IsDefault(T value) => EqualityComparer.Equals(value, DefaultValue); } } diff --git a/csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs b/csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs index b7097a2ad0..eabaf96d5c 100644 --- a/csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs +++ b/csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs @@ -32,9 +32,11 @@ using System; using System.Buffers; +using System.Collections.Generic; using System.IO; using System.Runtime.CompilerServices; using System.Security; +using Google.Protobuf.Collections; namespace Google.Protobuf { @@ -44,6 +46,8 @@ namespace Google.Protobuf [SecuritySafeCritical] internal static class ParsingPrimitivesMessages { + private static readonly byte[] ZeroLengthMessageStreamData = new byte[] { 0 }; + public static void SkipLastField(ref ReadOnlySpan buffer, ref ParserInternalState state) { if (state.lastTag == 0) @@ -134,6 +138,65 @@ namespace Google.Protobuf SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit); } + public static KeyValuePair ReadMapEntry(ref ParseContext ctx, MapField.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(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(key, value); + } + public static void ReadGroup(ref ParseContext ctx, IMessage message) { if (ctx.state.recursionDepth >= ctx.state.recursionLimit) diff --git a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs index 88e4a9de96..724bb3a04d 100644 --- a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs @@ -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 /// 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. + /// The extension registry to use when parsing, or null if no extensions are required. /// The file descriptors corresponding to . - public static IReadOnlyList BuildFromByteStrings(IEnumerable descriptorData) + public static IReadOnlyList BuildFromByteStrings(IEnumerable descriptorData, ExtensionRegistry registry) { 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. // This will all behave correctly, but it's less efficient than we'd like. var descriptors = new List(); var descriptorsByName = new Dictionary(); foreach (var data in descriptorData) { - var proto = FileDescriptorProto.Parser.ParseFrom(data); + var proto = parser.ParseFrom(data); var dependencies = new List(); foreach (var dependencyName in proto.Dependency) { @@ -518,6 +521,18 @@ namespace Google.Protobuf.Reflection return new ReadOnlyCollection(descriptors); } + /// + /// Converts the given descriptor binary data into FileDescriptor objects. + /// Note: reflection using the returned FileDescriptors is not currently supported. + /// + /// 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. + /// The file descriptors corresponding to . + public static IReadOnlyList BuildFromByteStrings(IEnumerable descriptorData) => + BuildFromByteStrings(descriptorData, null); + /// /// Returns a that represents this instance. /// diff --git a/csharp/src/Google.Protobuf/WritingPrimitives.cs b/csharp/src/Google.Protobuf/WritingPrimitives.cs index 846df73502..cf8fc7ba71 100644 --- a/csharp/src/Google.Protobuf/WritingPrimitives.cs +++ b/csharp/src/Google.Protobuf/WritingPrimitives.cs @@ -163,10 +163,25 @@ namespace Google.Protobuf /// public static void WriteString(ref Span buffer, ref WriterInternalState state, string value) { - // Optimise the case where we have enough space to write - // the string directly to the buffer, which should be common. + const int MaxBytesPerChar = 3; + 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); 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 (length == value.Length) // Must be all ASCII... @@ -179,23 +194,7 @@ namespace Google.Protobuf } else { -#if NETSTANDARD1_1 - // slowpath when Encoding.GetBytes(Char*, Int32, Byte*, Int32) is not available - byte[] bytes = Utf8Encoding.GetBytes(value); - WriteRawBytes(ref buffer, ref state, bytes); -#else - ReadOnlySpan source = value.AsSpan(); - int bytesUsed; - unsafe - { - fixed (char* sourceChars = &MemoryMarshal.GetReference(source)) - fixed (byte* destinationBytes = &MemoryMarshal.GetReference(buffer.Slice(state.position))) - { - bytesUsed = Utf8Encoding.GetBytes(sourceChars, source.Length, destinationBytes, buffer.Length); - } - } - state.position += bytesUsed; -#endif + WriteStringToBuffer(buffer, ref state, value); } } else @@ -209,6 +208,33 @@ namespace Google.Protobuf } } + private static int WriteStringToBuffer(Span buffer, ref WriterInternalState state, string value) + { +#if NETSTANDARD1_1 + // slowpath when Encoding.GetBytes(Char*, Int32, Byte*, Int32) is not available + byte[] bytes = Utf8Encoding.GetBytes(value); + WriteRawBytes(ref buffer, ref state, bytes); + return bytes.Length; +#else + ReadOnlySpan source = value.AsSpan(); + int bytesUsed; + unsafe + { + fixed (char* sourceChars = &MemoryMarshal.GetReference(source)) + fixed (byte* destinationBytes = &MemoryMarshal.GetReference(buffer)) + { + bytesUsed = Utf8Encoding.GetBytes( + sourceChars, + source.Length, + destinationBytes + state.position, + buffer.Length - state.position); + } + } + state.position += bytesUsed; + return bytesUsed; +#endif + } + /// /// Write a byte string, without a tag, to the stream. /// The data is length-prefixed. diff --git a/java/core/src/main/java/com/google/protobuf/Android.java b/java/core/src/main/java/com/google/protobuf/Android.java index cad547839a..5a7ce9e581 100644 --- a/java/core/src/main/java/com/google/protobuf/Android.java +++ b/java/core/src/main/java/com/google/protobuf/Android.java @@ -31,14 +31,21 @@ package com.google.protobuf; 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 boolean IS_ROBOLECTRIC = - getClassForName("org.robolectric.Robolectric") != null; + !ASSUME_ANDROID && getClassForName("org.robolectric.Robolectric") != null; /** Returns {@code true} if running on an Android device. */ 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. */ diff --git a/java/core/src/main/java/com/google/protobuf/RawMessageInfo.java b/java/core/src/main/java/com/google/protobuf/RawMessageInfo.java index 3fbfaa108d..d66f5c4796 100644 --- a/java/core/src/main/java/com/google/protobuf/RawMessageInfo.java +++ b/java/core/src/main/java/com/google/protobuf/RawMessageInfo.java @@ -184,20 +184,20 @@ final class RawMessageInfo implements MessageInfo { int value; try { value = (int) info.charAt(0); - } catch (ArrayIndexOutOfBoundsException e) { + } catch (StringIndexOutOfBoundsException e) { // This is a fix for issues // that error out on a subset of phones on charAt(0) with an index out of bounds exception. char[] infoChars = info.toCharArray(); info = new String(infoChars); try { value = (int) info.charAt(0); - } catch (ArrayIndexOutOfBoundsException e2) { + } catch (StringIndexOutOfBoundsException e2) { try { char[] infoChars2 = new char[info.length()]; info.getChars(0, info.length(), infoChars2, 0); info = new String(infoChars2); value = (int) info.charAt(0); - } catch (ArrayIndexOutOfBoundsException e3) { + } catch (StringIndexOutOfBoundsException | ArrayIndexOutOfBoundsException e3) { throw new IllegalStateException( String.format( "Failed parsing '%s' with charArray.length of %d", info, infoChars.length), diff --git a/java/lite/proguard.pgcfg b/java/lite/proguard.pgcfg index 4bb31e57b2..54c798c87d 100644 --- a/java/lite/proguard.pgcfg +++ b/java/lite/proguard.pgcfg @@ -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 { ; } diff --git a/js/binary/reader_test.js b/js/binary/reader_test.js index daa0ab6985..7e4682885d 100644 --- a/js/binary/reader_test.js +++ b/js/binary/reader_test.js @@ -46,7 +46,8 @@ goog.require('jspb.BinaryConstants'); goog.require('jspb.BinaryDecoder'); goog.require('jspb.BinaryReader'); goog.require('jspb.BinaryWriter'); - +goog.require('jspb.utils'); +goog.requireType('jspb.BinaryMessage'); describe('binaryReaderTest', function() { @@ -55,7 +56,7 @@ describe('binaryReaderTest', function() { */ it('testInstanceCaches', /** @suppress {visibility} */ function() { var writer = new jspb.BinaryWriter(); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); writer.writeMessage(1, dummyMessage, goog.nullFunction); writer.writeMessage(2, dummyMessage, goog.nullFunction); @@ -135,7 +136,7 @@ describe('binaryReaderTest', function() { // Calling readMessage on a non-delimited field should trigger an // assertion. var reader = jspb.BinaryReader.alloc([8, 1]); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); reader.nextField(); assertThrows(function() { reader.readMessage(dummyMessage, goog.nullFunction); @@ -144,47 +145,91 @@ describe('binaryReaderTest', function() { // Reading past the end of the stream should trigger an assertion. reader = jspb.BinaryReader.alloc([9, 1]); reader.nextField(); - assertThrows(function() {reader.readFixed64()}); + assertThrows(function() { + reader.readFixed64() + }); // Reading past the end of a submessage should trigger an assertion. reader = jspb.BinaryReader.alloc([10, 4, 13, 1, 1, 1]); reader.nextField(); reader.readMessage(dummyMessage, function() { reader.nextField(); - assertThrows(function() {reader.readFixed32()}); + assertThrows(function() { + reader.readFixed32() + }); }); // Skipping an invalid field should trigger an assertion. reader = jspb.BinaryReader.alloc([12, 1]); reader.nextWireType_ = 1000; - assertThrows(function() {reader.skipField()}); + assertThrows(function() { + reader.skipField() + }); // Reading fields with the wrong wire type should assert. reader = jspb.BinaryReader.alloc([9, 0, 0, 0, 0, 0, 0, 0, 0]); reader.nextField(); - assertThrows(function() {reader.readInt32()}); - assertThrows(function() {reader.readInt32String()}); - assertThrows(function() {reader.readInt64()}); - assertThrows(function() {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()}); + assertThrows(function() { + reader.readInt32() + }); + assertThrows(function() { + reader.readInt32String() + }); + assertThrows(function() { + reader.readInt64() + }); + assertThrows(function() { + 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.nextField(); - assertThrows(function() {reader.readFixed32()}); - assertThrows(function() {reader.readFixed64()}); - assertThrows(function() {reader.readSfixed32()}); - assertThrows(function() {reader.readSfixed64()}); - assertThrows(function() {reader.readFloat()}); - assertThrows(function() {reader.readDouble()}); + assertThrows(function() { + reader.readFixed32() + }); + assertThrows(function() { + reader.readFixed64() + }); + assertThrows(function() { + reader.readSfixed32() + }); + assertThrows(function() { + reader.readSfixed64() + }); + assertThrows(function() { + reader.readFloat() + }); + assertThrows(function() { + reader.readDouble() + }); - assertThrows(function() {reader.readString()}); - assertThrows(function() {reader.readBytes()}); + assertThrows(function() { + reader.readString() + }); + assertThrows(function() { + reader.readBytes() + }); }); @@ -198,8 +243,8 @@ describe('binaryReaderTest', function() { * @private * @suppress {missingProperties} */ - var doTestUnsignedField_ = function(readField, - writeField, epsilon, upperLimit, filter) { + var doTestUnsignedField_ = function( + readField, writeField, epsilon, upperLimit, filter) { assertNotNull(readField); assertNotNull(writeField); @@ -250,8 +295,8 @@ describe('binaryReaderTest', function() { * @private * @suppress {missingProperties} */ - var doTestSignedField_ = function(readField, - writeField, epsilon, lowerLimit, upperLimit, filter) { + var doTestSignedField_ = function( + readField, writeField, epsilon, lowerLimit, upperLimit, filter) { var writer = new jspb.BinaryWriter(); // Encode zero and limits. @@ -267,20 +312,14 @@ describe('binaryReaderTest', function() { for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) { var val = filter(cursor); writeField.call(writer, 6, val); - inputValues.push({ - fieldNumber: 6, - value: val - }); + inputValues.push({fieldNumber: 6, value: val}); } // Encode positive values. for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) { var val = filter(cursor); writeField.call(writer, 7, val); - inputValues.push({ - fieldNumber: 7, - value: val - }); + inputValues.push({fieldNumber: 7, value: val}); } var reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); @@ -327,33 +366,34 @@ describe('binaryReaderTest', function() { assertNotUndefined(jspb.BinaryWriter.prototype.writeBool); doTestUnsignedField_( jspb.BinaryReader.prototype.readUint32, - jspb.BinaryWriter.prototype.writeUint32, - 1, Math.pow(2, 32) - 1, Math.round); + jspb.BinaryWriter.prototype.writeUint32, 1, Math.pow(2, 32) - 1, + Math.round); doTestUnsignedField_( jspb.BinaryReader.prototype.readUint64, - jspb.BinaryWriter.prototype.writeUint64, - 1, Math.pow(2, 64) - 1025, Math.round); + jspb.BinaryWriter.prototype.writeUint64, 1, Math.pow(2, 64) - 1025, + Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readInt32, - jspb.BinaryWriter.prototype.writeInt32, - 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); + jspb.BinaryWriter.prototype.writeInt32, 1, -Math.pow(2, 31), + Math.pow(2, 31) - 1, Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readInt64, - jspb.BinaryWriter.prototype.writeInt64, - 1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round); + jspb.BinaryWriter.prototype.writeInt64, 1, -Math.pow(2, 63), + Math.pow(2, 63) - 513, Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readEnum, - jspb.BinaryWriter.prototype.writeEnum, - 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); + jspb.BinaryWriter.prototype.writeEnum, 1, -Math.pow(2, 31), + Math.pow(2, 31) - 1, Math.round); doTestUnsignedField_( jspb.BinaryReader.prototype.readBool, - jspb.BinaryWriter.prototype.writeBool, - 1, 1, function(x) { return !!x; }); + jspb.BinaryWriter.prototype.writeBool, 1, 1, function(x) { + return !!x; + }); }); @@ -387,24 +427,22 @@ describe('binaryReaderTest', function() { // uint32 and sint32 take no more than 5 bytes // 08 - field prefix (type = 0 means varint) doTestHexStringVarint_( - jspb.BinaryReader.prototype.readUint32, - 12, '08 8C 80 80 80 00'); + jspb.BinaryReader.prototype.readUint32, 12, '08 8C 80 80 80 00'); // 11 stands for -6 in zigzag encoding doTestHexStringVarint_( - jspb.BinaryReader.prototype.readSint32, - -6, '08 8B 80 80 80 00'); + jspb.BinaryReader.prototype.readSint32, -6, '08 8B 80 80 80 00'); // uint64 and sint64 take no more than 10 bytes // 08 - field prefix (type = 0 means varint) doTestHexStringVarint_( - jspb.BinaryReader.prototype.readUint64, - 12, '08 8C 80 80 80 80 80 80 80 80 00'); + jspb.BinaryReader.prototype.readUint64, 12, + '08 8C 80 80 80 80 80 80 80 80 00'); // 11 stands for -6 in zigzag encoding doTestHexStringVarint_( - jspb.BinaryReader.prototype.readSint64, - -6, '08 8B 80 80 80 80 80 80 80 80 00'); + jspb.BinaryReader.prototype.readSint64, -6, + '08 8B 80 80 80 80 80 80 80 80 00'); }); /** @@ -440,27 +478,15 @@ describe('binaryReaderTest', function() { var writer = new jspb.BinaryWriter(); var testSignedData = [ - '2730538252207801776', - '-2688470994844604560', - '3398529779486536359', - '3568577411627971000', - '272477188847484900', - '-6649058714086158188', - '-7695254765712060806', - '-4525541438037104029', - '-4993706538836508568', + '2730538252207801776', '-2688470994844604560', '3398529779486536359', + '3568577411627971000', '272477188847484900', '-6649058714086158188', + '-7695254765712060806', '-4525541438037104029', '-4993706538836508568', '4990160321893729138' ]; var testUnsignedData = [ - '7822732630241694882', - '6753602971916687352', - '2399935075244442116', - '8724292567325338867', - '16948784802625696584', - '4136275908516066934', - '3575388346793700364', - '5167142028379259461', - '1557573948689737699', + '7822732630241694882', '6753602971916687352', '2399935075244442116', + '8724292567325338867', '16948784802625696584', '4136275908516066934', + '3575388346793700364', '5167142028379259461', '1557573948689737699', '17100725280812548567' ]; @@ -488,13 +514,13 @@ describe('binaryReaderTest', function() { it('testZigzagFields', function() { doTestSignedField_( jspb.BinaryReader.prototype.readSint32, - jspb.BinaryWriter.prototype.writeSint32, - 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); + jspb.BinaryWriter.prototype.writeSint32, 1, -Math.pow(2, 31), + Math.pow(2, 31) - 1, Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readSint64, - jspb.BinaryWriter.prototype.writeSint64, - 1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round); + jspb.BinaryWriter.prototype.writeSint64, 1, -Math.pow(2, 63), + Math.pow(2, 63) - 513, Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readSintHash64, @@ -509,23 +535,23 @@ describe('binaryReaderTest', function() { it('testFixedFields', function() { doTestUnsignedField_( jspb.BinaryReader.prototype.readFixed32, - jspb.BinaryWriter.prototype.writeFixed32, - 1, Math.pow(2, 32) - 1, Math.round); + jspb.BinaryWriter.prototype.writeFixed32, 1, Math.pow(2, 32) - 1, + Math.round); doTestUnsignedField_( jspb.BinaryReader.prototype.readFixed64, - jspb.BinaryWriter.prototype.writeFixed64, - 1, Math.pow(2, 64) - 1025, Math.round); + jspb.BinaryWriter.prototype.writeFixed64, 1, Math.pow(2, 64) - 1025, + Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readSfixed32, - jspb.BinaryWriter.prototype.writeSfixed32, - 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); + jspb.BinaryWriter.prototype.writeSfixed32, 1, -Math.pow(2, 31), + Math.pow(2, 31) - 1, Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readSfixed64, - jspb.BinaryWriter.prototype.writeSfixed64, - 1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round); + jspb.BinaryWriter.prototype.writeSfixed64, 1, -Math.pow(2, 63), + Math.pow(2, 63) - 513, Math.round); }); @@ -536,18 +562,17 @@ describe('binaryReaderTest', function() { doTestSignedField_( jspb.BinaryReader.prototype.readFloat, jspb.BinaryWriter.prototype.writeFloat, - jspb.BinaryConstants.FLOAT32_MIN, - -jspb.BinaryConstants.FLOAT32_MAX, - jspb.BinaryConstants.FLOAT32_MAX, - truncate); + jspb.BinaryConstants.FLOAT32_MIN, -jspb.BinaryConstants.FLOAT32_MAX, + jspb.BinaryConstants.FLOAT32_MAX, truncate); doTestSignedField_( jspb.BinaryReader.prototype.readDouble, jspb.BinaryWriter.prototype.writeDouble, jspb.BinaryConstants.FLOAT64_EPS * 10, - -jspb.BinaryConstants.FLOAT64_MIN, - jspb.BinaryConstants.FLOAT64_MIN, - function(x) { return x; }); + -jspb.BinaryConstants.FLOAT64_MIN, jspb.BinaryConstants.FLOAT64_MIN, + function(x) { + return x; + }); }); @@ -614,7 +639,7 @@ describe('binaryReaderTest', function() { */ it('testNesting', function() { var writer = new jspb.BinaryWriter(); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); writer.writeInt32(1, 100); @@ -707,7 +732,7 @@ describe('binaryReaderTest', function() { // Write a group with a nested group inside. writer.writeInt32(5, sentinel); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); writer.writeGroup(5, dummyMessage, function() { // Previously the skipGroup implementation was wrong, which only consume // the decoder by nextField. This case is for making the previous @@ -726,7 +751,7 @@ describe('binaryReaderTest', function() { writer.writeInt64(84, 42); writer.writeInt64(84, 44); writer.writeBytes( - 43, [255, 255, 255, 255, 255, 255, 255, 255, 255, 255]); + 43, [255, 255, 255, 255, 255, 255, 255, 255, 255, 255]); }); }); @@ -875,7 +900,7 @@ describe('binaryReaderTest', function() { var fieldTag = (1 << 3) | jspb.BinaryConstants.WireType.DELIMITED; var blob = [1, 2, 3, 4, 5]; var writer = new jspb.BinaryWriter(); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); writer.writeMessage(1, dummyMessage, function() { writer.writeMessage(1, dummyMessage, function() { @@ -908,7 +933,7 @@ describe('binaryReaderTest', function() { */ it('testReadCallbacks', function() { var writer = new jspb.BinaryWriter(); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); // Add an int, a submessage, and another int. writer.writeInt32(1, 100); diff --git a/js/binary/writer_test.js b/js/binary/writer_test.js index fca1ba47eb..6c5f36e921 100644 --- a/js/binary/writer_test.js +++ b/js/binary/writer_test.js @@ -44,7 +44,8 @@ goog.require('jspb.BinaryConstants'); goog.require('jspb.BinaryReader'); goog.require('jspb.BinaryWriter'); goog.require('jspb.utils'); - +goog.require('goog.crypt.base64'); +goog.requireType('jspb.BinaryMessage'); /** * @param {function()} func This function should throw an error when run. @@ -61,7 +62,7 @@ describe('binaryWriterTest', function() { it('testWriteErrors', function() { // Submessages with invalid field indices should assert. var writer = new jspb.BinaryWriter(); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); assertFails(function() { writer.writeMessage(-1, dummyMessage, goog.nullFunction); @@ -69,40 +70,82 @@ describe('binaryWriterTest', function() { // Writing invalid field indices should assert. writer = new jspb.BinaryWriter(); - assertFails(function() {writer.writeUint64(-1, 1);}); + assertFails(function() { + writer.writeUint64(-1, 1); + }); // Writing out-of-range field values should assert. writer = new jspb.BinaryWriter(); - assertFails(function() {writer.writeInt32(1, -Infinity);}); - assertFails(function() {writer.writeInt32(1, Infinity);}); + assertFails(function() { + writer.writeInt32(1, -Infinity); + }); + assertFails(function() { + writer.writeInt32(1, Infinity); + }); - assertFails(function() {writer.writeInt64(1, -Infinity);}); - assertFails(function() {writer.writeInt64(1, Infinity);}); + assertFails(function() { + writer.writeInt64(1, -Infinity); + }); + assertFails(function() { + writer.writeInt64(1, Infinity); + }); - assertFails(function() {writer.writeUint32(1, -1);}); - assertFails(function() {writer.writeUint32(1, Infinity);}); + assertFails(function() { + writer.writeUint32(1, -1); + }); + assertFails(function() { + writer.writeUint32(1, Infinity); + }); - assertFails(function() {writer.writeUint64(1, -1);}); - assertFails(function() {writer.writeUint64(1, Infinity);}); + assertFails(function() { + writer.writeUint64(1, -1); + }); + assertFails(function() { + writer.writeUint64(1, Infinity); + }); - assertFails(function() {writer.writeSint32(1, -Infinity);}); - assertFails(function() {writer.writeSint32(1, Infinity);}); + assertFails(function() { + writer.writeSint32(1, -Infinity); + }); + assertFails(function() { + writer.writeSint32(1, Infinity); + }); - assertFails(function() {writer.writeSint64(1, -Infinity);}); - assertFails(function() {writer.writeSint64(1, Infinity);}); + assertFails(function() { + writer.writeSint64(1, -Infinity); + }); + assertFails(function() { + writer.writeSint64(1, Infinity); + }); - assertFails(function() {writer.writeFixed32(1, -1);}); - assertFails(function() {writer.writeFixed32(1, Infinity);}); + assertFails(function() { + writer.writeFixed32(1, -1); + }); + assertFails(function() { + writer.writeFixed32(1, Infinity); + }); - assertFails(function() {writer.writeFixed64(1, -1);}); - assertFails(function() {writer.writeFixed64(1, Infinity);}); + assertFails(function() { + writer.writeFixed64(1, -1); + }); + assertFails(function() { + writer.writeFixed64(1, Infinity); + }); - assertFails(function() {writer.writeSfixed32(1, -Infinity);}); - assertFails(function() {writer.writeSfixed32(1, Infinity);}); + assertFails(function() { + writer.writeSfixed32(1, -Infinity); + }); + assertFails(function() { + writer.writeSfixed32(1, Infinity); + }); - assertFails(function() {writer.writeSfixed64(1, -Infinity);}); - assertFails(function() {writer.writeSfixed64(1, Infinity);}); + assertFails(function() { + writer.writeSfixed64(1, -Infinity); + }); + assertFails(function() { + writer.writeSfixed64(1, Infinity); + }); }); diff --git a/js/compatibility_tests/v3.1.0/binary/reader_test.js b/js/compatibility_tests/v3.1.0/binary/reader_test.js index 957113859e..d0062de56e 100644 --- a/js/compatibility_tests/v3.1.0/binary/reader_test.js +++ b/js/compatibility_tests/v3.1.0/binary/reader_test.js @@ -46,7 +46,7 @@ goog.require('jspb.BinaryConstants'); goog.require('jspb.BinaryDecoder'); goog.require('jspb.BinaryReader'); goog.require('jspb.BinaryWriter'); - +goog.requireType('jspb.BinaryMessage'); describe('binaryReaderTest', function() { @@ -55,7 +55,7 @@ describe('binaryReaderTest', function() { */ it('testInstanceCaches', /** @suppress {visibility} */ function() { var writer = new jspb.BinaryWriter(); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); writer.writeMessage(1, dummyMessage, goog.nullFunction); writer.writeMessage(2, dummyMessage, goog.nullFunction); @@ -135,7 +135,7 @@ describe('binaryReaderTest', function() { // Calling readMessage on a non-delimited field should trigger an // assertion. var reader = jspb.BinaryReader.alloc([8, 1]); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); reader.nextField(); assertThrows(function() { reader.readMessage(dummyMessage, goog.nullFunction); @@ -144,47 +144,91 @@ describe('binaryReaderTest', function() { // Reading past the end of the stream should trigger an assertion. reader = jspb.BinaryReader.alloc([9, 1]); reader.nextField(); - assertThrows(function() {reader.readFixed64()}); + assertThrows(function() { + reader.readFixed64() + }); // Reading past the end of a submessage should trigger an assertion. reader = jspb.BinaryReader.alloc([10, 4, 13, 1, 1, 1]); reader.nextField(); reader.readMessage(dummyMessage, function() { reader.nextField(); - assertThrows(function() {reader.readFixed32()}); + assertThrows(function() { + reader.readFixed32() + }); }); // Skipping an invalid field should trigger an assertion. reader = jspb.BinaryReader.alloc([12, 1]); reader.nextWireType_ = 1000; - assertThrows(function() {reader.skipField()}); + assertThrows(function() { + reader.skipField() + }); // Reading fields with the wrong wire type should assert. reader = jspb.BinaryReader.alloc([9, 0, 0, 0, 0, 0, 0, 0, 0]); reader.nextField(); - assertThrows(function() {reader.readInt32()}); - assertThrows(function() {reader.readInt32String()}); - assertThrows(function() {reader.readInt64()}); - assertThrows(function() {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()}); + assertThrows(function() { + reader.readInt32() + }); + assertThrows(function() { + reader.readInt32String() + }); + assertThrows(function() { + reader.readInt64() + }); + assertThrows(function() { + 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.nextField(); - assertThrows(function() {reader.readFixed32()}); - assertThrows(function() {reader.readFixed64()}); - assertThrows(function() {reader.readSfixed32()}); - assertThrows(function() {reader.readSfixed64()}); - assertThrows(function() {reader.readFloat()}); - assertThrows(function() {reader.readDouble()}); + assertThrows(function() { + reader.readFixed32() + }); + assertThrows(function() { + reader.readFixed64() + }); + assertThrows(function() { + reader.readSfixed32() + }); + assertThrows(function() { + reader.readSfixed64() + }); + assertThrows(function() { + reader.readFloat() + }); + assertThrows(function() { + reader.readDouble() + }); - assertThrows(function() {reader.readString()}); - assertThrows(function() {reader.readBytes()}); + assertThrows(function() { + reader.readString() + }); + assertThrows(function() { + reader.readBytes() + }); }); @@ -198,8 +242,8 @@ describe('binaryReaderTest', function() { * @private * @suppress {missingProperties} */ - var doTestUnsignedField_ = function(readField, - writeField, epsilon, upperLimit, filter) { + var doTestUnsignedField_ = function( + readField, writeField, epsilon, upperLimit, filter) { assertNotNull(readField); assertNotNull(writeField); @@ -250,8 +294,8 @@ describe('binaryReaderTest', function() { * @private * @suppress {missingProperties} */ - var doTestSignedField_ = function(readField, - writeField, epsilon, lowerLimit, upperLimit, filter) { + var doTestSignedField_ = function( + readField, writeField, epsilon, lowerLimit, upperLimit, filter) { var writer = new jspb.BinaryWriter(); // Encode zero and limits. @@ -267,20 +311,14 @@ describe('binaryReaderTest', function() { for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) { var val = filter(cursor); writeField.call(writer, 6, val); - inputValues.push({ - fieldNumber: 6, - value: val - }); + inputValues.push({fieldNumber: 6, value: val}); } // Encode positive values. for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) { var val = filter(cursor); writeField.call(writer, 7, val); - inputValues.push({ - fieldNumber: 7, - value: val - }); + inputValues.push({fieldNumber: 7, value: val}); } var reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); @@ -327,33 +365,34 @@ describe('binaryReaderTest', function() { assertNotUndefined(jspb.BinaryWriter.prototype.writeBool); doTestUnsignedField_( jspb.BinaryReader.prototype.readUint32, - jspb.BinaryWriter.prototype.writeUint32, - 1, Math.pow(2, 32) - 1, Math.round); + jspb.BinaryWriter.prototype.writeUint32, 1, Math.pow(2, 32) - 1, + Math.round); doTestUnsignedField_( jspb.BinaryReader.prototype.readUint64, - jspb.BinaryWriter.prototype.writeUint64, - 1, Math.pow(2, 64) - 1025, Math.round); + jspb.BinaryWriter.prototype.writeUint64, 1, Math.pow(2, 64) - 1025, + Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readInt32, - jspb.BinaryWriter.prototype.writeInt32, - 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); + jspb.BinaryWriter.prototype.writeInt32, 1, -Math.pow(2, 31), + Math.pow(2, 31) - 1, Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readInt64, - jspb.BinaryWriter.prototype.writeInt64, - 1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round); + jspb.BinaryWriter.prototype.writeInt64, 1, -Math.pow(2, 63), + Math.pow(2, 63) - 513, Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readEnum, - jspb.BinaryWriter.prototype.writeEnum, - 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); + jspb.BinaryWriter.prototype.writeEnum, 1, -Math.pow(2, 31), + Math.pow(2, 31) - 1, Math.round); doTestUnsignedField_( jspb.BinaryReader.prototype.readBool, - jspb.BinaryWriter.prototype.writeBool, - 1, 1, function(x) { return !!x; }); + jspb.BinaryWriter.prototype.writeBool, 1, 1, function(x) { + return !!x; + }); }); @@ -387,24 +426,22 @@ describe('binaryReaderTest', function() { // uint32 and sint32 take no more than 5 bytes // 08 - field prefix (type = 0 means varint) doTestHexStringVarint_( - jspb.BinaryReader.prototype.readUint32, - 12, '08 8C 80 80 80 00'); + jspb.BinaryReader.prototype.readUint32, 12, '08 8C 80 80 80 00'); // 11 stands for -6 in zigzag encoding doTestHexStringVarint_( - jspb.BinaryReader.prototype.readSint32, - -6, '08 8B 80 80 80 00'); + jspb.BinaryReader.prototype.readSint32, -6, '08 8B 80 80 80 00'); // uint64 and sint64 take no more than 10 bytes // 08 - field prefix (type = 0 means varint) doTestHexStringVarint_( - jspb.BinaryReader.prototype.readUint64, - 12, '08 8C 80 80 80 80 80 80 80 80 00'); + jspb.BinaryReader.prototype.readUint64, 12, + '08 8C 80 80 80 80 80 80 80 80 00'); // 11 stands for -6 in zigzag encoding doTestHexStringVarint_( - jspb.BinaryReader.prototype.readSint64, - -6, '08 8B 80 80 80 80 80 80 80 80 00'); + jspb.BinaryReader.prototype.readSint64, -6, + '08 8B 80 80 80 80 80 80 80 80 00'); }); @@ -415,27 +452,15 @@ describe('binaryReaderTest', function() { var writer = new jspb.BinaryWriter(); var testSignedData = [ - '2730538252207801776', - '-2688470994844604560', - '3398529779486536359', - '3568577411627971000', - '272477188847484900', - '-6649058714086158188', - '-7695254765712060806', - '-4525541438037104029', - '-4993706538836508568', + '2730538252207801776', '-2688470994844604560', '3398529779486536359', + '3568577411627971000', '272477188847484900', '-6649058714086158188', + '-7695254765712060806', '-4525541438037104029', '-4993706538836508568', '4990160321893729138' ]; var testUnsignedData = [ - '7822732630241694882', - '6753602971916687352', - '2399935075244442116', - '8724292567325338867', - '16948784802625696584', - '4136275908516066934', - '3575388346793700364', - '5167142028379259461', - '1557573948689737699', + '7822732630241694882', '6753602971916687352', '2399935075244442116', + '8724292567325338867', '16948784802625696584', '4136275908516066934', + '3575388346793700364', '5167142028379259461', '1557573948689737699', '17100725280812548567' ]; @@ -463,13 +488,13 @@ describe('binaryReaderTest', function() { it('testZigzagFields', function() { doTestSignedField_( jspb.BinaryReader.prototype.readSint32, - jspb.BinaryWriter.prototype.writeSint32, - 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); + jspb.BinaryWriter.prototype.writeSint32, 1, -Math.pow(2, 31), + Math.pow(2, 31) - 1, Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readSint64, - jspb.BinaryWriter.prototype.writeSint64, - 1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round); + jspb.BinaryWriter.prototype.writeSint64, 1, -Math.pow(2, 63), + Math.pow(2, 63) - 513, Math.round); }); @@ -479,23 +504,23 @@ describe('binaryReaderTest', function() { it('testFixedFields', function() { doTestUnsignedField_( jspb.BinaryReader.prototype.readFixed32, - jspb.BinaryWriter.prototype.writeFixed32, - 1, Math.pow(2, 32) - 1, Math.round); + jspb.BinaryWriter.prototype.writeFixed32, 1, Math.pow(2, 32) - 1, + Math.round); doTestUnsignedField_( jspb.BinaryReader.prototype.readFixed64, - jspb.BinaryWriter.prototype.writeFixed64, - 1, Math.pow(2, 64) - 1025, Math.round); + jspb.BinaryWriter.prototype.writeFixed64, 1, Math.pow(2, 64) - 1025, + Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readSfixed32, - jspb.BinaryWriter.prototype.writeSfixed32, - 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); + jspb.BinaryWriter.prototype.writeSfixed32, 1, -Math.pow(2, 31), + Math.pow(2, 31) - 1, Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readSfixed64, - jspb.BinaryWriter.prototype.writeSfixed64, - 1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round); + jspb.BinaryWriter.prototype.writeSfixed64, 1, -Math.pow(2, 63), + Math.pow(2, 63) - 513, Math.round); }); @@ -506,18 +531,17 @@ describe('binaryReaderTest', function() { doTestSignedField_( jspb.BinaryReader.prototype.readFloat, jspb.BinaryWriter.prototype.writeFloat, - jspb.BinaryConstants.FLOAT32_MIN, - -jspb.BinaryConstants.FLOAT32_MAX, - jspb.BinaryConstants.FLOAT32_MAX, - truncate); + jspb.BinaryConstants.FLOAT32_MIN, -jspb.BinaryConstants.FLOAT32_MAX, + jspb.BinaryConstants.FLOAT32_MAX, truncate); doTestSignedField_( jspb.BinaryReader.prototype.readDouble, jspb.BinaryWriter.prototype.writeDouble, jspb.BinaryConstants.FLOAT64_EPS * 10, - -jspb.BinaryConstants.FLOAT64_MIN, - jspb.BinaryConstants.FLOAT64_MIN, - function(x) { return x; }); + -jspb.BinaryConstants.FLOAT64_MIN, jspb.BinaryConstants.FLOAT64_MIN, + function(x) { + return x; + }); }); @@ -584,7 +608,7 @@ describe('binaryReaderTest', function() { */ it('testNesting', function() { var writer = new jspb.BinaryWriter(); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); writer.writeInt32(1, 100); @@ -677,7 +701,7 @@ describe('binaryReaderTest', function() { // Write a group with a nested group inside. writer.writeInt32(5, sentinel); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); writer.writeGroup(5, dummyMessage, function() { writer.writeInt64(42, 42); writer.writeGroup(6, dummyMessage, function() { @@ -830,7 +854,7 @@ describe('binaryReaderTest', function() { var fieldTag = (1 << 3) | jspb.BinaryConstants.WireType.DELIMITED; var blob = [1, 2, 3, 4, 5]; var writer = new jspb.BinaryWriter(); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); writer.writeMessage(1, dummyMessage, function() { writer.writeMessage(1, dummyMessage, function() { @@ -863,7 +887,7 @@ describe('binaryReaderTest', function() { */ it('testReadCallbacks', function() { var writer = new jspb.BinaryWriter(); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); // Add an int, a submessage, and another int. writer.writeInt32(1, 100); diff --git a/js/compatibility_tests/v3.1.0/binary/writer_test.js b/js/compatibility_tests/v3.1.0/binary/writer_test.js index d5dadb4135..55bc6bedc1 100644 --- a/js/compatibility_tests/v3.1.0/binary/writer_test.js +++ b/js/compatibility_tests/v3.1.0/binary/writer_test.js @@ -41,14 +41,14 @@ goog.require('goog.crypt'); goog.require('goog.testing.asserts'); goog.require('jspb.BinaryWriter'); - +goog.requireType('jspb.BinaryMessage'); /** * @param {function()} func This function should throw an error when run. */ function assertFails(func) { var e = assertThrows(func); - //assertNotNull(e.toString().match(/Error/)); + // assertNotNull(e.toString().match(/Error/)); } @@ -59,7 +59,7 @@ describe('binaryWriterTest', function() { it('testWriteErrors', function() { // Submessages with invalid field indices should assert. var writer = new jspb.BinaryWriter(); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); assertFails(function() { writer.writeMessage(-1, dummyMessage, goog.nullFunction); @@ -67,40 +67,82 @@ describe('binaryWriterTest', function() { // Writing invalid field indices should assert. writer = new jspb.BinaryWriter(); - assertFails(function() {writer.writeUint64(-1, 1);}); + assertFails(function() { + writer.writeUint64(-1, 1); + }); // Writing out-of-range field values should assert. writer = new jspb.BinaryWriter(); - assertFails(function() {writer.writeInt32(1, -Infinity);}); - assertFails(function() {writer.writeInt32(1, Infinity);}); + assertFails(function() { + writer.writeInt32(1, -Infinity); + }); + assertFails(function() { + writer.writeInt32(1, Infinity); + }); - assertFails(function() {writer.writeInt64(1, -Infinity);}); - assertFails(function() {writer.writeInt64(1, Infinity);}); + assertFails(function() { + writer.writeInt64(1, -Infinity); + }); + assertFails(function() { + writer.writeInt64(1, Infinity); + }); - assertFails(function() {writer.writeUint32(1, -1);}); - assertFails(function() {writer.writeUint32(1, Infinity);}); + assertFails(function() { + writer.writeUint32(1, -1); + }); + assertFails(function() { + writer.writeUint32(1, Infinity); + }); - assertFails(function() {writer.writeUint64(1, -1);}); - assertFails(function() {writer.writeUint64(1, Infinity);}); + assertFails(function() { + writer.writeUint64(1, -1); + }); + assertFails(function() { + writer.writeUint64(1, Infinity); + }); - assertFails(function() {writer.writeSint32(1, -Infinity);}); - assertFails(function() {writer.writeSint32(1, Infinity);}); + assertFails(function() { + writer.writeSint32(1, -Infinity); + }); + assertFails(function() { + writer.writeSint32(1, Infinity); + }); - assertFails(function() {writer.writeSint64(1, -Infinity);}); - assertFails(function() {writer.writeSint64(1, Infinity);}); + assertFails(function() { + writer.writeSint64(1, -Infinity); + }); + assertFails(function() { + writer.writeSint64(1, Infinity); + }); - assertFails(function() {writer.writeFixed32(1, -1);}); - assertFails(function() {writer.writeFixed32(1, Infinity);}); + assertFails(function() { + writer.writeFixed32(1, -1); + }); + assertFails(function() { + writer.writeFixed32(1, Infinity); + }); - assertFails(function() {writer.writeFixed64(1, -1);}); - assertFails(function() {writer.writeFixed64(1, Infinity);}); + assertFails(function() { + writer.writeFixed64(1, -1); + }); + assertFails(function() { + writer.writeFixed64(1, Infinity); + }); - assertFails(function() {writer.writeSfixed32(1, -Infinity);}); - assertFails(function() {writer.writeSfixed32(1, Infinity);}); + assertFails(function() { + writer.writeSfixed32(1, -Infinity); + }); + assertFails(function() { + writer.writeSfixed32(1, Infinity); + }); - assertFails(function() {writer.writeSfixed64(1, -Infinity);}); - assertFails(function() {writer.writeSfixed64(1, Infinity);}); + assertFails(function() { + writer.writeSfixed64(1, -Infinity); + }); + assertFails(function() { + writer.writeSfixed64(1, Infinity); + }); }); diff --git a/js/compatibility_tests/v3.1.0/maps_test.js b/js/compatibility_tests/v3.1.0/maps_test.js index 0d442f4fd1..452dfe59d5 100644 --- a/js/compatibility_tests/v3.1.0/maps_test.js +++ b/js/compatibility_tests/v3.1.0/maps_test.js @@ -40,6 +40,8 @@ goog.require('proto.jspb.test.TestMapFields'); goog.require('proto.jspb.test.MapValueMessageNoBinary'); goog.require('proto.jspb.test.TestMapFieldsNoBinary'); +goog.requireType('jspb.Map'); + /** * Helper: check that the given map has exactly this set of (sorted) entries. * @param {!jspb.Map} map @@ -98,7 +100,9 @@ function makeTests(msgInfo, submessageCtor, suffix) { msg.getMapStringMsgMap().get('k').setFoo(42); msg.getMapStringMsgMap().get('l').setFoo(84); 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'); }; @@ -107,42 +111,24 @@ function makeTests(msgInfo, submessageCtor, suffix) { * @param {?} msg */ var checkMapFields = function(msg) { - checkMapEquals(msg.getMapStringStringMap(), [ - ['asdf', 'jkl;'], - ['key 2', 'hello world'] - ]); - checkMapEquals(msg.getMapStringInt32Map(), [ - ['a', 1], - ['b', -2] - ]); - checkMapEquals(msg.getMapStringInt64Map(), [ - ['c', 0x100000000], - ['d', 0x200000000] - ]); - checkMapEquals(msg.getMapStringBoolMap(), [ - ['e', true], - ['f', false] - ]); - checkMapEquals(msg.getMapStringDoubleMap(), [ - ['g', 3.14159], - ['h', 2.71828] - ]); + checkMapEquals( + msg.getMapStringStringMap(), + [['asdf', 'jkl;'], ['key 2', 'hello world']]); + checkMapEquals(msg.getMapStringInt32Map(), [['a', 1], ['b', -2]]); + checkMapEquals( + msg.getMapStringInt64Map(), [['c', 0x100000000], ['d', 0x200000000]]); + checkMapEquals(msg.getMapStringBoolMap(), [['e', true], ['f', false]]); + checkMapEquals( + msg.getMapStringDoubleMap(), [['g', 3.14159], ['h', 2.71828]]); checkMapEquals(msg.getMapStringEnumMap(), [ - ['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR], - ['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ] - ]); - checkMapEquals(msg.getMapInt32StringMap(), [ - [-1, 'a'], - [42, 'b'] - ]); - checkMapEquals(msg.getMapInt64StringMap(), [ - [0x123456789abc, 'c'], - [0xcba987654321, 'd'] - ]); - checkMapEquals(msg.getMapBoolStringMap(), [ - [false, 'e'], - [true, 'f'] + ['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR], + ['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ] ]); + checkMapEquals(msg.getMapInt32StringMap(), [[-1, 'a'], [42, 'b']]); + checkMapEquals( + msg.getMapInt64StringMap(), + [[0x123456789abc, 'c'], [0xcba987654321, 'd']]); + checkMapEquals(msg.getMapBoolStringMap(), [[false, 'e'], [true, 'f']]); assertEquals(msg.getMapStringMsgMap().getLength(), 2); 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, ['jkl;', 'key 2']); assertEquals(it.next().done, true); - checkMapEquals(m, [ - ['asdf', 'hello world'], - ['jkl;', 'key 2'] - ]); + checkMapEquals(m, [['asdf', 'hello world'], ['jkl;', 'key 2']]); m.del('jkl;'); assertEquals(m.has('jkl;'), false); assertEquals(m.get('jkl;'), undefined); @@ -242,11 +225,11 @@ function makeTests(msgInfo, submessageCtor, suffix) { msg.getMapStringStringMap().set('A', 'a'); var serialized = msg.serializeBinary(); var expectedSerialized = [ - 0x0a, 0x6, // field 1 (map_string_string), delimited, length 6 - 0x0a, 0x1, // field 1 in submessage (key), delimited, length 1 - 0x41, // ASCII 'A' - 0x12, 0x1, // field 2 in submessage (value), delimited, length 1 - 0x61 // ASCII 'a' + 0x0a, 0x6, // field 1 (map_string_string), delimited, length 6 + 0x0a, 0x1, // field 1 in submessage (key), delimited, length 1 + 0x41, // ASCII 'A' + 0x12, 0x1, // field 2 in submessage (value), delimited, length 1 + 0x61 // ASCII 'a' ]; assertEquals(serialized.length, expectedSerialized.length); for (var i = 0; i < serialized.length; i++) { @@ -267,11 +250,7 @@ function makeTests(msgInfo, submessageCtor, suffix) { */ it('testLazyMapSync' + suffix, function() { // Start with a JSPB array containing a few map entries. - var entries = [ - ['a', 'entry 1'], - ['c', 'entry 2'], - ['b', 'entry 3'] - ]; + var entries = [['a', 'entry 1'], ['c', 'entry 2'], ['b', 'entry 3']]; var msg = new msgInfo.constructor([entries]); assertEquals(entries.length, 3); assertEquals(entries[0][0], 'a'); @@ -279,9 +258,9 @@ function makeTests(msgInfo, submessageCtor, suffix) { assertEquals(entries[2][0], 'b'); msg.getMapStringStringMap().del('a'); assertEquals(entries.length, 3); // not yet sync'd - msg.toArray(); // force a sync + msg.toArray(); // force a sync assertEquals(entries.length, 2); - assertEquals(entries[0][0], 'b'); // now in sorted order + assertEquals(entries[0][0], 'b'); // now in sorted order assertEquals(entries[1][0], 'c'); var a = msg.toArray(); @@ -290,12 +269,16 @@ function makeTests(msgInfo, submessageCtor, suffix) { } describe('mapsTest', function() { - makeTests({ - constructor: proto.jspb.test.TestMapFields, - deserializeBinary: proto.jspb.test.TestMapFields.deserializeBinary - }, proto.jspb.test.MapValueMessage, "_Binary"); - makeTests({ - constructor: proto.jspb.test.TestMapFieldsNoBinary, - deserializeBinary: null - }, proto.jspb.test.MapValueMessageNoBinary, "_NoBinary"); + makeTests( + { + constructor: proto.jspb.test.TestMapFields, + deserializeBinary: proto.jspb.test.TestMapFields.deserializeBinary + }, + proto.jspb.test.MapValueMessage, '_Binary'); + makeTests( + { + constructor: proto.jspb.test.TestMapFieldsNoBinary, + deserializeBinary: null + }, + proto.jspb.test.MapValueMessageNoBinary, '_NoBinary'); }); diff --git a/js/compatibility_tests/v3.1.0/message_test.js b/js/compatibility_tests/v3.1.0/message_test.js index 80a1c52b65..9830a02dfe 100644 --- a/js/compatibility_tests/v3.1.0/message_test.js +++ b/js/compatibility_tests/v3.1.0/message_test.js @@ -67,7 +67,6 @@ goog.require('proto.jspb.test.Simple1'); goog.require('proto.jspb.test.Simple2'); goog.require('proto.jspb.test.SpecialCases'); goog.require('proto.jspb.test.TestClone'); -goog.require('proto.jspb.test.TestEndsWithBytes'); goog.require('proto.jspb.test.TestGroup'); goog.require('proto.jspb.test.TestGroup1'); goog.require('proto.jspb.test.TestMessageWithOneof'); @@ -77,7 +76,7 @@ goog.require('proto.jspb.test.TestReservedNamesExtension'); // CommonJS-LoadFromFile: test2_pb proto.jspb.test goog.require('proto.jspb.test.ExtensionMessage'); goog.require('proto.jspb.test.TestExtensionsMessage'); - +goog.require('proto.jspb.test.simple1'); @@ -102,59 +101,59 @@ describe('Message test suite', function() { }); it('testComplexConversion', function() { - var data1 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, true]; - var data2 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, true]; + var data1 = ['a', , , [, 11], [[, 22], [, 33]], , ['s1', 's2'], , true]; + var data2 = ['a', , , [, 11], [[, 22], [, 33]], , ['s1', 's2'], , true]; var foo = new proto.jspb.test.Complex(data1); var bar = new proto.jspb.test.Complex(data2); var result = foo.toObject(); - assertObjectEquals({ - aString: 'a', - anOutOfOrderBool: true, - aNestedMessage: { - anInt: 11 - }, - aRepeatedMessageList: [{anInt: 22}, {anInt: 33}], - aRepeatedStringList: ['s1', 's2'] - }, result); + assertObjectEquals( + { + aString: 'a', + anOutOfOrderBool: true, + aNestedMessage: {anInt: 11}, + aRepeatedMessageList: [{anInt: 22}, {anInt: 33}], + aRepeatedStringList: ['s1', 's2'] + }, + result); // Now test with the jspb instances included. result = foo.toObject(true /* opt_includeInstance */); - assertObjectEquals({ - aString: 'a', - anOutOfOrderBool: true, - aNestedMessage: { - anInt: 11, - $jspbMessageInstance: foo.getANestedMessage() - }, - aRepeatedMessageList: [ - {anInt: 22, $jspbMessageInstance: foo.getARepeatedMessageList()[0]}, - {anInt: 33, $jspbMessageInstance: foo.getARepeatedMessageList()[1]} - ], - aRepeatedStringList: ['s1', 's2'], - $jspbMessageInstance: foo - }, result); - + assertObjectEquals( + { + aString: 'a', + anOutOfOrderBool: true, + aNestedMessage: + {anInt: 11, $jspbMessageInstance: foo.getANestedMessage()}, + aRepeatedMessageList: [ + {anInt: 22, $jspbMessageInstance: foo.getARepeatedMessageList()[0]}, + {anInt: 33, $jspbMessageInstance: foo.getARepeatedMessageList()[1]} + ], + aRepeatedStringList: ['s1', 's2'], + $jspbMessageInstance: foo + }, + result); }); it('testMissingFields', function() { 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([ - undefined, undefined, undefined, [], - undefined, undefined, undefined, undefined]); + undefined, undefined, undefined, [], undefined, undefined, undefined, + undefined + ]); var result = foo.toObject(); - assertObjectEquals({ - aString: undefined, - anOutOfOrderBool: undefined, - aNestedMessage: { - anInt: undefined - }, - // Note: JsPb converts undefined repeated fields to empty arrays. - aRepeatedMessageList: [], - aRepeatedStringList: [] - }, result); - + assertObjectEquals( + { + aString: undefined, + anOutOfOrderBool: undefined, + aNestedMessage: {anInt: undefined}, + // Note: JsPb converts undefined repeated fields to empty arrays. + aRepeatedMessageList: [], + aRepeatedStringList: [] + }, + result); }); it('testNestedComplexMessage', function() { @@ -167,20 +166,21 @@ describe('Message test suite', function() { it('testSpecialCases', function() { // Note: Some property names are reserved in JavaScript. // These names are converted to the Js property named pb_. - var special = - new proto.jspb.test.SpecialCases(['normal', 'default', 'function', - 'var']); + var special = new proto.jspb.test.SpecialCases( + ['normal', 'default', 'function', 'var']); var result = special.toObject(); - assertObjectEquals({ - normal: 'normal', - pb_default: 'default', - pb_function: 'function', - pb_var: 'var' - }, result); + assertObjectEquals( + { + normal: 'normal', + pb_default: 'default', + pb_function: 'function', + pb_var: 'var' + }, + result); }); it('testDefaultValues', function() { - var defaultString = "default<>\'\"abc"; + var defaultString = 'default<>\'"abc'; var response = new proto.jspb.test.DefaultValues(); // Test toObject @@ -244,8 +244,10 @@ describe('Message test suite', function() { // Test that clearing the values reverts them to the default state. response = makeDefault(['blah', false, 111, 77]); - response.clearStringField(); response.clearBoolField(); - response.clearIntField(); response.clearEnumField(); + response.clearStringField(); + response.clearBoolField(); + response.clearIntField(); + response.clearEnumField(); assertEquals(defaultString, response.getStringField()); assertEquals(true, response.getBoolField()); assertEquals(11, response.getIntField()); @@ -257,8 +259,10 @@ describe('Message test suite', function() { // Test that setFoo(null) clears the values. response = makeDefault(['blah', false, 111, 77]); - response.setStringField(null); response.setBoolField(null); - response.setIntField(undefined); response.setEnumField(undefined); + response.setStringField(null); + response.setBoolField(null); + response.setIntField(undefined); + response.setEnumField(undefined); assertEquals(defaultString, response.getStringField()); assertEquals(true, response.getBoolField()); assertEquals(11, response.getIntField()); @@ -288,15 +292,15 @@ describe('Message test suite', function() { // but we actually get a sparse array instead. We could use something // like [1,undefined,2] to avoid this, except that this is still // sparse on IE. No comment... - var expected = [,,, [], []]; + var expected = [, , , [], []]; expected[0] = expected[1] = expected[2] = undefined; assertObjectEquals(expected, foo.toArray()); }); it('testDifferenceRawObject', /** @suppress {visibility} */ function() { var p1 = new proto.jspb.test.HasExtensions(['hi', 'diff', {}]); - var p2 = new proto.jspb.test.HasExtensions(['hi', 'what', - {1000: 'unique'}]); + var p2 = + new proto.jspb.test.HasExtensions(['hi', 'what', {1000: 'unique'}]); var diff = /** @type {proto.jspb.test.HasExtensions} */ (jspb.Message.difference(p1, p2)); assertEquals('', diff.getStr1()); @@ -310,13 +314,13 @@ describe('Message test suite', function() { assertTrue(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['hi']))); assertFalse(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['bye']))); var s1b = new proto.jspb.test.Simple1(['hi', ['hello']]); - assertTrue(jspb.Message.equals(s1b, - new proto.jspb.test.Simple1(['hi', ['hello']]))); - assertTrue(jspb.Message.equals(s1b, - new proto.jspb.test.Simple1(['hi', ['hello', undefined, - undefined, undefined]]))); - assertFalse(jspb.Message.equals(s1b, - new proto.jspb.test.Simple1(['no', ['hello']]))); + assertTrue(jspb.Message.equals( + s1b, new proto.jspb.test.Simple1(['hi', ['hello']]))); + assertTrue(jspb.Message.equals(s1b, new proto.jspb.test.Simple1([ + 'hi', ['hello', undefined, undefined, undefined] + ]))); + assertFalse(jspb.Message.equals( + s1b, new proto.jspb.test.Simple1(['no', ['hello']]))); // Test with messages of different types var s2 = new proto.jspb.test.Simple2(['hi']); assertFalse(jspb.Message.equals(s1, s2)); @@ -324,18 +328,18 @@ describe('Message test suite', function() { it('testEquals_softComparison', function() { var s1 = new proto.jspb.test.Simple1(['hi', [], null]); - assertTrue(jspb.Message.equals(s1, - new proto.jspb.test.Simple1(['hi', []]))); + assertTrue( + jspb.Message.equals(s1, new proto.jspb.test.Simple1(['hi', []]))); var s1b = new proto.jspb.test.Simple1(['hi', [], true]); - assertTrue(jspb.Message.equals(s1b, - new proto.jspb.test.Simple1(['hi', [], 1]))); + assertTrue( + jspb.Message.equals(s1b, new proto.jspb.test.Simple1(['hi', [], 1]))); }); it('testEqualsComplex', function() { - var data1 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, 1]; - var data2 = ['a',,, [, 11], [[, 22], [, 34]],, ['s1', 's2'],, 1]; - var data3 = ['a',,, [, 11], [[, 22]],, ['s1', 's2'],, 1]; + var data1 = ['a', , , [, 11], [[, 22], [, 33]], , ['s1', 's2'], , 1]; + var data2 = ['a', , , [, 11], [[, 22], [, 34]], , ['s1', 's2'], , 1]; + var data3 = ['a', , , [, 11], [[, 22]], , ['s1', 's2'], , 1]; var data4 = ['hi']; var c1a = new proto.jspb.test.Complex(data1); var c1b = new proto.jspb.test.Complex(data1); @@ -352,42 +356,34 @@ describe('Message test suite', function() { it('testEqualsExtensionsConstructed', function() { assertTrue(jspb.Message.equals( new proto.jspb.test.HasExtensions([]), - new proto.jspb.test.HasExtensions([{}]) - )); + new proto.jspb.test.HasExtensions([{}]))); 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'}]}]))); assertFalse(jspb.Message.equals( 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( 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( 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( - 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( 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( - 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() { assertTrue(jspb.Message.compareFields([], [{}])); - assertTrue(jspb.Message.compareFields([,,, {}], [])); - assertTrue(jspb.Message.compareFields([,,, {}], [,, {}])); + assertTrue(jspb.Message.compareFields([, , , {}], [])); + assertTrue(jspb.Message.compareFields([, , , {}], [, , {}])); assertTrue(jspb.Message.compareFields( ['hi', {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}])); assertFalse(jspb.Message.compareFields( @@ -395,25 +391,25 @@ describe('Message test suite', function() { assertTrue(jspb.Message.compareFields( [{100: [{200: 'a'}]}], [{100: [{200: 'a'}]}])); assertTrue(jspb.Message.compareFields( - [{100: [{200: 'a'}]}], [,,, {100: [{200: 'a'}]}])); + [{100: [{200: 'a'}]}], [, , , {100: [{200: 'a'}]}])); assertTrue(jspb.Message.compareFields( - [,,, {100: [{200: 'a'}]}], [{100: [{200: 'a'}]}])); + [, , , {100: [{200: 'a'}]}], [{100: [{200: 'a'}]}])); assertTrue(jspb.Message.compareFields( - ['hi', {100: [{200: 'a'}]}], ['hi',,, {100: [{200: 'a'}]}])); + ['hi', {100: [{200: 'a'}]}], ['hi', , , {100: [{200: 'a'}]}])); assertTrue(jspb.Message.compareFields( - ['hi',,, {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}])); + ['hi', , , {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}])); }); it('testToMap', function() { var p1 = new proto.jspb.test.Simple1(['k', ['v']]); var p2 = new proto.jspb.test.Simple1(['k1', ['v1', 'v2']]); - var soymap = jspb.Message.toMap([p1, p2], - proto.jspb.test.Simple1.prototype.getAString, + var soymap = jspb.Message.toMap( + [p1, p2], proto.jspb.test.Simple1.prototype.getAString, proto.jspb.test.Simple1.prototype.toObject); assertEquals('k', soymap['k'].aString); assertArrayEquals(['v'], soymap['k'].aRepeatedStringList); - var protomap = jspb.Message.toMap([p1, p2], - proto.jspb.test.Simple1.prototype.getAString); + var protomap = jspb.Message.toMap( + [p1, p2], proto.jspb.test.Simple1.prototype.getAString); assertEquals('k', protomap['k'].getAString()); assertArrayEquals(['v'], protomap['k'].getARepeatedStringList()); }); @@ -434,8 +430,12 @@ describe('Message test suite', function() { extension.setExt('e1'); original.setExtension(proto.jspb.test.IsExtension.extField, extension); var clone = original.clone(); - assertArrayEquals(['v1',, ['x1', ['y1', 'z1']],, - [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1,, { 100: [, 'e1'] }], + assertArrayEquals( + [ + 'v1', , ['x1', ['y1', 'z1']], , + [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1, , + {100: [, 'e1']} + ], clone.toArray()); clone.setStr('v2'); 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(); newExtension.setExt('e2'); clone.setExtension(proto.jspb.test.CloneExtension.extField, newExtension); - assertArrayEquals(['v2',, ['a1', ['b1', 'c1']],, - [['a2', ['b2', 'c2']], ['a3', ['b3', 'c3']]], bytes2,, { 100: [, 'e2'] }], + assertArrayEquals( + [ + 'v2', , ['a1', ['b1', 'c1']], , + [['a2', ['b2', 'c2']], ['a3', ['b3', 'c3']]], bytes2, , + {100: [, 'e2']} + ], clone.toArray()); - assertArrayEquals(['v1',, ['x1', ['y1', 'z1']],, - [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1,, { 100: [, 'e1'] }], + assertArrayEquals( + [ + 'v1', , ['x1', ['y1', 'z1']], , + [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1, , + {100: [, 'e1']} + ], original.toArray()); }); @@ -488,11 +496,12 @@ describe('Message test suite', function() { jspb.Message.copyInto(original, dest); assertArrayEquals(original.toArray(), dest.toArray()); assertEquals('x1', dest.getSimple1().getAString()); - assertEquals('e1', + assertEquals( + 'e1', dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt()); dest.getSimple1().setAString('new value'); - assertNotEquals(dest.getSimple1().getAString(), - original.getSimple1().getAString()); + assertNotEquals( + dest.getSimple1().getAString(), original.getSimple1().getAString()); if (supportsUint8Array) { dest.getBytesField()[0] = 7; assertObjectEquals(bytes1, original.getBytesField()); @@ -502,12 +511,12 @@ describe('Message test suite', function() { assertObjectEquals(bytes1, original.getBytesField()); assertObjectEquals('789', dest.getBytesField()); } - dest.getExtension(proto.jspb.test.CloneExtension.extField). - setExt('new value'); + dest.getExtension(proto.jspb.test.CloneExtension.extField) + .setExt('new value'); assertNotEquals( dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt(), - original.getExtension( - proto.jspb.test.CloneExtension.extField).getExt()); + original.getExtension(proto.jspb.test.CloneExtension.extField) + .getExt()); }); it('testCopyInto_notSameType', function() { @@ -525,26 +534,32 @@ describe('Message test suite', function() { var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2']]); var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']); extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1); - extendable.setExtension(proto.jspb.test.IndirectExtension.simple, - extension2); + extendable.setExtension( + proto.jspb.test.IndirectExtension.simple, extension2); extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy'); - extendable.setExtension(proto.jspb.test.IndirectExtension.repeatedStrList, - ['a', 'b']); + extendable.setExtension( + proto.jspb.test.IndirectExtension.repeatedStrList, ['a', 'b']); var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]); var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2']]); extendable.setExtension( - proto.jspb.test.IndirectExtension.repeatedSimpleList, - [s1, s2]); - assertObjectEquals(extension1, + proto.jspb.test.IndirectExtension.repeatedSimpleList, [s1, s2]); + assertObjectEquals( + extension1, extendable.getExtension(proto.jspb.test.IsExtension.extField)); - assertObjectEquals(extension2, + assertObjectEquals( + extension2, extendable.getExtension(proto.jspb.test.IndirectExtension.simple)); - assertObjectEquals('xyzzy', + assertObjectEquals( + 'xyzzy', extendable.getExtension(proto.jspb.test.IndirectExtension.str)); - assertObjectEquals(['a', 'b'], extendable.getExtension( - proto.jspb.test.IndirectExtension.repeatedStrList)); - assertObjectEquals([s1, s2], extendable.getExtension( - proto.jspb.test.IndirectExtension.repeatedSimpleList)); + assertObjectEquals( + ['a', 'b'], + extendable.getExtension( + proto.jspb.test.IndirectExtension.repeatedStrList)); + assertObjectEquals( + [s1, s2], + extendable.getExtension( + proto.jspb.test.IndirectExtension.repeatedSimpleList)); // Not supported yet, but it should work... extendable.setExtension(proto.jspb.test.IndirectExtension.simple, null); assertNull( @@ -563,18 +578,18 @@ describe('Message test suite', function() { var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']); var extension = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]); extendable.setExtension(proto.jspb.test.simple1, extension); - assertObjectEquals(extension, - extendable.getExtension(proto.jspb.test.simple1)); + assertObjectEquals( + extension, extendable.getExtension(proto.jspb.test.simple1)); // From _lib mode. extension = new proto.jspb.test.ExtensionMessage(['s1']); extendable = new proto.jspb.test.TestExtensionsMessage([16]); extendable.setExtension(proto.jspb.test.floatingMsgField, extension); extendable.setExtension(proto.jspb.test.floatingStrField, 's2'); - assertObjectEquals(extension, - extendable.getExtension(proto.jspb.test.floatingMsgField)); - assertObjectEquals('s2', - extendable.getExtension(proto.jspb.test.floatingStrField)); + assertObjectEquals( + extension, extendable.getExtension(proto.jspb.test.floatingMsgField)); + assertObjectEquals( + 's2', extendable.getExtension(proto.jspb.test.floatingStrField)); assertNotUndefined(proto.jspb.exttest.floatingMsgField); assertNotUndefined(proto.jspb.exttest.floatingMsgFieldTwo); assertNotUndefined(proto.jspb.exttest.beta.floatingStrField); @@ -585,60 +600,72 @@ describe('Message test suite', function() { var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2'], true]); var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']); extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1); - extendable.setExtension(proto.jspb.test.IndirectExtension.simple, - extension2); + extendable.setExtension( + proto.jspb.test.IndirectExtension.simple, extension2); extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy'); - extendable.setExtension(proto.jspb.test.IndirectExtension.repeatedStrList, - ['a', 'b']); + extendable.setExtension( + proto.jspb.test.IndirectExtension.repeatedStrList, ['a', 'b']); var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2'], true]); var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2'], false]); extendable.setExtension( - proto.jspb.test.IndirectExtension.repeatedSimpleList, - [s1, s2]); - assertObjectEquals({ - str1: 'v1', str2: 'v2', str3: 'v3', - extField: { ext1: 'ext1field' }, - simple: { - aString: 'str', aRepeatedStringList: ['s1', 's2'], aBoolean: true - }, - str: 'xyzzy', - repeatedStrList: ['a', 'b'], - repeatedSimpleList: [ - { aString: 'foo', aRepeatedStringList: ['s1', 's2'], aBoolean: true}, - { aString: 'bar', aRepeatedStringList: ['t1', 't2'], aBoolean: false} - ] - }, extendable.toObject()); + proto.jspb.test.IndirectExtension.repeatedSimpleList, [s1, s2]); + assertObjectEquals( + { + str1: 'v1', + str2: 'v2', + str3: 'v3', + extField: {ext1: 'ext1field'}, + simple: { + aString: 'str', + aRepeatedStringList: ['s1', 's2'], + aBoolean: true + }, + str: 'xyzzy', + repeatedStrList: ['a', 'b'], + repeatedSimpleList: [ + {aString: 'foo', aRepeatedStringList: ['s1', 's2'], aBoolean: true}, + {aString: 'bar', aRepeatedStringList: ['t1', 't2'], aBoolean: false} + ] + }, + extendable.toObject()); // Now, with instances included. - assertObjectEquals({ - str1: 'v1', str2: 'v2', str3: 'v3', - extField: { - ext1: 'ext1field', - $jspbMessageInstance: - extendable.getExtension(proto.jspb.test.IsExtension.extField) - }, - simple: { - aString: 'str', - aRepeatedStringList: ['s1', 's2'], - aBoolean: true, - $jspbMessageInstance: - extendable.getExtension(proto.jspb.test.IndirectExtension.simple) - }, - str: 'xyzzy', - repeatedStrList: ['a', 'b'], - repeatedSimpleList: [{ - aString: 'foo', - aRepeatedStringList: ['s1', 's2'], - aBoolean: true, - $jspbMessageInstance: s1 - }, { - aString: 'bar', - aRepeatedStringList: ['t1', 't2'], - aBoolean: false, - $jspbMessageInstance: s2 - }], - $jspbMessageInstance: extendable - }, extendable.toObject(true /* opt_includeInstance */)); + assertObjectEquals( + { + str1: 'v1', + str2: 'v2', + str3: 'v3', + extField: { + ext1: 'ext1field', + $jspbMessageInstance: + extendable.getExtension(proto.jspb.test.IsExtension.extField) + }, + simple: { + aString: 'str', + aRepeatedStringList: ['s1', 's2'], + aBoolean: true, + $jspbMessageInstance: extendable.getExtension( + proto.jspb.test.IndirectExtension.simple) + }, + str: 'xyzzy', + repeatedStrList: ['a', 'b'], + repeatedSimpleList: [ + { + aString: 'foo', + aRepeatedStringList: ['s1', 's2'], + aBoolean: true, + $jspbMessageInstance: s1 + }, + { + aString: 'bar', + aRepeatedStringList: ['t1', 't2'], + aBoolean: false, + $jspbMessageInstance: s2 + } + ], + $jspbMessageInstance: extendable + }, + extendable.toObject(true /* opt_includeInstance */)); }); it('testInitialization_emptyArray', function() { @@ -690,8 +717,7 @@ describe('Message test suite', function() { var extensionMessage = new proto.jspb.test.IsExtension(['is_extension']); data.setExtension(proto.jspb.test.IsExtension.extField, extensionMessage); var obj = data.toObject(); - assertNotNull( - data.getExtension(proto.jspb.test.IsExtension.extField)); + assertNotNull(data.getExtension(proto.jspb.test.IsExtension.extField)); assertEquals('is_extension', obj.extField.ext1); }); @@ -708,16 +734,18 @@ describe('Message test suite', function() { var groups = group.getRepeatedGroupList(); assertEquals('g1', groups[0].getId()); assertObjectEquals([true, false], groups[0].getSomeBoolList()); - assertObjectEquals({id: 'g1', someBoolList: [true, false]}, - groups[0].toObject()); - assertObjectEquals({ - repeatedGroupList: [{id: 'g1', someBoolList: [true, false]}], - requiredGroup: {id: undefined}, - optionalGroup: undefined, - requiredSimple: {aRepeatedStringList: [], aString: undefined}, - optionalSimple: undefined, - id: undefined - }, group.toObject()); + assertObjectEquals( + {id: 'g1', someBoolList: [true, false]}, groups[0].toObject()); + assertObjectEquals( + { + repeatedGroupList: [{id: 'g1', someBoolList: [true, false]}], + requiredGroup: {id: undefined}, + optionalGroup: undefined, + requiredSimple: {aRepeatedStringList: [], aString: undefined}, + optionalSimple: undefined, + id: undefined + }, + group.toObject()); var group1 = new proto.jspb.test.TestGroup1(); group1.setGroup(someGroup); assertEquals(someGroup, group1.getGroup()); @@ -734,25 +762,26 @@ describe('Message test suite', function() { message.setExtension$(11); message.setExtension(proto.jspb.test.TestReservedNamesExtension.foo, 12); assertEquals(11, message.getExtension$()); - assertEquals(12, message.getExtension( - proto.jspb.test.TestReservedNamesExtension.foo)); + assertEquals( + 12, + message.getExtension(proto.jspb.test.TestReservedNamesExtension.foo)); assertObjectEquals({extension: 11, foo: 12}, message.toObject()); }); it('testInitializeMessageWithUnsetOneof', function() { var message = new proto.jspb.test.TestMessageWithOneof([]); assertEquals( - proto.jspb.test.TestMessageWithOneof.PartialOneofCase. - PARTIAL_ONEOF_NOT_SET, + proto.jspb.test.TestMessageWithOneof.PartialOneofCase + .PARTIAL_ONEOF_NOT_SET, message.getPartialOneofCase()); assertEquals( - proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase. - RECURSIVE_ONEOF_NOT_SET, + proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase + .RECURSIVE_ONEOF_NOT_SET, message.getRecursiveOneofCase()); }); it('testInitializeMessageWithSingleValueSetInOneof', function() { - var message = new proto.jspb.test.TestMessageWithOneof([,, 'x']); + var message = new proto.jspb.test.TestMessageWithOneof([, , 'x']); assertEquals('x', message.getPone()); assertEquals('', message.getPthree()); @@ -762,7 +791,7 @@ describe('Message test suite', function() { }); it('testKeepsLastWireValueSetInUnion_multipleValues', function() { - var message = new proto.jspb.test.TestMessageWithOneof([,, 'x',, 'y']); + var message = new proto.jspb.test.TestMessageWithOneof([, , 'x', , 'y']); assertEquals('', message.getPone()); assertEquals('y', message.getPthree()); @@ -819,8 +848,8 @@ describe('Message test suite', function() { it('testUnsetsOneofCaseWhenFieldIsCleared', function() { var message = new proto.jspb.test.TestMessageWithOneof; assertEquals( - proto.jspb.test.TestMessageWithOneof.PartialOneofCase. - PARTIAL_ONEOF_NOT_SET, + proto.jspb.test.TestMessageWithOneof.PartialOneofCase + .PARTIAL_ONEOF_NOT_SET, message.getPartialOneofCase()); message.setPone('hi'); @@ -830,8 +859,8 @@ describe('Message test suite', function() { message.clearPone(); assertEquals( - proto.jspb.test.TestMessageWithOneof.PartialOneofCase. - PARTIAL_ONEOF_NOT_SET, + proto.jspb.test.TestMessageWithOneof.PartialOneofCase + .PARTIAL_ONEOF_NOT_SET, message.getPartialOneofCase()); }); @@ -934,39 +963,39 @@ describe('Message test suite', function() { }); it('testInitializeMessageWithOneofDefaults_defaultNotSetOnFirstField', - function() { - var message; - - message = - new proto.jspb.test.TestMessageWithOneof(new Array(11).concat(567)); - assertEquals(567, message.getBone()); - assertEquals(1234, message.getBtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BONE, - message.getDefaultOneofBCase()); - - message = - new proto.jspb.test.TestMessageWithOneof(new Array(12).concat(890)); - assertEquals(0, message.getBone()); - assertEquals(890, message.getBtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO, - message.getDefaultOneofBCase()); - - message = new proto.jspb.test.TestMessageWithOneof( - new Array(11).concat(567, 890)); - assertEquals(0, message.getBone()); - assertEquals(890, message.getBtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO, - message.getDefaultOneofBCase()); - }); + function() { + var message; + + message = + new proto.jspb.test.TestMessageWithOneof(new Array(11).concat(567)); + assertEquals(567, message.getBone()); + assertEquals(1234, message.getBtwo()); + assertEquals( + proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BONE, + message.getDefaultOneofBCase()); + + message = + new proto.jspb.test.TestMessageWithOneof(new Array(12).concat(890)); + assertEquals(0, message.getBone()); + assertEquals(890, message.getBtwo()); + assertEquals( + proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO, + message.getDefaultOneofBCase()); + + message = new proto.jspb.test.TestMessageWithOneof( + new Array(11).concat(567, 890)); + assertEquals(0, message.getBone()); + assertEquals(890, message.getBtwo()); + assertEquals( + proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO, + message.getDefaultOneofBCase()); + }); it('testOneofContainingAnotherMessage', function() { var message = new proto.jspb.test.TestMessageWithOneof; assertEquals( - proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase. - RECURSIVE_ONEOF_NOT_SET, + proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase + .RECURSIVE_ONEOF_NOT_SET, message.getRecursiveOneofCase()); var other = new proto.jspb.test.TestMessageWithOneof; @@ -987,25 +1016,25 @@ describe('Message test suite', function() { it('testQueryingOneofCaseEnsuresOnlyOneFieldIsSetInUnderlyingArray', function() { - var message = new proto.jspb.test.TestMessageWithOneof; - message.setPone('x'); - assertEquals('x', message.getPone()); - assertEquals('', message.getPthree()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE, - message.getPartialOneofCase()); - - var array = message.toArray(); - assertEquals('x', array[2]); - assertUndefined(array[4]); - array[4] = 'y'; - - assertEquals( - proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PTHREE, - message.getPartialOneofCase()); - assertUndefined(array[2]); - assertEquals('y', array[4]); - }); + var message = new proto.jspb.test.TestMessageWithOneof; + message.setPone('x'); + assertEquals('x', message.getPone()); + assertEquals('', message.getPthree()); + assertEquals( + proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE, + message.getPartialOneofCase()); + + var array = message.toArray(); + assertEquals('x', array[2]); + assertUndefined(array[4]); + array[4] = 'y'; + + assertEquals( + proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PTHREE, + message.getPartialOneofCase()); + assertUndefined(array[2]); + assertEquals('y', array[4]); + }); it('testFloatingPointFieldsSupportNan', function() { var assertNan = function(x) { @@ -1015,8 +1044,7 @@ describe('Message test suite', function() { }; 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.getRequiredFloatField()); @@ -1029,5 +1057,4 @@ describe('Message test suite', function() { assertNan(message.getRepeatedDoubleFieldList()[1]); assertNan(message.getDefaultDoubleField()); }); - }); diff --git a/js/maps_test.js b/js/maps_test.js index 1cbff7b300..68ed6834c0 100644 --- a/js/maps_test.js +++ b/js/maps_test.js @@ -53,6 +53,8 @@ goog.require('proto.jspb.test.MapEntryOptionalValuesMessageValue'); goog.require('proto.jspb.test.MapValueMessageNoBinary'); goog.require('proto.jspb.test.TestMapFieldsNoBinary'); +goog.requireType('jspb.Map'); + /** * Helper: check that the given map has exactly this set of (sorted) entries. * @param {!jspb.Map} map @@ -116,7 +118,9 @@ function makeTests(msgInfo, submessageCtor, suffix) { msg.getMapStringMsgMap().get('k').setFoo(42); msg.getMapStringMsgMap().get('l').setFoo(84); 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'); }; @@ -125,42 +129,24 @@ function makeTests(msgInfo, submessageCtor, suffix) { * @param {?} msg */ var checkMapFields = function(msg) { - checkMapEquals(msg.getMapStringStringMap(), [ - ['asdf', 'jkl;'], - ['key 2', 'hello world'] - ]); - checkMapEquals(msg.getMapStringInt32Map(), [ - ['a', 1], - ['b', -2] - ]); - checkMapEquals(msg.getMapStringInt64Map(), [ - ['c', 0x100000000], - ['d', 0x200000000] - ]); - checkMapEquals(msg.getMapStringBoolMap(), [ - ['e', true], - ['f', false] - ]); - checkMapEquals(msg.getMapStringDoubleMap(), [ - ['g', 3.14159], - ['h', 2.71828] - ]); + checkMapEquals( + msg.getMapStringStringMap(), + [['asdf', 'jkl;'], ['key 2', 'hello world']]); + checkMapEquals(msg.getMapStringInt32Map(), [['a', 1], ['b', -2]]); + checkMapEquals( + msg.getMapStringInt64Map(), [['c', 0x100000000], ['d', 0x200000000]]); + checkMapEquals(msg.getMapStringBoolMap(), [['e', true], ['f', false]]); + checkMapEquals( + msg.getMapStringDoubleMap(), [['g', 3.14159], ['h', 2.71828]]); checkMapEquals(msg.getMapStringEnumMap(), [ - ['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR], - ['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ] - ]); - checkMapEquals(msg.getMapInt32StringMap(), [ - [-1, 'a'], - [42, 'b'] - ]); - checkMapEquals(msg.getMapInt64StringMap(), [ - [0x123456789abc, 'c'], - [0xcba987654321, 'd'] - ]); - checkMapEquals(msg.getMapBoolStringMap(), [ - [false, 'e'], - [true, 'f'] + ['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR], + ['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ] ]); + checkMapEquals(msg.getMapInt32StringMap(), [[-1, 'a'], [42, 'b']]); + checkMapEquals( + msg.getMapInt64StringMap(), + [[0x123456789abc, 'c'], [0xcba987654321, 'd']]); + checkMapEquals(msg.getMapBoolStringMap(), [[false, 'e'], [true, 'f']]); assertEquals(msg.getMapStringMsgMap().getLength(), 2); 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, ['jkl;', 'key 2']); assertEquals(it.next().done, true); - checkMapEquals(m, [ - ['asdf', 'hello world'], - ['jkl;', 'key 2'] - ]); + checkMapEquals(m, [['asdf', 'hello world'], ['jkl;', 'key 2']]); m.del('jkl;'); assertEquals(m.has('jkl;'), false); assertEquals(m.get('jkl;'), undefined); @@ -260,11 +243,11 @@ function makeTests(msgInfo, submessageCtor, suffix) { msg.getMapStringStringMap().set('A', 'a'); var serialized = msg.serializeBinary(); var expectedSerialized = [ - 0x0a, 0x6, // field 1 (map_string_string), delimited, length 6 - 0x0a, 0x1, // field 1 in submessage (key), delimited, length 1 - 0x41, // ASCII 'A' - 0x12, 0x1, // field 2 in submessage (value), delimited, length 1 - 0x61 // ASCII 'a' + 0x0a, 0x6, // field 1 (map_string_string), delimited, length 6 + 0x0a, 0x1, // field 1 in submessage (key), delimited, length 1 + 0x41, // ASCII 'A' + 0x12, 0x1, // field 2 in submessage (value), delimited, length 1 + 0x61 // ASCII 'a' ]; assertEquals(serialized.length, expectedSerialized.length); for (var i = 0; i < serialized.length; i++) { @@ -284,34 +267,27 @@ function makeTests(msgInfo, submessageCtor, suffix) { * binary format. */ it('testMapDeserializationForUndefinedKeys', function() { - var testMessageOptionalKeys = new proto.jspb.test.TestMapFieldsOptionalKeys(); - var mapEntryStringKey = new proto.jspb.test.MapEntryOptionalKeysStringKey(); - mapEntryStringKey.setValue("a"); + var testMessageOptionalKeys = + new proto.jspb.test.TestMapFieldsOptionalKeys(); + var mapEntryStringKey = + new proto.jspb.test.MapEntryOptionalKeysStringKey(); + mapEntryStringKey.setValue('a'); testMessageOptionalKeys.setMapStringString(mapEntryStringKey); var mapEntryInt32Key = new proto.jspb.test.MapEntryOptionalKeysInt32Key(); - mapEntryInt32Key.setValue("b"); + mapEntryInt32Key.setValue('b'); testMessageOptionalKeys.setMapInt32String(mapEntryInt32Key); var mapEntryInt64Key = new proto.jspb.test.MapEntryOptionalKeysInt64Key(); - mapEntryInt64Key.setValue("c"); + mapEntryInt64Key.setValue('c'); testMessageOptionalKeys.setMapInt64String(mapEntryInt64Key); var mapEntryBoolKey = new proto.jspb.test.MapEntryOptionalKeysBoolKey(); - mapEntryBoolKey.setValue("d"); + mapEntryBoolKey.setValue('d'); testMessageOptionalKeys.setMapBoolString(mapEntryBoolKey); - var deserializedMessage = msgInfo.deserializeBinary( - testMessageOptionalKeys.serializeBinary() - ); - checkMapEquals(deserializedMessage.getMapStringStringMap(), [ - ['', 'a'] - ]); - checkMapEquals(deserializedMessage.getMapInt32StringMap(), [ - [0, 'b'] - ]); - checkMapEquals(deserializedMessage.getMapInt64StringMap(), [ - [0, 'c'] - ]); - checkMapEquals(deserializedMessage.getMapBoolStringMap(), [ - [false, 'd'] - ]); + var deserializedMessage = + msgInfo.deserializeBinary(testMessageOptionalKeys.serializeBinary()); + checkMapEquals(deserializedMessage.getMapStringStringMap(), [['', 'a']]); + 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(); var mapEntryStringValue = new proto.jspb.test.MapEntryOptionalValuesStringValue(); - mapEntryStringValue.setKey("a"); + mapEntryStringValue.setKey('a'); testMessageOptionalValues.setMapStringString(mapEntryStringValue); var mapEntryInt32Value = new proto.jspb.test.MapEntryOptionalValuesInt32Value(); - mapEntryInt32Value.setKey("b"); + mapEntryInt32Value.setKey('b'); testMessageOptionalValues.setMapStringInt32(mapEntryInt32Value); var mapEntryInt64Value = new proto.jspb.test.MapEntryOptionalValuesInt64Value(); - mapEntryInt64Value.setKey("c"); + mapEntryInt64Value.setKey('c'); testMessageOptionalValues.setMapStringInt64(mapEntryInt64Value); var mapEntryBoolValue = new proto.jspb.test.MapEntryOptionalValuesBoolValue(); - mapEntryBoolValue.setKey("d"); + mapEntryBoolValue.setKey('d'); testMessageOptionalValues.setMapStringBool(mapEntryBoolValue); var mapEntryDoubleValue = new proto.jspb.test.MapEntryOptionalValuesDoubleValue(); - mapEntryDoubleValue.setKey("e"); + mapEntryDoubleValue.setKey('e'); testMessageOptionalValues.setMapStringDouble(mapEntryDoubleValue); var mapEntryEnumValue = new proto.jspb.test.MapEntryOptionalValuesEnumValue(); - mapEntryEnumValue.setKey("f"); + mapEntryEnumValue.setKey('f'); testMessageOptionalValues.setMapStringEnum(mapEntryEnumValue); var mapEntryMessageValue = new proto.jspb.test.MapEntryOptionalValuesMessageValue(); - mapEntryMessageValue.setKey("g"); + mapEntryMessageValue.setKey('g'); testMessageOptionalValues.setMapStringMsg(mapEntryMessageValue); var deserializedMessage = msgInfo.deserializeBinary( - testMessageOptionalValues.serializeBinary() - ); - checkMapEquals(deserializedMessage.getMapStringStringMap(), [ - ['a', ''] - ]); - checkMapEquals(deserializedMessage.getMapStringInt32Map(), [ - ['b', 0] - ]); - 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', []] - ]); + testMessageOptionalValues.serializeBinary()); + checkMapEquals(deserializedMessage.getMapStringStringMap(), [['a', '']]); + checkMapEquals(deserializedMessage.getMapStringInt32Map(), [['b', 0]]); + 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() { // Start with a JSPB array containing a few map entries. - var entries = [ - ['a', 'entry 1'], - ['c', 'entry 2'], - ['b', 'entry 3'] - ]; + var entries = [['a', 'entry 1'], ['c', 'entry 2'], ['b', 'entry 3']]; var msg = new msgInfo.constructor([entries]); assertEquals(entries.length, 3); assertEquals(entries[0][0], 'a'); @@ -394,9 +351,9 @@ function makeTests(msgInfo, submessageCtor, suffix) { assertEquals(entries[2][0], 'b'); msg.getMapStringStringMap().del('a'); assertEquals(entries.length, 3); // not yet sync'd - msg.toArray(); // force a sync + msg.toArray(); // force a sync assertEquals(entries.length, 2); - assertEquals(entries[0][0], 'b'); // now in sorted order + assertEquals(entries[0][0], 'b'); // now in sorted order assertEquals(entries[1][0], 'c'); var a = msg.toArray(); diff --git a/js/message_test.js b/js/message_test.js index 3db8716b8c..2a524deeba 100644 --- a/js/message_test.js +++ b/js/message_test.js @@ -121,6 +121,8 @@ goog.require('proto.jspb.test.TestAllowAliasEnum'); // CommonJS-LoadFromFile: testlargenumbers_pb proto.jspb.test goog.require('proto.jspb.test.MessageWithLargeFieldNumbers'); +goog.require('proto.jspb.test.simple1'); + describe('Message test suite', function() { var stubs = new goog.testing.PropertyReplacer(); @@ -185,7 +187,6 @@ describe('Message test suite', function() { $jspbMessageInstance: foo }, result); - }); it('testMissingFields', function() { @@ -209,7 +210,6 @@ describe('Message test suite', function() { aFloatingPointField: undefined, }, result); - }); it('testNestedComplexMessage', function() { @@ -1108,5 +1108,4 @@ describe('Message test suite', function() { message.setAInt(42); assertEquals(42, message.getAInt()); }); - }); diff --git a/js/proto3_test.js b/js/proto3_test.js index fd59ae50d6..8de157524b 100644 --- a/js/proto3_test.js +++ b/js/proto3_test.js @@ -41,7 +41,7 @@ goog.require('proto.google.protobuf.Any'); goog.require('proto.google.protobuf.Timestamp'); // CommonJS-LoadFromFile: google/protobuf/struct_pb proto.google.protobuf goog.require('proto.google.protobuf.Struct'); - +goog.require('jspb.Message'); var BYTES = new Uint8Array([1, 2, 8, 9]); var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES); @@ -70,7 +70,6 @@ function bytesCompare(arr, expected) { describe('proto3Test', function() { - /** * Test default values don't affect equality test. */ @@ -182,8 +181,8 @@ describe('proto3Test', function() { assertEquals(msg.getOptionalBytes_asU8().length, 0); assertEquals(msg.getOptionalBytes_asB64(), ''); - assertEquals(msg.getOptionalForeignEnum(), - proto.jspb.test.Proto3Enum.PROTO3_FOO); + assertEquals( + msg.getOptionalForeignEnum(), proto.jspb.test.Proto3Enum.PROTO3_FOO); assertEquals(msg.getOptionalForeignMessage(), undefined); assertEquals(msg.getOptionalForeignMessage(), undefined); @@ -309,7 +308,8 @@ describe('proto3Test', function() { assertEquals(true, bytesCompare(msg.getRepeatedBytesList()[0], BYTES)); assertEquals(msg.getRepeatedForeignMessageList().length, 1); assertEquals(msg.getRepeatedForeignMessageList()[0].getC(), 1000); - assertElementsEquals(msg.getRepeatedForeignEnumList(), + assertElementsEquals( + msg.getRepeatedForeignEnumList(), [proto.jspb.test.Proto3Enum.PROTO3_BAR]); assertEquals(msg.getOneofString(), 'asdf'); @@ -374,7 +374,8 @@ describe('proto3Test', function() { assertEquals(msg.getOneofUint32(), 0); assertEquals(msg.getOneofForeignMessage(), undefined); assertEquals(msg.getOneofString(), ''); - assertEquals(msg.getOneofBytes_asB64(), + assertEquals( + msg.getOneofBytes_asB64(), goog.crypt.base64.encodeString('\u00FF\u00FF')); assertFalse(msg.hasOneofUint32()); @@ -454,24 +455,24 @@ describe('proto3Test', function() { it('testStructWellKnownType', function() { var jsObj = { - abc: "def", + abc: 'def', number: 12345.678, nullKey: null, boolKey: true, - listKey: [1, null, true, false, "abc"], - structKey: {foo: "bar", somenum: 123}, - complicatedKey: [{xyz: {abc: [3, 4, null, false]}}, "zzz"] + listKey: [1, null, true, false, 'abc'], + structKey: {foo: 'bar', somenum: 123}, + complicatedKey: [{xyz: {abc: [3, 4, null, false]}}, 'zzz'] }; var struct = proto.google.protobuf.Struct.fromJavaScript(jsObj); var jsObj2 = struct.toJavaScript(); - assertEquals("def", jsObj2.abc); + assertEquals('def', jsObj2.abc); assertEquals(12345.678, jsObj2.number); assertEquals(null, jsObj2.nullKey); assertEquals(true, jsObj2.boolKey); - assertEquals("abc", jsObj2.listKey[4]); - assertEquals("bar", jsObj2.structKey.foo); + assertEquals('abc', jsObj2.listKey[4]); + assertEquals('bar', jsObj2.structKey.foo); assertEquals(4, jsObj2.complicatedKey[0].xyz.abc[1]); }); }); diff --git a/kokoro/README.md b/kokoro/README.md index 0791c9253b..590d7bd36b 100644 --- a/kokoro/README.md +++ b/kokoro/README.md @@ -3,4 +3,10 @@ Kokoro Infrastructure ---------------------- The files in this directory serve as plumbing for running Protobuf -tests under Kokoro, our internal CI. \ No newline at end of file +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). diff --git a/kokoro/linux/dockerfile/test/php/Dockerfile b/kokoro/linux/dockerfile/test/php/Dockerfile index f2fe836a55..4c9d69d181 100644 --- a/kokoro/linux/dockerfile/test/php/Dockerfile +++ b/kokoro/linux/dockerfile/test/php/Dockerfile @@ -55,6 +55,26 @@ RUN mv composer.phar /usr/local/bin/composer # Download php source code 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 RUN cd php-src \ && git checkout PHP-7.0.33 \ diff --git a/kokoro/linux/dockerfile/test/php_32bit/Dockerfile b/kokoro/linux/dockerfile/test/php_32bit/Dockerfile index ed2acbef7c..d657af1649 100644 --- a/kokoro/linux/dockerfile/test/php_32bit/Dockerfile +++ b/kokoro/linux/dockerfile/test/php_32bit/Dockerfile @@ -53,6 +53,25 @@ RUN mv composer.phar /usr/local/bin/composer # Download php source code 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 RUN wget https://github.com/php/php-src/archive/php-7.0.33.tar.gz -O /var/local/php-7.0.33.tar.gz diff --git a/kokoro/linux/dockerfile/test/python39/Dockerfile b/kokoro/linux/dockerfile/test/python39/Dockerfile new file mode 100644 index 0000000000..ee7554dd64 --- /dev/null +++ b/kokoro/linux/dockerfile/test/python39/Dockerfile @@ -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 diff --git a/kokoro/linux/python39/build.sh b/kokoro/linux/python39/build.sh new file mode 100755 index 0000000000..497dc66e7c --- /dev/null +++ b/kokoro/linux/python39/build.sh @@ -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 diff --git a/kokoro/linux/python39/continuous.cfg b/kokoro/linux/python39/continuous.cfg new file mode 100644 index 0000000000..b03bc908df --- /dev/null +++ b/kokoro/linux/python39/continuous.cfg @@ -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" + } +} diff --git a/kokoro/linux/python39/presubmit.cfg b/kokoro/linux/python39/presubmit.cfg new file mode 100644 index 0000000000..b03bc908df --- /dev/null +++ b/kokoro/linux/python39/presubmit.cfg @@ -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" + } +} diff --git a/kokoro/linux/python39_cpp/build.sh b/kokoro/linux/python39_cpp/build.sh new file mode 100755 index 0000000000..f45d2ec7c3 --- /dev/null +++ b/kokoro/linux/python39_cpp/build.sh @@ -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 diff --git a/kokoro/linux/python39_cpp/continuous.cfg b/kokoro/linux/python39_cpp/continuous.cfg new file mode 100644 index 0000000000..dd84fbe86b --- /dev/null +++ b/kokoro/linux/python39_cpp/continuous.cfg @@ -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" + } +} diff --git a/kokoro/linux/python39_cpp/presubmit.cfg b/kokoro/linux/python39_cpp/presubmit.cfg new file mode 100644 index 0000000000..dd84fbe86b --- /dev/null +++ b/kokoro/linux/python39_cpp/presubmit.cfg @@ -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" + } +} diff --git a/kokoro/release/csharp/windows/build_nuget.bat b/kokoro/release/csharp/windows/build_nuget.bat index 0ff8db0428..590c391dd4 100644 --- a/kokoro/release/csharp/windows/build_nuget.bat +++ b/kokoro/release/csharp/windows/build_nuget.bat @@ -11,4 +11,7 @@ set PATH=%LOCALAPPDATA%\Microsoft\dotnet;%PATH% set DOTNET_SKIP_FIRST_TIME_EXPERIENCE=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 diff --git a/kokoro/release/python/linux/build_artifacts.sh b/kokoro/release/python/linux/build_artifacts.sh index fd9d5a9395..6b1836f407 100755 --- a/kokoro/release/python/linux/build_artifacts.sh +++ b/kokoro/release/python/linux/build_artifacts.sh @@ -54,3 +54,4 @@ build_artifact_version 3.5 build_artifact_version 3.6 build_artifact_version 3.7 build_artifact_version 3.8 +build_artifact_version 3.9 diff --git a/kokoro/release/python/macos/build_artifacts.sh b/kokoro/release/python/macos/build_artifacts.sh index 15aae39777..7801b0125f 100755 --- a/kokoro/release/python/macos/build_artifacts.sh +++ b/kokoro/release/python/macos/build_artifacts.sh @@ -55,6 +55,7 @@ build_artifact_version 2.7 build_artifact_version 3.6 build_artifact_version 3.7 build_artifact_version 3.8 +build_artifact_version 3.9 # python OSX10.9 does not have python 3.5 export MB_PYTHON_OSX_VER=10.6 diff --git a/kokoro/release/python/windows/build_artifacts.bat b/kokoro/release/python/windows/build_artifacts.bat index 70a86a199c..b2adbe03f3 100644 --- a/kokoro/release/python/windows/build_artifacts.bat +++ b/kokoro/release/python/windows/build_artifacts.bat @@ -72,6 +72,16 @@ SET PYTHON_VERSION=3.8 SET PYTHON_ARCH=64 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 :error diff --git a/kokoro/release/python/windows/build_single_artifact.bat b/kokoro/release/python/windows/build_single_artifact.bat index 45843e1a09..a3cfef95d6 100644 --- a/kokoro/release/python/windows/build_single_artifact.bat +++ b/kokoro/release/python/windows/build_single_artifact.bat @@ -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 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 done from inside the powershell script as it would require to restart 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 pip install wheel diff --git a/kokoro/windows/csharp/build.bat b/kokoro/windows/csharp/build.bat index 95224f2eb2..4f1df377c0 100644 --- a/kokoro/windows/csharp/build.bat +++ b/kokoro/windows/csharp/build.bat @@ -11,4 +11,7 @@ set PATH=%LOCALAPPDATA%\Microsoft\dotnet;%PATH% set DOTNET_SKIP_FIRST_TIME_EXPERIENCE=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 diff --git a/php/composer.json b/php/composer.json index 28d379bdec..4c1b5ac675 100644 --- a/php/composer.json +++ b/php/composer.json @@ -6,10 +6,10 @@ "homepage": "https://developers.google.com/protocol-buffers/", "license": "BSD-3-Clause", "require": { - "php": ">=7.0.0" + "php": ">=5.5.0" }, "require-dev": { - "phpunit/phpunit": ">=6.0.0" + "phpunit/phpunit": ">=5.0.0" }, "autoload": { "psr-4": { diff --git a/php/ext/google/protobuf/array.c b/php/ext/google/protobuf/array.c index e6412c0832..3a2f734a71 100644 --- a/php/ext/google/protobuf/array.c +++ b/php/ext/google/protobuf/array.c @@ -55,8 +55,7 @@ typedef struct { zend_object std; zval arena; upb_array *array; - upb_fieldtype_t type; - const Descriptor* desc; // When values are messages. + TypeInfo type; } RepeatedField; 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; Arena_Init(&intern->arena); intern->array = NULL; - intern->desc = NULL; // Skip object_properties_init(), we don't allow derived classes. return &intern->std; } @@ -106,13 +104,35 @@ static void RepeatedField_destructor(zend_object* obj) { static int RepeatedField_compare_objects(zval *rf1, zval *rf2) { RepeatedField* intern1 = (RepeatedField*)Z_OBJ_P(rf1); 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; - if (intern1->desc != intern2->desc) return 1; + return TypeInfo_Eq(intern1->type, intern2->type) && + 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) { @@ -129,8 +149,8 @@ static zval *RepeatedField_GetPropertyPtrPtr(PROTO_VAL *object, // These are documented in the header file. -void RepeatedField_GetPhpWrapper(zval *val, upb_array *arr, - const upb_fielddef *f, zval *arena) { +void RepeatedField_GetPhpWrapper(zval *val, upb_array *arr, TypeInfo type, + zval *arena) { if (!arr) { ZVAL_NULL(val); return; @@ -142,15 +162,14 @@ void RepeatedField_GetPhpWrapper(zval *val, upb_array *arr, intern->std.handlers = &RepeatedField_object_handlers; ZVAL_COPY(&intern->arena, arena); intern->array = arr; - intern->type = upb_fielddef_type(f); - intern->desc = Descriptor_GetFromFieldDef(f); + intern->type = type; // Skip object_properties_init(), we don't allow derived classes. ObjCache_Add(intern->array, &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) { if (Z_ISREF_P(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) { // 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); HashPosition pos; - upb_fieldtype_t type = upb_fielddef_type(f); - const Descriptor *desc = Descriptor_GetFromFieldDef(f); 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 (!Convert_PhpToUpbAutoWrap(zv, &val, type, desc, arena)) { + if (!Convert_PhpToUpbAutoWrap(zv, &val, type, arena)) { return NULL; } @@ -183,9 +200,8 @@ upb_array *RepeatedField_GetUpbArray(zval *val, const upb_fielddef *f, Z_OBJCE_P(val) == RepeatedField_class_entry) { // Unwrap existing RepeatedField object to get the upb_array* inside. 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, "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, - const upb_msgdef *m) { +bool ArrayEq(const upb_array *a1, const upb_array *a2, TypeInfo type) { size_t i; 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++) { upb_msgval val1 = upb_array_get(a1, 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; @@ -238,16 +253,16 @@ PHP_METHOD(RepeatedField, __construct) { return; } - intern->type = pbphp_dtype_to_type(type); - intern->desc = Descriptor_GetFromClassEntry(klass); + intern->type.type = pbphp_dtype_to_type(type); + 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, "Message/enum type must have concrete class."); return; } - intern->array = upb_array_new(arena, intern->type); + intern->array = upb_array_new(arena, intern->type.type); ObjCache_Add(intern->array, &intern->std); } @@ -264,7 +279,7 @@ PHP_METHOD(RepeatedField, append) { upb_msgval msgval; 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; } @@ -321,7 +336,7 @@ PHP_METHOD(RepeatedField, offsetGet) { } 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); } @@ -357,7 +372,7 @@ PHP_METHOD(RepeatedField, offsetSet) { return; } - if (!Convert_PhpToUpb(val, &msgval, intern->type, intern->desc, arena)) { + if (!Convert_PhpToUpb(val, &msgval, intern->type, arena)) { return; } @@ -563,7 +578,7 @@ PHP_METHOD(RepeatedFieldIter, current) { 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); } @@ -638,6 +653,7 @@ void Array_ModuleInit() { #else h->compare = RepeatedField_compare_objects; #endif + h->clone_obj = RepeatedField_clone_obj; h->get_properties = RepeatedField_GetProperties; h->get_property_ptr_ptr = RepeatedField_GetPropertyPtrPtr; diff --git a/php/ext/google/protobuf/array.h b/php/ext/google/protobuf/array.h index 921e0bf564..031effa711 100644 --- a/php/ext/google/protobuf/array.h +++ b/php/ext/google/protobuf/array.h @@ -33,6 +33,7 @@ #include +#include "def.h" #include "php-upb.h" // Registers PHP classes for RepeatedField. @@ -40,27 +41,27 @@ void Array_ModuleInit(); // Gets a upb_array* for the PHP object |val|: // * 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 -// wrapped upb_array*. We also make sure that this array's arena is fused to -// |arena|, so the returned upb_array is guaranteed to live as long as +// that that the elements have the correct type for |type|. If so, we return +// the wrapped upb_array*. We also make sure that this array's arena is fused +// to |arena|, so the returned upb_array is guaranteed to live as long as // |arena|. // * 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. // // 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 // ensure the underlying array data stays alive. // // If |arr| is NULL, this will return a PHP null object. -void RepeatedField_GetPhpWrapper(zval *val, upb_array *arr, - const upb_fielddef *f, zval *arena); +void RepeatedField_GetPhpWrapper(zval *val, upb_array *arr, TypeInfo type, + zval *arena); // 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|. -bool ArrayEq(const upb_array *a1, const upb_array *a2, upb_fieldtype_t type, - const upb_msgdef *m); +bool ArrayEq(const upb_array *a1, const upb_array *a2, TypeInfo type); #endif // PHP_PROTOBUF_ARRAY_H_ diff --git a/php/ext/google/protobuf/convert.c b/php/ext/google/protobuf/convert.c index 1c2f6288b5..c518ccaa4d 100644 --- a/php/ext/google/protobuf/convert.c +++ b/php/ext/google/protobuf/convert.c @@ -348,15 +348,15 @@ static bool to_string(zval* from) { } } -bool Convert_PhpToUpb(zval *php_val, upb_msgval *upb_val, upb_fieldtype_t type, - const Descriptor *desc, upb_arena *arena) { +bool Convert_PhpToUpb(zval *php_val, upb_msgval *upb_val, TypeInfo type, + upb_arena *arena) { int64_t i64; if (Z_ISREF_P(php_val)) { ZVAL_DEREF(php_val); } - switch (type) { + switch (type.type) { case UPB_TYPE_INT64: return Convert_PhpToInt64(php_val, &upb_val->int64_val); case UPB_TYPE_INT32: @@ -408,17 +408,17 @@ bool Convert_PhpToUpb(zval *php_val, upb_msgval *upb_val, upb_fieldtype_t type, return true; } case UPB_TYPE_MESSAGE: - PBPHP_ASSERT(desc); - return Message_GetUpbMessage(php_val, desc, arena, + PBPHP_ASSERT(type.desc); + return Message_GetUpbMessage(php_val, type.desc, arena, (upb_msg **)&upb_val->msg_val); } return false; } -void Convert_UpbToPhp(upb_msgval upb_val, zval *php_val, upb_fieldtype_t type, - const Descriptor *desc, zval *arena) { - switch (type) { +void Convert_UpbToPhp(upb_msgval upb_val, zval *php_val, TypeInfo type, + zval *arena) { + switch (type.type) { case UPB_TYPE_INT64: #if SIZEOF_ZEND_LONG == 8 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; } case UPB_TYPE_MESSAGE: - PBPHP_ASSERT(desc); - Message_GetPhpWrapper(php_val, desc, (upb_msg*)upb_val.msg_val, arena); + PBPHP_ASSERT(type.desc); + Message_GetPhpWrapper(php_val, type.desc, (upb_msg *)upb_val.msg_val, + arena); break; } } -bool Convert_PhpToUpbAutoWrap(zval *val, upb_msgval *upb_val, - upb_fieldtype_t type, const Descriptor *desc, +bool Convert_PhpToUpbAutoWrap(zval *val, upb_msgval *upb_val, TypeInfo type, 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) { // 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]) // message manually. upb_msg *wrapper = upb_msg_new(subm, arena); const upb_fielddef *val_f = upb_msgdef_itof(subm, 1); - upb_fieldtype_t type_f = upb_fielddef_type(val_f); 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_val->msg_val = wrapper; return true; @@ -495,7 +494,7 @@ bool Convert_PhpToUpbAutoWrap(zval *val, upb_msgval *upb_val, // ['foo_submsg': new Foo(['a' => 1])] // not: // ['foo_submsg': ['a' => 1]] - return Convert_PhpToUpb(val, upb_val, type, desc, arena); + return Convert_PhpToUpb(val, upb_val, type, arena); } } diff --git a/php/ext/google/protobuf/convert.h b/php/ext/google/protobuf/convert.h index 06c05c7275..1bae233425 100644 --- a/php/ext/google/protobuf/convert.h +++ b/php/ext/google/protobuf/convert.h @@ -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. // 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. -bool Convert_PhpToUpb(zval *php_val, upb_msgval *upb_val, upb_fieldtype_t type, - const Descriptor *desc, upb_arena *arena); +bool Convert_PhpToUpb(zval *php_val, upb_msgval *upb_val, TypeInfo type, + upb_arena *arena); // Similar to Convert_PhpToUpb, but supports automatically wrapping the wrapper // 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 // assignment. -bool Convert_PhpToUpbAutoWrap(zval *val, upb_msgval *upb_val, - upb_fieldtype_t type, const Descriptor *desc, +bool Convert_PhpToUpbAutoWrap(zval *val, upb_msgval *upb_val, TypeInfo type, upb_arena *arena); // 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 // be the Descriptor for this message type. Any newly created wrapper object // will reference |arena|. -void Convert_UpbToPhp(upb_msgval upb_val, zval *php_val, upb_fieldtype_t type, - const Descriptor *desc, zval *arena); +void Convert_UpbToPhp(upb_msgval upb_val, zval *php_val, TypeInfo type, + zval *arena); // Registers the GPBUtil class. void Convert_ModuleInit(void); diff --git a/php/ext/google/protobuf/def.h b/php/ext/google/protobuf/def.h index 2a89cd0fd4..372c889b31 100644 --- a/php/ext/google/protobuf/def.h +++ b/php/ext/google/protobuf/def.h @@ -72,4 +72,27 @@ Descriptor* Descriptor_GetFromClassEntry(zend_class_entry *ce); Descriptor* Descriptor_GetFromMessageDef(const upb_msgdef *m); 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_ diff --git a/php/ext/google/protobuf/map.c b/php/ext/google/protobuf/map.c index 26776e677e..babd638dab 100644 --- a/php/ext/google/protobuf/map.c +++ b/php/ext/google/protobuf/map.c @@ -51,14 +51,31 @@ typedef struct { zend_object std; zval arena; upb_map *map; - upb_fieldtype_t key_type; - upb_fieldtype_t val_type; - const Descriptor* desc; // When values are messages. + MapField_Type type; } MapField; zend_class_entry *MapField_class_entry; 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 ///////////////////////////////////////////////////////// /** @@ -102,15 +119,36 @@ static void MapField_destructor(zend_object* obj) { static int MapField_compare_objects(zval *map1, zval *map2) { MapField* intern1 = (MapField*)Z_OBJ_P(map1); 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; - if (val_type != intern2->val_type) return 1; - if (intern1->desc != intern2->desc) return 1; + return MapType_Eq(intern1->type, intern2->type) && + MapEq(intern1->map, intern2->map, intern1->type) + ? 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); + } - return MapEq(intern1->map, intern2->map, key_type, val_type, m) ? 0 : 1; + 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, @@ -126,7 +164,7 @@ static HashTable *Map_GetProperties(PROTO_VAL *object) { // 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) { if (!map) { ZVAL_NULL(val); @@ -134,37 +172,25 @@ void MapField_GetPhpWrapper(zval *val, upb_map *map, const upb_fielddef *f, } 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)); zend_object_std_init(&intern->std, MapField_class_entry); intern->std.handlers = &MapField_object_handlers; ZVAL_COPY(&intern->arena, arena); intern->map = map; - intern->key_type = upb_fielddef_type(key_f); - intern->val_type = upb_fielddef_type(val_f); - intern->desc = Descriptor_GetFromFieldDef(val_f); + intern->type = type; // Skip object_properties_init(), we don't allow derived classes. ObjCache_Add(intern->map, &intern->std); ZVAL_OBJ(val, &intern->std); } } -upb_map *MapField_GetUpbMap(zval *val, const upb_fielddef *f, 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); - +upb_map *MapField_GetUpbMap(zval *val, MapField_Type type, upb_arena *arena) { if (Z_ISREF_P(val)) { ZVAL_DEREF(val); } 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); 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 (!Convert_PhpToUpb(&php_key, &upb_key, key_type, NULL, arena) || - !Convert_PhpToUpbAutoWrap(php_val, &upb_val, val_type, desc, arena)) { + if (!Convert_PhpToUpb(&php_key, &upb_key, KeyType(type), arena) || + !Convert_PhpToUpbAutoWrap(php_val, &upb_val, type.val_type, arena)) { 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) { MapField *intern = (MapField*)Z_OBJ_P(val); - if (intern->key_type != key_type || intern->val_type != val_type || - intern->desc != desc) { + if (!MapType_Eq(intern->type, type)) { php_error_docref(NULL, E_USER_ERROR, "Wrong type for this map field."); 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, - upb_fieldtype_t val_type, const upb_msgdef *m) { +bool MapEq(const upb_map *m1, const upb_map *m2, MapField_Type type) { size_t iter = UPB_MAP_BEGIN; 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; 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; @@ -250,12 +274,12 @@ PHP_METHOD(MapField, __construct) { return; } - intern->key_type = pbphp_dtype_to_type(key_type); - intern->val_type = pbphp_dtype_to_type(val_type); - intern->desc = Descriptor_GetFromClassEntry(klass); + intern->type.key_type = pbphp_dtype_to_type(key_type); + intern->type.val_type.type = pbphp_dtype_to_type(val_type); + intern->type.val_type.desc = Descriptor_GetFromClassEntry(klass); // 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_INT64: case UPB_TYPE_UINT32: @@ -269,13 +293,14 @@ PHP_METHOD(MapField, __construct) { 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, "Message/enum type must have concrete class."); 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); } @@ -296,7 +321,7 @@ PHP_METHOD(MapField, offsetExists) { upb_msgval upb_key; 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; } @@ -322,7 +347,7 @@ PHP_METHOD(MapField, offsetGet) { upb_msgval upb_key, upb_val; 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; } @@ -331,7 +356,7 @@ PHP_METHOD(MapField, offsetGet) { 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); } @@ -355,8 +380,8 @@ PHP_METHOD(MapField, offsetSet) { upb_msgval upb_key, upb_val; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &key, &val) != SUCCESS || - !Convert_PhpToUpb(key, &upb_key, intern->key_type, NULL, NULL) || - !Convert_PhpToUpb(val, &upb_val, intern->val_type, intern->desc, arena)) { + !Convert_PhpToUpb(key, &upb_key, KeyType(intern->type), NULL) || + !Convert_PhpToUpb(val, &upb_val, intern->type.val_type, arena)) { return; } @@ -380,7 +405,7 @@ PHP_METHOD(MapField, offsetUnset) { upb_msgval upb_key; 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; } @@ -543,7 +568,7 @@ PHP_METHOD(MapFieldIter, current) { MapField *field = (MapField*)Z_OBJ_P(&intern->map_field); upb_msgval upb_val = upb_mapiter_value(field->map, intern->position); 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); } @@ -557,7 +582,7 @@ PHP_METHOD(MapFieldIter, key) { MapField *field = (MapField*)Z_OBJ_P(&intern->map_field); upb_msgval upb_key = upb_mapiter_key(field->map, intern->position); 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); } @@ -624,6 +649,7 @@ void Map_ModuleInit() { #else h->compare = MapField_compare_objects; #endif + h->clone_obj = MapField_clone_obj; h->get_properties = Map_GetProperties; h->get_property_ptr_ptr = Map_GetPropertyPtrPtr; diff --git a/php/ext/google/protobuf/map.h b/php/ext/google/protobuf/map.h index 6eb0620c2e..c523cd0da9 100644 --- a/php/ext/google/protobuf/map.h +++ b/php/ext/google/protobuf/map.h @@ -33,10 +33,18 @@ #include +#include "def.h" #include "php-upb.h" 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|: // * 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 @@ -47,17 +55,16 @@ void Map_ModuleInit(); // |arena| and add all of the PHP elements to it. // // 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 // in |val|. The PHP object will keep a reference to this |arena| to ensure the // underlying array data stays alive. // // 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); -bool MapEq(const upb_map *m1, const upb_map *m2, upb_fieldtype_t key_type, - upb_fieldtype_t val_type, const upb_msgdef *m); +bool MapEq(const upb_map *m1, const upb_map *m2, MapField_Type type); #endif // PHP_PROTOBUF_MAP_H_ diff --git a/php/ext/google/protobuf/message.c b/php/ext/google/protobuf/message.c index 0e61770eef..7f27670320 100644 --- a/php/ext/google/protobuf/message.c +++ b/php/ext/google/protobuf/message.c @@ -60,6 +60,21 @@ typedef struct { zend_class_entry *message_ce; 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 ///////////////////////////////////////////////////////// /** @@ -69,8 +84,7 @@ static zend_object_handlers message_object_handlers; */ static zend_object* Message_create(zend_class_entry *class_type) { Message *intern = emalloc(sizeof(Message)); - // XXX(haberman): verify whether we actually want to take this route. - class_type->default_properties_count = 0; + Message_SuppressDefaultProperties(class_type); zend_object_std_init(&intern->std, class_type); intern->std.handlers = &message_object_handlers; 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)) { 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)) { 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 { upb_msgval msgval = upb_msg_get(intern->msg, f); - const Descriptor *subdesc = Descriptor_GetFromFieldDef(f); - Convert_UpbToPhp(msgval, rv, upb_fielddef_type(f), subdesc, &intern->arena); + Convert_UpbToPhp(msgval, rv, TypeInfo_Get(f), &intern->arena); } } @@ -130,16 +144,13 @@ static bool Message_set(Message *intern, const upb_fielddef *f, zval *val) { upb_msgval msgval; 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; } 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; } else { - upb_fieldtype_t type = upb_fielddef_type(f); - const Descriptor *subdesc = Descriptor_GetFromFieldDef(f); - bool ok = Convert_PhpToUpb(val, &msgval, type, subdesc, arena); - if (!ok) return false; + if (!Convert_PhpToUpb(val, &msgval, TypeInfo_Get(f), arena)) return false; } 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); /** - * ValueEq()() + * ValueEq() */ -bool ValueEq(upb_msgval val1, upb_msgval val2, upb_fieldtype_t type, - const upb_msgdef *m) { - switch (type) { +bool ValueEq(upb_msgval val1, upb_msgval val2, TypeInfo type) { + switch (type.type) { case UPB_TYPE_BOOL: return val1.bool_val == val2.bool_val; 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 && memcmp(val1.str_val.data, val2.str_val.data, val1.str_val.size) == 0; 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: 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); upb_msgval val1 = upb_msg_get(m1, 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_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)) { - const upb_fielddef *key_f = upb_msgdef_itof(sub_m, 1); - 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; - } + if (!MapEq(val1.map_val, val2.map_val, MapType_Get(f))) return false; } 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 { - 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, int has_set_exists, void **cache_slot) { - Message* intern = PROTO_MSG_P(obj); + Message* intern = PROTO_VAL_P(obj); const upb_fielddef *f = get_field(intern, member); 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, void **cache_slot) { - Message* intern = PROTO_MSG_P(obj); + Message* intern = PROTO_VAL_P(obj); const upb_fielddef *f = get_field(intern, member); 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, 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); 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( 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); 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. } +/** + * 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() * @@ -415,8 +435,7 @@ void Message_GetPhpWrapper(zval *val, const Descriptor *desc, upb_msg *msg, if (!ObjCache_Get(msg, val)) { Message *intern = emalloc(sizeof(Message)); - // XXX(haberman): verify whether we actually want to take this route. - desc->class_entry->default_properties_count = 0; + Message_SuppressDefaultProperties(desc->class_entry); zend_object_std_init(&intern->std, desc->class_entry); intern->std.handlers = &message_object_handlers; 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)) { - msgval.map_val = MapField_GetUpbMap(val, f, arena); + msgval.map_val = MapField_GetUpbMap(val, MapType_Get(f), arena); if (!msgval.map_val) return false; } 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; } else { - const Descriptor *desc = Descriptor_GetFromFieldDef(f); - upb_fieldtype_t type = upb_fielddef_type(f); - if (!Convert_PhpToUpbAutoWrap(val, &msgval, type, desc, arena)) { + if (!Convert_PhpToUpbAutoWrap(val, &msgval, TypeInfo_Get(f), arena)) { return false; } } @@ -554,10 +571,32 @@ static void Message_Initialize(Message *intern, const Descriptor *desc) { */ PHP_METHOD(Message, __construct) { 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); 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); 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_msgdef *m = upb_fielddef_msgsubdef(f); 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); 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); } else { RETURN_NULL(); @@ -861,10 +899,9 @@ PHP_METHOD(Message, writeWrapperValue) { } else { const upb_msgdef *m = upb_fielddef_msgsubdef(f); const upb_fielddef *val_f = upb_msgdef_itof(m, 1); - upb_fieldtype_t val_type = upb_fielddef_type(val_f); 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. } @@ -974,9 +1011,7 @@ PHP_METHOD(Message, readOneof) { { upb_msgval msgval = upb_msg_get(intern->msg, f); - const Descriptor *subdesc = Descriptor_GetFromFieldDef(f); - Convert_UpbToPhp(msgval, &ret, upb_fielddef_type(f), subdesc, - &intern->arena); + Convert_UpbToPhp(msgval, &ret, TypeInfo_Get(f), &intern->arena); } RETURN_ZVAL(&ret, 1, 0); @@ -1017,8 +1052,7 @@ PHP_METHOD(Message, writeOneof) { f = upb_msgdef_itof(intern->desc->msgdef, field_num); - if (!Convert_PhpToUpb(val, &msgval, upb_fielddef_type(f), - Descriptor_GetFromFieldDef(f), arena)) { + if (!Convert_PhpToUpb(val, &msgval, TypeInfo_Get(f), arena)) { return; } @@ -1225,8 +1259,8 @@ PHP_METHOD(google_protobuf_Timestamp, fromDateTime) { if (call_user_function(EG(function_table), NULL, &function_name, &retval, 1, datetime) == FAILURE || - !Convert_PhpToUpb(&retval, ×tamp_seconds, UPB_TYPE_INT64, NULL, - NULL)) { + !Convert_PhpToUpb(&retval, ×tamp_seconds, + TypeInfo_FromType(UPB_TYPE_INT64), NULL)) { zend_error(E_ERROR, "Cannot get timestamp from DateTime."); return; } @@ -1251,8 +1285,8 @@ PHP_METHOD(google_protobuf_Timestamp, fromDateTime) { if (call_user_function(EG(function_table), NULL, &function_name, &retval, 2, params) == FAILURE || - !Convert_PhpToUpb(&retval, ×tamp_nanos, UPB_TYPE_INT32, NULL, - NULL)) { + !Convert_PhpToUpb(&retval, ×tamp_nanos, + TypeInfo_FromType(UPB_TYPE_INT32), NULL)) { zend_error(E_ERROR, "Cannot format DateTime."); return; } @@ -1338,6 +1372,7 @@ void Message_ModuleInit() { h->unset_property = Message_unset_property; h->get_properties = Message_get_properties; h->get_property_ptr_ptr = Message_get_property_ptr_ptr; + h->clone_obj = Message_clone_obj; WellKnownTypes_ModuleInit(); /* From wkt.inc. */ } diff --git a/php/ext/google/protobuf/message.h b/php/ext/google/protobuf/message.h index 0e6fb5a4fc..5b49e0db84 100644 --- a/php/ext/google/protobuf/message.h +++ b/php/ext/google/protobuf/message.h @@ -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, zval *arena); -bool ValueEq(upb_msgval val1, upb_msgval val2, upb_fieldtype_t type, - const upb_msgdef *m); +bool ValueEq(upb_msgval val1, upb_msgval val2, TypeInfo type); #endif // PHP_PROTOBUF_MESSAGE_H_ diff --git a/php/ext/google/protobuf/php-upb.c b/php/ext/google/protobuf/php-upb.c index 738386890b..c56a567ca3 100644 --- a/php/ext/google/protobuf/php-upb.c +++ b/php/ext/google/protobuf/php-upb.c @@ -23,12 +23,10 @@ * This file is private and must not be included by users! */ -#if !(__STDC_VERSION__ >= 199901L || __cplusplus >= 201103L) -#error upb requires C99 or C++11 -#endif - -#if (defined(_MSC_VER) && _MSC_VER < 1900) -#error upb requires MSVC >= 2015. +#if !((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + (defined(__cplusplus) && __cplusplus >= 201103L) || \ + (defined(_MSC_VER) && _MSC_VER >= 1900)) +#error upb requires C99 or C++11 or MSVC >= 2015. #endif #include @@ -84,14 +82,17 @@ #define UPB_FORCEINLINE __inline__ __attribute__((always_inline)) #define UPB_NOINLINE __attribute__((noinline)) #define UPB_NORETURN __attribute__((__noreturn__)) +#define UPB_PRINTF(str, first_vararg) __attribute__((format (printf, str, first_vararg))) #elif defined(_MSC_VER) #define UPB_NOINLINE #define UPB_FORCEINLINE #define UPB_NORETURN __declspec(noreturn) +#define UPB_PRINTF(str, first_vararg) #else /* !defined(__GNUC__) */ #define UPB_FORCEINLINE #define UPB_NOINLINE #define UPB_NORETURN +#define UPB_PRINTF(str, first_vararg) #endif #define UPB_MAX(x, y) ((x) > (y) ? (x) : (y)) @@ -127,6 +128,52 @@ #define UPB_UNREACHABLE() do { assert(0); } while(0) #endif +/* UPB_SETJMP() / UPB_LONGJMP(): avoid setting/restoring signal mask. */ +#ifdef __APPLE__ +#define UPB_SETJMP(buf) _setjmp(buf) +#define UPB_LONGJMP(buf, val) _longjmp(buf, val) +#else +#define UPB_SETJMP(buf) setjmp(buf) +#define UPB_LONGJMP(buf, val) longjmp(buf, val) +#endif + +/* Configure whether fasttable is switched on or not. *************************/ + +#if defined(__x86_64__) && defined(__GNUC__) +#define UPB_FASTTABLE_SUPPORTED 1 +#else +#define UPB_FASTTABLE_SUPPORTED 0 +#endif + +/* define UPB_ENABLE_FASTTABLE to force fast table support. + * This is useful when we want to ensure we are really getting fasttable, + * for example for testing or benchmarking. */ +#if defined(UPB_ENABLE_FASTTABLE) +#if !UPB_FASTTABLE_SUPPORTED +#error fasttable is x86-64 + Clang/GCC only +#endif +#define UPB_FASTTABLE 1 +/* Define UPB_TRY_ENABLE_FASTTABLE to use fasttable if possible. + * This is useful for releasing code that might be used on multiple platforms, + * for example the PHP or Ruby C extensions. */ +#elif defined(UPB_TRY_ENABLE_FASTTABLE) +#define UPB_FASTTABLE UPB_FASTTABLE_SUPPORTED +#else +#define UPB_FASTTABLE 0 +#endif + +/* UPB_FASTTABLE_INIT() allows protos compiled for fasttable to gracefully + * degrade to non-fasttable if we are using UPB_TRY_ENABLE_FASTTABLE. */ +#if !UPB_FASTTABLE && defined(UPB_TRY_ENABLE_FASTTABLE) +#define UPB_FASTTABLE_INIT(...) +#else +#define UPB_FASTTABLE_INIT(...) __VA_ARGS__ +#endif + +#undef UPB_FASTTABLE_SUPPORTED + +/* ASAN poisoning (for arena) *************************************************/ + #if defined(__SANITIZE_ADDRESS__) #define UPB_ASAN 1 #ifdef __cplusplus @@ -283,19 +330,6 @@ static const int8_t delim_ops[37] = { OP_VARPCK_LG2(3), /* REPEATED SINT64 */ }; -/* Data pertaining to the parse. */ -typedef struct { - const char *end; /* Can read up to 16 bytes slop beyond this. */ - const char *limit_ptr; /* = end + UPB_MIN(limit, 0) */ - int limit; /* Submessage limit relative to end. */ - int depth; - uint32_t end_group; /* Set to field number of END_GROUP tag, if any. */ - bool alias; - char patch[32]; - upb_arena arena; - jmp_buf err; -} upb_decstate; - typedef union { bool bool_val; uint32_t uint32_val; @@ -306,40 +340,41 @@ typedef union { static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg, const upb_msglayout *layout); -UPB_NORETURN static void decode_err(upb_decstate *d) { longjmp(d->err, 1); } - -void decode_verifyutf8(upb_decstate *d, const char *buf, int len) { - static const uint8_t utf8_offset[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, - }; +UPB_NORETURN static void decode_err(upb_decstate *d) { UPB_LONGJMP(d->err, 1); } - int i, j; - uint8_t offset; +// We don't want to mark this NORETURN, see comment in .h. +// Unfortunately this code to suppress the warning doesn't appear to be working. +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunknown-warning-option" +#pragma clang diagnostic ignored "-Wsuggest-attribute" +#endif - i = 0; - while (i < len) { - offset = utf8_offset[(uint8_t)buf[i]]; - if (offset == 0 || i + offset > len) { - decode_err(d); - } - for (j = i + 1; j < i + offset; j++) { - if ((buf[j] & 0xc0) != 0x80) { - decode_err(d); - } - } - i += offset; - } - if (i != len) decode_err(d); +const char *fastdecode_err(upb_decstate *d) { + longjmp(d->err, 1); + return NULL; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +const uint8_t upb_utf8_offsets[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static void decode_verifyutf8(upb_decstate *d, const char *buf, int len) { + if (!decode_verifyutf8_inl(buf, len)) decode_err(d); } static bool decode_reserve(upb_decstate *d, upb_array *arr, size_t elem) { @@ -388,13 +423,20 @@ static const char *decode_varint64(upb_decstate *d, const char *ptr, } UPB_FORCEINLINE -static const char *decode_varint32(upb_decstate *d, const char *ptr, +static const char *decode_tag(upb_decstate *d, const char *ptr, uint32_t *val) { - uint64_t u64; - ptr = decode_varint64(d, ptr, &u64); - if (u64 > UINT32_MAX) decode_err(d); - *val = (uint32_t)u64; - return ptr; + uint64_t byte = (uint8_t)*ptr; + if (UPB_LIKELY((byte & 0x80) == 0)) { + *val = byte; + return ptr + 1; + } else { + const char *start = ptr; + decode_vret res = decode_longvarint64(ptr, byte); + ptr = res.ptr; + *val = res.val; + if (!ptr || *val > UINT32_MAX || ptr - start > 5) decode_err(d); + return ptr; + } } static void decode_munge(int type, wireval *val) { @@ -444,55 +486,14 @@ static upb_msg *decode_newsubmsg(upb_decstate *d, const upb_msglayout *layout, return _upb_msg_new_inl(subl, &d->arena); } -static int decode_pushlimit(upb_decstate *d, const char *ptr, int size) { - int limit = size + (int)(ptr - d->end); - int delta = d->limit - limit; - d->limit = limit; - d->limit_ptr = d->end + UPB_MIN(0, limit); - return delta; -} - -static void decode_poplimit(upb_decstate *d, int saved_delta) { - d->limit += saved_delta; - d->limit_ptr = d->end + UPB_MIN(0, d->limit); -} - -typedef struct { - bool ok; - const char *ptr; -} decode_doneret; - UPB_NOINLINE -static const char *decode_isdonefallback(upb_decstate *d, const char *ptr, - int overrun) { - if (overrun < d->limit) { - /* Need to copy remaining data into patch buffer. */ - UPB_ASSERT(overrun < 16); - memset(d->patch + 16, 0, 16); - memcpy(d->patch, d->end, 16); - ptr = &d->patch[0] + overrun; - d->end = &d->patch[16]; - d->limit -= 16; - d->limit_ptr = d->end + d->limit; - d->alias = false; - UPB_ASSERT(ptr < d->limit_ptr); - return ptr; - } else { +const char *decode_isdonefallback(upb_decstate *d, const char *ptr, + int overrun) { + ptr = decode_isdonefallback_inl(d, ptr, overrun); + if (ptr == NULL) { decode_err(d); } -} - -UPB_FORCEINLINE -static bool decode_isdone(upb_decstate *d, const char **ptr) { - int overrun = *ptr - d->end; - if (UPB_LIKELY(*ptr < d->limit_ptr)) { - return false; - } else if (UPB_LIKELY(overrun == d->limit)) { - return true; - } else { - *ptr = decode_isdonefallback(d, *ptr, overrun); - return false; - } + return ptr; } static const char *decode_readstr(upb_decstate *d, const char *ptr, int size, @@ -509,30 +510,38 @@ static const char *decode_readstr(upb_decstate *d, const char *ptr, int size, return ptr + size; } +UPB_FORCEINLINE static const char *decode_tosubmsg(upb_decstate *d, const char *ptr, upb_msg *submsg, const upb_msglayout *layout, const upb_msglayout_field *field, int size) { const upb_msglayout *subl = layout->submsgs[field->submsg_index]; int saved_delta = decode_pushlimit(d, ptr, size); if (--d->depth < 0) decode_err(d); - ptr = decode_msg(d, ptr, submsg, subl); - decode_poplimit(d, saved_delta); - if (d->end_group != 0) decode_err(d); + if (!decode_isdone(d, &ptr)) { + ptr = decode_msg(d, ptr, submsg, subl); + } + if (d->end_group != DECODE_NOGROUP) decode_err(d); + decode_poplimit(d, ptr, saved_delta); d->depth++; return ptr; } +UPB_FORCEINLINE static const char *decode_group(upb_decstate *d, const char *ptr, upb_msg *submsg, const upb_msglayout *subl, uint32_t number) { if (--d->depth < 0) decode_err(d); + if (decode_isdone(d, &ptr)) { + decode_err(d); + } ptr = decode_msg(d, ptr, submsg, subl); if (d->end_group != number) decode_err(d); - d->end_group = 0; + d->end_group = DECODE_NOGROUP; d->depth++; return ptr; } +UPB_FORCEINLINE static const char *decode_togroup(upb_decstate *d, const char *ptr, upb_msg *submsg, const upb_msglayout *layout, const upb_msglayout_field *field) { @@ -621,7 +630,7 @@ static const char *decode_toarray(upb_decstate *d, const char *ptr, memcpy(out, &elem, scale); out += scale; } - decode_poplimit(d, saved_limit); + decode_poplimit(d, ptr, saved_limit); return ptr; } default: @@ -720,9 +729,24 @@ static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg, return ptr; } +UPB_FORCEINLINE +static bool decode_tryfastdispatch(upb_decstate *d, const char **ptr, + upb_msg *msg, const upb_msglayout *layout) { +#if UPB_FASTTABLE + if (layout && layout->table_mask != (unsigned char)-1) { + uint16_t tag = fastdecode_loadtag(*ptr); + intptr_t table = decode_totable(layout); + *ptr = fastdecode_tagdispatch(d, *ptr, msg, table, 0, tag); + return true; + } +#endif + return false; +} + +UPB_NOINLINE static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg, const upb_msglayout *layout) { - while (!decode_isdone(d, &ptr)) { + while (true) { uint32_t tag; const upb_msglayout_field *field; int field_number; @@ -731,7 +755,8 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg, wireval val; int op; - ptr = decode_varint32(d, ptr, &tag); + UPB_ASSERT(ptr < d->limit_ptr); + ptr = decode_tag(d, ptr, &tag); field_number = tag >> 3; wire_type = tag & 7; @@ -759,13 +784,15 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg, break; case UPB_WIRE_TYPE_DELIMITED: { int ndx = field->descriptortype; + uint64_t size; if (_upb_isrepeated(field)) ndx += 18; - ptr = decode_varint32(d, ptr, &val.size); - if (val.size >= INT32_MAX || - ptr - d->end + (int32_t)val.size > d->limit) { + ptr = decode_varint64(d, ptr, &size); + if (size >= INT32_MAX || + ptr - d->end + (int32_t)size > d->limit) { decode_err(d); /* Length overflow. */ } op = delim_ops[ndx]; + val.size = size; break; } case UPB_WIRE_TYPE_START_GROUP: @@ -798,30 +825,54 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg, unknown: /* Skip unknown field. */ if (field_number == 0) decode_err(d); - if (wire_type == UPB_WIRE_TYPE_START_GROUP) { - ptr = decode_group(d, ptr, NULL, NULL, field_number); - } + if (wire_type == UPB_WIRE_TYPE_DELIMITED) ptr += val.size; if (msg) { - if (wire_type == UPB_WIRE_TYPE_DELIMITED) ptr += val.size; + if (wire_type == UPB_WIRE_TYPE_START_GROUP) { + d->unknown = field_start; + d->unknown_msg = msg; + ptr = decode_group(d, ptr, NULL, NULL, field_number); + d->unknown_msg = NULL; + field_start = d->unknown; + } if (!_upb_msg_addunknown(msg, field_start, ptr - field_start, &d->arena)) { decode_err(d); } + } else if (wire_type == UPB_WIRE_TYPE_START_GROUP) { + ptr = decode_group(d, ptr, NULL, NULL, field_number); } } + + if (decode_isdone(d, &ptr)) return ptr; + if (decode_tryfastdispatch(d, &ptr, msg, layout)) return ptr; } +} - return ptr; +const char *fastdecode_generic(struct upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, uint64_t hasbits, + uint64_t data) { + (void)data; + *(uint32_t*)msg |= hasbits; + return decode_msg(d, ptr, msg, decode_totablep(table)); +} + +static bool decode_top(struct upb_decstate *d, const char *buf, void *msg, + const upb_msglayout *l) { + if (!decode_tryfastdispatch(d, &buf, msg, l)) { + decode_msg(d, buf, msg, l); + } + return d->end_group == DECODE_NOGROUP; } -bool upb_decode(const char *buf, size_t size, void *msg, const upb_msglayout *l, - upb_arena *arena) { +bool _upb_decode(const char *buf, size_t size, void *msg, + const upb_msglayout *l, upb_arena *arena, int options) { bool ok; upb_decstate state; + unsigned depth = (unsigned)options >> 16; if (size == 0) { return true; - } else if (size < 16) { + } else if (size <= 16) { memset(&state.patch, 0, 32); memcpy(&state.patch, buf, size); buf = state.patch; @@ -831,25 +882,27 @@ bool upb_decode(const char *buf, size_t size, void *msg, const upb_msglayout *l, } else { state.end = buf + size - 16; state.limit = 16; - state.alias = true; + state.alias = options & UPB_DECODE_ALIAS; } state.limit_ptr = state.end; - state.depth = 64; - state.end_group = 0; + state.unknown_msg = NULL; + state.depth = depth ? depth : 64; + state.end_group = DECODE_NOGROUP; state.arena.head = arena->head; state.arena.last_size = arena->last_size; + state.arena.cleanups = arena->cleanups; state.arena.parent = arena; - if (UPB_UNLIKELY(setjmp(state.err))) { + if (UPB_UNLIKELY(UPB_SETJMP(state.err))) { ok = false; } else { - decode_msg(&state, buf, msg, l); - ok = state.end_group == 0; + ok = decode_top(&state, buf, msg, l); } arena->head.ptr = state.arena.head.ptr; arena->head.end = state.arena.head.end; + arena->cleanups = state.arena.cleanups; return ok; } @@ -865,6 +918,7 @@ bool upb_decode(const char *buf, size_t size, void *msg, const upb_msglayout *l, #include +/* Must be last. */ #define UPB_PB_VARINT_MAX_LEN 10 @@ -887,6 +941,9 @@ typedef struct { jmp_buf err; upb_alloc *alloc; char *buf, *ptr, *limit; + int options; + int depth; + _upb_mapsorter sorter; } upb_encstate; static size_t upb_roundup_pow2(size_t bytes) { @@ -897,7 +954,9 @@ static size_t upb_roundup_pow2(size_t bytes) { return ret; } -UPB_NORETURN static void encode_err(upb_encstate *e) { longjmp(e->err, 1); } +UPB_NORETURN static void encode_err(upb_encstate *e) { + UPB_LONGJMP(e->err, 1); +} UPB_NOINLINE static void encode_growbuffer(upb_encstate *e, size_t bytes) { @@ -984,7 +1043,8 @@ static void encode_float(upb_encstate *e, float d) { encode_fixed32(e, u32); } -static void encode_tag(upb_encstate *e, int field_number, int wire_type) { +static void encode_tag(upb_encstate *e, uint32_t field_number, + uint8_t wire_type) { encode_varint(e, (field_number << 3) | wire_type); } @@ -1068,9 +1128,11 @@ static void encode_scalar(upb_encstate *e, const void *_field_mem, if (submsg == NULL) { return; } + if (--e->depth == 0) encode_err(e); encode_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP); encode_message(e, submsg, subm, &size); wire_type = UPB_WIRE_TYPE_START_GROUP; + e->depth++; break; } case UPB_DESCRIPTOR_TYPE_MESSAGE: { @@ -1080,9 +1142,11 @@ static void encode_scalar(upb_encstate *e, const void *_field_mem, if (submsg == NULL) { return; } + if (--e->depth == 0) encode_err(e); encode_message(e, submsg, subm, &size); encode_varint(e, size); wire_type = UPB_WIRE_TYPE_DELIMITED; + e->depth++; break; } default: @@ -1163,6 +1227,7 @@ static void encode_array(upb_encstate *e, const char *field_mem, const void *const*start = _upb_array_constptr(arr); const void *const*ptr = start + arr->len; const upb_msglayout *subm = m->submsgs[f->submsg_index]; + if (--e->depth == 0) encode_err(e); do { size_t size; ptr--; @@ -1170,12 +1235,14 @@ static void encode_array(upb_encstate *e, const char *field_mem, encode_message(e, *ptr, subm, &size); encode_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP); } while (ptr != start); + e->depth++; return; } case UPB_DESCRIPTOR_TYPE_MESSAGE: { const void *const*start = _upb_array_constptr(arr); const void *const*ptr = start + arr->len; const upb_msglayout *subm = m->submsgs[f->submsg_index]; + if (--e->depth == 0) encode_err(e); do { size_t size; ptr--; @@ -1183,6 +1250,7 @@ static void encode_array(upb_encstate *e, const char *field_mem, encode_varint(e, size); encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); } while (ptr != start); + e->depth++; return; } } @@ -1194,31 +1262,48 @@ static void encode_array(upb_encstate *e, const char *field_mem, } } +static void encode_mapentry(upb_encstate *e, uint32_t number, + const upb_msglayout *layout, + const upb_map_entry *ent) { + const upb_msglayout_field *key_field = &layout->fields[0]; + const upb_msglayout_field *val_field = &layout->fields[1]; + size_t pre_len = e->limit - e->ptr; + size_t size; + encode_scalar(e, &ent->v, layout, val_field, false); + encode_scalar(e, &ent->k, layout, key_field, false); + size = (e->limit - e->ptr) - pre_len; + encode_varint(e, size); + encode_tag(e, number, UPB_WIRE_TYPE_DELIMITED); +} + static void encode_map(upb_encstate *e, const char *field_mem, const upb_msglayout *m, const upb_msglayout_field *f) { const upb_map *map = *(const upb_map**)field_mem; - const upb_msglayout *entry = m->submsgs[f->submsg_index]; - const upb_msglayout_field *key_field = &entry->fields[0]; - const upb_msglayout_field *val_field = &entry->fields[1]; - upb_strtable_iter i; - if (map == NULL) { - return; - } + const upb_msglayout *layout = m->submsgs[f->submsg_index]; + UPB_ASSERT(layout->field_count == 2); - upb_strtable_begin(&i, &map->table); - for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { - size_t pre_len = e->limit - e->ptr; - size_t size; - upb_strview key = upb_strtable_iter_key(&i); - const upb_value val = upb_strtable_iter_value(&i); + if (map == NULL) return; + + if (e->options & UPB_ENCODE_DETERMINISTIC) { + _upb_sortedmap sorted; + _upb_mapsorter_pushmap(&e->sorter, layout->fields[0].descriptortype, map, + &sorted); upb_map_entry ent; - _upb_map_fromkey(key, &ent.k, map->key_size); - _upb_map_fromvalue(val, &ent.v, map->val_size); - encode_scalar(e, &ent.v, entry, val_field, false); - encode_scalar(e, &ent.k, entry, key_field, false); - size = (e->limit - e->ptr) - pre_len; - encode_varint(e, size); - encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); + while (_upb_sortedmap_next(&e->sorter, map, &sorted, &ent)) { + encode_mapentry(e, f->number, layout, &ent); + } + _upb_mapsorter_popmap(&e->sorter, &sorted); + } else { + upb_strtable_iter i; + upb_strtable_begin(&i, &map->table); + for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { + upb_strview key = upb_strtable_iter_key(&i); + const upb_value val = upb_strtable_iter_value(&i); + upb_map_entry ent; + _upb_map_fromkey(key, &ent.k, map->key_size); + _upb_map_fromvalue(val, &ent.v, map->val_size); + encode_mapentry(e, f->number, layout, &ent); + } } } @@ -1242,15 +1327,16 @@ static void encode_scalarfield(upb_encstate *e, const char *msg, static void encode_message(upb_encstate *e, const char *msg, const upb_msglayout *m, size_t *size) { size_t pre_len = e->limit - e->ptr; - const char *unknown; - size_t unknown_size; const upb_msglayout_field *f = &m->fields[m->field_count]; const upb_msglayout_field *first = &m->fields[0]; - unknown = upb_msg_getunknown(msg, &unknown_size); + if ((e->options & UPB_ENCODE_SKIPUNKNOWN) == 0) { + size_t unknown_size; + const char *unknown = upb_msg_getunknown(msg, &unknown_size); - if (unknown) { - encode_bytes(e, unknown, unknown_size); + if (unknown) { + encode_bytes(e, unknown, unknown_size); + } } while (f != first) { @@ -1267,30 +1353,37 @@ static void encode_message(upb_encstate *e, const char *msg, *size = (e->limit - e->ptr) - pre_len; } -char *upb_encode(const void *msg, const upb_msglayout *m, upb_arena *arena, - size_t *size) { +char *upb_encode_ex(const void *msg, const upb_msglayout *l, int options, + upb_arena *arena, size_t *size) { upb_encstate e; + unsigned depth = (unsigned)options >> 16; + e.alloc = upb_arena_alloc(arena); e.buf = NULL; e.limit = NULL; e.ptr = NULL; + e.depth = depth ? depth : 64; + e.options = options; + _upb_mapsorter_init(&e.sorter); + char *ret = NULL; - if (setjmp(e.err)) { + if (UPB_SETJMP(e.err)) { *size = 0; - return NULL; - } - - encode_message(&e, msg, m, size); - - *size = e.limit - e.ptr; - - if (*size == 0) { - static char ch; - return &ch; + ret = NULL; } else { - UPB_ASSERT(e.ptr); - return e.ptr; + encode_message(&e, msg, l, size); + *size = e.limit - e.ptr; + if (*size == 0) { + static char ch; + ret = &ch; + } else { + UPB_ASSERT(e.ptr); + ret = e.ptr; + } } + + _upb_mapsorter_destroy(&e.sorter); + return ret; } @@ -1430,6 +1523,121 @@ upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size) { return map; } + +static void _upb_mapsorter_getkeys(const void *_a, const void *_b, void *a_key, + void *b_key, size_t size) { + const upb_tabent *const*a = _a; + const upb_tabent *const*b = _b; + upb_strview a_tabkey = upb_tabstrview((*a)->key); + upb_strview b_tabkey = upb_tabstrview((*b)->key); + _upb_map_fromkey(a_tabkey, a_key, size); + _upb_map_fromkey(b_tabkey, b_key, size); +} + +static int _upb_mapsorter_cmpi64(const void *_a, const void *_b) { + int64_t a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 8); + return a - b; +} + +static int _upb_mapsorter_cmpu64(const void *_a, const void *_b) { + uint64_t a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 8); + return a - b; +} + +static int _upb_mapsorter_cmpi32(const void *_a, const void *_b) { + int32_t a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 4); + return a - b; +} + +static int _upb_mapsorter_cmpu32(const void *_a, const void *_b) { + uint32_t a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 4); + return a - b; +} + +static int _upb_mapsorter_cmpbool(const void *_a, const void *_b) { + bool a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 1); + return a - b; +} + +static int _upb_mapsorter_cmpstr(const void *_a, const void *_b) { + upb_strview a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, UPB_MAPTYPE_STRING); + size_t common_size = UPB_MIN(a.size, b.size); + int cmp = memcmp(a.data, b.data, common_size); + if (cmp) return cmp; + return a.size - b.size; +} + +bool _upb_mapsorter_pushmap(_upb_mapsorter *s, upb_descriptortype_t key_type, + const upb_map *map, _upb_sortedmap *sorted) { + int map_size = _upb_map_size(map); + sorted->start = s->size; + sorted->pos = sorted->start; + sorted->end = sorted->start + map_size; + + /* Grow s->entries if necessary. */ + if (sorted->end > s->cap) { + s->cap = _upb_lg2ceilsize(sorted->end); + s->entries = realloc(s->entries, s->cap * sizeof(*s->entries)); + if (!s->entries) return false; + } + + s->size = sorted->end; + + /* Copy non-empty entries from the table to s->entries. */ + upb_tabent const**dst = &s->entries[sorted->start]; + const upb_tabent *src = map->table.t.entries; + const upb_tabent *end = src + upb_table_size(&map->table.t); + for (; src < end; src++) { + if (!upb_tabent_isempty(src)) { + *dst = src; + dst++; + } + } + UPB_ASSERT(dst == &s->entries[sorted->end]); + + /* Sort entries according to the key type. */ + + int (*compar)(const void *, const void *); + + switch (key_type) { + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_SFIXED64: + case UPB_DESCRIPTOR_TYPE_SINT64: + compar = _upb_mapsorter_cmpi64; + break; + case UPB_DESCRIPTOR_TYPE_UINT64: + case UPB_DESCRIPTOR_TYPE_FIXED64: + compar = _upb_mapsorter_cmpu64; + break; + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_SINT32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + case UPB_DESCRIPTOR_TYPE_ENUM: + compar = _upb_mapsorter_cmpi32; + break; + case UPB_DESCRIPTOR_TYPE_UINT32: + case UPB_DESCRIPTOR_TYPE_FIXED32: + compar = _upb_mapsorter_cmpu32; + break; + case UPB_DESCRIPTOR_TYPE_BOOL: + compar = _upb_mapsorter_cmpbool; + break; + case UPB_DESCRIPTOR_TYPE_STRING: + compar = _upb_mapsorter_cmpstr; + break; + default: + UPB_UNREACHABLE(); + } + + qsort(&s->entries[sorted->start], map_size, sizeof(*s->entries), compar); + return true; +} /* ** upb_table Implementation ** @@ -1614,7 +1822,7 @@ static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey, /* Head of collider's chain. */ upb_tabent *chain = getentry_mutable(t, hashfunc(mainpos_e->key)); if (chain == mainpos_e) { - /* Existing ent is in its main posisiton (it has the same hash as us, and + /* Existing ent is in its main position (it has the same hash as us, and * is the head of our chain). Insert to new ent and append to this chain. */ new_e->next = mainpos_e->next; mainpos_e->next = new_e; @@ -2208,206 +2416,1242 @@ static void *upb_global_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize, free(ptr); return NULL; } else { - return realloc(ptr, size); + return realloc(ptr, size); + } +} + +upb_alloc upb_alloc_global = {&upb_global_allocfunc}; + +/* upb_arena ******************************************************************/ + +/* Be conservative and choose 16 in case anyone is using SSE. */ + +struct mem_block { + struct mem_block *next; + uint32_t size; + uint32_t cleanups; + /* Data follows. */ +}; + +typedef struct cleanup_ent { + upb_cleanup_func *cleanup; + void *ud; +} cleanup_ent; + +static const size_t memblock_reserve = UPB_ALIGN_UP(sizeof(mem_block), 16); + +static upb_arena *arena_findroot(upb_arena *a) { + /* Path splitting keeps time complexity down, see: + * https://en.wikipedia.org/wiki/Disjoint-set_data_structure */ + while (a->parent != a) { + upb_arena *next = a->parent; + a->parent = next->parent; + a = next; + } + return a; +} + +static void upb_arena_addblock(upb_arena *a, upb_arena *root, void *ptr, + size_t size) { + mem_block *block = ptr; + + /* The block is for arena |a|, but should appear in the freelist of |root|. */ + block->next = root->freelist; + block->size = (uint32_t)size; + block->cleanups = 0; + root->freelist = block; + a->last_size = block->size; + if (!root->freelist_tail) root->freelist_tail = block; + + a->head.ptr = UPB_PTR_AT(block, memblock_reserve, char); + a->head.end = UPB_PTR_AT(block, size, char); + a->cleanups = &block->cleanups; + + UPB_POISON_MEMORY_REGION(a->head.ptr, a->head.end - a->head.ptr); +} + +static bool upb_arena_allocblock(upb_arena *a, size_t size) { + upb_arena *root = arena_findroot(a); + size_t block_size = UPB_MAX(size, a->last_size * 2) + memblock_reserve; + mem_block *block = upb_malloc(root->block_alloc, block_size); + + if (!block) return false; + upb_arena_addblock(a, root, block, block_size); + return true; +} + +void *_upb_arena_slowmalloc(upb_arena *a, size_t size) { + if (!upb_arena_allocblock(a, size)) return NULL; /* Out of memory. */ + UPB_ASSERT(_upb_arenahas(a) >= size); + return upb_arena_malloc(a, size); +} + +static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize, + size_t size) { + upb_arena *a = (upb_arena*)alloc; /* upb_alloc is initial member. */ + return upb_arena_realloc(a, ptr, oldsize, size); +} + +/* Public Arena API ***********************************************************/ + +upb_arena *arena_initslow(void *mem, size_t n, upb_alloc *alloc) { + const size_t first_block_overhead = sizeof(upb_arena) + memblock_reserve; + upb_arena *a; + + /* We need to malloc the initial block. */ + n = first_block_overhead + 256; + if (!alloc || !(mem = upb_malloc(alloc, n))) { + return NULL; + } + + a = UPB_PTR_AT(mem, n - sizeof(*a), upb_arena); + n -= sizeof(*a); + + a->head.alloc.func = &upb_arena_doalloc; + a->block_alloc = alloc; + a->parent = a; + a->refcount = 1; + a->freelist = NULL; + a->freelist_tail = NULL; + + upb_arena_addblock(a, a, mem, n); + + return a; +} + +upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc) { + upb_arena *a; + + /* Round block size down to alignof(*a) since we will allocate the arena + * itself at the end. */ + n = UPB_ALIGN_DOWN(n, UPB_ALIGN_OF(upb_arena)); + + if (UPB_UNLIKELY(n < sizeof(upb_arena))) { + return arena_initslow(mem, n, alloc); + } + + a = UPB_PTR_AT(mem, n - sizeof(*a), upb_arena); + + a->head.alloc.func = &upb_arena_doalloc; + a->block_alloc = alloc; + a->parent = a; + a->refcount = 1; + a->last_size = UPB_MAX(128, n); + a->head.ptr = mem; + a->head.end = UPB_PTR_AT(mem, n - sizeof(*a), char); + a->freelist = NULL; + a->cleanups = NULL; + + return a; +} + +static void arena_dofree(upb_arena *a) { + mem_block *block = a->freelist; + UPB_ASSERT(a->parent == a); + UPB_ASSERT(a->refcount == 0); + + while (block) { + /* Load first since we are deleting block. */ + mem_block *next = block->next; + + if (block->cleanups > 0) { + cleanup_ent *end = UPB_PTR_AT(block, block->size, void); + cleanup_ent *ptr = end - block->cleanups; + + for (; ptr < end; ptr++) { + ptr->cleanup(ptr->ud); + } + } + + upb_free(a->block_alloc, block); + block = next; + } +} + +void upb_arena_free(upb_arena *a) { + a = arena_findroot(a); + if (--a->refcount == 0) arena_dofree(a); +} + +bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func) { + cleanup_ent *ent; + + if (!a->cleanups || _upb_arenahas(a) < sizeof(cleanup_ent)) { + if (!upb_arena_allocblock(a, 128)) return false; /* Out of memory. */ + UPB_ASSERT(_upb_arenahas(a) >= sizeof(cleanup_ent)); + } + + a->head.end -= sizeof(cleanup_ent); + ent = (cleanup_ent*)a->head.end; + (*a->cleanups)++; + UPB_UNPOISON_MEMORY_REGION(ent, sizeof(cleanup_ent)); + + ent->cleanup = func; + ent->ud = ud; + + return true; +} + +void upb_arena_fuse(upb_arena *a1, upb_arena *a2) { + upb_arena *r1 = arena_findroot(a1); + upb_arena *r2 = arena_findroot(a2); + + if (r1 == r2) return; /* Already fused. */ + + /* We want to join the smaller tree to the larger tree. + * So swap first if they are backwards. */ + if (r1->refcount < r2->refcount) { + upb_arena *tmp = r1; + r1 = r2; + r2 = tmp; + } + + /* r1 takes over r2's freelist and refcount. */ + r1->refcount += r2->refcount; + if (r2->freelist_tail) { + UPB_ASSERT(r2->freelist_tail->next == NULL); + r2->freelist_tail->next = r1->freelist; + r1->freelist = r2->freelist; + } + r2->parent = r1; +} +// Fast decoder: ~3x the speed of decode.c, but x86-64 specific. +// Also the table size grows by 2x. +// +// Could potentially be ported to ARM64 or other 64-bit archs that pass at +// least six arguments in registers. +// +// The overall design is to create specialized functions for every possible +// field type (eg. oneof boolean field with a 1 byte tag) and then dispatch +// to the specialized function as quickly as possible. + + + +/* Must be last. */ + +#if UPB_FASTTABLE + +// The standard set of arguments passed to each parsing function. +// Thanks to x86-64 calling conventions, these will stay in registers. +#define UPB_PARSE_PARAMS \ + upb_decstate *d, const char *ptr, upb_msg *msg, intptr_t table, \ + uint64_t hasbits, uint64_t data + +#define UPB_PARSE_ARGS d, ptr, msg, table, hasbits, data + +#define RETURN_GENERIC(m) \ + /* fprintf(stderr, m); */ \ + return fastdecode_generic(d, ptr, msg, table, hasbits, 0); + +typedef enum { + CARD_s = 0, /* Singular (optional, non-repeated) */ + CARD_o = 1, /* Oneof */ + CARD_r = 2, /* Repeated */ + CARD_p = 3 /* Packed Repeated */ +} upb_card; + +UPB_NOINLINE +static const char *fastdecode_isdonefallback(upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, + uint64_t hasbits, int overrun) { + ptr = decode_isdonefallback_inl(d, ptr, overrun); + if (ptr == NULL) { + return fastdecode_err(d); + } + uint16_t tag = fastdecode_loadtag(ptr); + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, tag); +} + +UPB_FORCEINLINE +static const char *fastdecode_dispatch(upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, + uint64_t hasbits) { + if (UPB_UNLIKELY(ptr >= d->limit_ptr)) { + int overrun = ptr - d->end; + if (UPB_LIKELY(overrun == d->limit)) { + // Parse is finished. + *(uint32_t*)msg |= hasbits; // Sync hasbits. + return ptr; + } else { + return fastdecode_isdonefallback(d, ptr, msg, table, hasbits, overrun); + } + } + + // Read two bytes of tag data (for a one-byte tag, the high byte is junk). + uint16_t tag = fastdecode_loadtag(ptr); + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, tag); +} + +UPB_FORCEINLINE +static bool fastdecode_checktag(uint64_t data, int tagbytes) { + if (tagbytes == 1) { + return (data & 0xff) == 0; + } else { + return (data & 0xffff) == 0; + } +} + +UPB_FORCEINLINE +static const char *fastdecode_longsize(const char *ptr, int *size) { + int i; + UPB_ASSERT(*size & 0x80); + *size &= 0xff; + for (i = 0; i < 3; i++) { + ptr++; + size_t byte = (uint8_t)ptr[-1]; + *size += (byte - 1) << (7 + 7 * i); + if (UPB_LIKELY((byte & 0x80) == 0)) return ptr; + } + ptr++; + size_t byte = (uint8_t)ptr[-1]; + // len is limited by 2gb not 4gb, hence 8 and not 16 as normally expected + // for a 32 bit varint. + if (UPB_UNLIKELY(byte >= 8)) return NULL; + *size += (byte - 1) << 28; + return ptr; +} + +UPB_FORCEINLINE +static bool fastdecode_boundscheck(const char *ptr, size_t len, + const char *end) { + uintptr_t uptr = (uintptr_t)ptr; + uintptr_t uend = (uintptr_t)end + 16; + uintptr_t res = uptr + len; + return res < uptr || res > uend; +} + +UPB_FORCEINLINE +static bool fastdecode_boundscheck2(const char *ptr, size_t len, + const char *end) { + // This is one extra branch compared to the more normal: + // return (size_t)(end - ptr) < size; + // However it is one less computation if we are just about to use "ptr + len": + // https://godbolt.org/z/35YGPz + // In microbenchmarks this shows an overall 4% improvement. + uintptr_t uptr = (uintptr_t)ptr; + uintptr_t uend = (uintptr_t)end; + uintptr_t res = uptr + len; + return res < uptr || res > uend; +} + +typedef const char *fastdecode_delimfunc(upb_decstate *d, const char *ptr, + void *ctx); + +UPB_FORCEINLINE +static const char *fastdecode_delimited(upb_decstate *d, const char *ptr, + fastdecode_delimfunc *func, void *ctx) { + ptr++; + int len = (int8_t)ptr[-1]; + if (fastdecode_boundscheck2(ptr, len, d->limit_ptr)) { + // Slow case: Sub-message is >=128 bytes and/or exceeds the current buffer. + // If it exceeds the buffer limit, limit/limit_ptr will change during + // sub-message parsing, so we need to preserve delta, not limit. + if (UPB_UNLIKELY(len & 0x80)) { + // Size varint >1 byte (length >= 128). + ptr = fastdecode_longsize(ptr, &len); + if (!ptr) { + // Corrupt wire format: size exceeded INT_MAX. + return NULL; + } + } + if (ptr - d->end + (int)len > d->limit) { + // Corrupt wire format: invalid limit. + return NULL; + } + int delta = decode_pushlimit(d, ptr, len); + ptr = func(d, ptr, ctx); + decode_poplimit(d, ptr, delta); + } else { + // Fast case: Sub-message is <128 bytes and fits in the current buffer. + // This means we can preserve limit/limit_ptr verbatim. + const char *saved_limit_ptr = d->limit_ptr; + int saved_limit = d->limit; + d->limit_ptr = ptr + len; + d->limit = d->limit_ptr - d->end; + UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit)); + ptr = func(d, ptr, ctx); + d->limit_ptr = saved_limit_ptr; + d->limit = saved_limit; + UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit)); + } + return ptr; +} + +/* singular, oneof, repeated field handling ***********************************/ + +typedef struct { + upb_array *arr; + void *end; +} fastdecode_arr; + +typedef enum { + FD_NEXT_ATLIMIT, + FD_NEXT_SAMEFIELD, + FD_NEXT_OTHERFIELD +} fastdecode_next; + +typedef struct { + void *dst; + fastdecode_next next; + uint32_t tag; +} fastdecode_nextret; + +UPB_FORCEINLINE +static void *fastdecode_resizearr(upb_decstate *d, void *dst, + fastdecode_arr *farr, int valbytes) { + if (UPB_UNLIKELY(dst == farr->end)) { + size_t old_size = farr->arr->size; + size_t old_bytes = old_size * valbytes; + size_t new_size = old_size * 2; + size_t new_bytes = new_size * valbytes; + char *old_ptr = _upb_array_ptr(farr->arr); + char *new_ptr = upb_arena_realloc(&d->arena, old_ptr, old_bytes, new_bytes); + uint8_t elem_size_lg2 = __builtin_ctz(valbytes); + farr->arr->size = new_size; + farr->arr->data = _upb_array_tagptr(new_ptr, elem_size_lg2); + dst = (void*)(new_ptr + (old_size * valbytes)); + farr->end = (void*)(new_ptr + (new_size * valbytes)); + } + return dst; +} + +UPB_FORCEINLINE +static bool fastdecode_tagmatch(uint32_t tag, uint64_t data, int tagbytes) { + if (tagbytes == 1) { + return (uint8_t)tag == (uint8_t)data; + } else { + return (uint16_t)tag == (uint16_t)data; + } +} + +UPB_FORCEINLINE +static void fastdecode_commitarr(void *dst, fastdecode_arr *farr, + int valbytes) { + farr->arr->len = + (size_t)((char *)dst - (char *)_upb_array_ptr(farr->arr)) / valbytes; +} + +UPB_FORCEINLINE +static fastdecode_nextret fastdecode_nextrepeated(upb_decstate *d, void *dst, + const char **ptr, + fastdecode_arr *farr, + uint64_t data, int tagbytes, + int valbytes) { + fastdecode_nextret ret; + dst = (char *)dst + valbytes; + + if (UPB_LIKELY(!decode_isdone(d, ptr))) { + ret.tag = fastdecode_loadtag(*ptr); + if (fastdecode_tagmatch(ret.tag, data, tagbytes)) { + ret.next = FD_NEXT_SAMEFIELD; + } else { + fastdecode_commitarr(dst, farr, valbytes); + ret.next = FD_NEXT_OTHERFIELD; + } + } else { + fastdecode_commitarr(dst, farr, valbytes); + ret.next = FD_NEXT_ATLIMIT; + } + + ret.dst = dst; + return ret; +} + +UPB_FORCEINLINE +static void *fastdecode_fieldmem(upb_msg *msg, uint64_t data) { + size_t ofs = data >> 48; + return (char *)msg + ofs; +} + +UPB_FORCEINLINE +static void *fastdecode_getfield(upb_decstate *d, const char *ptr, upb_msg *msg, + uint64_t *data, uint64_t *hasbits, + fastdecode_arr *farr, int valbytes, + upb_card card) { + switch (card) { + case CARD_s: { + uint8_t hasbit_index = *data >> 24; + // Set hasbit and return pointer to scalar field. + *hasbits |= 1ull << hasbit_index; + return fastdecode_fieldmem(msg, *data); + } + case CARD_o: { + uint16_t case_ofs = *data >> 32; + uint32_t *oneof_case = UPB_PTR_AT(msg, case_ofs, uint32_t); + uint8_t field_number = *data >> 24; + *oneof_case = field_number; + return fastdecode_fieldmem(msg, *data); + } + case CARD_r: { + // Get pointer to upb_array and allocate/expand if necessary. + uint8_t elem_size_lg2 = __builtin_ctz(valbytes); + upb_array **arr_p = fastdecode_fieldmem(msg, *data); + char *begin; + *(uint32_t*)msg |= *hasbits; + *hasbits = 0; + if (UPB_LIKELY(!*arr_p)) { + farr->arr = _upb_array_new(&d->arena, 8, elem_size_lg2); + *arr_p = farr->arr; + } else { + farr->arr = *arr_p; + } + begin = _upb_array_ptr(farr->arr); + farr->end = begin + (farr->arr->size * valbytes); + *data = fastdecode_loadtag(ptr); + return begin + (farr->arr->len * valbytes); + } + default: + UPB_UNREACHABLE(); + } +} + +UPB_FORCEINLINE +static bool fastdecode_flippacked(uint64_t *data, int tagbytes) { + *data ^= (0x2 ^ 0x0); // Patch data to match packed wiretype. + return fastdecode_checktag(*data, tagbytes); +} + +/* varint fields **************************************************************/ + +UPB_FORCEINLINE +static uint64_t fastdecode_munge(uint64_t val, int valbytes, bool zigzag) { + if (valbytes == 1) { + return val != 0; + } else if (zigzag) { + if (valbytes == 4) { + uint32_t n = val; + return (n >> 1) ^ -(int32_t)(n & 1); + } else if (valbytes == 8) { + return (val >> 1) ^ -(int64_t)(val & 1); + } + UPB_UNREACHABLE(); + } + return val; +} + +UPB_FORCEINLINE +static const char *fastdecode_varint64(const char *ptr, uint64_t *val) { + ptr++; + *val = (uint8_t)ptr[-1]; + if (UPB_UNLIKELY(*val & 0x80)) { + int i; + for (i = 0; i < 8; i++) { + ptr++; + uint64_t byte = (uint8_t)ptr[-1]; + *val += (byte - 1) << (7 + 7 * i); + if (UPB_LIKELY((byte & 0x80) == 0)) goto done; + } + ptr++; + uint64_t byte = (uint8_t)ptr[-1]; + if (byte > 1) { + return NULL; + } + *val += (byte - 1) << 63; + } +done: + UPB_ASSUME(ptr != NULL); + return ptr; +} + +UPB_FORCEINLINE +static const char *fastdecode_unpackedvarint(UPB_PARSE_PARAMS, int tagbytes, + int valbytes, upb_card card, + bool zigzag, + _upb_field_parser *packed) { + uint64_t val; + void *dst; + fastdecode_arr farr; + + if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { + if (card == CARD_r && fastdecode_flippacked(&data, tagbytes)) { + return packed(UPB_PARSE_ARGS); + } + RETURN_GENERIC("varint field tag mismatch\n"); + } + + dst = + fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes, card); + if (card == CARD_r) { + if (UPB_UNLIKELY(!dst)) { + RETURN_GENERIC("need array resize\n"); + } + } + +again: + if (card == CARD_r) { + dst = fastdecode_resizearr(d, dst, &farr, valbytes); + } + + ptr += tagbytes; + ptr = fastdecode_varint64(ptr, &val); + if (ptr == NULL) return fastdecode_err(d); + val = fastdecode_munge(val, valbytes, zigzag); + memcpy(dst, &val, valbytes); + + if (card == CARD_r) { + fastdecode_nextret ret = + fastdecode_nextrepeated(d, dst, &ptr, &farr, data, tagbytes, valbytes); + switch (ret.next) { + case FD_NEXT_SAMEFIELD: + dst = ret.dst; + goto again; + case FD_NEXT_OTHERFIELD: + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag); + case FD_NEXT_ATLIMIT: + return ptr; + } + } + + return fastdecode_dispatch(d, ptr, msg, table, hasbits); +} + +typedef struct { + uint8_t valbytes; + bool zigzag; + void *dst; + fastdecode_arr farr; +} fastdecode_varintdata; + +UPB_FORCEINLINE +static const char *fastdecode_topackedvarint(upb_decstate *d, const char *ptr, + void *ctx) { + fastdecode_varintdata *data = ctx; + void *dst = data->dst; + uint64_t val; + + while (!decode_isdone(d, &ptr)) { + dst = fastdecode_resizearr(d, dst, &data->farr, data->valbytes); + ptr = fastdecode_varint64(ptr, &val); + if (ptr == NULL) return NULL; + val = fastdecode_munge(val, data->valbytes, data->zigzag); + memcpy(dst, &val, data->valbytes); + dst = (char *)dst + data->valbytes; + } + + fastdecode_commitarr(dst, &data->farr, data->valbytes); + return ptr; +} + +UPB_FORCEINLINE +static const char *fastdecode_packedvarint(UPB_PARSE_PARAMS, int tagbytes, + int valbytes, bool zigzag, + _upb_field_parser *unpacked) { + fastdecode_varintdata ctx = {valbytes, zigzag}; + + if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { + if (fastdecode_flippacked(&data, tagbytes)) { + return unpacked(UPB_PARSE_ARGS); + } else { + RETURN_GENERIC("varint field tag mismatch\n"); + } + } + + ctx.dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &ctx.farr, + valbytes, CARD_r); + if (UPB_UNLIKELY(!ctx.dst)) { + RETURN_GENERIC("need array resize\n"); + } + + ptr += tagbytes; + ptr = fastdecode_delimited(d, ptr, &fastdecode_topackedvarint, &ctx); + + if (UPB_UNLIKELY(ptr == NULL)) { + return fastdecode_err(d); + } + + return fastdecode_dispatch(d, ptr, msg, table, hasbits); +} + +UPB_FORCEINLINE +static const char *fastdecode_varint(UPB_PARSE_PARAMS, int tagbytes, + int valbytes, upb_card card, bool zigzag, + _upb_field_parser *unpacked, + _upb_field_parser *packed) { + if (card == CARD_p) { + return fastdecode_packedvarint(UPB_PARSE_ARGS, tagbytes, valbytes, zigzag, + unpacked); + } else { + return fastdecode_unpackedvarint(UPB_PARSE_ARGS, tagbytes, valbytes, card, + zigzag, packed); + } +} + +#define z_ZZ true +#define b_ZZ false +#define v_ZZ false + +/* Generate all combinations: + * {s,o,r,p} x {b1,v4,z4,v8,z8} x {1bt,2bt} */ + +#define F(card, type, valbytes, tagbytes) \ + UPB_NOINLINE \ + const char *upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) { \ + return fastdecode_varint(UPB_PARSE_ARGS, tagbytes, valbytes, CARD_##card, \ + type##_ZZ, \ + &upb_pr##type##valbytes##_##tagbytes##bt, \ + &upb_pp##type##valbytes##_##tagbytes##bt); \ + } + +#define TYPES(card, tagbytes) \ + F(card, b, 1, tagbytes) \ + F(card, v, 4, tagbytes) \ + F(card, v, 8, tagbytes) \ + F(card, z, 4, tagbytes) \ + F(card, z, 8, tagbytes) + +#define TAGBYTES(card) \ + TYPES(card, 1) \ + TYPES(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) +TAGBYTES(p) + +#undef z_ZZ +#undef b_ZZ +#undef v_ZZ +#undef o_ONEOF +#undef s_ONEOF +#undef r_ONEOF +#undef F +#undef TYPES +#undef TAGBYTES + + +/* fixed fields ***************************************************************/ + +UPB_FORCEINLINE +static const char *fastdecode_unpackedfixed(UPB_PARSE_PARAMS, int tagbytes, + int valbytes, upb_card card, + _upb_field_parser *packed) { + void *dst; + fastdecode_arr farr; + + if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { + if (card == CARD_r && fastdecode_flippacked(&data, tagbytes)) { + return packed(UPB_PARSE_ARGS); + } + RETURN_GENERIC("fixed field tag mismatch\n"); + } + + dst = + fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes, card); + if (card == CARD_r) { + if (UPB_UNLIKELY(!dst)) { + RETURN_GENERIC("couldn't allocate array in arena\n"); + } + } + + +again: + if (card == CARD_r) { + dst = fastdecode_resizearr(d, dst, &farr, valbytes); + } + + ptr += tagbytes; + memcpy(dst, ptr, valbytes); + ptr += valbytes; + + if (card == CARD_r) { + fastdecode_nextret ret = + fastdecode_nextrepeated(d, dst, &ptr, &farr, data, tagbytes, valbytes); + switch (ret.next) { + case FD_NEXT_SAMEFIELD: + dst = ret.dst; + goto again; + case FD_NEXT_OTHERFIELD: + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag); + case FD_NEXT_ATLIMIT: + return ptr; + } + } + + return fastdecode_dispatch(d, ptr, msg, table, hasbits); +} + +UPB_FORCEINLINE +static const char *fastdecode_packedfixed(UPB_PARSE_PARAMS, int tagbytes, + int valbytes, + _upb_field_parser *unpacked) { + if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { + if (fastdecode_flippacked(&data, tagbytes)) { + return unpacked(UPB_PARSE_ARGS); + } else { + RETURN_GENERIC("varint field tag mismatch\n"); + } + } + + ptr += tagbytes; + int size = (uint8_t)ptr[0]; + ptr++; + if (size & 0x80) { + ptr = fastdecode_longsize(ptr, &size); + } + + if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr)) || + (size % valbytes) != 0) { + return fastdecode_err(d); + } + + upb_array **arr_p = fastdecode_fieldmem(msg, data); + upb_array *arr = *arr_p; + uint8_t elem_size_lg2 = __builtin_ctz(valbytes); + int elems = size / valbytes; + + if (UPB_LIKELY(!arr)) { + *arr_p = arr = _upb_array_new(&d->arena, elems, elem_size_lg2); + if (!arr) { + return fastdecode_err(d); + } + } else { + _upb_array_resize(arr, elems, &d->arena); + } + + char *dst = _upb_array_ptr(arr); + memcpy(dst, ptr, size); + arr->len = elems; + + return fastdecode_dispatch(d, ptr + size, msg, table, hasbits); +} + +UPB_FORCEINLINE +static const char *fastdecode_fixed(UPB_PARSE_PARAMS, int tagbytes, + int valbytes, upb_card card, + _upb_field_parser *unpacked, + _upb_field_parser *packed) { + if (card == CARD_p) { + return fastdecode_packedfixed(UPB_PARSE_ARGS, tagbytes, valbytes, unpacked); + } else { + return fastdecode_unpackedfixed(UPB_PARSE_ARGS, tagbytes, valbytes, card, + packed); } } -upb_alloc upb_alloc_global = {&upb_global_allocfunc}; +/* Generate all combinations: + * {s,o,r,p} x {f4,f8} x {1bt,2bt} */ -/* upb_arena ******************************************************************/ +#define F(card, valbytes, tagbytes) \ + UPB_NOINLINE \ + const char *upb_p##card##f##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) { \ + return fastdecode_fixed(UPB_PARSE_ARGS, tagbytes, valbytes, CARD_##card, \ + &upb_ppf##valbytes##_##tagbytes##bt, \ + &upb_prf##valbytes##_##tagbytes##bt); \ + } -/* Be conservative and choose 16 in case anyone is using SSE. */ +#define TYPES(card, tagbytes) \ + F(card, 4, tagbytes) \ + F(card, 8, tagbytes) -struct mem_block { - struct mem_block *next; - uint32_t size; - uint32_t cleanups; - /* Data follows. */ -}; +#define TAGBYTES(card) \ + TYPES(card, 1) \ + TYPES(card, 2) -typedef struct cleanup_ent { - upb_cleanup_func *cleanup; - void *ud; -} cleanup_ent; +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) +TAGBYTES(p) -static const size_t memblock_reserve = UPB_ALIGN_UP(sizeof(mem_block), 16); +#undef F +#undef TYPES +#undef TAGBYTES -static upb_arena *arena_findroot(upb_arena *a) { - /* Path splitting keeps time complexity down, see: - * https://en.wikipedia.org/wiki/Disjoint-set_data_structure */ - while (a->parent != a) { - upb_arena *next = a->parent; - a->parent = next->parent; - a = next; +/* string fields **************************************************************/ + +typedef const char *fastdecode_copystr_func(struct upb_decstate *d, + const char *ptr, upb_msg *msg, + const upb_msglayout *table, + uint64_t hasbits, upb_strview *dst); + +UPB_NOINLINE +static const char *fastdecode_verifyutf8(upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, + uint64_t hasbits, upb_strview *dst) { + if (!decode_verifyutf8_inl(dst->data, dst->size)) { + return fastdecode_err(d); } - return a; + return fastdecode_dispatch(d, ptr, msg, table, hasbits); } -static void upb_arena_addblock(upb_arena *a, upb_arena *root, void *ptr, - size_t size) { - mem_block *block = ptr; +UPB_FORCEINLINE +static const char *fastdecode_longstring(struct upb_decstate *d, + const char *ptr, upb_msg *msg, + intptr_t table, uint64_t hasbits, + upb_strview *dst, + bool validate_utf8) { + int size = (uint8_t)ptr[0]; // Could plumb through hasbits. + ptr++; + if (size & 0x80) { + ptr = fastdecode_longsize(ptr, &size); + } - /* The block is for arena |a|, but should appear in the freelist of |root|. */ - block->next = root->freelist; - block->size = (uint32_t)size; - block->cleanups = 0; - root->freelist = block; - a->last_size = block->size; - if (!root->freelist_tail) root->freelist_tail = block; + if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr))) { + dst->size = 0; + return fastdecode_err(d); + } - a->head.ptr = UPB_PTR_AT(block, memblock_reserve, char); - a->head.end = UPB_PTR_AT(block, size, char); - a->cleanups = &block->cleanups; + if (d->alias) { + dst->data = ptr; + dst->size = size; + } else { + char *data = upb_arena_malloc(&d->arena, size); + if (!data) { + return fastdecode_err(d); + } + memcpy(data, ptr, size); + dst->data = data; + dst->size = size; + } - UPB_POISON_MEMORY_REGION(a->head.ptr, a->head.end - a->head.ptr); + if (validate_utf8) { + return fastdecode_verifyutf8(d, ptr + size, msg, table, hasbits, dst); + } else { + return fastdecode_dispatch(d, ptr + size, msg, table, hasbits); + } } -static bool upb_arena_allocblock(upb_arena *a, size_t size) { - upb_arena *root = arena_findroot(a); - size_t block_size = UPB_MAX(size, a->last_size * 2) + memblock_reserve; - mem_block *block = upb_malloc(root->block_alloc, block_size); - - if (!block) return false; - upb_arena_addblock(a, root, block, block_size); - return true; +UPB_NOINLINE +static const char *fastdecode_longstring_utf8(struct upb_decstate *d, + const char *ptr, upb_msg *msg, + intptr_t table, uint64_t hasbits, + upb_strview *dst) { + return fastdecode_longstring(d, ptr, msg, table, hasbits, dst, true); } -void *_upb_arena_slowmalloc(upb_arena *a, size_t size) { - if (!upb_arena_allocblock(a, size)) return NULL; /* Out of memory. */ - UPB_ASSERT(_upb_arenahas(a, size)); - return upb_arena_malloc(a, size); +UPB_NOINLINE +static const char *fastdecode_longstring_noutf8(struct upb_decstate *d, + const char *ptr, upb_msg *msg, + intptr_t table, + uint64_t hasbits, + upb_strview *dst) { + return fastdecode_longstring(d, ptr, msg, table, hasbits, dst, false); } -static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize, - size_t size) { - upb_arena *a = (upb_arena*)alloc; /* upb_alloc is initial member. */ - return upb_arena_realloc(a, ptr, oldsize, size); +UPB_FORCEINLINE +static void fastdecode_docopy(upb_decstate *d, const char *ptr, uint32_t size, + int copy, char *data, upb_strview *dst) { + d->arena.head.ptr += copy; + dst->data = data; + UPB_UNPOISON_MEMORY_REGION(data, copy); + memcpy(data, ptr, copy); + UPB_POISON_MEMORY_REGION(data + size, copy - size); } -/* Public Arena API ***********************************************************/ +UPB_FORCEINLINE +static const char *fastdecode_copystring(UPB_PARSE_PARAMS, int tagbytes, + upb_card card, bool validate_utf8) { + upb_strview *dst; + fastdecode_arr farr; + int64_t size; + size_t arena_has; + size_t common_has; + char *buf; + + UPB_ASSERT(!d->alias); + UPB_ASSERT(fastdecode_checktag(data, tagbytes)); + + dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, + sizeof(upb_strview), card); + +again: + if (card == CARD_r) { + dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_strview)); + } + + size = (uint8_t)ptr[tagbytes]; + ptr += tagbytes + 1; + dst->size = size; + + buf = d->arena.head.ptr; + arena_has = _upb_arenahas(&d->arena); + common_has = UPB_MIN(arena_has, (d->end - ptr) + 16); + + if (UPB_LIKELY(size <= 15 - tagbytes)) { + if (arena_has < 16) goto longstr; + d->arena.head.ptr += 16; + memcpy(buf, ptr - tagbytes - 1, 16); + dst->data = buf + tagbytes + 1; + } else if (UPB_LIKELY(size <= 32)) { + if (UPB_UNLIKELY(common_has < 32)) goto longstr; + fastdecode_docopy(d, ptr, size, 32, buf, dst); + } else if (UPB_LIKELY(size <= 64)) { + if (UPB_UNLIKELY(common_has < 64)) goto longstr; + fastdecode_docopy(d, ptr, size, 64, buf, dst); + } else if (UPB_LIKELY(size < 128)) { + if (UPB_UNLIKELY(common_has < 128)) goto longstr; + fastdecode_docopy(d, ptr, size, 128, buf, dst); + } else { + goto longstr; + } -upb_arena *arena_initslow(void *mem, size_t n, upb_alloc *alloc) { - const size_t first_block_overhead = sizeof(upb_arena) + memblock_reserve; - upb_arena *a; + ptr += size; - /* We need to malloc the initial block. */ - n = first_block_overhead + 256; - if (!alloc || !(mem = upb_malloc(alloc, n))) { - return NULL; + if (card == CARD_r) { + if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) { + return fastdecode_err(d); + } + fastdecode_nextret ret = fastdecode_nextrepeated( + d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_strview)); + switch (ret.next) { + case FD_NEXT_SAMEFIELD: + dst = ret.dst; + goto again; + case FD_NEXT_OTHERFIELD: + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag); + case FD_NEXT_ATLIMIT: + return ptr; + } } - a = UPB_PTR_AT(mem, n - sizeof(*a), upb_arena); - n -= sizeof(*a); - - a->head.alloc.func = &upb_arena_doalloc; - a->block_alloc = alloc; - a->parent = a; - a->refcount = 1; - a->freelist = NULL; - a->freelist_tail = NULL; + if (card != CARD_r && validate_utf8) { + return fastdecode_verifyutf8(d, ptr, msg, table, hasbits, dst); + } - upb_arena_addblock(a, a, mem, n); + return fastdecode_dispatch(d, ptr, msg, table, hasbits); - return a; +longstr: + ptr--; + if (validate_utf8) { + return fastdecode_longstring_utf8(d, ptr, msg, table, hasbits, dst); + } else { + return fastdecode_longstring_noutf8(d, ptr, msg, table, hasbits, dst); + } } -upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc) { - upb_arena *a; +UPB_FORCEINLINE +static const char *fastdecode_string(UPB_PARSE_PARAMS, int tagbytes, + upb_card card, _upb_field_parser *copyfunc, + bool validate_utf8) { + upb_strview *dst; + fastdecode_arr farr; + int64_t size; - /* Round block size down to alignof(*a) since we will allocate the arena - * itself at the end. */ - n = UPB_ALIGN_DOWN(n, UPB_ALIGN_OF(upb_arena)); + if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { + RETURN_GENERIC("string field tag mismatch\n"); + } - if (UPB_UNLIKELY(n < sizeof(upb_arena))) { - return arena_initslow(mem, n, alloc); + if (UPB_UNLIKELY(!d->alias)) { + return copyfunc(UPB_PARSE_ARGS); } - a = UPB_PTR_AT(mem, n - sizeof(*a), upb_arena); - n -= sizeof(*a); + dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, + sizeof(upb_strview), card); - a->head.alloc.func = &upb_arena_doalloc; - a->block_alloc = alloc; - a->parent = a; - a->refcount = 1; - a->last_size = 128; - a->head.ptr = mem; - a->head.end = UPB_PTR_AT(mem, n, char); - a->freelist = NULL; - a->cleanups = NULL; +again: + if (card == CARD_r) { + dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_strview)); + } - return a; + size = (int8_t)ptr[tagbytes]; + ptr += tagbytes + 1; + dst->data = ptr; + dst->size = size; + + if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->end))) { + ptr--; + if (validate_utf8) { + return fastdecode_longstring_utf8(d, ptr, msg, table, hasbits, dst); + } else { + return fastdecode_longstring_noutf8(d, ptr, msg, table, hasbits, dst); + } + } + + ptr += size; + + if (card == CARD_r) { + if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) { + return fastdecode_err(d); + } + fastdecode_nextret ret = fastdecode_nextrepeated( + d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_strview)); + switch (ret.next) { + case FD_NEXT_SAMEFIELD: + dst = ret.dst; + if (UPB_UNLIKELY(!d->alias)) { + // Buffer flipped and we can't alias any more. Bounce to copyfunc(), + // but via dispatch since we need to reload table data also. + fastdecode_commitarr(dst, &farr, sizeof(upb_strview)); + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag); + } + goto again; + case FD_NEXT_OTHERFIELD: + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag); + case FD_NEXT_ATLIMIT: + return ptr; + } + } + + if (card != CARD_r && validate_utf8) { + return fastdecode_verifyutf8(d, ptr, msg, table, hasbits, dst); + } + + return fastdecode_dispatch(d, ptr, msg, table, hasbits); } -static void arena_dofree(upb_arena *a) { - mem_block *block = a->freelist; - UPB_ASSERT(a->parent == a); - UPB_ASSERT(a->refcount == 0); +/* Generate all combinations: + * {p,c} x {s,o,r} x {s, b} x {1bt,2bt} */ - while (block) { - /* Load first since we are deleting block. */ - mem_block *next = block->next; +#define s_VALIDATE true +#define b_VALIDATE false - if (block->cleanups > 0) { - cleanup_ent *end = UPB_PTR_AT(block, block->size, void); - cleanup_ent *ptr = end - block->cleanups; +#define F(card, tagbytes, type) \ + UPB_NOINLINE \ + const char *upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) { \ + return fastdecode_copystring(UPB_PARSE_ARGS, tagbytes, CARD_##card, \ + type##_VALIDATE); \ + } \ + const char *upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) { \ + return fastdecode_string(UPB_PARSE_ARGS, tagbytes, CARD_##card, \ + &upb_c##card##type##_##tagbytes##bt, \ + type##_VALIDATE); \ + } - for (; ptr < end; ptr++) { - ptr->cleanup(ptr->ud); - } - } +#define UTF8(card, tagbytes) \ + F(card, tagbytes, s) \ + F(card, tagbytes, b) - upb_free(a->block_alloc, block); - block = next; +#define TAGBYTES(card) \ + UTF8(card, 1) \ + UTF8(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) + +#undef s_VALIDATE +#undef b_VALIDATE +#undef F +#undef TAGBYTES + +/* message fields *************************************************************/ + +UPB_INLINE +upb_msg *decode_newmsg_ceil(upb_decstate *d, const upb_msglayout *l, + int msg_ceil_bytes) { + size_t size = l->size + sizeof(upb_msg_internal); + char *msg_data; + if (UPB_LIKELY(msg_ceil_bytes > 0 && + _upb_arenahas(&d->arena) >= msg_ceil_bytes)) { + UPB_ASSERT(size <= (size_t)msg_ceil_bytes); + msg_data = d->arena.head.ptr; + d->arena.head.ptr += size; + UPB_UNPOISON_MEMORY_REGION(msg_data, msg_ceil_bytes); + memset(msg_data, 0, msg_ceil_bytes); + UPB_POISON_MEMORY_REGION(msg_data + size, msg_ceil_bytes - size); + } else { + msg_data = (char*)upb_arena_malloc(&d->arena, size); + memset(msg_data, 0, size); } + return msg_data + sizeof(upb_msg_internal); } -void upb_arena_free(upb_arena *a) { - a = arena_findroot(a); - if (--a->refcount == 0) arena_dofree(a); +typedef struct { + intptr_t table; + upb_msg *msg; +} fastdecode_submsgdata; + +UPB_FORCEINLINE +static const char *fastdecode_tosubmsg(upb_decstate *d, const char *ptr, + void *ctx) { + fastdecode_submsgdata *submsg = ctx; + ptr = fastdecode_dispatch(d, ptr, submsg->msg, submsg->table, 0); + UPB_ASSUME(ptr != NULL); + return ptr; } -bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func) { - cleanup_ent *ent; +UPB_FORCEINLINE +static const char *fastdecode_submsg(UPB_PARSE_PARAMS, int tagbytes, + int msg_ceil_bytes, upb_card card) { - if (!a->cleanups || !_upb_arenahas(a, sizeof(cleanup_ent))) { - if (!upb_arena_allocblock(a, 128)) return false; /* Out of memory. */ - UPB_ASSERT(_upb_arenahas(a, sizeof(cleanup_ent))); + if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { + RETURN_GENERIC("submessage field tag mismatch\n"); } - a->head.end -= sizeof(cleanup_ent); - ent = (cleanup_ent*)a->head.end; - (*a->cleanups)++; - UPB_UNPOISON_MEMORY_REGION(ent, sizeof(cleanup_ent)); + if (--d->depth == 0) return fastdecode_err(d); - ent->cleanup = func; - ent->ud = ud; + upb_msg **dst; + uint32_t submsg_idx = (data >> 16) & 0xff; + const upb_msglayout *tablep = decode_totablep(table); + const upb_msglayout *subtablep = tablep->submsgs[submsg_idx]; + fastdecode_submsgdata submsg = {decode_totable(subtablep)}; + fastdecode_arr farr; - return true; -} + if (subtablep->table_mask == (uint8_t)-1) { + RETURN_GENERIC("submessage doesn't have fast tables."); + } -void upb_arena_fuse(upb_arena *a1, upb_arena *a2) { - upb_arena *r1 = arena_findroot(a1); - upb_arena *r2 = arena_findroot(a2); + dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, + sizeof(upb_msg *), card); - if (r1 == r2) return; /* Already fused. */ + if (card == CARD_s) { + *(uint32_t*)msg |= hasbits; + hasbits = 0; + } - /* We want to join the smaller tree to the larger tree. - * So swap first if they are backwards. */ - if (r1->refcount < r2->refcount) { - upb_arena *tmp = r1; - r1 = r2; - r2 = tmp; +again: + if (card == CARD_r) { + dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_msg*)); } - /* r1 takes over r2's freelist and refcount. */ - r1->refcount += r2->refcount; - if (r2->freelist_tail) { - UPB_ASSERT(r2->freelist_tail->next == NULL); - r2->freelist_tail->next = r1->freelist; - r1->freelist = r2->freelist; + submsg.msg = *dst; + + if (card == CARD_r || UPB_LIKELY(!submsg.msg)) { + *dst = submsg.msg = decode_newmsg_ceil(d, subtablep, msg_ceil_bytes); } - r2->parent = r1; + + ptr += tagbytes; + ptr = fastdecode_delimited(d, ptr, fastdecode_tosubmsg, &submsg); + + if (UPB_UNLIKELY(ptr == NULL || d->end_group != DECODE_NOGROUP)) { + return fastdecode_err(d); + } + + if (card == CARD_r) { + fastdecode_nextret ret = fastdecode_nextrepeated( + d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_msg *)); + switch (ret.next) { + case FD_NEXT_SAMEFIELD: + dst = ret.dst; + goto again; + case FD_NEXT_OTHERFIELD: + d->depth++; + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag); + case FD_NEXT_ATLIMIT: + d->depth++; + return ptr; + } + } + + d->depth++; + return fastdecode_dispatch(d, ptr, msg, table, hasbits); } + +#define F(card, tagbytes, size_ceil, ceil_arg) \ + const char *upb_p##card##m_##tagbytes##bt_max##size_ceil##b( \ + UPB_PARSE_PARAMS) { \ + return fastdecode_submsg(UPB_PARSE_ARGS, tagbytes, ceil_arg, CARD_##card); \ + } + +#define SIZES(card, tagbytes) \ + F(card, tagbytes, 64, 64) \ + F(card, tagbytes, 128, 128) \ + F(card, tagbytes, 192, 192) \ + F(card, tagbytes, 256, 256) \ + F(card, tagbytes, max, -1) + +#define TAGBYTES(card) \ + SIZES(card, 1) \ + SIZES(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) + +#undef TAGBYTES +#undef SIZES +#undef F + +#endif /* UPB_FASTTABLE */ /* This file was generated by upbc (the upb compiler) from the input * file: * @@ -2430,7 +3674,7 @@ static const upb_msglayout_field google_protobuf_FileDescriptorSet__fields[1] = const upb_msglayout google_protobuf_FileDescriptorSet_msginit = { &google_protobuf_FileDescriptorSet_submsgs[0], &google_protobuf_FileDescriptorSet__fields[0], - UPB_SIZE(4, 8), 1, false, + UPB_SIZE(8, 8), 1, false, 255, }; static const upb_msglayout *const google_protobuf_FileDescriptorProto_submsgs[6] = { @@ -2450,17 +3694,17 @@ static const upb_msglayout_field google_protobuf_FileDescriptorProto__fields[12] {5, UPB_SIZE(44, 88), 0, 1, 11, 3}, {6, UPB_SIZE(48, 96), 0, 4, 11, 3}, {7, UPB_SIZE(52, 104), 0, 2, 11, 3}, - {8, UPB_SIZE(28, 56), 4, 3, 11, 1}, - {9, UPB_SIZE(32, 64), 5, 5, 11, 1}, + {8, UPB_SIZE(28, 56), 3, 3, 11, 1}, + {9, UPB_SIZE(32, 64), 4, 5, 11, 1}, {10, UPB_SIZE(56, 112), 0, 0, 5, 3}, {11, UPB_SIZE(60, 120), 0, 0, 5, 3}, - {12, UPB_SIZE(20, 40), 3, 0, 12, 1}, + {12, UPB_SIZE(20, 40), 5, 0, 12, 1}, }; const upb_msglayout google_protobuf_FileDescriptorProto_msginit = { &google_protobuf_FileDescriptorProto_submsgs[0], &google_protobuf_FileDescriptorProto__fields[0], - UPB_SIZE(64, 128), 12, false, + UPB_SIZE(64, 128), 12, false, 255, }; static const upb_msglayout *const google_protobuf_DescriptorProto_submsgs[7] = { @@ -2489,7 +3733,7 @@ static const upb_msglayout_field google_protobuf_DescriptorProto__fields[10] = { const upb_msglayout google_protobuf_DescriptorProto_msginit = { &google_protobuf_DescriptorProto_submsgs[0], &google_protobuf_DescriptorProto__fields[0], - UPB_SIZE(48, 96), 10, false, + UPB_SIZE(48, 96), 10, false, 255, }; static const upb_msglayout *const google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = { @@ -2505,7 +3749,7 @@ static const upb_msglayout_field google_protobuf_DescriptorProto_ExtensionRange_ const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit = { &google_protobuf_DescriptorProto_ExtensionRange_submsgs[0], &google_protobuf_DescriptorProto_ExtensionRange__fields[0], - UPB_SIZE(16, 24), 3, false, + UPB_SIZE(16, 24), 3, false, 255, }; static const upb_msglayout_field google_protobuf_DescriptorProto_ReservedRange__fields[2] = { @@ -2516,7 +3760,7 @@ static const upb_msglayout_field google_protobuf_DescriptorProto_ReservedRange__ const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit = { NULL, &google_protobuf_DescriptorProto_ReservedRange__fields[0], - UPB_SIZE(12, 12), 2, false, + UPB_SIZE(16, 16), 2, false, 255, }; static const upb_msglayout *const google_protobuf_ExtensionRangeOptions_submsgs[1] = { @@ -2530,7 +3774,7 @@ static const upb_msglayout_field google_protobuf_ExtensionRangeOptions__fields[1 const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit = { &google_protobuf_ExtensionRangeOptions_submsgs[0], &google_protobuf_ExtensionRangeOptions__fields[0], - UPB_SIZE(4, 8), 1, false, + UPB_SIZE(8, 8), 1, false, 255, }; static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1] = { @@ -2538,23 +3782,23 @@ static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1 }; static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[11] = { - {1, UPB_SIZE(24, 24), 6, 0, 12, 1}, - {2, UPB_SIZE(32, 40), 7, 0, 12, 1}, + {1, UPB_SIZE(24, 24), 1, 0, 12, 1}, + {2, UPB_SIZE(32, 40), 2, 0, 12, 1}, {3, UPB_SIZE(12, 12), 3, 0, 5, 1}, - {4, UPB_SIZE(4, 4), 1, 0, 14, 1}, - {5, UPB_SIZE(8, 8), 2, 0, 14, 1}, - {6, UPB_SIZE(40, 56), 8, 0, 12, 1}, - {7, UPB_SIZE(48, 72), 9, 0, 12, 1}, - {8, UPB_SIZE(64, 104), 11, 0, 11, 1}, - {9, UPB_SIZE(16, 16), 4, 0, 5, 1}, + {4, UPB_SIZE(4, 4), 4, 0, 14, 1}, + {5, UPB_SIZE(8, 8), 5, 0, 14, 1}, + {6, UPB_SIZE(40, 56), 6, 0, 12, 1}, + {7, UPB_SIZE(48, 72), 7, 0, 12, 1}, + {8, UPB_SIZE(64, 104), 8, 0, 11, 1}, + {9, UPB_SIZE(16, 16), 9, 0, 5, 1}, {10, UPB_SIZE(56, 88), 10, 0, 12, 1}, - {17, UPB_SIZE(20, 20), 5, 0, 8, 1}, + {17, UPB_SIZE(20, 20), 11, 0, 8, 1}, }; const upb_msglayout google_protobuf_FieldDescriptorProto_msginit = { &google_protobuf_FieldDescriptorProto_submsgs[0], &google_protobuf_FieldDescriptorProto__fields[0], - UPB_SIZE(72, 112), 11, false, + UPB_SIZE(72, 112), 11, false, 255, }; static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1] = { @@ -2569,7 +3813,7 @@ static const upb_msglayout_field google_protobuf_OneofDescriptorProto__fields[2] const upb_msglayout google_protobuf_OneofDescriptorProto_msginit = { &google_protobuf_OneofDescriptorProto_submsgs[0], &google_protobuf_OneofDescriptorProto__fields[0], - UPB_SIZE(16, 32), 2, false, + UPB_SIZE(16, 32), 2, false, 255, }; static const upb_msglayout *const google_protobuf_EnumDescriptorProto_submsgs[3] = { @@ -2589,7 +3833,7 @@ static const upb_msglayout_field google_protobuf_EnumDescriptorProto__fields[5] const upb_msglayout google_protobuf_EnumDescriptorProto_msginit = { &google_protobuf_EnumDescriptorProto_submsgs[0], &google_protobuf_EnumDescriptorProto__fields[0], - UPB_SIZE(32, 64), 5, false, + UPB_SIZE(32, 64), 5, false, 255, }; static const upb_msglayout_field google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = { @@ -2600,7 +3844,7 @@ static const upb_msglayout_field google_protobuf_EnumDescriptorProto_EnumReserve const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit = { NULL, &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0], - UPB_SIZE(12, 12), 2, false, + UPB_SIZE(16, 16), 2, false, 255, }; static const upb_msglayout *const google_protobuf_EnumValueDescriptorProto_submsgs[1] = { @@ -2608,15 +3852,15 @@ static const upb_msglayout *const google_protobuf_EnumValueDescriptorProto_subms }; static const upb_msglayout_field google_protobuf_EnumValueDescriptorProto__fields[3] = { - {1, UPB_SIZE(8, 8), 2, 0, 12, 1}, - {2, UPB_SIZE(4, 4), 1, 0, 5, 1}, + {1, UPB_SIZE(8, 8), 1, 0, 12, 1}, + {2, UPB_SIZE(4, 4), 2, 0, 5, 1}, {3, UPB_SIZE(16, 24), 3, 0, 11, 1}, }; const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit = { &google_protobuf_EnumValueDescriptorProto_submsgs[0], &google_protobuf_EnumValueDescriptorProto__fields[0], - UPB_SIZE(24, 32), 3, false, + UPB_SIZE(24, 32), 3, false, 255, }; static const upb_msglayout *const google_protobuf_ServiceDescriptorProto_submsgs[2] = { @@ -2633,7 +3877,7 @@ static const upb_msglayout_field google_protobuf_ServiceDescriptorProto__fields[ const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit = { &google_protobuf_ServiceDescriptorProto_submsgs[0], &google_protobuf_ServiceDescriptorProto__fields[0], - UPB_SIZE(24, 48), 3, false, + UPB_SIZE(24, 48), 3, false, 255, }; static const upb_msglayout *const google_protobuf_MethodDescriptorProto_submsgs[1] = { @@ -2641,18 +3885,18 @@ static const upb_msglayout *const google_protobuf_MethodDescriptorProto_submsgs[ }; static const upb_msglayout_field google_protobuf_MethodDescriptorProto__fields[6] = { - {1, UPB_SIZE(4, 8), 3, 0, 12, 1}, - {2, UPB_SIZE(12, 24), 4, 0, 12, 1}, - {3, UPB_SIZE(20, 40), 5, 0, 12, 1}, - {4, UPB_SIZE(28, 56), 6, 0, 11, 1}, - {5, UPB_SIZE(1, 1), 1, 0, 8, 1}, - {6, UPB_SIZE(2, 2), 2, 0, 8, 1}, + {1, UPB_SIZE(4, 8), 1, 0, 12, 1}, + {2, UPB_SIZE(12, 24), 2, 0, 12, 1}, + {3, UPB_SIZE(20, 40), 3, 0, 12, 1}, + {4, UPB_SIZE(28, 56), 4, 0, 11, 1}, + {5, UPB_SIZE(1, 1), 5, 0, 8, 1}, + {6, UPB_SIZE(2, 2), 6, 0, 8, 1}, }; const upb_msglayout google_protobuf_MethodDescriptorProto_msginit = { &google_protobuf_MethodDescriptorProto_submsgs[0], &google_protobuf_MethodDescriptorProto__fields[0], - UPB_SIZE(32, 64), 6, false, + UPB_SIZE(32, 64), 6, false, 255, }; static const upb_msglayout *const google_protobuf_FileOptions_submsgs[1] = { @@ -2660,24 +3904,24 @@ static const upb_msglayout *const google_protobuf_FileOptions_submsgs[1] = { }; static const upb_msglayout_field google_protobuf_FileOptions__fields[21] = { - {1, UPB_SIZE(20, 24), 11, 0, 12, 1}, - {8, UPB_SIZE(28, 40), 12, 0, 12, 1}, - {9, UPB_SIZE(4, 4), 1, 0, 14, 1}, - {10, UPB_SIZE(8, 8), 2, 0, 8, 1}, - {11, UPB_SIZE(36, 56), 13, 0, 12, 1}, - {16, UPB_SIZE(9, 9), 3, 0, 8, 1}, - {17, UPB_SIZE(10, 10), 4, 0, 8, 1}, - {18, UPB_SIZE(11, 11), 5, 0, 8, 1}, - {20, UPB_SIZE(12, 12), 6, 0, 8, 1}, - {23, UPB_SIZE(13, 13), 7, 0, 8, 1}, - {27, UPB_SIZE(14, 14), 8, 0, 8, 1}, - {31, UPB_SIZE(15, 15), 9, 0, 8, 1}, - {36, UPB_SIZE(44, 72), 14, 0, 12, 1}, - {37, UPB_SIZE(52, 88), 15, 0, 12, 1}, - {39, UPB_SIZE(60, 104), 16, 0, 12, 1}, - {40, UPB_SIZE(68, 120), 17, 0, 12, 1}, - {41, UPB_SIZE(76, 136), 18, 0, 12, 1}, - {42, UPB_SIZE(16, 16), 10, 0, 8, 1}, + {1, UPB_SIZE(20, 24), 1, 0, 12, 1}, + {8, UPB_SIZE(28, 40), 2, 0, 12, 1}, + {9, UPB_SIZE(4, 4), 3, 0, 14, 1}, + {10, UPB_SIZE(8, 8), 4, 0, 8, 1}, + {11, UPB_SIZE(36, 56), 5, 0, 12, 1}, + {16, UPB_SIZE(9, 9), 6, 0, 8, 1}, + {17, UPB_SIZE(10, 10), 7, 0, 8, 1}, + {18, UPB_SIZE(11, 11), 8, 0, 8, 1}, + {20, UPB_SIZE(12, 12), 9, 0, 8, 1}, + {23, UPB_SIZE(13, 13), 10, 0, 8, 1}, + {27, UPB_SIZE(14, 14), 11, 0, 8, 1}, + {31, UPB_SIZE(15, 15), 12, 0, 8, 1}, + {36, UPB_SIZE(44, 72), 13, 0, 12, 1}, + {37, UPB_SIZE(52, 88), 14, 0, 12, 1}, + {39, UPB_SIZE(60, 104), 15, 0, 12, 1}, + {40, UPB_SIZE(68, 120), 16, 0, 12, 1}, + {41, UPB_SIZE(76, 136), 17, 0, 12, 1}, + {42, UPB_SIZE(16, 16), 18, 0, 8, 1}, {44, UPB_SIZE(84, 152), 19, 0, 12, 1}, {45, UPB_SIZE(92, 168), 20, 0, 12, 1}, {999, UPB_SIZE(100, 184), 0, 0, 11, 3}, @@ -2686,7 +3930,7 @@ static const upb_msglayout_field google_protobuf_FileOptions__fields[21] = { const upb_msglayout google_protobuf_FileOptions_msginit = { &google_protobuf_FileOptions_submsgs[0], &google_protobuf_FileOptions__fields[0], - UPB_SIZE(104, 192), 21, false, + UPB_SIZE(104, 192), 21, false, 255, }; static const upb_msglayout *const google_protobuf_MessageOptions_submsgs[1] = { @@ -2704,7 +3948,7 @@ static const upb_msglayout_field google_protobuf_MessageOptions__fields[5] = { const upb_msglayout google_protobuf_MessageOptions_msginit = { &google_protobuf_MessageOptions_submsgs[0], &google_protobuf_MessageOptions__fields[0], - UPB_SIZE(12, 16), 5, false, + UPB_SIZE(16, 16), 5, false, 255, }; static const upb_msglayout *const google_protobuf_FieldOptions_submsgs[1] = { @@ -2713,10 +3957,10 @@ static const upb_msglayout *const google_protobuf_FieldOptions_submsgs[1] = { static const upb_msglayout_field google_protobuf_FieldOptions__fields[7] = { {1, UPB_SIZE(4, 4), 1, 0, 14, 1}, - {2, UPB_SIZE(12, 12), 3, 0, 8, 1}, - {3, UPB_SIZE(13, 13), 4, 0, 8, 1}, - {5, UPB_SIZE(14, 14), 5, 0, 8, 1}, - {6, UPB_SIZE(8, 8), 2, 0, 14, 1}, + {2, UPB_SIZE(12, 12), 2, 0, 8, 1}, + {3, UPB_SIZE(13, 13), 3, 0, 8, 1}, + {5, UPB_SIZE(14, 14), 4, 0, 8, 1}, + {6, UPB_SIZE(8, 8), 5, 0, 14, 1}, {10, UPB_SIZE(15, 15), 6, 0, 8, 1}, {999, UPB_SIZE(16, 16), 0, 0, 11, 3}, }; @@ -2724,7 +3968,7 @@ static const upb_msglayout_field google_protobuf_FieldOptions__fields[7] = { const upb_msglayout google_protobuf_FieldOptions_msginit = { &google_protobuf_FieldOptions_submsgs[0], &google_protobuf_FieldOptions__fields[0], - UPB_SIZE(20, 24), 7, false, + UPB_SIZE(24, 24), 7, false, 255, }; static const upb_msglayout *const google_protobuf_OneofOptions_submsgs[1] = { @@ -2738,7 +3982,7 @@ static const upb_msglayout_field google_protobuf_OneofOptions__fields[1] = { const upb_msglayout google_protobuf_OneofOptions_msginit = { &google_protobuf_OneofOptions_submsgs[0], &google_protobuf_OneofOptions__fields[0], - UPB_SIZE(4, 8), 1, false, + UPB_SIZE(8, 8), 1, false, 255, }; static const upb_msglayout *const google_protobuf_EnumOptions_submsgs[1] = { @@ -2754,7 +3998,7 @@ static const upb_msglayout_field google_protobuf_EnumOptions__fields[3] = { const upb_msglayout google_protobuf_EnumOptions_msginit = { &google_protobuf_EnumOptions_submsgs[0], &google_protobuf_EnumOptions__fields[0], - UPB_SIZE(8, 16), 3, false, + UPB_SIZE(8, 16), 3, false, 255, }; static const upb_msglayout *const google_protobuf_EnumValueOptions_submsgs[1] = { @@ -2769,7 +4013,7 @@ static const upb_msglayout_field google_protobuf_EnumValueOptions__fields[2] = { const upb_msglayout google_protobuf_EnumValueOptions_msginit = { &google_protobuf_EnumValueOptions_submsgs[0], &google_protobuf_EnumValueOptions__fields[0], - UPB_SIZE(8, 16), 2, false, + UPB_SIZE(8, 16), 2, false, 255, }; static const upb_msglayout *const google_protobuf_ServiceOptions_submsgs[1] = { @@ -2784,7 +4028,7 @@ static const upb_msglayout_field google_protobuf_ServiceOptions__fields[2] = { const upb_msglayout google_protobuf_ServiceOptions_msginit = { &google_protobuf_ServiceOptions_submsgs[0], &google_protobuf_ServiceOptions__fields[0], - UPB_SIZE(8, 16), 2, false, + UPB_SIZE(8, 16), 2, false, 255, }; static const upb_msglayout *const google_protobuf_MethodOptions_submsgs[1] = { @@ -2792,15 +4036,15 @@ static const upb_msglayout *const google_protobuf_MethodOptions_submsgs[1] = { }; static const upb_msglayout_field google_protobuf_MethodOptions__fields[3] = { - {33, UPB_SIZE(8, 8), 2, 0, 8, 1}, - {34, UPB_SIZE(4, 4), 1, 0, 14, 1}, + {33, UPB_SIZE(8, 8), 1, 0, 8, 1}, + {34, UPB_SIZE(4, 4), 2, 0, 14, 1}, {999, UPB_SIZE(12, 16), 0, 0, 11, 3}, }; const upb_msglayout google_protobuf_MethodOptions_msginit = { &google_protobuf_MethodOptions_submsgs[0], &google_protobuf_MethodOptions__fields[0], - UPB_SIZE(16, 24), 3, false, + UPB_SIZE(16, 24), 3, false, 255, }; static const upb_msglayout *const google_protobuf_UninterpretedOption_submsgs[1] = { @@ -2809,10 +4053,10 @@ static const upb_msglayout *const google_protobuf_UninterpretedOption_submsgs[1] static const upb_msglayout_field google_protobuf_UninterpretedOption__fields[7] = { {2, UPB_SIZE(56, 80), 0, 0, 11, 3}, - {3, UPB_SIZE(32, 32), 4, 0, 12, 1}, - {4, UPB_SIZE(8, 8), 1, 0, 4, 1}, - {5, UPB_SIZE(16, 16), 2, 0, 3, 1}, - {6, UPB_SIZE(24, 24), 3, 0, 1, 1}, + {3, UPB_SIZE(32, 32), 1, 0, 12, 1}, + {4, UPB_SIZE(8, 8), 2, 0, 4, 1}, + {5, UPB_SIZE(16, 16), 3, 0, 3, 1}, + {6, UPB_SIZE(24, 24), 4, 0, 1, 1}, {7, UPB_SIZE(40, 48), 5, 0, 12, 1}, {8, UPB_SIZE(48, 64), 6, 0, 12, 1}, }; @@ -2820,18 +4064,18 @@ static const upb_msglayout_field google_protobuf_UninterpretedOption__fields[7] const upb_msglayout google_protobuf_UninterpretedOption_msginit = { &google_protobuf_UninterpretedOption_submsgs[0], &google_protobuf_UninterpretedOption__fields[0], - UPB_SIZE(64, 96), 7, false, + UPB_SIZE(64, 96), 7, false, 255, }; static const upb_msglayout_field google_protobuf_UninterpretedOption_NamePart__fields[2] = { - {1, UPB_SIZE(4, 8), 2, 0, 12, 2}, - {2, UPB_SIZE(1, 1), 1, 0, 8, 2}, + {1, UPB_SIZE(4, 8), 1, 0, 12, 2}, + {2, UPB_SIZE(1, 1), 2, 0, 8, 2}, }; const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit = { NULL, &google_protobuf_UninterpretedOption_NamePart__fields[0], - UPB_SIZE(16, 32), 2, false, + UPB_SIZE(16, 32), 2, false, 255, }; static const upb_msglayout *const google_protobuf_SourceCodeInfo_submsgs[1] = { @@ -2845,7 +4089,7 @@ static const upb_msglayout_field google_protobuf_SourceCodeInfo__fields[1] = { const upb_msglayout google_protobuf_SourceCodeInfo_msginit = { &google_protobuf_SourceCodeInfo_submsgs[0], &google_protobuf_SourceCodeInfo__fields[0], - UPB_SIZE(4, 8), 1, false, + UPB_SIZE(8, 8), 1, false, 255, }; static const upb_msglayout_field google_protobuf_SourceCodeInfo_Location__fields[5] = { @@ -2859,7 +4103,7 @@ static const upb_msglayout_field google_protobuf_SourceCodeInfo_Location__fields const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit = { NULL, &google_protobuf_SourceCodeInfo_Location__fields[0], - UPB_SIZE(32, 64), 5, false, + UPB_SIZE(32, 64), 5, false, 255, }; static const upb_msglayout *const google_protobuf_GeneratedCodeInfo_submsgs[1] = { @@ -2873,20 +4117,20 @@ static const upb_msglayout_field google_protobuf_GeneratedCodeInfo__fields[1] = const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit = { &google_protobuf_GeneratedCodeInfo_submsgs[0], &google_protobuf_GeneratedCodeInfo__fields[0], - UPB_SIZE(4, 8), 1, false, + UPB_SIZE(8, 8), 1, false, 255, }; static const upb_msglayout_field google_protobuf_GeneratedCodeInfo_Annotation__fields[4] = { {1, UPB_SIZE(20, 32), 0, 0, 5, _UPB_LABEL_PACKED}, - {2, UPB_SIZE(12, 16), 3, 0, 12, 1}, - {3, UPB_SIZE(4, 4), 1, 0, 5, 1}, - {4, UPB_SIZE(8, 8), 2, 0, 5, 1}, + {2, UPB_SIZE(12, 16), 1, 0, 12, 1}, + {3, UPB_SIZE(4, 4), 2, 0, 5, 1}, + {4, UPB_SIZE(8, 8), 3, 0, 5, 1}, }; const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit = { NULL, &google_protobuf_GeneratedCodeInfo_Annotation__fields[0], - UPB_SIZE(24, 48), 4, false, + UPB_SIZE(24, 48), 4, false, 255, }; @@ -3283,6 +4527,8 @@ upb_def_init google_protobuf_descriptor_proto_upbdefinit = { #include +/* Must be last. */ + typedef struct { size_t len; char str[1]; /* Null-terminated string data follows. */ @@ -3366,17 +4612,18 @@ struct upb_filedef { const char *package; const char *phpprefix; const char *phpnamespace; - upb_syntax_t syntax; const upb_filedef **deps; const upb_msgdef *msgs; const upb_enumdef *enums; const upb_fielddef *exts; + const upb_symtab *symtab; int dep_count; int msg_count; int enum_count; int ext_count; + upb_syntax_t syntax; }; struct upb_symtab { @@ -3679,6 +4926,23 @@ const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f) { return f->oneof; } +upb_msgval upb_fielddef_default(const upb_fielddef *f) { + UPB_ASSERT(!upb_fielddef_issubmsg(f)); + upb_msgval ret; + if (upb_fielddef_isstring(f)) { + str_t *str = f->defaultval.str; + if (str) { + ret.str_val.data = str->str; + ret.str_val.size = str->len; + } else { + ret.str_val.size = 0; + } + } else { + memcpy(&ret, &f->defaultval, 8); + } + return ret; +} + static void chkdefaulttype(const upb_fielddef *f, int ctype) { UPB_UNUSED(f); UPB_UNUSED(ctype); @@ -4096,6 +5360,10 @@ const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i) { return i < 0 || i >= f->enum_count ? NULL : &f->enums[i]; } +const upb_symtab *upb_filedef_symtab(const upb_filedef *f) { + return f->symtab; +} + void upb_symtab_free(upb_symtab *s) { upb_arena_free(s->arena); upb_gfree(s); @@ -4177,19 +5445,19 @@ typedef struct { jmp_buf err; /* longjmp() on error. */ } symtab_addctx; -UPB_NORETURN UPB_NOINLINE +UPB_NORETURN UPB_NOINLINE UPB_PRINTF(2, 3) static void symtab_errf(symtab_addctx *ctx, const char *fmt, ...) { va_list argp; va_start(argp, fmt); upb_status_vseterrf(ctx->status, fmt, argp); va_end(argp); - longjmp(ctx->err, 1); + UPB_LONGJMP(ctx->err, 1); } UPB_NORETURN UPB_NOINLINE static void symtab_oomerr(symtab_addctx *ctx) { upb_status_setoom(ctx->status); - longjmp(ctx->err, 1); + UPB_LONGJMP(ctx->err, 1); } void *symtab_alloc(symtab_addctx *ctx, size_t bytes) { @@ -4304,7 +5572,7 @@ static void make_layout(symtab_addctx *ctx, const upb_msgdef *m) { const upb_msglayout **submsgs; upb_msglayout_field *fields; - memset(l, 0, sizeof(*l)); + memset(l, 0, sizeof(*l) + sizeof(_upb_fasttable_entry)); fields = symtab_alloc(ctx, upb_msgdef_numfields(m) * sizeof(*fields)); submsgs = symtab_alloc(ctx, submsg_count * sizeof(*submsgs)); @@ -4312,6 +5580,12 @@ static void make_layout(symtab_addctx *ctx, const upb_msgdef *m) { l->field_count = upb_msgdef_numfields(m); l->fields = fields; l->submsgs = submsgs; + l->table_mask = 0; + + /* TODO(haberman): initialize fast tables so that reflection-based parsing + * can get the same speeds as linked-in types. */ + l->fasttable[0].field_parser = &fastdecode_generic; + l->fasttable[0].field_data = 0; if (upb_msgdef_mapentry(m)) { /* TODO(haberman): refactor this method so this special case is more @@ -4785,7 +6059,7 @@ static void parse_default(symtab_addctx *ctx, const char *str, size_t len, return; invalid: - symtab_errf(ctx, "Invalid default '%.*s' for field %f", (int)len, str, + symtab_errf(ctx, "Invalid default '%.*s' for field %s", (int)len, str, upb_fielddef_fullname(f)); } @@ -5074,7 +6348,8 @@ static void create_msgdef(symtab_addctx *ctx, const char *prefix, ctx->layouts++; } else { /* Allocate now (to allow cross-linking), populate later. */ - m->layout = symtab_alloc(ctx, sizeof(*m->layout)); + m->layout = symtab_alloc( + ctx, sizeof(*m->layout) + sizeof(_upb_fasttable_entry)); } m->oneof_count = 0; @@ -5359,8 +6634,9 @@ static const upb_filedef *_upb_symtab_addfile( file->msg_count = 0; file->enum_count = 0; file->ext_count = 0; + file->symtab = s; - if (UPB_UNLIKELY(setjmp(ctx.err))) { + if (UPB_UNLIKELY(UPB_SETJMP(ctx.err))) { UPB_ASSERT(!upb_ok(status)); remove_filedef(s, file); file = NULL; @@ -5406,8 +6682,8 @@ bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init) { if (!_upb_symtab_loaddefinit(s, *deps)) goto err; } - file = google_protobuf_FileDescriptorProto_parse( - init->descriptor.data, init->descriptor.size, arena); + file = google_protobuf_FileDescriptorProto_parse_ex( + init->descriptor.data, init->descriptor.size, arena, UPB_DECODE_ALIAS); s->bytes_loaded += init->descriptor.size; if (!file) { @@ -5435,6 +6711,10 @@ size_t _upb_symtab_bytesloaded(const upb_symtab *s) { return s->bytes_loaded; } +upb_arena *_upb_symtab_arena(const upb_symtab *s) { + return s->arena; +} + #undef CHK_OOM @@ -5570,7 +6850,7 @@ upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f) { val.double_val = upb_fielddef_defaultdouble(f); break; case UPB_TYPE_BOOL: - val.double_val = upb_fielddef_defaultbool(f); + val.bool_val = upb_fielddef_defaultbool(f); break; case UPB_TYPE_STRING: case UPB_TYPE_BYTES: @@ -5795,6 +7075,10 @@ bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val) { return _upb_map_get(map, &key, map->key_size, val, map->val_size); } +void upb_map_clear(upb_map *map) { + _upb_map_clear(map); +} + bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val, upb_arena *arena) { return _upb_map_set(map, &key, map->key_size, &val, map->val_size, arena); @@ -5838,31 +7122,6 @@ upb_msgval upb_mapiter_value(const upb_map *map, size_t iter) { /* void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value); */ -#ifdef UPB_MSVC_VSNPRINTF -/* Visual C++ earlier than 2015 doesn't have standard C99 snprintf and - * vsnprintf. To support them, missing functions are manually implemented - * using the existing secure functions. */ -int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg) { - if (!s) { - return _vscprintf(format, arg); - } - int ret = _vsnprintf_s(s, n, _TRUNCATE, format, arg); - if (ret < 0) { - ret = _vscprintf(format, arg); - } - return ret; -} - -int msvc_snprintf(char* s, size_t n, const char* format, ...) { - va_list arg; - va_start(arg, format); - int ret = msvc_vsnprintf(s, n, format, arg); - va_end(arg); - return ret; -} -#endif - - #include #include #include @@ -5918,9 +7177,10 @@ static bool jsondec_isvalue(const upb_fielddef *f) { UPB_NORETURN static void jsondec_err(jsondec *d, const char *msg) { upb_status_seterrf(d->status, "Error parsing JSON @%d:%d: %s", d->line, (int)(d->ptr - d->line_begin), msg); - longjmp(d->err, 1); + UPB_LONGJMP(d->err, 1); } +UPB_PRINTF(2, 3) UPB_NORETURN static void jsondec_errf(jsondec *d, const char *fmt, ...) { va_list argp; upb_status_seterrf(d->status, "Error parsing JSON @%d:%d: ", d->line, @@ -5928,7 +7188,7 @@ UPB_NORETURN static void jsondec_errf(jsondec *d, const char *fmt, ...) { va_start(argp, fmt); upb_status_vappenderrf(d->status, fmt, argp); va_end(argp); - longjmp(d->err, 1); + UPB_LONGJMP(d->err, 1); } static void jsondec_skipws(jsondec *d) { @@ -6537,7 +7797,7 @@ static upb_msgval jsondec_int(jsondec *d, const upb_fielddef *f) { } val.int64_val = dbl; /* must be guarded, overflow here is UB */ if (val.int64_val != dbl) { - jsondec_errf(d, "JSON number was not integral (%d != %" PRId64 ")", dbl, + jsondec_errf(d, "JSON number was not integral (%f != %" PRId64 ")", dbl, val.int64_val); } break; @@ -6563,7 +7823,7 @@ static upb_msgval jsondec_int(jsondec *d, const upb_fielddef *f) { /* Parse UINT32 or UINT64 value. */ static upb_msgval jsondec_uint(jsondec *d, const upb_fielddef *f) { - upb_msgval val; + upb_msgval val = {0}; switch (jsondec_peek(d)) { case JD_NUMBER: { @@ -6573,7 +7833,7 @@ static upb_msgval jsondec_uint(jsondec *d, const upb_fielddef *f) { } val.uint64_val = dbl; /* must be guarded, overflow here is UB */ if (val.uint64_val != dbl) { - jsondec_errf(d, "JSON number was not integral (%d != %" PRIu64 ")", dbl, + jsondec_errf(d, "JSON number was not integral (%f != %" PRIu64 ")", dbl, val.uint64_val); } break; @@ -6600,7 +7860,7 @@ static upb_msgval jsondec_uint(jsondec *d, const upb_fielddef *f) { /* Parse DOUBLE or FLOAT value. */ static upb_msgval jsondec_double(jsondec *d, const upb_fielddef *f) { upb_strview str; - upb_msgval val; + upb_msgval val = {0}; switch (jsondec_peek(d)) { case JD_NUMBER: @@ -6764,7 +8024,7 @@ static void jsondec_field(jsondec *d, upb_msg *msg, const upb_msgdef *m) { if (!f) { if ((d->options & UPB_JSONDEC_IGNOREUNKNOWN) == 0) { - jsondec_errf(d, "Unknown field: '" UPB_STRVIEW_FORMAT "'", + jsondec_errf(d, "No such field: " UPB_STRVIEW_FORMAT, UPB_STRVIEW_ARGS(name)); } jsondec_skipval(d); @@ -6917,7 +8177,8 @@ static void jsondec_timestamp(jsondec *d, upb_msg *msg, const upb_msgdef *m) { { /* [+-]08:00 or Z */ - int ofs = 0; + int ofs_hour = 0; + int ofs_min = 0; bool neg = false; if (ptr == end) goto malformed; @@ -6928,9 +8189,10 @@ static void jsondec_timestamp(jsondec *d, upb_msg *msg, const upb_msgdef *m) { /* fallthrough */ case '+': if ((end - ptr) != 5) goto malformed; - ofs = jsondec_tsdigits(d, &ptr, 2, ":00"); - ofs *= 60 * 60; - seconds.int64_val += (neg ? ofs : -ofs); + ofs_hour = jsondec_tsdigits(d, &ptr, 2, ":"); + ofs_min = jsondec_tsdigits(d, &ptr, 2, NULL); + ofs_min = ((ofs_hour * 60) + ofs_min) * 60; + seconds.int64_val += (neg ? ofs_min : -ofs_min); break; case 'Z': if (ptr != end) goto malformed; @@ -7295,7 +8557,7 @@ bool upb_json_decode(const char *buf, size_t size, upb_msg *msg, d.debug_field = NULL; d.is_first = false; - if (setjmp(d.err)) return false; + if (UPB_SETJMP(d.err)) return false; jsondec_tomsg(&d, msg, m); return true; @@ -7338,6 +8600,7 @@ UPB_NORETURN static void jsonenc_err(jsonenc *e, const char *msg) { longjmp(e->err, 1); } +UPB_PRINTF(2, 3) UPB_NORETURN static void jsonenc_errf(jsonenc *e, const char *fmt, ...) { va_list argp; va_start(argp, fmt); @@ -7370,6 +8633,7 @@ static void jsonenc_putstr(jsonenc *e, const char *str) { jsonenc_putbytes(e, str, strlen(str)); } +UPB_PRINTF(2, 3) static void jsonenc_printf(jsonenc *e, const char *fmt, ...) { size_t n; size_t have = e->end - e->ptr; @@ -7400,7 +8664,7 @@ static void jsonenc_nanos(jsonenc *e, int32_t nanos) { digits -= 3; } - jsonenc_printf(e, ".%0.*" PRId32, digits, nanos); + jsonenc_printf(e, ".%.*" PRId32, digits, nanos); } static void jsonenc_timestamp(jsonenc *e, const upb_msg *msg, @@ -7892,7 +9156,7 @@ static void jsonenc_mapkey(jsonenc *e, upb_msgval val, const upb_fielddef *f) { static void jsonenc_array(jsonenc *e, const upb_array *arr, const upb_fielddef *f) { size_t i; - size_t size = upb_array_size(arr); + size_t size = arr ? upb_array_size(arr) : 0; bool first = true; jsonenc_putstr(e, "["); @@ -7914,10 +9178,12 @@ static void jsonenc_map(jsonenc *e, const upb_map *map, const upb_fielddef *f) { jsonenc_putstr(e, "{"); - while (upb_mapiter_next(map, &iter)) { - jsonenc_putsep(e, ",", &first); - jsonenc_mapkey(e, upb_mapiter_key(map, iter), key_f); - jsonenc_scalar(e, upb_mapiter_value(map, iter), val_f); + if (map) { + while (upb_mapiter_next(map, &iter)) { + jsonenc_putsep(e, ",", &first); + jsonenc_mapkey(e, upb_mapiter_key(map, iter), key_f); + jsonenc_scalar(e, upb_mapiter_value(map, iter), val_f); + } } jsonenc_putstr(e, "}"); @@ -7957,7 +9223,9 @@ static void jsonenc_msgfields(jsonenc *e, const upb_msg *msg, int n = upb_msgdef_fieldcount(m); for (i = 0; i < n; i++) { f = upb_msgdef_field(m, i); - jsonenc_fieldval(e, f, upb_msg_get(msg, f), &first); + if (!upb_fielddef_haspresence(f) || upb_msg_has(msg, f)) { + jsonenc_fieldval(e, f, upb_msg_get(msg, f), &first); + } } } else { /* Iterate over non-empty fields. */ diff --git a/php/ext/google/protobuf/php-upb.h b/php/ext/google/protobuf/php-upb.h index d22b4aa0e0..bd72cd9c08 100644 --- a/php/ext/google/protobuf/php-upb.h +++ b/php/ext/google/protobuf/php-upb.h @@ -22,12 +22,10 @@ * This file is private and must not be included by users! */ -#if !(__STDC_VERSION__ >= 199901L || __cplusplus >= 201103L) -#error upb requires C99 or C++11 -#endif - -#if (defined(_MSC_VER) && _MSC_VER < 1900) -#error upb requires MSVC >= 2015. +#if !((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + (defined(__cplusplus) && __cplusplus >= 201103L) || \ + (defined(_MSC_VER) && _MSC_VER >= 1900)) +#error upb requires C99 or C++11 or MSVC >= 2015. #endif #include @@ -83,14 +81,17 @@ #define UPB_FORCEINLINE __inline__ __attribute__((always_inline)) #define UPB_NOINLINE __attribute__((noinline)) #define UPB_NORETURN __attribute__((__noreturn__)) +#define UPB_PRINTF(str, first_vararg) __attribute__((format (printf, str, first_vararg))) #elif defined(_MSC_VER) #define UPB_NOINLINE #define UPB_FORCEINLINE #define UPB_NORETURN __declspec(noreturn) +#define UPB_PRINTF(str, first_vararg) #else /* !defined(__GNUC__) */ #define UPB_FORCEINLINE #define UPB_NOINLINE #define UPB_NORETURN +#define UPB_PRINTF(str, first_vararg) #endif #define UPB_MAX(x, y) ((x) > (y) ? (x) : (y)) @@ -126,6 +127,52 @@ #define UPB_UNREACHABLE() do { assert(0); } while(0) #endif +/* UPB_SETJMP() / UPB_LONGJMP(): avoid setting/restoring signal mask. */ +#ifdef __APPLE__ +#define UPB_SETJMP(buf) _setjmp(buf) +#define UPB_LONGJMP(buf, val) _longjmp(buf, val) +#else +#define UPB_SETJMP(buf) setjmp(buf) +#define UPB_LONGJMP(buf, val) longjmp(buf, val) +#endif + +/* Configure whether fasttable is switched on or not. *************************/ + +#if defined(__x86_64__) && defined(__GNUC__) +#define UPB_FASTTABLE_SUPPORTED 1 +#else +#define UPB_FASTTABLE_SUPPORTED 0 +#endif + +/* define UPB_ENABLE_FASTTABLE to force fast table support. + * This is useful when we want to ensure we are really getting fasttable, + * for example for testing or benchmarking. */ +#if defined(UPB_ENABLE_FASTTABLE) +#if !UPB_FASTTABLE_SUPPORTED +#error fasttable is x86-64 + Clang/GCC only +#endif +#define UPB_FASTTABLE 1 +/* Define UPB_TRY_ENABLE_FASTTABLE to use fasttable if possible. + * This is useful for releasing code that might be used on multiple platforms, + * for example the PHP or Ruby C extensions. */ +#elif defined(UPB_TRY_ENABLE_FASTTABLE) +#define UPB_FASTTABLE UPB_FASTTABLE_SUPPORTED +#else +#define UPB_FASTTABLE 0 +#endif + +/* UPB_FASTTABLE_INIT() allows protos compiled for fasttable to gracefully + * degrade to non-fasttable if we are using UPB_TRY_ENABLE_FASTTABLE. */ +#if !UPB_FASTTABLE && defined(UPB_TRY_ENABLE_FASTTABLE) +#define UPB_FASTTABLE_INIT(...) +#else +#define UPB_FASTTABLE_INIT(...) __VA_ARGS__ +#endif + +#undef UPB_FASTTABLE_SUPPORTED + +/* ASAN poisoning (for arena) *************************************************/ + #if defined(__SANITIZE_ADDRESS__) #define UPB_ASAN 1 #ifdef __cplusplus @@ -165,6 +212,7 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); #define UPB_MSG_H_ #include +#include #include /* @@ -225,9 +273,12 @@ bool upb_ok(const upb_status *status); /* These are no-op if |status| is NULL. */ void upb_status_clear(upb_status *status); void upb_status_seterrmsg(upb_status *status, const char *msg); -void upb_status_seterrf(upb_status *status, const char *fmt, ...); -void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args); -void upb_status_vappenderrf(upb_status *status, const char *fmt, va_list args); +void upb_status_seterrf(upb_status *status, const char *fmt, ...) + UPB_PRINTF(2, 3); +void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) + UPB_PRINTF(2, 0); +void upb_status_vappenderrf(upb_status *status, const char *fmt, va_list args) + UPB_PRINTF(2, 0); /** upb_strview ************************************************************/ @@ -353,9 +404,9 @@ void *_upb_arena_slowmalloc(upb_arena *a, size_t size); UPB_INLINE upb_alloc *upb_arena_alloc(upb_arena *a) { return (upb_alloc*)a; } -UPB_INLINE bool _upb_arenahas(upb_arena *a, size_t size) { +UPB_INLINE size_t _upb_arenahas(upb_arena *a) { _upb_arena_head *h = (_upb_arena_head*)a; - return (size_t)(h->end - h->ptr) >= size; + return (size_t)(h->end - h->ptr); } UPB_INLINE void *upb_arena_malloc(upb_arena *a, size_t size) { @@ -363,7 +414,7 @@ UPB_INLINE void *upb_arena_malloc(upb_arena *a, size_t size) { void* ret; size = UPB_ALIGN_MALLOC(size); - if (UPB_UNLIKELY(!_upb_arenahas(a, size))) { + if (UPB_UNLIKELY(_upb_arenahas(a) < size)) { return _upb_arena_slowmalloc(a, size); } @@ -374,7 +425,7 @@ UPB_INLINE void *upb_arena_malloc(upb_arena *a, size_t size) { #if UPB_ASAN { size_t guard_size = 32; - if (_upb_arenahas(a, guard_size)) { + if (_upb_arenahas(a) >= guard_size) { h->ptr += guard_size; } else { h->ptr = h->end; @@ -516,6 +567,10 @@ UPB_INLINE int _upb_lg2ceil(int x) { #endif } +UPB_INLINE int _upb_lg2ceilsize(int x) { + return 1 << _upb_lg2ceil(x); +} + #ifdef __cplusplus } /* extern "C" */ @@ -645,10 +700,17 @@ UPB_INLINE char *upb_tabstr(upb_tabkey key, uint32_t *len) { return mem + sizeof(*len); } +UPB_INLINE upb_strview upb_tabstrview(upb_tabkey key) { + upb_strview ret; + uint32_t len; + ret.data = upb_tabstr(key, &len); + ret.size = len; + return ret; +} /* upb_tabval *****************************************************************/ -typedef struct { +typedef struct upb_tabval { uint64_t val; } upb_tabval; @@ -964,6 +1026,7 @@ bool upb_inttable_iter_isequal(const upb_inttable_iter *i1, #endif /* UPB_TABLE_H_ */ +/* Must be last. */ #ifdef __cplusplus extern "C" { @@ -995,6 +1058,18 @@ typedef struct { uint8_t label; /* google.protobuf.Label or _UPB_LABEL_* above. */ } upb_msglayout_field; +struct upb_decstate; +struct upb_msglayout; + +typedef const char *_upb_field_parser(struct upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, + uint64_t hasbits, uint64_t data); + +typedef struct { + uint64_t field_data; + _upb_field_parser *field_parser; +} _upb_fasttable_entry; + typedef struct upb_msglayout { const struct upb_msglayout *const* submsgs; const upb_msglayout_field *fields; @@ -1003,6 +1078,10 @@ typedef struct upb_msglayout { uint16_t size; uint16_t field_count; bool extendable; + uint8_t table_mask; + /* To constant-initialize the tables of variable length, we need a flexible + * array member, and we need to compile in C99 mode. */ + _upb_fasttable_entry fasttable[]; } upb_msglayout; /** upb_msg *******************************************************************/ @@ -1147,6 +1226,11 @@ UPB_INLINE const void *_upb_array_constptr(const upb_array *arr) { return (void*)(arr->data & ~(uintptr_t)7); } +UPB_INLINE uintptr_t _upb_array_tagptr(void* ptr, int elem_size_lg2) { + UPB_ASSERT(elem_size_lg2 <= 4); + return (uintptr_t)ptr | elem_size_lg2; +} + UPB_INLINE void *_upb_array_ptr(upb_array *arr) { return (void*)_upb_array_constptr(arr); } @@ -1481,6 +1565,53 @@ UPB_INLINE void _upb_msg_map_set_value(void* msg, const void* val, size_t size) } } +/** _upb_mapsorter *************************************************************/ + +/* _upb_mapsorter sorts maps and provides ordered iteration over the entries. + * Since maps can be recursive (map values can be messages which contain other maps). + * _upb_mapsorter can contain a stack of maps. */ + +typedef struct { + upb_tabent const**entries; + int size; + int cap; +} _upb_mapsorter; + +typedef struct { + int start; + int pos; + int end; +} _upb_sortedmap; + +UPB_INLINE void _upb_mapsorter_init(_upb_mapsorter *s) { + s->entries = NULL; + s->size = 0; + s->cap = 0; +} + +UPB_INLINE void _upb_mapsorter_destroy(_upb_mapsorter *s) { + if (s->entries) free(s->entries); +} + +bool _upb_mapsorter_pushmap(_upb_mapsorter *s, upb_descriptortype_t key_type, + const upb_map *map, _upb_sortedmap *sorted); + +UPB_INLINE void _upb_mapsorter_popmap(_upb_mapsorter *s, _upb_sortedmap *sorted) { + s->size = sorted->start; +} + +UPB_INLINE bool _upb_sortedmap_next(_upb_mapsorter *s, const upb_map *map, + _upb_sortedmap *sorted, + upb_map_entry *ent) { + if (sorted->pos == sorted->end) return false; + const upb_tabent *tabent = s->entries[sorted->pos++]; + upb_strview key = upb_tabstrview(tabent->key); + _upb_map_fromkey(key, &ent->k, map->key_size); + upb_value val = {tabent->val.val}; + _upb_map_fromvalue(val, &ent->v, map->val_size); + return true; +} + #undef PTR_AT #ifdef __cplusplus @@ -1490,18 +1621,45 @@ UPB_INLINE void _upb_msg_map_set_value(void* msg, const void* val, size_t size) #endif /* UPB_MSG_H_ */ +/* Must be last. */ + #ifdef __cplusplus extern "C" { #endif +enum { + /* If set, strings will alias the input buffer instead of copying into the + * arena. */ + UPB_DECODE_ALIAS = 1, +}; + +#define UPB_DECODE_MAXDEPTH(depth) ((depth) << 16) + +bool _upb_decode(const char *buf, size_t size, upb_msg *msg, + const upb_msglayout *l, upb_arena *arena, int options); + +UPB_INLINE bool upb_decode(const char *buf, size_t size, upb_msg *msg, - const upb_msglayout *l, upb_arena *arena); + const upb_msglayout *l, upb_arena *arena) { + return _upb_decode(buf, size, msg, l, arena, 0); +} #ifdef __cplusplus } /* extern "C" */ #endif + #endif /* UPB_DECODE_H_ */ +/* +** Internal implementation details of the decoder that are shared between +** decode.c and decode_fast.c. +*/ + +#ifndef UPB_DECODE_INT_H_ +#define UPB_DECODE_INT_H_ + +#include + #ifndef UPB_INT_H_ #define UPB_INT_H_ @@ -1530,6 +1688,155 @@ struct upb_arena { }; #endif /* UPB_INT_H_ */ + +/* Must be last. */ + +#define DECODE_NOGROUP (uint32_t)-1 + +typedef struct upb_decstate { + const char *end; /* Can read up to 16 bytes slop beyond this. */ + const char *limit_ptr; /* = end + UPB_MIN(limit, 0) */ + upb_msg *unknown_msg; /* If non-NULL, add unknown data at buffer flip. */ + const char *unknown; /* Start of unknown data. */ + int limit; /* Submessage limit relative to end. */ + int depth; + uint32_t end_group; /* field number of END_GROUP tag, else DECODE_NOGROUP */ + bool alias; + char patch[32]; + upb_arena arena; + jmp_buf err; +} upb_decstate; + +/* Error function that will abort decoding with longjmp(). We can't declare this + * UPB_NORETURN, even though it is appropriate, because if we do then compilers + * will "helpfully" refuse to tailcall to it + * (see: https://stackoverflow.com/a/55657013), which will defeat a major goal + * of our optimizations. That is also why we must declare it in a separate file, + * otherwise the compiler will see that it calls longjmp() and deduce that it is + * noreturn. */ +const char *fastdecode_err(upb_decstate *d); + +extern const uint8_t upb_utf8_offsets[]; + +UPB_INLINE +bool decode_verifyutf8_inl(const char *buf, int len) { + int i, j; + uint8_t offset; + + i = 0; + while (i < len) { + offset = upb_utf8_offsets[(uint8_t)buf[i]]; + if (offset == 0 || i + offset > len) { + return false; + } + for (j = i + 1; j < i + offset; j++) { + if ((buf[j] & 0xc0) != 0x80) { + return false; + } + } + i += offset; + } + return i == len; +} + +/* x86-64 pointers always have the high 16 bits matching. So we can shift + * left 8 and right 8 without loss of information. */ +UPB_INLINE intptr_t decode_totable(const upb_msglayout *tablep) { + return ((intptr_t)tablep << 8) | tablep->table_mask; +} + +UPB_INLINE const upb_msglayout *decode_totablep(intptr_t table) { + return (const upb_msglayout*)(table >> 8); +} + +UPB_INLINE +const char *decode_isdonefallback_inl(upb_decstate *d, const char *ptr, + int overrun) { + if (overrun < d->limit) { + /* Need to copy remaining data into patch buffer. */ + UPB_ASSERT(overrun < 16); + if (d->unknown_msg) { + if (!_upb_msg_addunknown(d->unknown_msg, d->unknown, ptr - d->unknown, + &d->arena)) { + return NULL; + } + d->unknown = &d->patch[0] + overrun; + } + memset(d->patch + 16, 0, 16); + memcpy(d->patch, d->end, 16); + ptr = &d->patch[0] + overrun; + d->end = &d->patch[16]; + d->limit -= 16; + d->limit_ptr = d->end + d->limit; + d->alias = false; + UPB_ASSERT(ptr < d->limit_ptr); + return ptr; + } else { + return NULL; + } +} + +const char *decode_isdonefallback(upb_decstate *d, const char *ptr, + int overrun); + +UPB_INLINE +bool decode_isdone(upb_decstate *d, const char **ptr) { + int overrun = *ptr - d->end; + if (UPB_LIKELY(*ptr < d->limit_ptr)) { + return false; + } else if (UPB_LIKELY(overrun == d->limit)) { + return true; + } else { + *ptr = decode_isdonefallback(d, *ptr, overrun); + return false; + } +} + +UPB_INLINE +const char *fastdecode_tagdispatch(upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, + uint64_t hasbits, uint32_t tag) { + const upb_msglayout *table_p = decode_totablep(table); + uint8_t mask = table; + uint64_t data; + size_t idx = tag & mask; + UPB_ASSUME((idx & 7) == 0); + idx >>= 3; + data = table_p->fasttable[idx].field_data ^ tag; + return table_p->fasttable[idx].field_parser(d, ptr, msg, table, hasbits, data); +} + +UPB_INLINE uint32_t fastdecode_loadtag(const char* ptr) { + uint16_t tag; + memcpy(&tag, ptr, 2); + return tag; +} + +UPB_INLINE void decode_checklimit(upb_decstate *d) { + UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit)); +} + +UPB_INLINE int decode_pushlimit(upb_decstate *d, const char *ptr, int size) { + int limit = size + (int)(ptr - d->end); + int delta = d->limit - limit; + decode_checklimit(d); + d->limit = limit; + d->limit_ptr = d->end + UPB_MIN(0, limit); + decode_checklimit(d); + return delta; +} + +UPB_INLINE void decode_poplimit(upb_decstate *d, const char *ptr, + int saved_delta) { + UPB_ASSERT(ptr - d->end == d->limit); + decode_checklimit(d); + d->limit += saved_delta; + d->limit_ptr = d->end + UPB_MIN(0, d->limit); + decode_checklimit(d); +} + + +#endif /* UPB_DECODE_INT_H_ */ /* ** upb_encode: parsing into a upb_msg using a upb_msglayout. */ @@ -1538,18 +1845,166 @@ struct upb_arena { #define UPB_ENCODE_H_ +/* Must be last. */ + #ifdef __cplusplus extern "C" { #endif -char *upb_encode(const void *msg, const upb_msglayout *l, upb_arena *arena, - size_t *size); +enum { + /* If set, the results of serializing will be deterministic across all + * instances of this binary. There are no guarantees across different + * binary builds. + * + * If your proto contains maps, the encoder will need to malloc()/free() + * memory during encode. */ + UPB_ENCODE_DETERMINISTIC = 1, + + /* When set, unknown fields are not printed. */ + UPB_ENCODE_SKIPUNKNOWN = 2, +}; + +#define UPB_ENCODE_MAXDEPTH(depth) ((depth) << 16) + +char *upb_encode_ex(const void *msg, const upb_msglayout *l, int options, + upb_arena *arena, size_t *size); + +UPB_INLINE char *upb_encode(const void *msg, const upb_msglayout *l, + upb_arena *arena, size_t *size) { + return upb_encode_ex(msg, l, 0, arena, size); +} + #ifdef __cplusplus } /* extern "C" */ #endif #endif /* UPB_ENCODE_H_ */ +// These are the specialized field parser functions for the fast parser. +// Generated tables will refer to these by name. +// +// The function names are encoded with names like: +// +// // 123 4 +// upb_pss_1bt(); // Parse singular string, 1 byte tag. +// +// In position 1: +// - 'p' for parse, most function use this +// - 'c' for copy, for when we are copying strings instead of aliasing +// +// In position 2 (cardinality): +// - 's' for singular, with or without hasbit +// - 'o' for oneof +// - 'r' for non-packed repeated +// - 'p' for packed repeated +// +// In position 3 (type): +// - 'b1' for bool +// - 'v4' for 4-byte varint +// - 'v8' for 8-byte varint +// - 'z4' for zig-zag-encoded 4-byte varint +// - 'z8' for zig-zag-encoded 8-byte varint +// - 'f4' for 4-byte fixed +// - 'f8' for 8-byte fixed +// - 'm' for sub-message +// - 's' for string (validate UTF-8) +// - 'b' for bytes +// +// In position 4 (tag length): +// - '1' for one-byte tags (field numbers 1-15) +// - '2' for two-byte tags (field numbers 16-2048) + +#ifndef UPB_DECODE_FAST_H_ +#define UPB_DECODE_FAST_H_ + + +struct upb_decstate; + +// The fallback, generic parsing function that can handle any field type. +// This just uses the regular (non-fast) parser to parse a single field. +const char *fastdecode_generic(struct upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, uint64_t hasbits, + uint64_t data); + +#define UPB_PARSE_PARAMS \ + struct upb_decstate *d, const char *ptr, upb_msg *msg, intptr_t table, \ + uint64_t hasbits, uint64_t data + +/* primitive fields ***********************************************************/ + +#define F(card, type, valbytes, tagbytes) \ + const char *upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS); + +#define TYPES(card, tagbytes) \ + F(card, b, 1, tagbytes) \ + F(card, v, 4, tagbytes) \ + F(card, v, 8, tagbytes) \ + F(card, z, 4, tagbytes) \ + F(card, z, 8, tagbytes) \ + F(card, f, 4, tagbytes) \ + F(card, f, 8, tagbytes) + +#define TAGBYTES(card) \ + TYPES(card, 1) \ + TYPES(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) +TAGBYTES(p) + +#undef F +#undef TYPES +#undef TAGBYTES + +/* string fields **************************************************************/ + +#define F(card, tagbytes, type) \ + const char *upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS); \ + const char *upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS); + +#define UTF8(card, tagbytes) \ + F(card, tagbytes, s) \ + F(card, tagbytes, b) + +#define TAGBYTES(card) \ + UTF8(card, 1) \ + UTF8(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) + +#undef F +#undef TAGBYTES + +/* sub-message fields *********************************************************/ + +#define F(card, tagbytes, size_ceil, ceil_arg) \ + const char *upb_p##card##m_##tagbytes##bt_max##size_ceil##b(UPB_PARSE_PARAMS); + +#define SIZES(card, tagbytes) \ + F(card, tagbytes, 64, 64) \ + F(card, tagbytes, 128, 128) \ + F(card, tagbytes, 192, 192) \ + F(card, tagbytes, 256, 256) \ + F(card, tagbytes, max, -1) + +#define TAGBYTES(card) \ + SIZES(card, 1) \ + SIZES(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) + +#undef TAGBYTES +#undef SIZES +#undef F + +#undef UPB_PARSE_PARAMS + +#endif /* UPB_DECODE_FAST_H_ */ /* This file was generated by upbc (the upb compiler) from the input * file: * @@ -1711,6 +2166,12 @@ UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_ google_protobuf_FileDescriptorSet *ret = google_protobuf_FileDescriptorSet_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_FileDescriptorSet *ret = google_protobuf_FileDescriptorSet_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_FileDescriptorSet_serialize(const google_protobuf_FileDescriptorSet *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_FileDescriptorSet_msginit, arena, len); } @@ -1742,6 +2203,12 @@ UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorPr google_protobuf_FileDescriptorProto *ret = google_protobuf_FileDescriptorProto_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_FileDescriptorProto *ret = google_protobuf_FileDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_FileDescriptorProto_serialize(const google_protobuf_FileDescriptorProto *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_FileDescriptorProto_msginit, arena, len); } @@ -1759,13 +2226,13 @@ UPB_INLINE bool google_protobuf_FileDescriptorProto_has_service(const google_pro UPB_INLINE const google_protobuf_ServiceDescriptorProto* const* google_protobuf_FileDescriptorProto_service(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_ServiceDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(48, 96), len); } UPB_INLINE bool google_protobuf_FileDescriptorProto_has_extension(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(52, 104)); } UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_FileDescriptorProto_extension(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(52, 104), len); } -UPB_INLINE bool google_protobuf_FileDescriptorProto_has_options(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_options(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 3); } UPB_INLINE const google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_options(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_FileOptions*); } -UPB_INLINE bool google_protobuf_FileDescriptorProto_has_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 5); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 4); } UPB_INLINE const google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 64), const google_protobuf_SourceCodeInfo*); } UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_public_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(56, 112), len); } UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_weak_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(60, 120), len); } -UPB_INLINE bool google_protobuf_FileDescriptorProto_has_syntax(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_syntax(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 5); } UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_syntax(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); } UPB_INLINE void google_protobuf_FileDescriptorProto_set_name(google_protobuf_FileDescriptorProto *msg, upb_strview value) { @@ -1839,7 +2306,7 @@ UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_FileDesc return sub; } UPB_INLINE void google_protobuf_FileDescriptorProto_set_options(google_protobuf_FileDescriptorProto *msg, google_protobuf_FileOptions* value) { - _upb_sethas(msg, 4); + _upb_sethas(msg, 3); *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_FileOptions*) = value; } UPB_INLINE struct google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_mutable_options(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { @@ -1852,7 +2319,7 @@ UPB_INLINE struct google_protobuf_FileOptions* google_protobuf_FileDescriptorPro return sub; } UPB_INLINE void google_protobuf_FileDescriptorProto_set_source_code_info(google_protobuf_FileDescriptorProto *msg, google_protobuf_SourceCodeInfo* value) { - _upb_sethas(msg, 5); + _upb_sethas(msg, 4); *UPB_PTR_AT(msg, UPB_SIZE(32, 64), google_protobuf_SourceCodeInfo*) = value; } UPB_INLINE struct google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_mutable_source_code_info(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { @@ -1885,7 +2352,7 @@ UPB_INLINE bool google_protobuf_FileDescriptorProto_add_weak_dependency(google_p arena); } UPB_INLINE void google_protobuf_FileDescriptorProto_set_syntax(google_protobuf_FileDescriptorProto *msg, upb_strview value) { - _upb_sethas(msg, 3); + _upb_sethas(msg, 5); *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value; } @@ -1899,6 +2366,12 @@ UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_pars google_protobuf_DescriptorProto *ret = google_protobuf_DescriptorProto_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_DescriptorProto *ret = google_protobuf_DescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_DescriptorProto_serialize(const google_protobuf_DescriptorProto *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_DescriptorProto_msginit, arena, len); } @@ -2052,6 +2525,12 @@ UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_Descr google_protobuf_DescriptorProto_ExtensionRange *ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_DescriptorProto_ExtensionRange *ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_DescriptorProto_ExtensionRange_serialize(const google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena, len); } @@ -2095,6 +2574,12 @@ UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_Descri google_protobuf_DescriptorProto_ReservedRange *ret = google_protobuf_DescriptorProto_ReservedRange_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_DescriptorProto_ReservedRange *ret = google_protobuf_DescriptorProto_ReservedRange_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_DescriptorProto_ReservedRange_serialize(const google_protobuf_DescriptorProto_ReservedRange *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena, len); } @@ -2123,6 +2608,12 @@ UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRange google_protobuf_ExtensionRangeOptions *ret = google_protobuf_ExtensionRangeOptions_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_ExtensionRangeOptions *ret = google_protobuf_ExtensionRangeOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_ExtensionRangeOptions_serialize(const google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_ExtensionRangeOptions_msginit, arena, len); } @@ -2154,39 +2645,45 @@ UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptor google_protobuf_FieldDescriptorProto *ret = google_protobuf_FieldDescriptorProto_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_FieldDescriptorProto *ret = google_protobuf_FieldDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_FieldDescriptorProto_serialize(const google_protobuf_FieldDescriptorProto *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_FieldDescriptorProto_msginit, arena, len); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 6); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 1); } UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), upb_strview); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 7); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 2); } UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 40), upb_strview); } UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_number(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 3); } UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_number(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), int32_t); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 4); } UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 5); } UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_type(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 8); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 6); } UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(40, 56), upb_strview); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 9); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 7); } UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(48, 72), upb_strview); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 11); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 8); } UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_options(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(64, 104), const google_protobuf_FieldOptions*); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 9); } UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t); } UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 10); } UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(56, 88), upb_strview); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 5); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 11); } UPB_INLINE bool google_protobuf_FieldDescriptorProto_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool); } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { - _upb_sethas(msg, 6); + _upb_sethas(msg, 1); *UPB_PTR_AT(msg, UPB_SIZE(24, 24), upb_strview) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { - _upb_sethas(msg, 7); + _upb_sethas(msg, 2); *UPB_PTR_AT(msg, UPB_SIZE(32, 40), upb_strview) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_number(google_protobuf_FieldDescriptorProto *msg, int32_t value) { @@ -2194,23 +2691,23 @@ UPB_INLINE void google_protobuf_FieldDescriptorProto_set_number(google_protobuf_ *UPB_PTR_AT(msg, UPB_SIZE(12, 12), int32_t) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_label(google_protobuf_FieldDescriptorProto *msg, int32_t value) { - _upb_sethas(msg, 1); + _upb_sethas(msg, 4); *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type(google_protobuf_FieldDescriptorProto *msg, int32_t value) { - _upb_sethas(msg, 2); + _upb_sethas(msg, 5); *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { - _upb_sethas(msg, 8); + _upb_sethas(msg, 6); *UPB_PTR_AT(msg, UPB_SIZE(40, 56), upb_strview) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { - _upb_sethas(msg, 9); + _upb_sethas(msg, 7); *UPB_PTR_AT(msg, UPB_SIZE(48, 72), upb_strview) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldOptions* value) { - _upb_sethas(msg, 11); + _upb_sethas(msg, 8); *UPB_PTR_AT(msg, UPB_SIZE(64, 104), google_protobuf_FieldOptions*) = value; } UPB_INLINE struct google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_mutable_options(google_protobuf_FieldDescriptorProto *msg, upb_arena *arena) { @@ -2223,7 +2720,7 @@ UPB_INLINE struct google_protobuf_FieldOptions* google_protobuf_FieldDescriptorP return sub; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_oneof_index(google_protobuf_FieldDescriptorProto *msg, int32_t value) { - _upb_sethas(msg, 4); + _upb_sethas(msg, 9); *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { @@ -2231,7 +2728,7 @@ UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protob *UPB_PTR_AT(msg, UPB_SIZE(56, 88), upb_strview) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_proto3_optional(google_protobuf_FieldDescriptorProto *msg, bool value) { - _upb_sethas(msg, 5); + _upb_sethas(msg, 11); *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool) = value; } @@ -2245,6 +2742,12 @@ UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptor google_protobuf_OneofDescriptorProto *ret = google_protobuf_OneofDescriptorProto_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_OneofDescriptorProto *ret = google_protobuf_OneofDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_OneofDescriptorProto_serialize(const google_protobuf_OneofDescriptorProto *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_OneofDescriptorProto_msginit, arena, len); } @@ -2282,6 +2785,12 @@ UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorPr google_protobuf_EnumDescriptorProto *ret = google_protobuf_EnumDescriptorProto_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_EnumDescriptorProto *ret = google_protobuf_EnumDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_EnumDescriptorProto_serialize(const google_protobuf_EnumDescriptorProto *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_EnumDescriptorProto_msginit, arena, len); } @@ -2360,6 +2869,12 @@ UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobu google_protobuf_EnumDescriptorProto_EnumReservedRange *ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_EnumDescriptorProto_EnumReservedRange *ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena, len); } @@ -2388,23 +2903,29 @@ UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDe google_protobuf_EnumValueDescriptorProto *ret = google_protobuf_EnumValueDescriptorProto_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_EnumValueDescriptorProto *ret = google_protobuf_EnumValueDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_EnumValueDescriptorProto_serialize(const google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_EnumValueDescriptorProto_msginit, arena, len); } -UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_name(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_name(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 1); } UPB_INLINE upb_strview google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview); } -UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_number(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_number(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 2); } UPB_INLINE int32_t google_protobuf_EnumValueDescriptorProto_number(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_options(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 3); } UPB_INLINE const google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_options(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), const google_protobuf_EnumValueOptions*); } UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_name(google_protobuf_EnumValueDescriptorProto *msg, upb_strview value) { - _upb_sethas(msg, 2); + _upb_sethas(msg, 1); *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview) = value; } UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_number(google_protobuf_EnumValueDescriptorProto *msg, int32_t value) { - _upb_sethas(msg, 1); + _upb_sethas(msg, 2); *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; } UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_options(google_protobuf_EnumValueDescriptorProto *msg, google_protobuf_EnumValueOptions* value) { @@ -2431,6 +2952,12 @@ UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescri google_protobuf_ServiceDescriptorProto *ret = google_protobuf_ServiceDescriptorProto_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_ServiceDescriptorProto *ret = google_protobuf_ServiceDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_ServiceDescriptorProto_serialize(const google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_ServiceDescriptorProto_msginit, arena, len); } @@ -2483,37 +3010,43 @@ UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescript google_protobuf_MethodDescriptorProto *ret = google_protobuf_MethodDescriptorProto_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_MethodDescriptorProto *ret = google_protobuf_MethodDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_MethodDescriptorProto_serialize(const google_protobuf_MethodDescriptorProto *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_MethodDescriptorProto_msginit, arena, len); } -UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_name(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_name(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 1); } UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } -UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_input_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_input_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 2); } UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_input_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); } -UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_output_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 5); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_output_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 3); } UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_output_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); } -UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_options(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 6); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_options(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 4); } UPB_INLINE const google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_options(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_MethodOptions*); } -UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 5); } UPB_INLINE bool google_protobuf_MethodDescriptorProto_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } -UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 6); } UPB_INLINE bool google_protobuf_MethodDescriptorProto_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); } UPB_INLINE void google_protobuf_MethodDescriptorProto_set_name(google_protobuf_MethodDescriptorProto *msg, upb_strview value) { - _upb_sethas(msg, 3); + _upb_sethas(msg, 1); *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; } UPB_INLINE void google_protobuf_MethodDescriptorProto_set_input_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) { - _upb_sethas(msg, 4); + _upb_sethas(msg, 2); *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value; } UPB_INLINE void google_protobuf_MethodDescriptorProto_set_output_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) { - _upb_sethas(msg, 5); + _upb_sethas(msg, 3); *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value; } UPB_INLINE void google_protobuf_MethodDescriptorProto_set_options(google_protobuf_MethodDescriptorProto *msg, google_protobuf_MethodOptions* value) { - _upb_sethas(msg, 6); + _upb_sethas(msg, 4); *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_MethodOptions*) = value; } UPB_INLINE struct google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_mutable_options(google_protobuf_MethodDescriptorProto *msg, upb_arena *arena) { @@ -2526,11 +3059,11 @@ UPB_INLINE struct google_protobuf_MethodOptions* google_protobuf_MethodDescripto return sub; } UPB_INLINE void google_protobuf_MethodDescriptorProto_set_client_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) { - _upb_sethas(msg, 1); + _upb_sethas(msg, 5); *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; } UPB_INLINE void google_protobuf_MethodDescriptorProto_set_server_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) { - _upb_sethas(msg, 2); + _upb_sethas(msg, 6); *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value; } @@ -2544,45 +3077,51 @@ UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_parse(const google_protobuf_FileOptions *ret = google_protobuf_FileOptions_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_FileOptions_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_FileOptions *ret = google_protobuf_FileOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_FileOptions_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_FileOptions_serialize(const google_protobuf_FileOptions *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_FileOptions_msginit, arena, len); } -UPB_INLINE bool google_protobuf_FileOptions_has_java_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 11); } +UPB_INLINE bool google_protobuf_FileOptions_has_java_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 1); } UPB_INLINE upb_strview google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 24), upb_strview); } -UPB_INLINE bool google_protobuf_FileOptions_has_java_outer_classname(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 12); } +UPB_INLINE bool google_protobuf_FileOptions_has_java_outer_classname(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 2); } UPB_INLINE upb_strview google_protobuf_FileOptions_java_outer_classname(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 40), upb_strview); } -UPB_INLINE bool google_protobuf_FileOptions_has_optimize_for(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE bool google_protobuf_FileOptions_has_optimize_for(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 3); } UPB_INLINE int32_t google_protobuf_FileOptions_optimize_for(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } -UPB_INLINE bool google_protobuf_FileOptions_has_java_multiple_files(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE bool google_protobuf_FileOptions_has_java_multiple_files(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 4); } UPB_INLINE bool google_protobuf_FileOptions_java_multiple_files(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool); } -UPB_INLINE bool google_protobuf_FileOptions_has_go_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 13); } +UPB_INLINE bool google_protobuf_FileOptions_has_go_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 5); } UPB_INLINE upb_strview google_protobuf_FileOptions_go_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(36, 56), upb_strview); } -UPB_INLINE bool google_protobuf_FileOptions_has_cc_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE bool google_protobuf_FileOptions_has_cc_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 6); } UPB_INLINE bool google_protobuf_FileOptions_cc_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(9, 9), bool); } -UPB_INLINE bool google_protobuf_FileOptions_has_java_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE bool google_protobuf_FileOptions_has_java_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 7); } UPB_INLINE bool google_protobuf_FileOptions_java_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(10, 10), bool); } -UPB_INLINE bool google_protobuf_FileOptions_has_py_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 5); } +UPB_INLINE bool google_protobuf_FileOptions_has_py_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 8); } UPB_INLINE bool google_protobuf_FileOptions_py_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(11, 11), bool); } -UPB_INLINE bool google_protobuf_FileOptions_has_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 6); } +UPB_INLINE bool google_protobuf_FileOptions_has_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 9); } UPB_INLINE bool google_protobuf_FileOptions_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool); } -UPB_INLINE bool google_protobuf_FileOptions_has_deprecated(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 7); } +UPB_INLINE bool google_protobuf_FileOptions_has_deprecated(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 10); } UPB_INLINE bool google_protobuf_FileOptions_deprecated(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool); } -UPB_INLINE bool google_protobuf_FileOptions_has_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 8); } +UPB_INLINE bool google_protobuf_FileOptions_has_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 11); } UPB_INLINE bool google_protobuf_FileOptions_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool); } -UPB_INLINE bool google_protobuf_FileOptions_has_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 9); } +UPB_INLINE bool google_protobuf_FileOptions_has_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 12); } UPB_INLINE bool google_protobuf_FileOptions_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool); } -UPB_INLINE bool google_protobuf_FileOptions_has_objc_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 14); } +UPB_INLINE bool google_protobuf_FileOptions_has_objc_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 13); } UPB_INLINE upb_strview google_protobuf_FileOptions_objc_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(44, 72), upb_strview); } -UPB_INLINE bool google_protobuf_FileOptions_has_csharp_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 15); } +UPB_INLINE bool google_protobuf_FileOptions_has_csharp_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 14); } UPB_INLINE upb_strview google_protobuf_FileOptions_csharp_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(52, 88), upb_strview); } -UPB_INLINE bool google_protobuf_FileOptions_has_swift_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 16); } +UPB_INLINE bool google_protobuf_FileOptions_has_swift_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 15); } UPB_INLINE upb_strview google_protobuf_FileOptions_swift_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(60, 104), upb_strview); } -UPB_INLINE bool google_protobuf_FileOptions_has_php_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 17); } +UPB_INLINE bool google_protobuf_FileOptions_has_php_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 16); } UPB_INLINE upb_strview google_protobuf_FileOptions_php_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(68, 120), upb_strview); } -UPB_INLINE bool google_protobuf_FileOptions_has_php_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 18); } +UPB_INLINE bool google_protobuf_FileOptions_has_php_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 17); } UPB_INLINE upb_strview google_protobuf_FileOptions_php_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(76, 136), upb_strview); } -UPB_INLINE bool google_protobuf_FileOptions_has_php_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 10); } +UPB_INLINE bool google_protobuf_FileOptions_has_php_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 18); } UPB_INLINE bool google_protobuf_FileOptions_php_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool); } UPB_INLINE bool google_protobuf_FileOptions_has_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 19); } UPB_INLINE upb_strview google_protobuf_FileOptions_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(84, 152), upb_strview); } @@ -2592,75 +3131,75 @@ UPB_INLINE bool google_protobuf_FileOptions_has_uninterpreted_option(const googl UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FileOptions_uninterpreted_option(const google_protobuf_FileOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(100, 184), len); } UPB_INLINE void google_protobuf_FileOptions_set_java_package(google_protobuf_FileOptions *msg, upb_strview value) { - _upb_sethas(msg, 11); + _upb_sethas(msg, 1); *UPB_PTR_AT(msg, UPB_SIZE(20, 24), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_java_outer_classname(google_protobuf_FileOptions *msg, upb_strview value) { - _upb_sethas(msg, 12); + _upb_sethas(msg, 2); *UPB_PTR_AT(msg, UPB_SIZE(28, 40), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_optimize_for(google_protobuf_FileOptions *msg, int32_t value) { - _upb_sethas(msg, 1); + _upb_sethas(msg, 3); *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; } UPB_INLINE void google_protobuf_FileOptions_set_java_multiple_files(google_protobuf_FileOptions *msg, bool value) { - _upb_sethas(msg, 2); + _upb_sethas(msg, 4); *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_go_package(google_protobuf_FileOptions *msg, upb_strview value) { - _upb_sethas(msg, 13); + _upb_sethas(msg, 5); *UPB_PTR_AT(msg, UPB_SIZE(36, 56), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_cc_generic_services(google_protobuf_FileOptions *msg, bool value) { - _upb_sethas(msg, 3); + _upb_sethas(msg, 6); *UPB_PTR_AT(msg, UPB_SIZE(9, 9), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_java_generic_services(google_protobuf_FileOptions *msg, bool value) { - _upb_sethas(msg, 4); + _upb_sethas(msg, 7); *UPB_PTR_AT(msg, UPB_SIZE(10, 10), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_py_generic_services(google_protobuf_FileOptions *msg, bool value) { - _upb_sethas(msg, 5); + _upb_sethas(msg, 8); *UPB_PTR_AT(msg, UPB_SIZE(11, 11), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_java_generate_equals_and_hash(google_protobuf_FileOptions *msg, bool value) { - _upb_sethas(msg, 6); + _upb_sethas(msg, 9); *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_deprecated(google_protobuf_FileOptions *msg, bool value) { - _upb_sethas(msg, 7); + _upb_sethas(msg, 10); *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_java_string_check_utf8(google_protobuf_FileOptions *msg, bool value) { - _upb_sethas(msg, 8); + _upb_sethas(msg, 11); *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_cc_enable_arenas(google_protobuf_FileOptions *msg, bool value) { - _upb_sethas(msg, 9); + _upb_sethas(msg, 12); *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_objc_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) { - _upb_sethas(msg, 14); + _upb_sethas(msg, 13); *UPB_PTR_AT(msg, UPB_SIZE(44, 72), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_csharp_namespace(google_protobuf_FileOptions *msg, upb_strview value) { - _upb_sethas(msg, 15); + _upb_sethas(msg, 14); *UPB_PTR_AT(msg, UPB_SIZE(52, 88), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_swift_prefix(google_protobuf_FileOptions *msg, upb_strview value) { - _upb_sethas(msg, 16); + _upb_sethas(msg, 15); *UPB_PTR_AT(msg, UPB_SIZE(60, 104), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_php_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) { - _upb_sethas(msg, 17); + _upb_sethas(msg, 16); *UPB_PTR_AT(msg, UPB_SIZE(68, 120), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_php_namespace(google_protobuf_FileOptions *msg, upb_strview value) { - _upb_sethas(msg, 18); + _upb_sethas(msg, 17); *UPB_PTR_AT(msg, UPB_SIZE(76, 136), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_php_generic_services(google_protobuf_FileOptions *msg, bool value) { - _upb_sethas(msg, 10); + _upb_sethas(msg, 18); *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_php_metadata_namespace(google_protobuf_FileOptions *msg, upb_strview value) { @@ -2695,6 +3234,12 @@ UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_parse( google_protobuf_MessageOptions *ret = google_protobuf_MessageOptions_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_MessageOptions_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_MessageOptions *ret = google_protobuf_MessageOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_MessageOptions_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_MessageOptions_serialize(const google_protobuf_MessageOptions *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_MessageOptions_msginit, arena, len); } @@ -2750,19 +3295,25 @@ UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_parse(cons google_protobuf_FieldOptions *ret = google_protobuf_FieldOptions_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_FieldOptions_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_FieldOptions *ret = google_protobuf_FieldOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_FieldOptions_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_FieldOptions_serialize(const google_protobuf_FieldOptions *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_FieldOptions_msginit, arena, len); } UPB_INLINE bool google_protobuf_FieldOptions_has_ctype(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 1); } UPB_INLINE int32_t google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } -UPB_INLINE bool google_protobuf_FieldOptions_has_packed(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE bool google_protobuf_FieldOptions_has_packed(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 2); } UPB_INLINE bool google_protobuf_FieldOptions_packed(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool); } -UPB_INLINE bool google_protobuf_FieldOptions_has_deprecated(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE bool google_protobuf_FieldOptions_has_deprecated(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 3); } UPB_INLINE bool google_protobuf_FieldOptions_deprecated(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool); } -UPB_INLINE bool google_protobuf_FieldOptions_has_lazy(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 5); } +UPB_INLINE bool google_protobuf_FieldOptions_has_lazy(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 4); } UPB_INLINE bool google_protobuf_FieldOptions_lazy(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool); } -UPB_INLINE bool google_protobuf_FieldOptions_has_jstype(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE bool google_protobuf_FieldOptions_has_jstype(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 5); } UPB_INLINE int32_t google_protobuf_FieldOptions_jstype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } UPB_INLINE bool google_protobuf_FieldOptions_has_weak(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 6); } UPB_INLINE bool google_protobuf_FieldOptions_weak(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool); } @@ -2774,19 +3325,19 @@ UPB_INLINE void google_protobuf_FieldOptions_set_ctype(google_protobuf_FieldOpti *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; } UPB_INLINE void google_protobuf_FieldOptions_set_packed(google_protobuf_FieldOptions *msg, bool value) { - _upb_sethas(msg, 3); + _upb_sethas(msg, 2); *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool) = value; } UPB_INLINE void google_protobuf_FieldOptions_set_deprecated(google_protobuf_FieldOptions *msg, bool value) { - _upb_sethas(msg, 4); + _upb_sethas(msg, 3); *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool) = value; } UPB_INLINE void google_protobuf_FieldOptions_set_lazy(google_protobuf_FieldOptions *msg, bool value) { - _upb_sethas(msg, 5); + _upb_sethas(msg, 4); *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool) = value; } UPB_INLINE void google_protobuf_FieldOptions_set_jstype(google_protobuf_FieldOptions *msg, int32_t value) { - _upb_sethas(msg, 2); + _upb_sethas(msg, 5); *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; } UPB_INLINE void google_protobuf_FieldOptions_set_weak(google_protobuf_FieldOptions *msg, bool value) { @@ -2817,6 +3368,12 @@ UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_parse(cons google_protobuf_OneofOptions *ret = google_protobuf_OneofOptions_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_OneofOptions_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_OneofOptions *ret = google_protobuf_OneofOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_OneofOptions_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_OneofOptions_serialize(const google_protobuf_OneofOptions *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_OneofOptions_msginit, arena, len); } @@ -2848,6 +3405,12 @@ UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_parse(const google_protobuf_EnumOptions *ret = google_protobuf_EnumOptions_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumOptions_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_EnumOptions *ret = google_protobuf_EnumOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumOptions_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_EnumOptions_serialize(const google_protobuf_EnumOptions *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_EnumOptions_msginit, arena, len); } @@ -2891,6 +3454,12 @@ UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_pa google_protobuf_EnumValueOptions *ret = google_protobuf_EnumValueOptions_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumValueOptions_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_EnumValueOptions *ret = google_protobuf_EnumValueOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumValueOptions_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_EnumValueOptions_serialize(const google_protobuf_EnumValueOptions *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_EnumValueOptions_msginit, arena, len); } @@ -2928,6 +3497,12 @@ UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_parse( google_protobuf_ServiceOptions *ret = google_protobuf_ServiceOptions_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_ServiceOptions_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_ServiceOptions *ret = google_protobuf_ServiceOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_ServiceOptions_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_ServiceOptions_serialize(const google_protobuf_ServiceOptions *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_ServiceOptions_msginit, arena, len); } @@ -2965,23 +3540,29 @@ UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_parse(co google_protobuf_MethodOptions *ret = google_protobuf_MethodOptions_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_MethodOptions_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_MethodOptions *ret = google_protobuf_MethodOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_MethodOptions_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_MethodOptions_serialize(const google_protobuf_MethodOptions *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_MethodOptions_msginit, arena, len); } -UPB_INLINE bool google_protobuf_MethodOptions_has_deprecated(const google_protobuf_MethodOptions *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE bool google_protobuf_MethodOptions_has_deprecated(const google_protobuf_MethodOptions *msg) { return _upb_hasbit(msg, 1); } UPB_INLINE bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool); } -UPB_INLINE bool google_protobuf_MethodOptions_has_idempotency_level(const google_protobuf_MethodOptions *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE bool google_protobuf_MethodOptions_has_idempotency_level(const google_protobuf_MethodOptions *msg) { return _upb_hasbit(msg, 2); } UPB_INLINE int32_t google_protobuf_MethodOptions_idempotency_level(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } UPB_INLINE bool google_protobuf_MethodOptions_has_uninterpreted_option(const google_protobuf_MethodOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(12, 16)); } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MethodOptions_uninterpreted_option(const google_protobuf_MethodOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(12, 16), len); } UPB_INLINE void google_protobuf_MethodOptions_set_deprecated(google_protobuf_MethodOptions *msg, bool value) { - _upb_sethas(msg, 2); + _upb_sethas(msg, 1); *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool) = value; } UPB_INLINE void google_protobuf_MethodOptions_set_idempotency_level(google_protobuf_MethodOptions *msg, int32_t value) { - _upb_sethas(msg, 1); + _upb_sethas(msg, 2); *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_mutable_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t *len) { @@ -3008,19 +3589,25 @@ UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOpt google_protobuf_UninterpretedOption *ret = google_protobuf_UninterpretedOption_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_UninterpretedOption *ret = google_protobuf_UninterpretedOption_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_UninterpretedOption_serialize(const google_protobuf_UninterpretedOption *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_UninterpretedOption_msginit, arena, len); } UPB_INLINE bool google_protobuf_UninterpretedOption_has_name(const google_protobuf_UninterpretedOption *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(56, 80)); } UPB_INLINE const google_protobuf_UninterpretedOption_NamePart* const* google_protobuf_UninterpretedOption_name(const google_protobuf_UninterpretedOption *msg, size_t *len) { return (const google_protobuf_UninterpretedOption_NamePart* const*)_upb_array_accessor(msg, UPB_SIZE(56, 80), len); } -UPB_INLINE bool google_protobuf_UninterpretedOption_has_identifier_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE bool google_protobuf_UninterpretedOption_has_identifier_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 1); } UPB_INLINE upb_strview google_protobuf_UninterpretedOption_identifier_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview); } -UPB_INLINE bool google_protobuf_UninterpretedOption_has_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE bool google_protobuf_UninterpretedOption_has_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 2); } UPB_INLINE uint64_t google_protobuf_UninterpretedOption_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t); } -UPB_INLINE bool google_protobuf_UninterpretedOption_has_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE bool google_protobuf_UninterpretedOption_has_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 3); } UPB_INLINE int64_t google_protobuf_UninterpretedOption_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t); } -UPB_INLINE bool google_protobuf_UninterpretedOption_has_double_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE bool google_protobuf_UninterpretedOption_has_double_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 4); } UPB_INLINE double google_protobuf_UninterpretedOption_double_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double); } UPB_INLINE bool google_protobuf_UninterpretedOption_has_string_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 5); } UPB_INLINE upb_strview google_protobuf_UninterpretedOption_string_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview); } @@ -3041,19 +3628,19 @@ UPB_INLINE struct google_protobuf_UninterpretedOption_NamePart* google_protobuf_ return sub; } UPB_INLINE void google_protobuf_UninterpretedOption_set_identifier_value(google_protobuf_UninterpretedOption *msg, upb_strview value) { - _upb_sethas(msg, 4); + _upb_sethas(msg, 1); *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview) = value; } UPB_INLINE void google_protobuf_UninterpretedOption_set_positive_int_value(google_protobuf_UninterpretedOption *msg, uint64_t value) { - _upb_sethas(msg, 1); + _upb_sethas(msg, 2); *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t) = value; } UPB_INLINE void google_protobuf_UninterpretedOption_set_negative_int_value(google_protobuf_UninterpretedOption *msg, int64_t value) { - _upb_sethas(msg, 2); + _upb_sethas(msg, 3); *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t) = value; } UPB_INLINE void google_protobuf_UninterpretedOption_set_double_value(google_protobuf_UninterpretedOption *msg, double value) { - _upb_sethas(msg, 3); + _upb_sethas(msg, 4); *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double) = value; } UPB_INLINE void google_protobuf_UninterpretedOption_set_string_value(google_protobuf_UninterpretedOption *msg, upb_strview value) { @@ -3075,21 +3662,27 @@ UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_Uninter google_protobuf_UninterpretedOption_NamePart *ret = google_protobuf_UninterpretedOption_NamePart_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_UninterpretedOption_NamePart *ret = google_protobuf_UninterpretedOption_NamePart_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_UninterpretedOption_NamePart_serialize(const google_protobuf_UninterpretedOption_NamePart *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_UninterpretedOption_NamePart_msginit, arena, len); } -UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_hasbit(msg, 1); } UPB_INLINE upb_strview google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } -UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_hasbit(msg, 2); } UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_name_part(google_protobuf_UninterpretedOption_NamePart *msg, upb_strview value) { - _upb_sethas(msg, 2); + _upb_sethas(msg, 1); *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; } UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_is_extension(google_protobuf_UninterpretedOption_NamePart *msg, bool value) { - _upb_sethas(msg, 1); + _upb_sethas(msg, 2); *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; } @@ -3103,6 +3696,12 @@ UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_parse( google_protobuf_SourceCodeInfo *ret = google_protobuf_SourceCodeInfo_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_SourceCodeInfo *ret = google_protobuf_SourceCodeInfo_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_SourceCodeInfo_serialize(const google_protobuf_SourceCodeInfo *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_SourceCodeInfo_msginit, arena, len); } @@ -3134,6 +3733,12 @@ UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeIn google_protobuf_SourceCodeInfo_Location *ret = google_protobuf_SourceCodeInfo_Location_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_SourceCodeInfo_Location *ret = google_protobuf_SourceCodeInfo_Location_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_SourceCodeInfo_Location_serialize(const google_protobuf_SourceCodeInfo_Location *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_SourceCodeInfo_Location_msginit, arena, len); } @@ -3195,6 +3800,12 @@ UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_ google_protobuf_GeneratedCodeInfo *ret = google_protobuf_GeneratedCodeInfo_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_GeneratedCodeInfo *ret = google_protobuf_GeneratedCodeInfo_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_GeneratedCodeInfo_serialize(const google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_msginit, arena, len); } @@ -3226,16 +3837,22 @@ UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_Generat google_protobuf_GeneratedCodeInfo_Annotation *ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena); return (ret && upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena)) ? ret : NULL; } +UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_GeneratedCodeInfo_Annotation *ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena, options)) + ? ret : NULL; +} UPB_INLINE char *google_protobuf_GeneratedCodeInfo_Annotation_serialize(const google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_arena *arena, size_t *len) { return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena, len); } UPB_INLINE int32_t const* google_protobuf_GeneratedCodeInfo_Annotation_path(const google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 32), len); } -UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 1); } UPB_INLINE upb_strview google_protobuf_GeneratedCodeInfo_Annotation_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview); } -UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 2); } UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } -UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 3); } UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_mutable_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) { @@ -3249,15 +3866,15 @@ UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_add_path(google_pro arena); } UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_source_file(google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_strview value) { - _upb_sethas(msg, 3); + _upb_sethas(msg, 1); *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview) = value; } UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_begin(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) { - _upb_sethas(msg, 1); + _upb_sethas(msg, 2); *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; } UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) { - _upb_sethas(msg, 2); + _upb_sethas(msg, 3); *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; } @@ -3284,6 +3901,7 @@ UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_prot #define UPB_DEF_H_ +/* Must be last. */ #ifdef __cplusplus extern "C" { @@ -3542,6 +4160,7 @@ int upb_filedef_enumcount(const upb_filedef *f); 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_enumdef *upb_filedef_enum(const upb_filedef *f, int i); +const upb_symtab *upb_filedef_symtab(const upb_filedef *f); /* upb_symtab *****************************************************************/ @@ -3559,6 +4178,7 @@ const upb_filedef *upb_symtab_addfile( upb_symtab *s, const google_protobuf_FileDescriptorProto *file, upb_status *status); 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. */ typedef struct upb_def_init { @@ -3742,6 +4362,10 @@ UPB_INLINE const upb_msgdef *google_protobuf_GeneratedCodeInfo_Annotation_getmsg +#ifdef __cplusplus +extern "C" { +#endif + typedef union { bool bool_val; float float_val; @@ -3762,6 +4386,8 @@ typedef union { upb_array* array; } upb_mutmsgval; +upb_msgval upb_fielddef_default(const upb_fielddef *f); + /** upb_msg *******************************************************************/ /* Creates a new message of the given type in the given arena. */ @@ -3897,6 +4523,10 @@ upb_msgval upb_mapiter_value(const upb_map *map, size_t iter); * iterator must not have been initialized const. */ void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value); +#ifdef __cplusplus +} /* extern "C" */ +#endif + #endif /* UPB_REFLECTION_H_ */ diff --git a/php/ext/google/protobuf/protobuf.h b/php/ext/google/protobuf/protobuf.h index 322567ec70..232528288a 100644 --- a/php/ext/google/protobuf/protobuf.h +++ b/php/ext/google/protobuf/protobuf.h @@ -58,13 +58,13 @@ const zval *get_generated_pool(); #if PHP_VERSION_ID < 80000 #define PROTO_VAL 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_STRLEN_P(obj) Z_STRLEN_P(obj) #else #define PROTO_VAL zend_object #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_STRLEN_P(obj) ZSTR_LEN(obj) #endif diff --git a/php/src/Google/Protobuf/Internal/FileOptions.php b/php/src/Google/Protobuf/Internal/FileOptions.php index f415b07f2c..6283b2ad7a 100644 --- a/php/src/Google/Protobuf/Internal/FileOptions.php +++ b/php/src/Google/Protobuf/Internal/FileOptions.php @@ -49,6 +49,7 @@ class FileOptions extends \Google\Protobuf\Internal\Message * This option does nothing. * * Generated from protobuf field optional bool java_generate_equals_and_hash = 20 [deprecated = true]; + * @deprecated */ protected $java_generate_equals_and_hash = null; /** @@ -412,19 +413,23 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool java_generate_equals_and_hash = 20 [deprecated = true]; * @return bool + * @deprecated */ 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; } public function hasJavaGenerateEqualsAndHash() { + @trigger_error('java_generate_equals_and_hash is deprecated.', E_USER_DEPRECATED); return isset($this->java_generate_equals_and_hash); } public function clearJavaGenerateEqualsAndHash() { + @trigger_error('java_generate_equals_and_hash is deprecated.', E_USER_DEPRECATED); unset($this->java_generate_equals_and_hash); } @@ -434,9 +439,11 @@ class FileOptions extends \Google\Protobuf\Internal\Message * Generated from protobuf field optional bool java_generate_equals_and_hash = 20 [deprecated = true]; * @param bool $var * @return $this + * @deprecated */ public function setJavaGenerateEqualsAndHash($var) { + @trigger_error('java_generate_equals_and_hash is deprecated.', E_USER_DEPRECATED); GPBUtil::checkBool($var); $this->java_generate_equals_and_hash = $var; diff --git a/php/src/Google/Protobuf/Internal/GPBWire.php b/php/src/Google/Protobuf/Internal/GPBWire.php index 7f1eab3c65..29569530fd 100644 --- a/php/src/Google/Protobuf/Internal/GPBWire.php +++ b/php/src/Google/Protobuf/Internal/GPBWire.php @@ -50,8 +50,8 @@ class GPBWire public static function getTagFieldNumber($tag) { - return ($tag >> self::TAG_TYPE_BITS) & - (1 << ((PHP_INT_SIZE * 8) - self::TAG_TYPE_BITS)) - 1; + // We have to mask because PHP has no arithmetic shift. + return ($tag >> self::TAG_TYPE_BITS) & 0x1fffffff; } public static function getTagWireType($tag) diff --git a/php/src/Google/Protobuf/Internal/Message.php b/php/src/Google/Protobuf/Internal/Message.php index c02d2b4517..64aadf9d26 100644 --- a/php/src/Google/Protobuf/Internal/Message.php +++ b/php/src/Google/Protobuf/Internal/Message.php @@ -93,8 +93,9 @@ class Message $pool = DescriptorPool::getGeneratedPool(); $this->desc = $pool->getDescriptorByClassName(get_class($this)); if (is_null($this->desc)) { - user_error(get_class($this) . " is not found in descriptor pool."); - return; + throw new \InvalidArgumentException( + get_class($this) ." is not found in descriptor pool. " . + 'Only generated classes may derive from Message.'); } foreach ($this->desc->getField() as $field) { $setter = $field->getSetter(); diff --git a/php/tests/ArrayTest.php b/php/tests/ArrayTest.php index 269d11d3a2..0585ca5b1c 100644 --- a/php/tests/ArrayTest.php +++ b/php/tests/ArrayTest.php @@ -624,4 +624,16 @@ class ArrayTest extends TestBase new RepeatedField(GPBType::MESSAGE, TestMessage::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]); + } } diff --git a/php/tests/EncodeDecodeTest.php b/php/tests/EncodeDecodeTest.php index 6368a188a4..d471a5a17a 100644 --- a/php/tests/EncodeDecodeTest.php +++ b/php/tests/EncodeDecodeTest.php @@ -14,6 +14,7 @@ use Foo\TestStringValue; use Foo\TestBytesValue; use Foo\TestAny; use Foo\TestEnum; +use Foo\TestLargeFieldNumber; use Foo\TestMessage; use Foo\TestMessage\Sub; use Foo\TestPackedMessage; @@ -529,6 +530,15 @@ class EncodeDecodeTest extends TestBase $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() { $this->expectException(Exception::class); diff --git a/php/tests/GeneratedClassTest.php b/php/tests/GeneratedClassTest.php index f3f74d1d3c..f2a9fb057d 100644 --- a/php/tests/GeneratedClassTest.php +++ b/php/tests/GeneratedClassTest.php @@ -24,6 +24,13 @@ use Foo\testLowerCaseEnum; use PBEmpty\PBEcho\TestEmptyPackage; 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 { @@ -71,6 +78,33 @@ class GeneratedClassTest extends TestBase $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. ######################################################### @@ -1491,6 +1525,28 @@ class GeneratedClassTest extends TestBase $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. ######################################################### @@ -1696,6 +1752,16 @@ class GeneratedClassTest extends TestBase $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 ######################################################### diff --git a/php/tests/GeneratedPhpdocTest.php b/php/tests/GeneratedPhpdocTest.php index de672ac84e..18963a9b39 100644 --- a/php/tests/GeneratedPhpdocTest.php +++ b/php/tests/GeneratedPhpdocTest.php @@ -340,6 +340,13 @@ class GeneratedPhpdocTest extends TestBase ], '@param \NoNamespaceMessage $var' ], + [ + [ + 'setDeprecatedOptionalInt32', + 'getDeprecatedOptionalInt32', + ], + '@deprecated' + ], ]; } } diff --git a/php/tests/MapFieldTest.php b/php/tests/MapFieldTest.php index a96f24fb58..2d8ae61c7b 100644 --- a/php/tests/MapFieldTest.php +++ b/php/tests/MapFieldTest.php @@ -511,6 +511,24 @@ class MapFieldTest extends TestBase { 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 ######################################################### diff --git a/php/tests/proto/test.proto b/php/tests/proto/test.proto index 368b19ec4d..609b8cfe0c 100644 --- a/php/tests/proto/test.proto +++ b/php/tests/proto/test.proto @@ -147,6 +147,9 @@ message TestMessage { map map_string_any = 122; map map_string_list = 123; map map_string_struct = 124; + + // deprecated field + int32 deprecated_optional_int32 = 125 [deprecated=true]; } enum TestEnum { @@ -220,6 +223,10 @@ message TestRandomFieldOrder { string tag14 = 160; } +message TestLargeFieldNumber { + int32 large_field_number = 536870911; +} + message TestReverseFieldOrder { repeated int32 a = 2; string b = 1; diff --git a/python/release/wheel/Dockerfile b/python/release/wheel/Dockerfile deleted file mode 100644 index f38ec2f584..0000000000 --- a/python/release/wheel/Dockerfile +++ /dev/null @@ -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 / diff --git a/python/release/wheel/README.md b/python/release/wheel/README.md deleted file mode 100644 index edda2cd701..0000000000 --- a/python/release/wheel/README.md +++ /dev/null @@ -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. | diff --git a/python/release/wheel/build_wheel_manylinux.sh b/python/release/wheel/build_wheel_manylinux.sh deleted file mode 100755 index 39fd8c1273..0000000000 --- a/python/release/wheel/build_wheel_manylinux.sh +++ /dev/null @@ -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 diff --git a/python/release/wheel/protobuf_optimized_pip.sh b/python/release/wheel/protobuf_optimized_pip.sh deleted file mode 100755 index 07c2a093bb..0000000000 --- a/python/release/wheel/protobuf_optimized_pip.sh +++ /dev/null @@ -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/* diff --git a/python/setup.py b/python/setup.py index 39eb18d4bb..aab240a0e5 100755 --- a/python/setup.py +++ b/python/setup.py @@ -207,7 +207,7 @@ if __name__ == '__main__': # 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. 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) < pkg_resources.parse_version('10.9.0')): os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.9' @@ -254,7 +254,7 @@ if __name__ == '__main__': os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp' # 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): install_requires.append('ordereddict') install_requires.append('unittest2') diff --git a/python/tox.ini b/python/tox.ini index 56be1258ae..9fabb6ddbb 100644 --- a/python/tox.ini +++ b/python/tox.ini @@ -1,6 +1,6 @@ [tox] envlist = - py{27,33,34,35,36}-{cpp,python} + py{27,33,34,35,36,37,38,39}-{cpp,python} [testenv] usedevelop=true diff --git a/ruby/ext/google/protobuf_c/ruby-upb.c b/ruby/ext/google/protobuf_c/ruby-upb.c index 9c048da98b..a7aeda2df2 100755 --- a/ruby/ext/google/protobuf_c/ruby-upb.c +++ b/ruby/ext/google/protobuf_c/ruby-upb.c @@ -7793,7 +7793,8 @@ static void jsondec_timestamp(jsondec *d, upb_msg *msg, const upb_msgdef *m) { { /* [+-]08:00 or Z */ - int ofs = 0; + int ofs_hour = 0; + int ofs_min = 0; bool neg = false; if (ptr == end) goto malformed; @@ -7804,9 +7805,10 @@ static void jsondec_timestamp(jsondec *d, upb_msg *msg, const upb_msgdef *m) { /* fallthrough */ case '+': if ((end - ptr) != 5) goto malformed; - ofs = jsondec_tsdigits(d, &ptr, 2, ":00"); - ofs *= 60 * 60; - seconds.int64_val += (neg ? ofs : -ofs); + ofs_hour = jsondec_tsdigits(d, &ptr, 2, ":"); + ofs_min = jsondec_tsdigits(d, &ptr, 2, NULL); + ofs_min = ((ofs_hour * 60) + ofs_min) * 60; + seconds.int64_val += (neg ? ofs_min : -ofs_min); break; case 'Z': if (ptr != end) goto malformed; diff --git a/ruby/ext/google/protobuf_c/ruby-upb.h b/ruby/ext/google/protobuf_c/ruby-upb.h index 106c73b693..fa04393558 100755 --- a/ruby/ext/google/protobuf_c/ruby-upb.h +++ b/ruby/ext/google/protobuf_c/ruby-upb.h @@ -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_enumdef *upb_filedef_enum(const upb_filedef *f, int i); const upb_symtab *upb_filedef_symtab(const upb_filedef *f); -upb_arena *_upb_symtab_arena(const upb_symtab *s); /* upb_symtab *****************************************************************/ @@ -4179,6 +4178,7 @@ const upb_filedef *upb_symtab_addfile( upb_symtab *s, const google_protobuf_FileDescriptorProto *file, upb_status *status); 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. */ typedef struct upb_def_init { diff --git a/src/Makefile.am b/src/Makefile.am index 980a357afd..5940ce187e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -341,6 +341,7 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/cpp/cpp_message_field.cc \ google/protobuf/compiler/cpp/cpp_message_field.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_padding_optimizer.cc \ google/protobuf/compiler/cpp/cpp_padding_optimizer.h \ diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h index cf1de66371..8aa7f4645f 100644 --- a/src/google/protobuf/arena.h +++ b/src/google/protobuf/arena.h @@ -327,7 +327,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { template PROTOBUF_NDEBUG_INLINE static T* CreateArray(Arena* arena, size_t num_elements) { - static_assert(std::is_pod::value, + static_assert(std::is_trivially_default_constructible::value, "CreateArray requires a trivially constructible type"); static_assert(std::is_trivially_destructible::value, "CreateArray requires a trivially destructible type"); diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index ab49ac2614..48594c438c 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -1216,21 +1216,9 @@ PopulateSingleSimpleDescriptorDatabase(const std::string& descriptor_set_name) { bool CommandLineInterface::AllowProto3Optional( const FileDescriptor& file) const { - // If the --experimental_allow_proto3_optional flag was set, we allow. - if (allow_proto3_optional_) return true; - - // 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 false; + // Proto3 optional is enabled by default now, the experimental flag is no + // longer required. + return true; } diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index 1987e08268..2bf0582630 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -2378,48 +2378,6 @@ TEST_F(CommandLineInterfaceTest, MissingValueAtEndError) { 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) { CreateTempFile("google/foo.proto", diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h index e05f49b3d7..5a77639407 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_field.h @@ -165,7 +165,7 @@ class FieldGenerator { } // 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 // syntax (eg `field_(args)`). Does not include `:` or `,` separators. virtual void GenerateConstinitInitializer(io::Printer* printer) const {} diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index d590af3087..6d4412b22a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -75,11 +75,6 @@ std::string GetSortKey(const FileDescriptor& val) { return val.name(); } -template <> -std::string GetSortKey(const SCC& val) { - return val.GetRepresentative()->full_name(); -} - template bool CompareSortKeys(const T* a, const T* b) { return GetSortKey(*a) < GetSortKey(*b); diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc index 4f14802f12..3aebf72c7e 100644 --- a/src/google/protobuf/compiler/java/java_helpers.cc +++ b/src/google/protobuf/compiler/java/java_helpers.cc @@ -90,17 +90,6 @@ const std::unordered_set* kReservedNames = "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* kKotlinForbiddenNames = - new std::unordered_set({ - "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) { for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) { if (field_name == kForbiddenWordList[i]) { diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc index 96c0c11276..f657c17957 100644 --- a/src/google/protobuf/compiler/java/java_message_field.cc +++ b/src/google/protobuf/compiler/java/java_message_field.cc @@ -49,6 +49,7 @@ namespace protobuf { namespace compiler { namespace java { + namespace { void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc index 746ecb2da7..aa5a89c29e 100644 --- a/src/google/protobuf/compiler/js/js_generator.cc +++ b/src/google/protobuf/compiler/js/js_generator.cc @@ -28,9 +28,19 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include #include #include #include @@ -39,17 +49,6 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - namespace google { namespace protobuf { namespace compiler { @@ -173,8 +172,8 @@ std::string GetNestedMessageName(const Descriptor* descriptor) { if (descriptor == NULL) { return ""; } - std::string result = StripPrefixString( - descriptor->full_name(), descriptor->file()->package()); + std::string result = + StripPrefixString(descriptor->full_name(), descriptor->file()->package()); // Add a leading dot if one is not already present. if (!result.empty() && result[0] != '.') { result = "." + result; @@ -411,7 +410,7 @@ std::string GetMessagesFileName(const GeneratorOptions& options, const SCC* scc, GetSnakeFilename(scc->GetRepresentative()->file()->name())); (*long_name_dict)[scc->GetRepresentative()] = StrCat(snake_name, "_long_sccs_", - static_cast((*long_name_dict).size())); + static_cast((*long_name_dict).size())); } filename_base = (*long_name_dict)[scc->GetRepresentative()]; } @@ -431,9 +430,7 @@ std::string GetEnumFileName(const GeneratorOptions& options, } // Returns the message/response ID, if set. -std::string GetMessageId(const Descriptor* desc) { - return std::string(); -} +std::string GetMessageId(const Descriptor* desc) { return std::string(); } bool IgnoreExtensionField(const FieldDescriptor* field) { // 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"; } - // Used inside Google only -- do not remove. bool IsResponse(const Descriptor* desc) { return false; } @@ -452,7 +448,6 @@ bool IgnoreField(const FieldDescriptor* field) { return IgnoreExtensionField(field); } - // Do we ignore this message type? bool IgnoreMessage(const Descriptor* d) { return d->options().map_entry(); } @@ -537,7 +532,6 @@ std::string JSGetterName(const GeneratorOptions& options, return name; } - std::string JSOneofName(const OneofDescriptor* oneof) { return ToUpperCamel(ParseLowerUnderscore(oneof->name())); } @@ -818,23 +812,19 @@ std::string JSFieldDefault(const FieldDescriptor* field) { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: - return MaybeNumberString(field, - StrCat(field->default_value_int32())); + return MaybeNumberString(field, StrCat(field->default_value_int32())); case FieldDescriptor::CPPTYPE_UINT32: // The original codegen is in Java, and Java protobufs store unsigned // integer values as signed integer values. In order to exactly match the // output, we need to reinterpret as base-2 signed. Ugh. return MaybeNumberString( - field, - StrCat(static_cast(field->default_value_uint32()))); + field, StrCat(static_cast(field->default_value_uint32()))); case FieldDescriptor::CPPTYPE_INT64: - return MaybeNumberString(field, - StrCat(field->default_value_int64())); + return MaybeNumberString(field, StrCat(field->default_value_int64())); case FieldDescriptor::CPPTYPE_UINT64: // See above note for uint32 -- reinterpreting as signed. return MaybeNumberString( - field, - StrCat(static_cast(field->default_value_uint64()))); + field, StrCat(static_cast(field->default_value_uint64()))); case FieldDescriptor::CPPTYPE_ENUM: return StrCat(field->default_value_enum()->number()); case FieldDescriptor::CPPTYPE_BOOL: @@ -849,9 +839,10 @@ std::string JSFieldDefault(const FieldDescriptor* field) { bool is_valid = EscapeJSString(field->default_value_string(), &out); if (!is_valid) { // TODO(b/115551870): Decide whether this should be a hard error. - GOOGLE_LOG(WARNING) << "The default value for field " << field->full_name() - << " was truncated since it contained invalid UTF-8 or" - " codepoints outside the basic multilingual plane."; + GOOGLE_LOG(WARNING) + << "The default value for field " << field->full_name() + << " was truncated since it contained invalid UTF-8 or" + " codepoints outside the basic multilingual plane."; } return "\"" + out + "\""; } else { // Bytes @@ -1114,7 +1105,6 @@ std::string JSBinaryWriterMethodName(const GeneratorOptions& options, JSBinaryReadWriteMethodName(field, /* is_writer = */ true); } - std::string JSTypeTag(const FieldDescriptor* desc) { switch (desc->type()) { case FieldDescriptor::TYPE_DOUBLE: @@ -1149,7 +1139,6 @@ std::string JSTypeTag(const FieldDescriptor* desc) { return ""; } - bool HasRepeatedFields(const GeneratorOptions& options, const Descriptor* desc) { for (int i = 0; i < desc->field_count(); i++) { @@ -1638,6 +1627,8 @@ void Generator::GenerateHeader(const GeneratorOptions& options, "/**\n" " * @fileoverview\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 " "error if a variable or\n" " * field starts with 'MSG_' and isn't a translatable " @@ -1902,16 +1893,13 @@ void Generator::GenerateRequiresImpl(const GeneratorOptions& options, } } -bool NamespaceOnly(const Descriptor* desc) { - return false; -} +bool NamespaceOnly(const Descriptor* desc) { return false; } void Generator::FindRequiresForMessage(const GeneratorOptions& options, const Descriptor* desc, std::set* required, std::set* forwards, bool* have_message) const { - if (!NamespaceOnly(desc)) { *have_message = true; for (int i = 0; i < desc->field_count(); i++) { @@ -1960,7 +1948,8 @@ void Generator::FindRequiresForField(const GeneratorOptions& options, void Generator::FindRequiresForExtension( const GeneratorOptions& options, const FieldDescriptor* field, std::set* required, std::set* 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())); } FindRequiresForField(options, field, required, forwards); @@ -2000,7 +1989,6 @@ void Generator::GenerateClass(const GeneratorOptions& options, printer->Print("\n"); GenerateClassFieldInfo(options, printer, desc); - GenerateClassToObject(options, printer, desc); // These must come *before* the extension-field info generation in // GenerateClassRegistration so that references to the binary @@ -2084,7 +2072,8 @@ void Generator::GenerateClassConstructorAndDeclareExtensionFieldInfo( const Descriptor* desc) const { if (!NamespaceOnly(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); } } @@ -2524,7 +2513,6 @@ void Generator::GenerateClassRegistration(const GeneratorOptions& options, GenerateExtension(options, printer, extension); } } - } void Generator::GenerateClassFields(const GeneratorOptions& options, @@ -2687,8 +2675,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options, } } else { - bool untyped = - false; + bool untyped = false; // Simple (primitive) field, either singular or repeated. @@ -3037,7 +3024,6 @@ void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options, } } - void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options, io::Printer* printer, const Descriptor* desc) const { @@ -3067,36 +3053,36 @@ void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options, "$class$.deserializeBinaryFromReader = function(msg, reader) {\n" " while (reader.nextField()) {\n", "class", GetMessagePath(options, desc)); - printer->Print( - " if (reader.isEndGroup()) {\n" - " break;\n" - " }\n" - " var field = reader.getFieldNumber();\n" - " switch (field) {\n"); + printer->Print( + " if (reader.isEndGroup()) {\n" + " break;\n" + " }\n" + " var field = reader.getFieldNumber();\n" + " switch (field) {\n"); - for (int i = 0; i < desc->field_count(); i++) { - if (!IgnoreField(desc->field(i))) { - GenerateClassDeserializeBinaryField(options, printer, desc->field(i)); - } + for (int i = 0; i < desc->field_count(); i++) { + if (!IgnoreField(desc->field(i))) { + GenerateClassDeserializeBinaryField(options, printer, desc->field(i)); } + } - printer->Print(" default:\n"); - if (IsExtendable(desc)) { - printer->Print( - " jspb.Message.readBinaryExtension(msg, reader,\n" - " $extobj$Binary,\n" - " $class$.prototype.getExtension,\n" - " $class$.prototype.setExtension);\n" - " break;\n" - " }\n", - "extobj", JSExtensionsObjectName(options, desc->file(), desc), - "class", GetMessagePath(options, desc)); - } else { - printer->Print( - " reader.skipField();\n" - " break;\n" - " }\n"); - } + printer->Print(" default:\n"); + if (IsExtendable(desc)) { + printer->Print( + " jspb.Message.readBinaryExtension(msg, reader,\n" + " $extobj$Binary,\n" + " $class$.prototype.getExtension,\n" + " $class$.prototype.setExtension);\n" + " break;\n" + " }\n", + "extobj", JSExtensionsObjectName(options, desc->file(), desc), "class", + GetMessagePath(options, desc)); + } else { + printer->Print( + " reader.skipField();\n" + " break;\n" + " }\n"); + } printer->Print( " }\n" @@ -3381,9 +3367,8 @@ void Generator::GenerateEnum(const GeneratorOptions& options, for (auto i : valid_index) { const EnumValueDescriptor* value = enumdesc->value(i); printer->Print(" $name$: $value$$comma$\n", "name", - ToEnumCase(value->name()), "value", - StrCat(value->number()), "comma", - (i == valid_index.back()) ? "" : ","); + ToEnumCase(value->name()), "value", StrCat(value->number()), + "comma", (i == valid_index.back()) ? "" : ","); printer->Annotate("name", value); } @@ -3424,8 +3409,7 @@ void Generator::GenerateExtension(const GeneratorOptions& options, "!Object} */ (\n" " $toObject$),\n" " $repeated$);\n", - "index", StrCat(field->number()), "name", extension_object_name, - "ctor", + "index", StrCat(field->number()), "name", extension_object_name, "ctor", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ? SubmessageTypeRef(options, field) : std::string("null")), @@ -3732,7 +3716,6 @@ bool Generator::GenerateAll(const std::vector& files, return false; } - if (options.output_mode() == GeneratorOptions::kEverythingInOneFile) { // All output should go in a single file. std::string filename = options.output_dir + "/" + options.library + diff --git a/src/google/protobuf/compiler/php/php_generator.cc b/src/google/protobuf/compiler/php/php_generator.cc index 04d8f8c070..203b49f918 100644 --- a/src/google/protobuf/compiler/php/php_generator.cc +++ b/src/google/protobuf/compiler/php/php_generator.cc @@ -644,43 +644,50 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options, // Generate getter. 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) { printer->Print( "public function get^camel_name^()\n" "{\n" - " return $this->readOneof(^number^);\n" + " ^deprecation_trigger^return $this->readOneof(^number^);\n" "}\n\n" "public function has^camel_name^()\n" "{\n" - " return $this->hasOneof(^number^);\n" + " ^deprecation_trigger^return $this->hasOneof(^number^);\n" "}\n\n", "camel_name", UnderscoresToCamelCase(field->name(), true), - "number", IntToString(field->number())); + "number", IntToString(field->number()), + "deprecation_trigger", deprecation_trigger); } else if (field->has_presence()) { printer->Print( "public function get^camel_name^()\n" "{\n" - " return isset($this->^name^) ? $this->^name^ : ^default_value^;\n" + " ^deprecation_trigger^return isset($this->^name^) ? $this->^name^ : ^default_value^;\n" "}\n\n" "public function has^camel_name^()\n" "{\n" - " return isset($this->^name^);\n" + " ^deprecation_trigger^return isset($this->^name^);\n" "}\n\n" "public function clear^camel_name^()\n" "{\n" - " unset($this->^name^);\n" + " ^deprecation_trigger^unset($this->^name^);\n" "}\n\n", "camel_name", UnderscoresToCamelCase(field->name(), true), "name", field->name(), - "default_value", DefaultForField(field)); + "default_value", DefaultForField(field), + "deprecation_trigger", deprecation_trigger); } else { printer->Print( "public function get^camel_name^()\n" "{\n" - " return $this->^name^;\n" + " ^deprecation_trigger^return $this->^name^;\n" "}\n\n", - "camel_name", UnderscoresToCamelCase(field->name(), true), "name", - field->name()); + "camel_name", UnderscoresToCamelCase(field->name(), true), + "name", field->name(), + "deprecation_trigger", deprecation_trigger); } // For wrapper types, generate an additional getXXXUnwrapped getter @@ -692,10 +699,11 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options, printer->Print( "public function get^camel_name^Unwrapped()\n" "{\n" - " return $this->readWrapperValue(\"^field_name^\");\n" + " ^deprecation_trigger^return $this->readWrapperValue(\"^field_name^\");\n" "}\n\n", "camel_name", UnderscoresToCamelCase(field->name(), true), - "field_name", field->name()); + "field_name", field->name(), + "deprecation_trigger", deprecation_trigger); } // Generate setter. @@ -707,6 +715,13 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options, Indent(printer); + if (field->options().deprecated()) { + printer->Print( + "^deprecation_trigger^", + "deprecation_trigger", deprecation_trigger + ); + } + // Type check. if (field->is_map()) { const Descriptor* map_entry = field->message_type(); @@ -1741,6 +1756,9 @@ void GenerateFieldDocComment(io::Printer* printer, const FieldDescriptor* field, "php_type", PhpGetterTypeName(field, options), "maybe_null", can_return_null ? "|null" : ""); } + if (field->options().deprecated()) { + printer->Print(" * @deprecated\n"); + } printer->Print(" */\n"); } diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc index 0a52804c35..ef7e1f2e7a 100644 --- a/src/google/protobuf/dynamic_message.cc +++ b/src/google/protobuf/dynamic_message.cc @@ -198,44 +198,6 @@ int FieldSpaceUsed(const FieldDescriptor* field) { 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; } static const int kSafeAlignment = sizeof(uint64); diff --git a/src/google/protobuf/generated_message_table_driven_lite.h b/src/google/protobuf/generated_message_table_driven_lite.h index 6813d18bdf..6d58ac72fd 100644 --- a/src/google/protobuf/generated_message_table_driven_lite.h +++ b/src/google/protobuf/generated_message_table_driven_lite.h @@ -87,7 +87,7 @@ inline ExtensionSet* GetExtensionSet(MessageLite* msg, int64 extension_offset) { template inline Type* AddField(MessageLite* msg, int64 offset) { - static_assert(std::is_pod::value, + static_assert(std::is_trivially_copy_assignable::value, "Do not assign"); RepeatedField* repeated = Raw>(msg, offset); @@ -104,7 +104,7 @@ inline std::string* AddField(MessageLite* msg, int64 offset) { template inline void AddField(MessageLite* msg, int64 offset, Type value) { - static_assert(std::is_pod::value, + static_assert(std::is_trivially_copy_assignable::value, "Do not assign"); *AddField(msg, offset) = value; } @@ -126,7 +126,7 @@ inline Type* MutableField(MessageLite* msg, uint32* has_bits, template inline void SetField(MessageLite* msg, uint32* has_bits, uint32 has_bit_index, int64 offset, Type value) { - static_assert(std::is_pod::value, + static_assert(std::is_trivially_copy_assignable::value, "Do not assign"); *MutableField(msg, has_bits, has_bit_index, offset) = value; } diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc index 0cae40fbae..f137675beb 100644 --- a/src/google/protobuf/message_lite.cc +++ b/src/google/protobuf/message_lite.cc @@ -529,6 +529,23 @@ void GenericTypeHandler::Merge(const std::string& from, *to = from; } +// Non-inline variants of std::string specializations for +// various InternalMetadata routines. +template <> +void InternalMetadata::DoClear() { + mutable_unknown_fields()->clear(); +} + +template <> +void InternalMetadata::DoMergeFrom(const std::string& other) { + mutable_unknown_fields()->append(other); +} + +template <> +void InternalMetadata::DoSwap(std::string* other) { + mutable_unknown_fields()->swap(*other); +} + } // namespace internal diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h index dcc6e2411c..8a9b79dfb1 100644 --- a/src/google/protobuf/message_lite.h +++ b/src/google/protobuf/message_lite.h @@ -146,7 +146,7 @@ class ExplicitlyConstructed { private: // Prefer c++14 aligned_storage, but for compatibility this will do. union AlignedUnion { - char space[sizeof(T)]; + alignas(T) char space[sizeof(T)]; int64 align_to_int64; void* align_to_ptr; } union_; diff --git a/src/google/protobuf/message_unittest.inc b/src/google/protobuf/message_unittest.inc index 4608714d1e..003f1fe859 100644 --- a/src/google/protobuf/message_unittest.inc +++ b/src/google/protobuf/message_unittest.inc @@ -552,6 +552,34 @@ TEST(MESSAGE_TEST_NAME, 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) { EXPECT_EQ(MessageFactory::generated_factory()->GetPrototype( UNITTEST::TestAllTypes::descriptor()), diff --git a/src/google/protobuf/metadata_lite.h b/src/google/protobuf/metadata_lite.h index 9f16180915..8e1d24edea 100644 --- a/src/google/protobuf/metadata_lite.h +++ b/src/google/protobuf/metadata_lite.h @@ -68,7 +68,7 @@ class InternalMetadata { void Delete() { // Note that Delete<> should be called not more than once. if (have_unknown_fields() && arena() == NULL) { - delete PtrValue>(); + DeleteOutOfLineHelper(); } } @@ -202,6 +202,11 @@ class InternalMetadata { T unknown_fields; }; + template + PROTOBUF_NOINLINE void DeleteOutOfLineHelper() { + delete PtrValue>(); + } + template PROTOBUF_NOINLINE T* mutable_unknown_fields_slow() { Arena* my_arena = arena(); @@ -221,17 +226,17 @@ class InternalMetadata { // Templated functions. template - void DoClear() { + PROTOBUF_NOINLINE void DoClear() { mutable_unknown_fields()->Clear(); } template - void DoMergeFrom(const T& other) { + PROTOBUF_NOINLINE void DoMergeFrom(const T& other) { mutable_unknown_fields()->MergeFrom(other); } template - void DoSwap(T* other) { + PROTOBUF_NOINLINE void DoSwap(T* other) { mutable_unknown_fields()->Swap(other); } }; @@ -239,20 +244,12 @@ class InternalMetadata { // String Template specializations. template <> -inline void InternalMetadata::DoClear() { - mutable_unknown_fields()->clear(); -} - +PROTOBUF_EXPORT void InternalMetadata::DoClear(); template <> -inline void InternalMetadata::DoMergeFrom( - const std::string& other) { - mutable_unknown_fields()->append(other); -} - +PROTOBUF_EXPORT void InternalMetadata::DoMergeFrom( + const std::string& other); template <> -inline void InternalMetadata::DoSwap(std::string* other) { - mutable_unknown_fields()->swap(*other); -} +PROTOBUF_EXPORT void InternalMetadata::DoSwap(std::string* other); // This helper RAII class is needed to efficiently parse unknown fields. We // should only call mutable_unknown_fields if there are actual unknown fields. diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index 840b80d7f6..6e06281a3c 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -438,7 +438,7 @@ class RepeatedField final { // // The first version executes at 7 cycles per iteration while the second // version near 1 or 2 cycles. - template ::value> + template ::value> class FastAdderImpl { public: explicit FastAdderImpl(RepeatedField* rf) : repeated_field_(rf) { @@ -501,7 +501,7 @@ namespace internal { // effectively. template ::value> + std::is_trivially_copy_constructible::value> struct ElementCopier { void operator()(Element* to, const Element* from, int array_size); }; diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc index 60a44dbe52..c9ab4464ea 100644 --- a/src/google/protobuf/util/internal/default_value_objectwriter.cc +++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc @@ -39,7 +39,6 @@ namespace google { namespace protobuf { namespace util { -using util::Status; namespace converter { namespace { diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc index 0a321386a1..db18b1a333 100644 --- a/src/google/protobuf/util/internal/json_stream_parser.cc +++ b/src/google/protobuf/util/internal/json_stream_parser.cc @@ -52,7 +52,6 @@ namespace util { // Allow these symbols to be referenced as util::Status, util::error::* in // this file. -using util::Status; namespace error { using util::error::CANCELLED; using util::error::INTERNAL; diff --git a/src/google/protobuf/util/internal/json_stream_parser_test.cc b/src/google/protobuf/util/internal/json_stream_parser_test.cc index aa4751d80b..ac6fe3d656 100644 --- a/src/google/protobuf/util/internal/json_stream_parser_test.cc +++ b/src/google/protobuf/util/internal/json_stream_parser_test.cc @@ -42,13 +42,11 @@ namespace google { namespace protobuf { namespace util { -using util::Status; namespace error { using util::error::INVALID_ARGUMENT; } // namespace error namespace converter { -using util::Status; // Tests for the JSON Stream Parser. These tests are intended to be // comprehensive and cover the following: diff --git a/src/google/protobuf/util/internal/proto_writer.cc b/src/google/protobuf/util/internal/proto_writer.cc index a08296471c..0102259e44 100644 --- a/src/google/protobuf/util/internal/proto_writer.cc +++ b/src/google/protobuf/util/internal/proto_writer.cc @@ -54,7 +54,6 @@ namespace converter { using io::CodedOutputStream; using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite; -using util::Status; using util::error::INVALID_ARGUMENT; diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc index 37811b3f5d..49074fbe31 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource.cc +++ b/src/google/protobuf/util/internal/protostream_objectsource.cc @@ -59,7 +59,6 @@ namespace google { namespace protobuf { namespace util { -using util::Status; namespace error { using util::error::Code; using util::error::INTERNAL; @@ -67,7 +66,6 @@ using util::error::INTERNAL; namespace converter { using ::PROTOBUF_NAMESPACE_ID::internal::WireFormat; using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite; -using util::Status; namespace { diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h index 7d98b4e56a..807cbf179e 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource.h +++ b/src/google/protobuf/util/internal/protostream_objectsource.h @@ -74,69 +74,58 @@ class TypeInfo; class PROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { public: struct RenderOptions { - RenderOptions() {} + 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 + // to false, enum values are output without any case conversions. + // + // For example, if we have an enum: + // enum Type { + // ACTION_AND_ADVENTURE = 1; + // } + // Type type = 20; + // + // And this option is set to true. Then the rendered "type" field will have + // the string "actionAndAdventure". + // { + // ... + // "type": "actionAndAdventure", + // ... + // } + // + // If set to false, the rendered "type" field will have the string + // "ACTION_AND_ADVENTURE". + // { + // ... + // "type": "ACTION_AND_ADVENTURE", + // ... + // } bool use_lower_camel_for_enums = false; - // whether to render enums as ints always. defaults to false. + // Sets whether to always output enums as ints, by default this is off, and + // enums are rendered as strings. bool use_ints_for_enums = false; - // whether to preserve proto field names + // Whether to preserve proto field names bool preserve_proto_field_names = false; }; + 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 = {}); + 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: - // enum Type { - // ACTION_AND_ADVENTURE = 1; - // } - // Type type = 20; - // - // And this option is set to true. Then the rendered "type" field will have - // the string "actionAndAdventure". - // { - // ... - // "type": "actionAndAdventure", - // ... - // } - // - // If set to false, the rendered "type" field will have the string - // "ACTION_AND_ADVENTURE". - // { - // ... - // "type": "ACTION_AND_ADVENTURE", - // ... - // } - void set_use_lower_camel_for_enums(bool value) { - render_options_.use_lower_camel_for_enums = value; - } - - // Sets whether to always output enums as ints, by default this is off, and - // enums are rendered as strings. - void set_use_ints_for_enums(bool value) { - render_options_.use_ints_for_enums = value; - } - - // Sets whether to use original proto field names - void set_preserve_proto_field_names(bool value) { - render_options_.preserve_proto_field_names = value; - } - // Sets the max recursion depth of proto message to be deserialized. Proto // messages over this depth will fail to be deserialized. // Default value is 64. @@ -144,7 +133,6 @@ class PROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { max_recursion_depth_ = max_depth; } - protected: // 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 @@ -317,7 +305,7 @@ class PROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { const google::protobuf::Type& type_; - RenderOptions render_options_; + const RenderOptions render_options_; // Tracks current recursion depth. mutable int recursion_depth_; diff --git a/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/google/protobuf/util/internal/protostream_objectsource_test.cc index 4c0caed356..100fef90fa 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource_test.cc +++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc @@ -79,7 +79,6 @@ using proto_util_converter::testing::Proto3Message; using proto_util_converter::testing::StructType; using proto_util_converter::testing::TimestampDuration; using ::testing::_; -using util::Status; namespace { @@ -117,12 +116,13 @@ class ProtostreamObjectSourceTest ArrayInputStream arr_stream(proto.data(), proto.size()); 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 os( - helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor))); - if (use_lower_camel_for_enums_) os->set_use_lower_camel_for_enums(true); - 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); + helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor), + render_options)); os->set_max_recursion_depth(64); return os->WriteTo(&mock_); } diff --git a/src/google/protobuf/util/internal/type_info_test_helper.cc b/src/google/protobuf/util/internal/type_info_test_helper.cc index ccf6fbd836..e8c3c5a3eb 100644 --- a/src/google/protobuf/util/internal/type_info_test_helper.cc +++ b/src/google/protobuf/util/internal/type_info_test_helper.cc @@ -86,12 +86,13 @@ void TypeInfoTestHelper::ResetTypeInfo(const Descriptor* descriptor1, TypeInfo* TypeInfoTestHelper::GetTypeInfo() { return typeinfo_.get(); } 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); switch (type_) { case USE_TYPE_RESOLVER: { return new ProtoStreamObjectSource(coded_input, type_resolver_.get(), - *type); + *type, render_options); } } GOOGLE_LOG(FATAL) << "Can not reach here."; diff --git a/src/google/protobuf/util/internal/type_info_test_helper.h b/src/google/protobuf/util/internal/type_info_test_helper.h index 923050d8b7..c42289e66e 100644 --- a/src/google/protobuf/util/internal/type_info_test_helper.h +++ b/src/google/protobuf/util/internal/type_info_test_helper.h @@ -71,8 +71,9 @@ class TypeInfoTestHelper { // Returns the TypeInfo created after ResetTypeInfo. TypeInfo* GetTypeInfo(); - ProtoStreamObjectSource* NewProtoSource(io::CodedInputStream* coded_input, - const std::string& type_url); + ProtoStreamObjectSource* NewProtoSource( + io::CodedInputStream* coded_input, const std::string& type_url, + ProtoStreamObjectSource::RenderOptions render_options = {}); ProtoStreamObjectWriter* NewProtoWriter( const std::string& type_url, strings::ByteSink* output, diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc index 4cf720e93e..eb81b65e1a 100644 --- a/src/google/protobuf/util/json_util.cc +++ b/src/google/protobuf/util/json_util.cc @@ -92,10 +92,12 @@ util::Status BinaryToJsonStream(TypeResolver* resolver, io::CodedInputStream in_stream(binary_input); google::protobuf::Type type; RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type)); - converter::ProtoStreamObjectSource proto_source(&in_stream, resolver, type); - proto_source.set_use_ints_for_enums(options.always_print_enums_as_ints); - proto_source.set_preserve_proto_field_names( - options.preserve_proto_field_names); + converter::ProtoStreamObjectSource::RenderOptions render_options; + render_options.use_ints_for_enums = options.always_print_enums_as_ints; + render_options.preserve_proto_field_names = + options.preserve_proto_field_names; + converter::ProtoStreamObjectSource proto_source(&in_stream, resolver, type, + render_options); io::CodedOutputStream out_stream(json_output); converter::JsonObjectWriter json_writer(options.add_whitespace ? " " : "", &out_stream); diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc index bf016e4b25..c3c24dafdf 100644 --- a/src/google/protobuf/util/message_differencer.cc +++ b/src/google/protobuf/util/message_differencer.cc @@ -1927,11 +1927,6 @@ void MessageDifferencer::StreamReporter::PrintPath( } } -void MessageDifferencer::StreamReporter::PrintPath( - const std::vector& field_path, bool left_side, - const Message& message) { - PrintPath(field_path, left_side); -} void MessageDifferencer::StreamReporter::PrintValue( const Message& message, const std::vector& field_path, @@ -2100,7 +2095,7 @@ void MessageDifferencer::StreamReporter::ReportAdded( const Message& message1, const Message& message2, const std::vector& field_path) { printer_->Print("added: "); - PrintPath(field_path, false, message2); + PrintPath(field_path, false); printer_->Print(": "); PrintValue(message2, field_path, false); printer_->Print("\n"); // Print for newlines. @@ -2110,7 +2105,7 @@ void MessageDifferencer::StreamReporter::ReportDeleted( const Message& message1, const Message& message2, const std::vector& field_path) { printer_->Print("deleted: "); - PrintPath(field_path, true, message1); + PrintPath(field_path, true); printer_->Print(": "); PrintValue(message1, field_path, true); printer_->Print("\n"); // Print for newlines @@ -2133,10 +2128,10 @@ void MessageDifferencer::StreamReporter::ReportModified( } printer_->Print("modified: "); - PrintPath(field_path, true, message1); + PrintPath(field_path, true); if (CheckPathChanged(field_path)) { printer_->Print(" -> "); - PrintPath(field_path, false, message2); + PrintPath(field_path, false); } printer_->Print(": "); PrintValue(message1, field_path, true); @@ -2149,9 +2144,9 @@ void MessageDifferencer::StreamReporter::ReportMoved( const Message& message1, const Message& message2, const std::vector& field_path) { printer_->Print("moved: "); - PrintPath(field_path, true, message1); + PrintPath(field_path, true); printer_->Print(" -> "); - PrintPath(field_path, false, message2); + PrintPath(field_path, false); printer_->Print(" : "); PrintValue(message1, field_path, true); printer_->Print("\n"); // Print for newlines. @@ -2161,10 +2156,10 @@ void MessageDifferencer::StreamReporter::ReportMatched( const Message& message1, const Message& message2, const std::vector& field_path) { printer_->Print("matched: "); - PrintPath(field_path, true, message1); + PrintPath(field_path, true); if (CheckPathChanged(field_path)) { printer_->Print(" -> "); - PrintPath(field_path, false, message2); + PrintPath(field_path, false); } printer_->Print(" : "); PrintValue(message1, field_path, true); @@ -2175,10 +2170,10 @@ void MessageDifferencer::StreamReporter::ReportIgnored( const Message& message1, const Message& message2, const std::vector& field_path) { printer_->Print("ignored: "); - PrintPath(field_path, true, message1); + PrintPath(field_path, true); if (CheckPathChanged(field_path)) { printer_->Print(" -> "); - PrintPath(field_path, false, message2); + PrintPath(field_path, false); } printer_->Print("\n"); // Print for newlines. } @@ -2193,10 +2188,10 @@ void MessageDifferencer::StreamReporter::ReportUnknownFieldIgnored( const Message& message1, const Message& message2, const std::vector& field_path) { printer_->Print("ignored: "); - PrintPath(field_path, true, message1); + PrintPath(field_path, true); if (CheckPathChanged(field_path)) { printer_->Print(" -> "); - PrintPath(field_path, false, message2); + PrintPath(field_path, false); } printer_->Print("\n"); // Print for newlines. } diff --git a/src/google/protobuf/util/message_differencer.h b/src/google/protobuf/util/message_differencer.h index 5889a9a9ef..61d9f9b5d3 100644 --- a/src/google/protobuf/util/message_differencer.h +++ b/src/google/protobuf/util/message_differencer.h @@ -673,11 +673,6 @@ class PROTOBUF_EXPORT MessageDifferencer { void SetMessages(const Message& message1, const Message& message2); protected: - // Prints the specified path of fields to the buffer. message is used to - // print map keys. - virtual void PrintPath(const std::vector& field_path, - bool left_side, const Message& message); - // Prints the specified path of fields to the buffer. virtual void PrintPath(const std::vector& field_path, bool left_side); diff --git a/tests.sh b/tests.sh index e445384e53..1135f95ca8 100755 --- a/tests.sh +++ b/tests.sh @@ -356,6 +356,10 @@ build_python38() { build_python_version py38-python } +build_python39() { + build_python_version py39-python +} + build_python_cpp() { internal_build_cpp export LD_LIBRARY_PATH=../src/.libs # for Linux @@ -408,6 +412,10 @@ build_python38_cpp() { build_python_cpp_version py38-cpp } +build_python39_cpp() { + build_python_cpp_version py39-cpp +} + build_python_compatibility() { internal_build_cpp # Use the unit-tests extracted from 2.5.0 to test the compatibility. @@ -476,6 +484,16 @@ use_php_zts() { internal_build_cpp } +build_php5.6() { + use_php 5.6 + pushd php + rm -rf vendor + composer update + composer test + popd + (cd conformance && make test_php) +} + build_php7.0() { use_php 7.0 pushd php @@ -675,6 +693,7 @@ build_php8.0_all() { } build_php_all_32() { + build_php5.6 build_php7.0 build_php7.1 build_php7.4