Merge branch 'master' into expand-wildcards

pull/5044/head
Laszlo Csomor 6 years ago
commit ea61636cbc
  1. 26
      BUILD
  2. 2
      Makefile.am
  3. 42
      Protobuf-C++.podspec
  4. 62
      build_files_updated_unittest.sh
  5. 1
      cmake/extract_includes.bat.in
  6. 14
      cmake/tests.cmake
  7. 286
      conformance/binary_json_conformance_suite.cc
  8. 6
      conformance/binary_json_conformance_suite.h
  9. 11
      conformance/conformance_objc.m
  10. 41
      conformance/conformance_test.cc
  11. 6
      conformance/conformance_test.h
  12. 70
      conformance/failure_list_js.txt
  13. 4
      conformance/failure_list_objc.txt
  14. 40
      conformance/failure_list_php.txt
  15. 42
      conformance/failure_list_php_c.txt
  16. 46
      conformance/failure_list_ruby.txt
  17. 48
      conformance/failure_list_ruby_mac.txt
  18. 6
      csharp/compatibility_tests/v3.0.0/test.sh
  19. BIN
      csharp/src/Google.Protobuf.Test/testprotos.pb
  20. 197
      csharp/src/Google.Protobuf/FieldCodec.cs
  21. 2
      csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs
  22. 571
      java/core/src/main/java/com/google/protobuf/FieldSet.java
  23. 102
      java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
  24. 3
      java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java
  25. 196
      java/core/src/main/java/com/google/protobuf/TextFormat.java
  26. 160
      java/core/src/main/java/com/google/protobuf/TypeRegistry.java
  27. 154
      java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
  28. 6
      java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java
  29. 191
      java/core/src/test/java/com/google/protobuf/TextFormatTest.java
  30. 70
      java/core/src/test/java/com/google/protobuf/TypeRegistryTest.java
  31. 2
      java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto
  32. 1
      java/lite/pom.xml
  33. 136
      java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
  34. 51
      java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
  35. 94
      js/binary/decoder.js
  36. 37
      js/binary/decoder_test.js
  37. 34
      js/binary/reader.js
  38. 20
      js/binary/reader_test.js
  39. 67
      js/binary/utils.js
  40. 216
      js/binary/utils_test.js
  41. 98
      js/binary/writer.js
  42. 71
      js/binary/writer_test.js
  43. 8
      js/map.js
  44. 98
      js/message.js
  45. 1
      js/message_test.js
  46. 9
      js/test.proto
  47. 19
      kokoro/linux/bazel/build.sh
  48. 1
      kokoro/release/python/linux/build_artifacts.sh
  49. 1
      kokoro/release/python/macos/build_artifacts.sh
  50. 2
      objectivec/google/protobuf/Duration.pbobjc.h
  51. 28
      protobuf_deps.bzl
  52. 7
      python/google/protobuf/internal/message_test.py
  53. 2
      python/google/protobuf/internal/python_message.py
  54. 4
      python/google/protobuf/internal/well_known_types.py
  55. 9
      python/google/protobuf/internal/well_known_types_test.py
  56. 5
      python/google/protobuf/pyext/map_container.cc
  57. 6
      python/google/protobuf/pyext/message.cc
  58. 8
      ruby/ext/google/protobuf_c/map.c
  59. 4
      ruby/ext/google/protobuf_c/message.c
  60. 14
      ruby/tests/basic.rb
  61. 54
      ruby/tests/well_known_types_test.rb
  62. 8
      src/Makefile.am
  63. 26
      src/google/protobuf/any.pb.cc
  64. 44
      src/google/protobuf/any.pb.h
  65. 1
      src/google/protobuf/any_lite.cc
  66. 1
      src/google/protobuf/any_test.cc
  67. 176
      src/google/protobuf/api.pb.cc
  68. 157
      src/google/protobuf/api.pb.h
  69. 2
      src/google/protobuf/arena.h
  70. 4
      src/google/protobuf/compiler/command_line_interface.cc
  71. 5
      src/google/protobuf/compiler/command_line_interface_unittest.cc
  72. 2
      src/google/protobuf/compiler/cpp/cpp_extension.cc
  73. 1
      src/google/protobuf/compiler/cpp/cpp_field.cc
  74. 85
      src/google/protobuf/compiler/cpp/cpp_file.cc
  75. 3
      src/google/protobuf/compiler/cpp/cpp_file.h
  76. 2
      src/google/protobuf/compiler/cpp/cpp_generator.cc
  77. 34
      src/google/protobuf/compiler/cpp/cpp_helpers.cc
  78. 15
      src/google/protobuf/compiler/cpp/cpp_helpers.h
  79. 53
      src/google/protobuf/compiler/cpp/cpp_message.cc
  80. 122
      src/google/protobuf/compiler/cpp/cpp_message_field.cc
  81. 1
      src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
  82. 163
      src/google/protobuf/compiler/cpp/cpp_string_field.cc
  83. 2
      src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
  84. 2
      src/google/protobuf/compiler/csharp/csharp_helpers.h
  85. 2
      src/google/protobuf/compiler/csharp/csharp_names.h
  86. 10
      src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
  87. 5
      src/google/protobuf/compiler/importer.cc
  88. 1
      src/google/protobuf/compiler/java/java_context.cc
  89. 52
      src/google/protobuf/compiler/java/java_doc_comment.cc
  90. 2
      src/google/protobuf/compiler/java/java_doc_comment.h
  91. 11
      src/google/protobuf/compiler/java/java_enum.cc
  92. 1
      src/google/protobuf/compiler/java/java_enum_field.cc
  93. 1
      src/google/protobuf/compiler/java/java_enum_field_lite.cc
  94. 1
      src/google/protobuf/compiler/java/java_enum_lite.cc
  95. 1
      src/google/protobuf/compiler/java/java_extension.cc
  96. 1
      src/google/protobuf/compiler/java/java_field.cc
  97. 1
      src/google/protobuf/compiler/java/java_file.cc
  98. 3
      src/google/protobuf/compiler/java/java_helpers.cc
  99. 2
      src/google/protobuf/compiler/java/java_message.cc
  100. 2
      src/google/protobuf/compiler/java/java_message_builder.cc
  101. Some files were not shown because too many files have changed in this diff Show More

26
BUILD

@ -1,5 +1,9 @@
# Bazel (https://bazel.build/) BUILD file for Protobuf.
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test", "objc_library")
load("@rules_java//java:defs.bzl", "java_library")
load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain", "proto_library")
licenses(["notice"])
exports_files(["LICENSE"])
@ -103,10 +107,10 @@ LINK_OPTS = select({
load(
":protobuf.bzl",
"cc_proto_library",
"py_proto_library",
"internal_copied_filegroup",
"internal_gen_well_known_protos_java",
"internal_protobuf_py_tests",
"py_proto_library",
)
cc_library(
@ -493,6 +497,7 @@ cc_proto_library(
COMMON_TEST_SRCS = [
# AUTOGEN(common_test_srcs)
"src/google/protobuf/arena_test_util.cc",
"src/google/protobuf/map_test_util.inc",
"src/google/protobuf/test_util.cc",
"src/google/protobuf/test_util.inc",
"src/google/protobuf/testing/file.cc",
@ -605,7 +610,7 @@ cc_test(
"src/google/protobuf/wire_format_unittest.cc",
] + select({
"//conditions:default": [
# Doesn't pass on Windows with MSVC
# AUTOGEN(non_msvc_test_srcs)
"src/google/protobuf/compiler/command_line_interface_unittest.cc",
],
":msvc": [],
@ -1216,3 +1221,20 @@ cc_binary(
":text_format_conformance_suite",
],
)
sh_test(
name = "build_files_updated_unittest",
srcs = [
"build_files_updated_unittest.sh",
],
data = [
"BUILD",
"cmake/extract_includes.bat.in",
"cmake/libprotobuf.cmake",
"cmake/libprotobuf-lite.cmake",
"cmake/libprotoc.cmake",
"cmake/tests.cmake",
"src/Makefile.am",
"update_file_lists.sh",
],
)

@ -339,6 +339,7 @@ java_EXTRA_DIST=
java/core/src/main/java/com/google/protobuf/TextFormatEscaper.java \
java/core/src/main/java/com/google/protobuf/TextFormatParseInfoTree.java \
java/core/src/main/java/com/google/protobuf/TextFormatParseLocation.java \
java/core/src/main/java/com/google/protobuf/TypeRegistry.java \
java/core/src/main/java/com/google/protobuf/UninitializedMessageException.java \
java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java \
java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java \
@ -435,6 +436,7 @@ java_EXTRA_DIST=
java/core/src/test/java/com/google/protobuf/TextFormatParseInfoTreeTest.java \
java/core/src/test/java/com/google/protobuf/TextFormatParseLocationTest.java \
java/core/src/test/java/com/google/protobuf/TextFormatTest.java \
java/core/src/test/java/com/google/protobuf/TypeRegistryTest.java \
java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java \
java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java \
java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java \

@ -0,0 +1,42 @@
Pod::Spec.new do |s|
s.name = 'Protobuf-C++'
s.version = '3.9.0-rc1'
s.summary = 'Protocol Buffers v3 runtime library for C++.'
s.homepage = 'https://github.com/google/protobuf'
s.license = '3-Clause BSD License'
s.authors = { 'The Protocol Buffers contributors' => 'protobuf@googlegroups.com' }
s.cocoapods_version = '>= 1.0'
s.source = { :git => 'https://github.com/google/protobuf.git',
:tag => "v#{s.version}" }
s.source_files = 'src/google/protobuf/*.{h,cc,inc}',
'src/google/protobuf/stubs/*.{h,cc}',
'src/google/protobuf/io/*.{h,cc}',
'src/google/protobuf/util/*.{h,cc}',
'src/google/protobuf/util/internal/*.{h,cc}'
# Excluding all the tests in the directories above
s.exclude_files = 'src/google/**/*_test.{h,cc,inc}',
'src/google/**/*_unittest.{h,cc}',
'src/google/protobuf/test_util*.{h,cc}',
'src/google/protobuf/map_lite_test_util.{h,cc}',
'src/google/protobuf/map_test_util*.{h,cc,inc}'
s.header_mappings_dir = 'src'
s.ios.deployment_target = '7.0'
s.osx.deployment_target = '10.9'
s.tvos.deployment_target = '9.0'
s.watchos.deployment_target = '2.0'
s.pod_target_xcconfig = {
# Do not let src/google/protobuf/stubs/time.h override system API
'USE_HEADERMAP' => 'NO',
'ALWAYS_SEARCH_USER_PATHS' => 'NO',
# Configure tool is not being used for Xcode. When building, assume pthread is supported.
'GCC_PREPROCESSOR_DEFINITIONS' => '"$(inherited)" "HAVE_PTHREAD=1"',
}
end

@ -0,0 +1,62 @@
#!/bin/bash
# This script verifies that BUILD files and cmake files are in sync with src/Makefile.am
set -eo pipefail
if [ "$(uname)" != "Linux" ]; then
echo "build_files_updated_unittest only supported on Linux. Skipping..."
exit 0
fi
# Keep in sync with files needed by update_file_lists.sh
generated_files=(
"BUILD"
"cmake/extract_includes.bat.in"
"cmake/libprotobuf-lite.cmake"
"cmake/libprotobuf.cmake"
"cmake/libprotoc.cmake"
"cmake/tests.cmake"
"src/Makefile.am"
)
# If we're running in Bazel, use the Bazel-provided temp-dir.
if [ -n "${TEST_TMPDIR}" ]; then
# Env-var TEST_TMPDIR is set, assume that this is Bazel.
# Bazel may have opinions whether we are allowed to delete TEST_TMPDIR.
test_root="${TEST_TMPDIR}/build_files_updated_unittest"
mkdir "${test_root}"
else
# Seems like we're not executed by Bazel.
test_root=$(mktemp -d)
fi
# From now on, fail if there are any unbound variables.
set -u
# Remove artifacts after test is finished.
function cleanup {
rm -rf "${test_root}"
}
trap cleanup EXIT
# Create golden dir and add snapshot of current state.
golden_dir="${test_root}/golden"
mkdir -p "${golden_dir}/cmake" "${golden_dir}/src"
for file in ${generated_files[@]}; do
cp "${file}" "${golden_dir}/${file}"
done
# Create test dir, copy current state into it, and execute update script.
test_dir="${test_root}/test"
cp -R "${golden_dir}" "${test_dir}"
cp "update_file_lists.sh" "${test_dir}/update_file_lists.sh"
chmod +x "${test_dir}/update_file_lists.sh"
cd "${test_root}/test"
bash "${test_dir}/update_file_lists.sh"
# Test whether there are any differences
for file in ${generated_files[@]}; do
diff "${golden_dir}/${file}" "${test_dir}/${file}"
done

@ -92,6 +92,7 @@ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\fastmem.h" incl
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\hash.h" include\google\protobuf\stubs\hash.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\logging.h" include\google\protobuf\stubs\logging.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\macros.h" include\google\protobuf\stubs\macros.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\map_util.h" include\google\protobuf\stubs\map_util.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\mutex.h" include\google\protobuf\stubs\mutex.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\once.h" include\google\protobuf\stubs\once.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\platform_macros.h" include\google\protobuf\stubs\platform_macros.h

@ -132,7 +132,6 @@ set(tests_files
${protobuf_source_dir}/src/google/protobuf/arena_unittest.cc
${protobuf_source_dir}/src/google/protobuf/arenastring_unittest.cc
${protobuf_source_dir}/src/google/protobuf/compiler/annotation_test_util.cc
${protobuf_source_dir}/src/google/protobuf/compiler/command_line_interface_unittest.cc
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_move_unittest.cc
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
@ -203,12 +202,21 @@ set(tests_files
${protobuf_source_dir}/src/google/protobuf/wire_format_unittest.cc
)
set(non_msvc_tests_files
${protobuf_source_dir}/src/google/protobuf/compiler/command_line_interface_unittest.cc
)
set(all_tests_files
${tests_files}
${non_msvc_tests_files}
)
if(protobuf_ABSOLUTE_TEST_PLUGIN_PATH)
add_compile_options(-DGOOGLE_PROTOBUF_TEST_PLUGIN_PATH="$<TARGET_FILE:test_plugin>")
endif()
if(MINGW)
set_source_files_properties(${tests_files} PROPERTIES COMPILE_FLAGS "-Wno-narrowing")
set_source_files_properties(${all_tests_files} PROPERTIES COMPILE_FLAGS "-Wno-narrowing")
# required for tests on MinGW Win64
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
@ -218,7 +226,7 @@ if(MINGW)
endif()
add_executable(tests ${tests_files} ${common_test_files} ${tests_proto_files} ${lite_test_proto_files})
add_executable(tests ${all_tests_files} ${common_test_files} ${tests_proto_files} ${lite_test_proto_files})
target_link_libraries(tests libprotoc libprotobuf gmock_main)
set(test_plugin_files

@ -149,10 +149,6 @@ string tag(uint32_t fieldnum, char wire_type) {
return varint((fieldnum << 3) | wire_type);
}
string submsg(uint32_t fn, const string& buf) {
return cat( tag(fn, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), delim(buf) );
}
#define UNKNOWN_FIELD 666
const FieldDescriptor* GetFieldForType(FieldDescriptor::Type type,
@ -375,12 +371,21 @@ void BinaryAndJsonConformanceSuite::RunValidProtobufTest(
void BinaryAndJsonConformanceSuite::RunValidBinaryProtobufTest(
const string& test_name, ConformanceLevel level,
const string& input_protobuf, bool is_proto3) {
RunValidBinaryProtobufTest(
test_name, level, input_protobuf, input_protobuf, is_proto3);
}
void BinaryAndJsonConformanceSuite::RunValidBinaryProtobufTest(
const string& test_name, ConformanceLevel level,
const string& input_protobuf,
const string& expected_protobuf,
bool is_proto3) {
std::unique_ptr<Message> prototype = NewTestMessage(is_proto3);
ConformanceRequestSetting setting(
level, conformance::PROTOBUF, conformance::PROTOBUF,
conformance::BINARY_TEST,
*prototype, test_name, input_protobuf);
RunValidBinaryInputTest(setting, input_protobuf);
RunValidBinaryInputTest(setting, expected_protobuf, true);
}
void BinaryAndJsonConformanceSuite::RunValidProtobufTestWithMessage(
@ -594,27 +599,149 @@ void BinaryAndJsonConformanceSuite::TestValidDataForType(
const FieldDescriptor* field = GetFieldForType(type, false, is_proto3);
const FieldDescriptor* rep_field = GetFieldForType(type, true, is_proto3);
RunValidProtobufTest("ValidDataScalar" + type_name, REQUIRED,
cat(tag(field->number(), wire_type), values[0].first),
field->name() + ": " + values[0].second, is_proto3);
// Test singular data for singular fields.
for (size_t i = 0; i < values.size(); i++) {
string proto =
cat(tag(field->number(), wire_type), values[i].first);
string expected_proto =
cat(tag(field->number(), wire_type), values[i].second);
std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
test_message->MergeFromString(expected_proto);
string text = test_message->DebugString();
RunValidProtobufTest(StrCat("ValidDataScalar", type_name, "[", i, "]"),
REQUIRED, proto, text, is_proto3);
}
// Test repeated data for singular fields.
// For scalar message fields, repeated values are merged, which is tested
// separately.
if (type != FieldDescriptor::TYPE_MESSAGE) {
string proto;
string text = field->name() + ": " + values.back().second;
for (size_t i = 0; i < values.size(); i++) {
proto += cat(tag(field->number(), wire_type), values[i].first);
}
string expected_proto =
cat(tag(field->number(), wire_type), values.back().second);
std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
test_message->MergeFromString(expected_proto);
string text = test_message->DebugString();
RunValidProtobufTest("RepeatedScalarSelectsLast" + type_name, REQUIRED,
proto, text, is_proto3);
}
proto.clear();
text.clear();
// Test repeated fields.
if (FieldDescriptor::IsTypePackable(type)) {
string packed_proto;
string unpacked_proto;
string packed_proto_expected;
string unpacked_proto_expected;
for (size_t i = 0; i < values.size(); i++) {
unpacked_proto +=
cat(tag(rep_field->number(), wire_type), values[i].first);
unpacked_proto_expected +=
cat(tag(rep_field->number(), wire_type), values[i].second);
packed_proto += values[i].first;
packed_proto_expected += values[i].second;
}
packed_proto =
cat(tag(rep_field->number(),
WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
delim(packed_proto));
packed_proto_expected =
cat(tag(rep_field->number(),
WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
delim(packed_proto_expected));
std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
test_message->MergeFromString(packed_proto_expected);
string text = test_message->DebugString();
// Ensures both packed and unpacked data can be parsed.
RunValidProtobufTest(
StrCat("ValidDataRepeated", type_name, ".UnpackedInput"),
REQUIRED, unpacked_proto, text, is_proto3);
RunValidProtobufTest(
StrCat("ValidDataRepeated", type_name, ".PackedInput"),
REQUIRED, packed_proto, text, is_proto3);
// proto2 should encode as unpacked by default and proto3 should encode as
// packed by default.
string expected_proto =
rep_field->is_packed() ? packed_proto_expected :
unpacked_proto_expected;
RunValidBinaryProtobufTest(
StrCat("ValidDataRepeated", type_name,
".UnpackedInput.DefaultOutput"),
RECOMMENDED,
unpacked_proto,
expected_proto, is_proto3);
RunValidBinaryProtobufTest(
StrCat("ValidDataRepeated", type_name,
".PackedInput.DefaultOutput"),
RECOMMENDED,
packed_proto,
expected_proto, is_proto3);
} else {
string proto;
string expected_proto;
for (size_t i = 0; i < values.size(); i++) {
proto += cat(tag(rep_field->number(), wire_type), values[i].first);
text += rep_field->name() + ": " + values[i].second + " ";
expected_proto +=
cat(tag(rep_field->number(), wire_type), values[i].second);
}
std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
test_message->MergeFromString(expected_proto);
string text = test_message->DebugString();
RunValidProtobufTest(
StrCat("ValidDataRepeated", type_name),
REQUIRED, proto, text, is_proto3);
}
RunValidProtobufTest("ValidDataRepeated" + type_name, REQUIRED,
proto, text, is_proto3);
}
}
void BinaryAndJsonConformanceSuite::TestValidDataForRepeatedScalarMessage() {
std::vector<std::string> values = {
delim(cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
delim(cat(
tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234),
tag(2, WireFormatLite::WIRETYPE_VARINT), varint(1234),
tag(31, WireFormatLite::WIRETYPE_VARINT), varint(1234)
)))),
delim(cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
delim(cat(
tag(1, WireFormatLite::WIRETYPE_VARINT), varint(4321),
tag(3, WireFormatLite::WIRETYPE_VARINT), varint(4321),
tag(31, WireFormatLite::WIRETYPE_VARINT), varint(4321)
)))),
};
const std::string expected =
R"({
corecursive: {
optional_int32: 4321,
optional_int64: 1234,
optional_uint32: 4321,
repeated_int32: [1234, 4321],
}
})";
for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) {
string proto;
const FieldDescriptor* field =
GetFieldForType(FieldDescriptor::TYPE_MESSAGE, false, is_proto3);
for (size_t i = 0; i < values.size(); i++) {
proto +=
cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
values[i]);
}
RunValidProtobufTest(
"RepeatedScalarMessageMerge", REQUIRED, proto,
field->name() + ": " + expected, is_proto3);
}
}
@ -714,88 +841,109 @@ void BinaryAndJsonConformanceSuite::RunSuiteImpl() {
uint32 kUint32Max = 4294967295UL;
TestValidDataForType(FieldDescriptor::TYPE_DOUBLE, {
{dbl(0.1), "0.1"},
{dbl(1.7976931348623157e+308), "1.7976931348623157e+308"},
{dbl(2.22507385850720138309e-308), "2.22507385850720138309e-308"}
{dbl(0.1), dbl(0.1)},
{dbl(1.7976931348623157e+308), dbl(1.7976931348623157e+308)},
{dbl(2.22507385850720138309e-308), dbl(2.22507385850720138309e-308)}
});
TestValidDataForType(FieldDescriptor::TYPE_FLOAT, {
{flt(0.1), "0.1"},
{flt(1.00000075e-36), "1.00000075e-36"},
{flt(3.402823e+38), "3.402823e+38"}, // 3.40282347e+38
{flt(1.17549435e-38f), "1.17549435e-38"}
{flt(0.1), flt(0.1)},
{flt(1.00000075e-36), flt(1.00000075e-36)},
{flt(3.402823e+38), flt(3.402823e+38)}, // 3.40282347e+38
{flt(1.17549435e-38f), flt(1.17549435e-38)}
});
TestValidDataForType(FieldDescriptor::TYPE_INT64, {
{varint(12345), "12345"},
{varint(kInt64Max), std::to_string(kInt64Max)},
{varint(kInt64Min), std::to_string(kInt64Min)}
{varint(12345), varint(12345)},
{varint(kInt64Max), varint(kInt64Max)},
{varint(kInt64Min), varint(kInt64Min)}
});
TestValidDataForType(FieldDescriptor::TYPE_UINT64, {
{varint(12345), "12345"},
{varint(kUint64Max), std::to_string(kUint64Max)},
{varint(0), "0"}
{varint(12345), varint(12345)},
{varint(kUint64Max), varint(kUint64Max)},
{varint(0), varint(0)}
});
TestValidDataForType(FieldDescriptor::TYPE_INT32, {
{varint(12345), "12345"},
{longvarint(12345, 2), "12345"},
{longvarint(12345, 7), "12345"},
{varint(kInt32Max), std::to_string(kInt32Max)},
{varint(kInt32Min), std::to_string(kInt32Min)},
{varint(1LL << 33), std::to_string(static_cast<int32>(1LL << 33))},
{varint((1LL << 33) - 1),
std::to_string(static_cast<int32>((1LL << 33) - 1))},
{varint(12345), varint(12345)},
{longvarint(12345, 2), varint(12345)},
{longvarint(12345, 7), varint(12345)},
{varint(kInt32Max), varint(kInt32Max)},
{varint(kInt32Min), varint(kInt32Min)},
{varint(1LL << 33), varint(0)},
{varint((1LL << 33) - 1), varint(-1)},
});
TestValidDataForType(FieldDescriptor::TYPE_UINT32, {
{varint(12345), "12345"},
{longvarint(12345, 2), "12345"},
{longvarint(12345, 7), "12345"},
{varint(kUint32Max), std::to_string(kUint32Max)}, // UINT32_MAX
{varint(0), "0"},
{varint(1LL << 33), std::to_string(static_cast<uint32>(1LL << 33))},
{varint((1LL << 33) - 1),
std::to_string(static_cast<uint32>((1LL << 33) - 1))},
{varint(12345), varint(12345)},
{longvarint(12345, 2), varint(12345)},
{longvarint(12345, 7), varint(12345)},
{varint(kUint32Max), varint(kUint32Max)}, // UINT32_MAX
{varint(0), varint(0)},
{varint(1LL << 33), varint(0)},
{varint((1LL << 33) - 1), varint((1LL << 32) - 1)},
});
TestValidDataForType(FieldDescriptor::TYPE_FIXED64, {
{u64(12345), "12345"},
{u64(kUint64Max), std::to_string(kUint64Max)},
{u64(0), "0"}
{u64(12345), u64(12345)},
{u64(kUint64Max), u64(kUint64Max)},
{u64(0), u64(0)}
});
TestValidDataForType(FieldDescriptor::TYPE_FIXED32, {
{u32(12345), "12345"},
{u32(kUint32Max), std::to_string(kUint32Max)}, // UINT32_MAX
{u32(0), "0"}
{u32(12345), u32(12345)},
{u32(kUint32Max), u32(kUint32Max)}, // UINT32_MAX
{u32(0), u32(0)}
});
TestValidDataForType(FieldDescriptor::TYPE_SFIXED64, {
{u64(12345), "12345"},
{u64(kInt64Max), std::to_string(kInt64Max)},
{u64(kInt64Min), std::to_string(kInt64Min)}
{u64(12345), u64(12345)},
{u64(kInt64Max), u64(kInt64Max)},
{u64(kInt64Min), u64(kInt64Min)}
});
TestValidDataForType(FieldDescriptor::TYPE_SFIXED32, {
{u32(12345), "12345"},
{u32(kInt32Max), std::to_string(kInt32Max)},
{u32(kInt32Min), std::to_string(kInt32Min)}
{u32(12345), u32(12345)},
{u32(kInt32Max), u32(kInt32Max)},
{u32(kInt32Min), u32(kInt32Min)}
});
TestValidDataForType(FieldDescriptor::TYPE_BOOL, {
{varint(1), "true"},
{varint(0), "false"},
{varint(12345678), "true"}
{varint(1), varint(1)},
{varint(0), varint(0)},
{varint(12345678), varint(1)}
});
TestValidDataForType(FieldDescriptor::TYPE_SINT32, {
{zz32(12345), "12345"},
{zz32(kInt32Max), std::to_string(kInt32Max)},
{zz32(kInt32Min), std::to_string(kInt32Min)}
{zz32(12345), zz32(12345)},
{zz32(kInt32Max), zz32(kInt32Max)},
{zz32(kInt32Min), zz32(kInt32Min)}
});
TestValidDataForType(FieldDescriptor::TYPE_SINT64, {
{zz64(12345), "12345"},
{zz64(kInt64Max), std::to_string(kInt64Max)},
{zz64(kInt64Min), std::to_string(kInt64Min)}
{zz64(12345), zz64(12345)},
{zz64(kInt64Max), zz64(kInt64Max)},
{zz64(kInt64Min), zz64(kInt64Min)}
});
TestValidDataForType(FieldDescriptor::TYPE_STRING, {
{delim("Hello world!"), delim("Hello world!")},
{delim("\'\"\?\\\a\b\f\n\r\t\v"),
delim("\'\"\?\\\a\b\f\n\r\t\v")}, // escape
{delim("谷歌"), delim("谷歌")}, // Google in Chinese
{delim("\u8C37\u6B4C"), delim("谷歌")}, // unicode escape
{delim("\u8c37\u6b4c"), delim("谷歌")}, // lowercase unicode
{delim("\xF0\x9F\x98\x81"), delim("\xF0\x9F\x98\x81")}, // emoji: 😁
{delim(""), delim("")},
});
TestValidDataForType(FieldDescriptor::TYPE_BYTES, {
{delim("\x01\x02"), delim("\x01\x02")},
{delim("\xfb"), delim("\xfb")},
{delim(""), delim("")},
});
TestValidDataForType(FieldDescriptor::TYPE_ENUM, {
{varint(0), varint(0)},
{varint(1), varint(1)},
{varint(2), varint(2)},
{varint(-1), varint(-1)},
});
TestValidDataForRepeatedScalarMessage();
TestValidDataForType(FieldDescriptor::TYPE_MESSAGE, {
{delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234))),
delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234)))},
{delim(""), delim("")},
});
// TODO(haberman):
// TestValidDataForType(FieldDescriptor::TYPE_STRING
// TestValidDataForType(FieldDescriptor::TYPE_GROUP
// TestValidDataForType(FieldDescriptor::TYPE_MESSAGE
// TestValidDataForType(FieldDescriptor::TYPE_BYTES
// TestValidDataForType(FieldDescriptor::TYPE_ENUM
RunValidJsonTest("HelloWorld", REQUIRED,
"{\"optionalString\":\"Hello, World!\"}",

@ -63,6 +63,11 @@ class BinaryAndJsonConformanceSuite : public ConformanceTestSuite {
ConformanceLevel level,
const string& input_protobuf,
bool is_proto3);
void RunValidBinaryProtobufTest(const string& test_name,
ConformanceLevel level,
const string& input_protobuf,
const string& expected_protobuf,
bool is_proto3);
void RunValidProtobufTestWithMessage(
const string& test_name, ConformanceLevel level,
const Message *input,
@ -109,6 +114,7 @@ class BinaryAndJsonConformanceSuite : public ConformanceTestSuite {
void TestValidDataForType(
google::protobuf::FieldDescriptor::Type,
std::vector<std::pair<std::string, std::string>> values);
void TestValidDataForRepeatedScalarMessage();
std::unique_ptr<google::protobuf::util::TypeResolver>
type_resolver_;

@ -68,7 +68,8 @@ static ConformanceResponse *DoTest(ConformanceRequest *request) {
switch (request.payloadOneOfCase) {
case ConformanceRequest_Payload_OneOfCase_GPBUnsetOneOfCase:
Die(@"Request didn't have a payload: %@", request);
response.runtimeError =
[NSString stringWithFormat:@"Request didn't have a payload: %@", request];
break;
case ConformanceRequest_Payload_OneOfCase_ProtobufPayload: {
@ -78,7 +79,10 @@ static ConformanceResponse *DoTest(ConformanceRequest *request) {
} else if ([request.messageType isEqual:@"protobuf_test_messages.proto2.TestAllTypesProto2"]) {
msgClass = [TestAllTypesProto2 class];
} else {
Die(@"Protobuf request had an unknown message_type: %@", request.messageType);
response.runtimeError =
[NSString stringWithFormat:
@"Protobuf request had an unknown message_type: %@", request.messageType];
break;
}
NSError *error = nil;
testMessage = [msgClass parseFromData:request.protobufPayload error:&error];
@ -108,7 +112,8 @@ static ConformanceResponse *DoTest(ConformanceRequest *request) {
switch (request.requestedOutputFormat) {
case WireFormat_GPBUnrecognizedEnumeratorValue:
case WireFormat_Unspecified:
Die(@"Unrecognized/unspecified output format: %@", request);
response.runtimeError =
[NSString stringWithFormat:@"Unrecognized/unspecified output format: %@", request];
break;
case WireFormat_Protobuf:

@ -54,6 +54,25 @@ using google::protobuf::util::MessageDifferencer;
using google::protobuf::util::Status;
using std::string;
namespace {
static string ToOctString(const string& binary_string) {
string oct_string;
for (size_t i = 0; i < binary_string.size(); i++) {
uint8_t c = binary_string.at(i);
uint8_t high = c / 64;
uint8_t mid = (c % 64) / 8;
uint8_t low = c % 8;
oct_string.push_back('\\');
oct_string.push_back('0' + high);
oct_string.push_back('0' + mid);
oct_string.push_back('0' + low);
}
return oct_string;
}
}
namespace google {
namespace protobuf {
@ -220,18 +239,21 @@ void ConformanceTestSuite::RunValidInputTest(
void ConformanceTestSuite::RunValidBinaryInputTest(
const ConformanceRequestSetting& setting,
const string& equivalent_wire_format) {
const string& equivalent_wire_format,
bool require_same_wire_format) {
const ConformanceRequest& request = setting.GetRequest();
ConformanceResponse response;
RunTest(setting.GetTestName(), request, &response);
VerifyResponse(setting, equivalent_wire_format, response, true);
VerifyResponse(setting, equivalent_wire_format, response,
true, require_same_wire_format);
}
void ConformanceTestSuite::VerifyResponse(
const ConformanceRequestSetting& setting,
const string& equivalent_wire_format,
const ConformanceResponse& response,
bool need_report_success) {
bool need_report_success,
bool require_same_wire_format) {
Message* test_message = setting.GetTestMessage();
const ConformanceRequest& request = setting.GetRequest();
const string& test_name = setting.GetTestName();
@ -270,8 +292,19 @@ void ConformanceTestSuite::VerifyResponse(
string differences;
differencer.ReportDifferencesToString(&differences);
bool check;
bool check = false;
if (require_same_wire_format) {
GOOGLE_DCHECK_EQ(response.result_case(),
ConformanceResponse::kProtobufPayload);
const string& protobuf_payload = response.protobuf_payload();
check = equivalent_wire_format == protobuf_payload;
differences = StrCat("Expect: ", ToOctString(equivalent_wire_format),
", but got: ", ToOctString(protobuf_payload));
} else {
check = differencer.Compare(*reference_message, *test_message);
}
if (check) {
if (need_report_success) {
ReportSuccess(test_name);

@ -261,7 +261,8 @@ class ConformanceTestSuite {
const ConformanceRequestSetting& setting,
const string& equivalent_wire_format,
const conformance::ConformanceResponse& response,
bool need_report_success);
bool need_report_success,
bool require_same_wire_format);
void ReportSuccess(const std::string& test_name);
void ReportFailure(const string& test_name,
@ -276,7 +277,8 @@ class ConformanceTestSuite {
void RunValidInputTest(const ConformanceRequestSetting& setting,
const string& equivalent_text_format);
void RunValidBinaryInputTest(const ConformanceRequestSetting& setting,
const string& equivalent_wire_format);
const string& equivalent_wire_format,
bool require_same_wire_format = false);
void RunTest(const std::string& test_name,
const conformance::ConformanceRequest& request,

@ -1,13 +1,57 @@
Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
Required.Proto2.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.ProtobufOutput
Required.Proto2.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.ProtobufOutput
Required.Proto2.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.ProtobufOutput
Required.Proto2.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.ProtobufOutput
Required.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.ProtobufOutput
Required.Proto2.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.ProtobufOutput
Required.Proto2.ProtobufInput.ValidDataRepeated.INT32.PackedInput.ProtobufOutput
Required.Proto2.ProtobufInput.ValidDataRepeated.INT64.PackedInput.ProtobufOutput
Required.Proto2.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.ProtobufOutput
Required.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.ProtobufOutput
Required.Proto2.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.ProtobufOutput
Required.Proto2.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.ProtobufOutput
Required.Proto2.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.ProtobufOutput
Required.Proto2.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.ProtobufOutput

@ -1,2 +1,6 @@
# JSON input or output tests are skipped (in conformance_objc.m) as mobile
# platforms don't support JSON wire format to avoid code bloat.
Recommended.Proto2.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput

@ -4,17 +4,49 @@ Recommended.FieldMaskTooManyUnderscore.JsonOutput
Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
Required.Proto3.JsonInput.DoubleFieldTooSmall
Required.Proto3.JsonInput.FloatFieldTooLarge
Required.Proto3.JsonInput.FloatFieldTooSmall
Required.Proto3.JsonInput.DoubleFieldTooSmall
Required.Proto3.JsonInput.Int32FieldLeadingSpace
Required.Proto3.JsonInput.Int32FieldNotInteger
Required.Proto3.JsonInput.Int64FieldNotInteger
Required.Proto3.JsonInput.OneofFieldDuplicate
Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
Required.Proto3.JsonInput.RepeatedListValue.JsonOutput
Required.Proto3.JsonInput.RepeatedListValue.ProtobufOutput
Required.Proto3.JsonInput.StringFieldNotAString
Required.Proto3.JsonInput.Uint32FieldNotInteger
Required.Proto3.JsonInput.Uint64FieldNotInteger
Required.Proto3.JsonInput.Int32FieldLeadingSpace
Required.Proto3.JsonInput.OneofFieldDuplicate
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.JsonOutput
Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.JsonOutput
Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[1].JsonOutput

@ -17,10 +17,36 @@ Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
Recommended.Proto3.JsonInput.TimestampHas3FractionalDigits.Validator
Recommended.Proto3.JsonInput.TimestampHas6FractionalDigits.Validator
Recommended.Proto3.ProtobufInput.OneofZeroBytes.JsonOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
Required.DurationProtoInputTooLarge.JsonOutput
Required.DurationProtoInputTooSmall.JsonOutput
Required.TimestampProtoInputTooLarge.JsonOutput
Required.TimestampProtoInputTooSmall.JsonOutput
Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.JsonOutput
@ -34,11 +60,19 @@ Required.Proto3.JsonInput.FloatFieldNegativeInfinity.JsonOutput
Required.Proto3.JsonInput.OneofFieldDuplicate
Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
Required.Proto3.JsonInput.RejectTopLevelNull
Required.Proto3.JsonInput.StringFieldSurrogatePair.JsonOutput
Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput
Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.JsonOutput
Required.Proto3.JsonInput.RejectTopLevelNull
Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[1].JsonOutput
Required.TimestampProtoInputTooLarge.JsonOutput
Required.TimestampProtoInputTooSmall.JsonOutput

@ -15,6 +15,34 @@ Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate
Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
Recommended.Proto3.JsonInput.TimestampHas3FractionalDigits.Validator
Recommended.Proto3.JsonInput.TimestampHas6FractionalDigits.Validator
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
Required.DurationProtoInputTooLarge.JsonOutput
Required.DurationProtoInputTooSmall.JsonOutput
Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
@ -27,6 +55,12 @@ Required.Proto3.JsonInput.DurationRepeatedValue.JsonOutput
Required.Proto3.JsonInput.FloatFieldInfinity.JsonOutput
Required.Proto3.JsonInput.FloatFieldNan.JsonOutput
Required.Proto3.JsonInput.FloatFieldNegativeInfinity.JsonOutput
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.OneofFieldDuplicate
Required.Proto3.JsonInput.OptionalBoolWrapper.JsonOutput
Required.Proto3.JsonInput.OptionalBytesWrapper.JsonOutput
@ -39,6 +73,7 @@ Required.Proto3.JsonInput.OptionalUint32Wrapper.JsonOutput
Required.Proto3.JsonInput.OptionalUint64Wrapper.JsonOutput
Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
Required.Proto3.JsonInput.RejectTopLevelNull
Required.Proto3.JsonInput.RepeatedBoolWrapper.JsonOutput
Required.Proto3.JsonInput.RepeatedBytesWrapper.JsonOutput
Required.Proto3.JsonInput.RepeatedDoubleWrapper.JsonOutput
@ -54,13 +89,8 @@ Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[1].JsonOutput
Required.TimestampProtoInputTooLarge.JsonOutput
Required.TimestampProtoInputTooSmall.JsonOutput
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.RejectTopLevelNull

@ -5,6 +5,7 @@ Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator
Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator
Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
Recommended.Proto3.JsonInput.MapFieldValueIsNull
Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull
Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull
@ -14,6 +15,34 @@ Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate
Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
Recommended.Proto3.JsonInput.TimestampHas3FractionalDigits.Validator
Recommended.Proto3.JsonInput.TimestampHas6FractionalDigits.Validator
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
Required.DurationProtoInputTooLarge.JsonOutput
Required.DurationProtoInputTooSmall.JsonOutput
Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
@ -26,6 +55,12 @@ Required.Proto3.JsonInput.DurationRepeatedValue.JsonOutput
Required.Proto3.JsonInput.FloatFieldInfinity.JsonOutput
Required.Proto3.JsonInput.FloatFieldNan.JsonOutput
Required.Proto3.JsonInput.FloatFieldNegativeInfinity.JsonOutput
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.OneofFieldDuplicate
Required.Proto3.JsonInput.OptionalBoolWrapper.JsonOutput
Required.Proto3.JsonInput.OptionalBytesWrapper.JsonOutput
@ -38,6 +73,7 @@ Required.Proto3.JsonInput.OptionalUint32Wrapper.JsonOutput
Required.Proto3.JsonInput.OptionalUint64Wrapper.JsonOutput
Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
Required.Proto3.JsonInput.RejectTopLevelNull
Required.Proto3.JsonInput.RepeatedBoolWrapper.JsonOutput
Required.Proto3.JsonInput.RepeatedBytesWrapper.JsonOutput
Required.Proto3.JsonInput.RepeatedDoubleWrapper.JsonOutput
@ -53,14 +89,8 @@ Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[1].JsonOutput
Required.TimestampProtoInputTooLarge.JsonOutput
Required.TimestampProtoInputTooSmall.JsonOutput
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
Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
Required.Proto3.JsonInput.RejectTopLevelNull

@ -34,6 +34,8 @@ cd $(dirname $0)
# these tests).
TEST_VERSION=3.0.0
LAST_RELEASED=3.9.0
# The old version of protobuf that we are testing compatibility against. This
# is usually the same as TEST_VERSION (i.e., we use the tests extracted from
# that version to test compatibility of the newest runtime against it), but it
@ -52,6 +54,10 @@ case "$1" in
OLD_VERSION=3.1.0
OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.1.0/protoc-3.1.0-linux-x86_64.exe
;;
$LAST_RELEASED)
OLD_VERSION=$LAST_RELEASED
OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/$OLD_VERSION/protoc-$OLD_VERSION-linux-x86_64.exe
;;
*)
echo "[ERROR]: Unknown version number: $1"
exit 1

@ -45,13 +45,178 @@ namespace Google.Protobuf
{
// TODO: Avoid the "dual hit" of lambda expressions: create open delegates instead. (At least test...)
/// <summary>
/// Retrieves a codec suitable for a string field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<string> ForString(uint tag)
{
return FieldCodec.ForString(tag, "");
}
/// <summary>
/// Retrieves a codec suitable for a bytes field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<ByteString> ForBytes(uint tag)
{
return FieldCodec.ForBytes(tag, ByteString.Empty);
}
/// <summary>
/// Retrieves a codec suitable for a bool field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<bool> ForBool(uint tag)
{
return FieldCodec.ForBool(tag, false);
}
/// <summary>
/// Retrieves a codec suitable for an int32 field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<int> ForInt32(uint tag)
{
return FieldCodec.ForInt32(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for an sint32 field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<int> ForSInt32(uint tag)
{
return FieldCodec.ForSInt32(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for a fixed32 field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<uint> ForFixed32(uint tag)
{
return FieldCodec.ForFixed32(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for an sfixed32 field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<int> ForSFixed32(uint tag)
{
return FieldCodec.ForSFixed32(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for a uint32 field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<uint> ForUInt32(uint tag)
{
return FieldCodec.ForUInt32(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for an int64 field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<long> ForInt64(uint tag)
{
return FieldCodec.ForInt64(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for an sint64 field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<long> ForSInt64(uint tag)
{
return FieldCodec.ForSInt64(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for a fixed64 field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<ulong> ForFixed64(uint tag)
{
return FieldCodec.ForFixed64(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for an sfixed64 field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<long> ForSFixed64(uint tag)
{
return FieldCodec.ForSFixed64(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for a uint64 field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<ulong> ForUInt64(uint tag)
{
return FieldCodec.ForUInt64(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for a float field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<float> ForFloat(uint tag)
{
return FieldCodec.ForFloat(tag, 0);
}
/// <summary>
/// Retrieves a codec suitable for a double field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<double> ForDouble(uint tag)
{
return FieldCodec.ForDouble(tag, 0);
}
// Enums are tricky. We can probably use expression trees to build these delegates automatically,
// but it's easy to generate the code for it.
/// <summary>
/// Retrieves a codec suitable for an enum field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <param name="toInt32">A conversion function from <see cref="Int32"/> to the enum type.</param>
/// <param name="fromInt32">A conversion function from the enum type to <see cref="Int32"/>.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<T> ForEnum<T>(uint tag, Func<T, int> toInt32, Func<int, T> fromInt32)
{
return FieldCodec.ForEnum(tag, toInt32, fromInt32, default(T));
}
/// <summary>
/// Retrieves a codec suitable for a string field with the given tag.
/// </summary>
/// <param name="tag">The tag.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<string> ForString(uint tag, string defaultValue = "")
public static FieldCodec<string> ForString(uint tag, string defaultValue)
{
return new FieldCodec<string>(input => input.ReadString(), (output, value) => output.WriteString(value), CodedOutputStream.ComputeStringSize, tag);
}
@ -62,7 +227,7 @@ namespace Google.Protobuf
/// <param name="tag">The tag.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<ByteString> ForBytes(uint tag, ByteString defaultValue = null)
public static FieldCodec<ByteString> ForBytes(uint tag, ByteString defaultValue)
{
return new FieldCodec<ByteString>(input => input.ReadBytes(), (output, value) => output.WriteBytes(value), CodedOutputStream.ComputeBytesSize, tag);
}
@ -73,7 +238,7 @@ namespace Google.Protobuf
/// <param name="tag">The tag.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<bool> ForBool(uint tag, bool defaultValue = false)
public static FieldCodec<bool> ForBool(uint tag, bool defaultValue)
{
return new FieldCodec<bool>(input => input.ReadBool(), (output, value) => output.WriteBool(value), CodedOutputStream.BoolSize, tag);
}
@ -84,7 +249,7 @@ namespace Google.Protobuf
/// <param name="tag">The tag.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<int> ForInt32(uint tag, int defaultValue = 0)
public static FieldCodec<int> ForInt32(uint tag, int defaultValue)
{
return new FieldCodec<int>(input => input.ReadInt32(), (output, value) => output.WriteInt32(value), CodedOutputStream.ComputeInt32Size, tag);
}
@ -95,7 +260,7 @@ namespace Google.Protobuf
/// <param name="tag">The tag.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<int> ForSInt32(uint tag, int defaultValue = 0)
public static FieldCodec<int> ForSInt32(uint tag, int defaultValue)
{
return new FieldCodec<int>(input => input.ReadSInt32(), (output, value) => output.WriteSInt32(value), CodedOutputStream.ComputeSInt32Size, tag);
}
@ -106,7 +271,7 @@ namespace Google.Protobuf
/// <param name="tag">The tag.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<uint> ForFixed32(uint tag, uint defaultValue = 0)
public static FieldCodec<uint> ForFixed32(uint tag, uint defaultValue)
{
return new FieldCodec<uint>(input => input.ReadFixed32(), (output, value) => output.WriteFixed32(value), 4, tag);
}
@ -117,7 +282,7 @@ namespace Google.Protobuf
/// <param name="tag">The tag.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<int> ForSFixed32(uint tag, int defaultValue = 0)
public static FieldCodec<int> ForSFixed32(uint tag, int defaultValue)
{
return new FieldCodec<int>(input => input.ReadSFixed32(), (output, value) => output.WriteSFixed32(value), 4, tag);
}
@ -128,7 +293,7 @@ namespace Google.Protobuf
/// <param name="tag">The tag.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<uint> ForUInt32(uint tag, uint defaultValue = 0)
public static FieldCodec<uint> ForUInt32(uint tag, uint defaultValue)
{
return new FieldCodec<uint>(input => input.ReadUInt32(), (output, value) => output.WriteUInt32(value), CodedOutputStream.ComputeUInt32Size, tag);
}
@ -139,7 +304,7 @@ namespace Google.Protobuf
/// <param name="tag">The tag.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<long> ForInt64(uint tag, long defaultValue = 0)
public static FieldCodec<long> ForInt64(uint tag, long defaultValue)
{
return new FieldCodec<long>(input => input.ReadInt64(), (output, value) => output.WriteInt64(value), CodedOutputStream.ComputeInt64Size, tag);
}
@ -150,7 +315,7 @@ namespace Google.Protobuf
/// <param name="tag">The tag.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<long> ForSInt64(uint tag, long defaultValue = 0)
public static FieldCodec<long> ForSInt64(uint tag, long defaultValue)
{
return new FieldCodec<long>(input => input.ReadSInt64(), (output, value) => output.WriteSInt64(value), CodedOutputStream.ComputeSInt64Size, tag);
}
@ -161,7 +326,7 @@ namespace Google.Protobuf
/// <param name="tag">The tag.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<ulong> ForFixed64(uint tag, ulong defaultValue = 0)
public static FieldCodec<ulong> ForFixed64(uint tag, ulong defaultValue)
{
return new FieldCodec<ulong>(input => input.ReadFixed64(), (output, value) => output.WriteFixed64(value), 8, tag);
}
@ -172,7 +337,7 @@ namespace Google.Protobuf
/// <param name="tag">The tag.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<long> ForSFixed64(uint tag, long defaultValue = 0)
public static FieldCodec<long> ForSFixed64(uint tag, long defaultValue)
{
return new FieldCodec<long>(input => input.ReadSFixed64(), (output, value) => output.WriteSFixed64(value), 8, tag);
}
@ -183,7 +348,7 @@ namespace Google.Protobuf
/// <param name="tag">The tag.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<ulong> ForUInt64(uint tag, ulong defaultValue = 0)
public static FieldCodec<ulong> ForUInt64(uint tag, ulong defaultValue)
{
return new FieldCodec<ulong>(input => input.ReadUInt64(), (output, value) => output.WriteUInt64(value), CodedOutputStream.ComputeUInt64Size, tag);
}
@ -194,7 +359,7 @@ namespace Google.Protobuf
/// <param name="tag">The tag.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<float> ForFloat(uint tag, float defaultValue = 0)
public static FieldCodec<float> ForFloat(uint tag, float defaultValue)
{
return new FieldCodec<float>(input => input.ReadFloat(), (output, value) => output.WriteFloat(value), CodedOutputStream.FloatSize, tag);
}
@ -205,7 +370,7 @@ namespace Google.Protobuf
/// <param name="tag">The tag.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<double> ForDouble(uint tag, double defaultValue = 0)
public static FieldCodec<double> ForDouble(uint tag, double defaultValue)
{
return new FieldCodec<double>(input => input.ReadDouble(), (output, value) => output.WriteDouble(value), CodedOutputStream.DoubleSize, tag);
}
@ -221,7 +386,7 @@ namespace Google.Protobuf
/// <param name="fromInt32">A conversion function from the enum type to <see cref="Int32"/>.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<T> ForEnum<T>(uint tag, Func<T, int> toInt32, Func<int, T> fromInt32, T defaultValue = default(T))
public static FieldCodec<T> ForEnum<T>(uint tag, Func<T, int> toInt32, Func<int, T> fromInt32, T defaultValue)
{
return new FieldCodec<T>(input => fromInt32(
input.ReadEnum()),

@ -62,7 +62,7 @@ namespace Google.Protobuf.WellKnownTypes {
/// if (duration.seconds &lt; 0 &amp;&amp; duration.nanos > 0) {
/// duration.seconds += 1;
/// duration.nanos -= 1000000000;
/// } else if (durations.seconds > 0 &amp;&amp; duration.nanos &lt; 0) {
/// } else if (duration.seconds > 0 &amp;&amp; duration.nanos &lt; 0) {
/// duration.seconds -= 1;
/// duration.nanos += 1000000000;
/// }

@ -48,8 +48,7 @@ import java.util.Map;
*
* @author kenton@google.com Kenton Varda
*/
final class FieldSet<
FieldDescriptorType extends FieldSet.FieldDescriptorLite<FieldDescriptorType>> {
final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
/**
* Interface for a FieldDescriptor or lite extension descriptor. This prevents FieldSet from
* depending on {@link Descriptors.FieldDescriptor}.
@ -72,18 +71,26 @@ final class FieldSet<
MessageLite.Builder internalMergeFrom(MessageLite.Builder to, MessageLite from);
}
private final SmallSortedMap<FieldDescriptorType, Object> fields;
private static final int DEFAULT_FIELD_MAP_ARRAY_SIZE = 16;
private final SmallSortedMap<T, Object> fields;
private boolean isImmutable;
private boolean hasLazyField = false;
private boolean hasLazyField;
/** Construct a new FieldSet. */
private FieldSet() {
this.fields = SmallSortedMap.newFieldMap(16);
this.fields = SmallSortedMap.newFieldMap(DEFAULT_FIELD_MAP_ARRAY_SIZE);
}
/** Construct an empty FieldSet. This is only used to initialize DEFAULT_INSTANCE. */
@SuppressWarnings("unused")
private FieldSet(final boolean dummy) {
this.fields = SmallSortedMap.newFieldMap(0);
this(SmallSortedMap.<T>newFieldMap(0));
makeImmutable();
}
private FieldSet(SmallSortedMap<T, Object> fields) {
this.fields = fields;
makeImmutable();
}
@ -98,6 +105,11 @@ final class FieldSet<
return DEFAULT_INSTANCE;
}
/** Construct a new Builder. */
public static <T extends FieldDescriptorLite<T>> Builder<T> newBuilder() {
return new Builder<T>();
}
@SuppressWarnings("rawtypes")
private static final FieldSet DEFAULT_INSTANCE = new FieldSet(true);
@ -152,18 +164,16 @@ final class FieldSet<
* @return the newly cloned FieldSet
*/
@Override
public FieldSet<FieldDescriptorType> clone() {
public FieldSet<T> clone() {
// We can't just call fields.clone because List objects in the map
// should not be shared.
FieldSet<FieldDescriptorType> clone = FieldSet.newFieldSet();
FieldSet<T> clone = FieldSet.newFieldSet();
for (int i = 0; i < fields.getNumArrayEntries(); i++) {
Map.Entry<FieldDescriptorType, Object> entry = fields.getArrayEntryAt(i);
FieldDescriptorType descriptor = entry.getKey();
clone.setField(descriptor, entry.getValue());
Map.Entry<T, Object> entry = fields.getArrayEntryAt(i);
clone.setField(entry.getKey(), entry.getValue());
}
for (Map.Entry<FieldDescriptorType, Object> entry : fields.getOverflowEntries()) {
FieldDescriptorType descriptor = entry.getKey();
clone.setField(descriptor, entry.getValue());
for (Map.Entry<T, Object> entry : fields.getOverflowEntries()) {
clone.setField(entry.getKey(), entry.getValue());
}
clone.hasLazyField = hasLazyField;
return clone;
@ -179,15 +189,9 @@ final class FieldSet<
}
/** Get a simple map containing all the fields. */
public Map<FieldDescriptorType, Object> getAllFields() {
public Map<T, Object> getAllFields() {
if (hasLazyField) {
SmallSortedMap<FieldDescriptorType, Object> result = SmallSortedMap.newFieldMap(16);
for (int i = 0; i < fields.getNumArrayEntries(); i++) {
cloneFieldEntry(result, fields.getArrayEntryAt(i));
}
for (Map.Entry<FieldDescriptorType, Object> entry : fields.getOverflowEntries()) {
cloneFieldEntry(result, entry);
}
SmallSortedMap<T, Object> result = cloneAllFieldsMap(fields, /* copyList */ false);
if (fields.isImmutable()) {
result.makeImmutable();
}
@ -196,12 +200,26 @@ final class FieldSet<
return fields.isImmutable() ? fields : Collections.unmodifiableMap(fields);
}
private void cloneFieldEntry(
Map<FieldDescriptorType, Object> map, Map.Entry<FieldDescriptorType, Object> entry) {
FieldDescriptorType key = entry.getKey();
private static <T extends FieldDescriptorLite<T>> SmallSortedMap<T, Object> cloneAllFieldsMap(
SmallSortedMap<T, Object> fields, boolean copyList) {
SmallSortedMap<T, Object> result = SmallSortedMap.newFieldMap(DEFAULT_FIELD_MAP_ARRAY_SIZE);
for (int i = 0; i < fields.getNumArrayEntries(); i++) {
cloneFieldEntry(result, fields.getArrayEntryAt(i), copyList);
}
for (Map.Entry<T, Object> entry : fields.getOverflowEntries()) {
cloneFieldEntry(result, entry, copyList);
}
return result;
}
private static <T extends FieldDescriptorLite<T>> void cloneFieldEntry(
Map<T, Object> map, Map.Entry<T, Object> entry, boolean copyList) {
T key = entry.getKey();
Object value = entry.getValue();
if (value instanceof LazyField) {
map.put(key, ((LazyField) value).getValue());
} else if (copyList && value instanceof List) {
map.put(key, new ArrayList<>((List<?>) value));
} else {
map.put(key, value);
}
@ -211,9 +229,9 @@ final class FieldSet<
* Get an iterator to the field map. This iterator should not be leaked out of the protobuf
* library as it is not protected from mutation when fields is not immutable.
*/
public Iterator<Map.Entry<FieldDescriptorType, Object>> iterator() {
public Iterator<Map.Entry<T, Object>> iterator() {
if (hasLazyField) {
return new LazyIterator<FieldDescriptorType>(fields.entrySet().iterator());
return new LazyIterator<T>(fields.entrySet().iterator());
}
return fields.entrySet().iterator();
}
@ -223,15 +241,15 @@ final class FieldSet<
* should not be leaked out of the protobuf library as it is not protected from mutation when
* fields is not immutable.
*/
Iterator<Map.Entry<FieldDescriptorType, Object>> descendingIterator() {
Iterator<Map.Entry<T, Object>> descendingIterator() {
if (hasLazyField) {
return new LazyIterator<FieldDescriptorType>(fields.descendingEntrySet().iterator());
return new LazyIterator<T>(fields.descendingEntrySet().iterator());
}
return fields.descendingEntrySet().iterator();
}
/** Useful for implementing {@link Message#hasField(Descriptors.FieldDescriptor)}. */
public boolean hasField(final FieldDescriptorType descriptor) {
public boolean hasField(final T descriptor) {
if (descriptor.isRepeated()) {
throw new IllegalArgumentException("hasField() can only be called on non-repeated fields.");
}
@ -244,7 +262,7 @@ final class FieldSet<
* returns {@code null} if the field is not set; in this case it is up to the caller to fetch the
* field's default value.
*/
public Object getField(final FieldDescriptorType descriptor) {
public Object getField(final T descriptor) {
Object o = fields.get(descriptor);
if (o instanceof LazyField) {
return ((LazyField) o).getValue();
@ -256,7 +274,7 @@ final class FieldSet<
* Useful for implementing {@link Message.Builder#setField(Descriptors.FieldDescriptor,Object)}.
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public void setField(final FieldDescriptorType descriptor, Object value) {
public void setField(final T descriptor, Object value) {
if (descriptor.isRepeated()) {
if (!(value instanceof List)) {
throw new IllegalArgumentException(
@ -282,7 +300,7 @@ final class FieldSet<
}
/** Useful for implementing {@link Message.Builder#clearField(Descriptors.FieldDescriptor)}. */
public void clearField(final FieldDescriptorType descriptor) {
public void clearField(final T descriptor) {
fields.remove(descriptor);
if (fields.isEmpty()) {
hasLazyField = false;
@ -290,7 +308,7 @@ final class FieldSet<
}
/** Useful for implementing {@link Message#getRepeatedFieldCount(Descriptors.FieldDescriptor)}. */
public int getRepeatedFieldCount(final FieldDescriptorType descriptor) {
public int getRepeatedFieldCount(final T descriptor) {
if (!descriptor.isRepeated()) {
throw new IllegalArgumentException(
"getRepeatedField() can only be called on repeated fields.");
@ -305,7 +323,7 @@ final class FieldSet<
}
/** Useful for implementing {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)}. */
public Object getRepeatedField(final FieldDescriptorType descriptor, final int index) {
public Object getRepeatedField(final T descriptor, final int index) {
if (!descriptor.isRepeated()) {
throw new IllegalArgumentException(
"getRepeatedField() can only be called on repeated fields.");
@ -325,8 +343,7 @@ final class FieldSet<
* Message.Builder#setRepeatedField(Descriptors.FieldDescriptor,int,Object)}.
*/
@SuppressWarnings("unchecked")
public void setRepeatedField(
final FieldDescriptorType descriptor, final int index, final Object value) {
public void setRepeatedField(final T descriptor, final int index, final Object value) {
if (!descriptor.isRepeated()) {
throw new IllegalArgumentException(
"getRepeatedField() can only be called on repeated fields.");
@ -346,7 +363,7 @@ final class FieldSet<
* Message.Builder#addRepeatedField(Descriptors.FieldDescriptor,Object)}.
*/
@SuppressWarnings("unchecked")
public void addRepeatedField(final FieldDescriptorType descriptor, final Object value) {
public void addRepeatedField(final T descriptor, final Object value) {
if (!descriptor.isRepeated()) {
throw new IllegalArgumentException(
"addRepeatedField() can only be called on repeated fields.");
@ -373,53 +390,45 @@ final class FieldSet<
*
* @throws IllegalArgumentException The value is not of the right type.
*/
private static void verifyType(final WireFormat.FieldType type, final Object value) {
checkNotNull(value);
private void verifyType(final WireFormat.FieldType type, final Object value) {
if (!isValidType(type, value)) {
// TODO(kenton): When chaining calls to setField(), it can be hard to
// tell from the stack trace which exact call failed, since the whole
// chain is considered one line of code. It would be nice to print
// more information here, e.g. naming the field. We used to do that.
// But we can't now that FieldSet doesn't use descriptors. Maybe this
// isn't a big deal, though, since it would only really apply when using
// reflection and generally people don't chain reflection setters.
throw new IllegalArgumentException(
"Wrong object type used with protocol message reflection.");
}
}
boolean isValid = false;
private static boolean isValidType(final WireFormat.FieldType type, final Object value) {
checkNotNull(value);
switch (type.getJavaType()) {
case INT:
isValid = value instanceof Integer;
break;
return value instanceof Integer;
case LONG:
isValid = value instanceof Long;
break;
return value instanceof Long;
case FLOAT:
isValid = value instanceof Float;
break;
return value instanceof Float;
case DOUBLE:
isValid = value instanceof Double;
break;
return value instanceof Double;
case BOOLEAN:
isValid = value instanceof Boolean;
break;
return value instanceof Boolean;
case STRING:
isValid = value instanceof String;
break;
return value instanceof String;
case BYTE_STRING:
isValid = value instanceof ByteString || value instanceof byte[];
break;
return value instanceof ByteString || value instanceof byte[];
case ENUM:
// TODO(kenton): Caller must do type checking here, I guess.
isValid = (value instanceof Integer || value instanceof Internal.EnumLite);
break;
return (value instanceof Integer || value instanceof Internal.EnumLite);
case MESSAGE:
// TODO(kenton): Caller must do type checking here, I guess.
isValid = (value instanceof MessageLite) || (value instanceof LazyField);
break;
}
if (!isValid) {
// TODO(kenton): When chaining calls to setField(), it can be hard to
// tell from the stack trace which exact call failed, since the whole
// chain is considered one line of code. It would be nice to print
// more information here, e.g. naming the field. We used to do that.
// But we can't now that FieldSet doesn't use descriptors. Maybe this
// isn't a big deal, though, since it would only really apply when using
// reflection and generally people don't chain reflection setters.
throw new IllegalArgumentException(
"Wrong object type used with protocol message reflection.");
return (value instanceof MessageLite) || (value instanceof LazyField);
}
return false;
}
// =================================================================
@ -436,7 +445,7 @@ final class FieldSet<
return false;
}
}
for (final Map.Entry<FieldDescriptorType, Object> entry : fields.getOverflowEntries()) {
for (final Map.Entry<T, Object> entry : fields.getOverflowEntries()) {
if (!isInitialized(entry)) {
return false;
}
@ -445,8 +454,9 @@ final class FieldSet<
}
@SuppressWarnings("unchecked")
private boolean isInitialized(final Map.Entry<FieldDescriptorType, Object> entry) {
final FieldDescriptorType descriptor = entry.getKey();
private static <T extends FieldDescriptorLite<T>> boolean isInitialized(
final Map.Entry<T, Object> entry) {
final T descriptor = entry.getKey();
if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
if (descriptor.isRepeated()) {
for (final MessageLite element : (List<MessageLite>) entry.getValue()) {
@ -485,16 +495,16 @@ final class FieldSet<
}
/** Like {@link Message.Builder#mergeFrom(Message)}, but merges from another {@link FieldSet}. */
public void mergeFrom(final FieldSet<FieldDescriptorType> other) {
public void mergeFrom(final FieldSet<T> other) {
for (int i = 0; i < other.fields.getNumArrayEntries(); i++) {
mergeFromField(other.fields.getArrayEntryAt(i));
}
for (final Map.Entry<FieldDescriptorType, Object> entry : other.fields.getOverflowEntries()) {
for (final Map.Entry<T, Object> entry : other.fields.getOverflowEntries()) {
mergeFromField(entry);
}
}
private Object cloneIfMutable(Object value) {
private static Object cloneIfMutable(Object value) {
if (value instanceof byte[]) {
byte[] bytes = (byte[]) value;
byte[] copy = new byte[bytes.length];
@ -506,8 +516,8 @@ final class FieldSet<
}
@SuppressWarnings({"unchecked", "rawtypes"})
private void mergeFromField(final Map.Entry<FieldDescriptorType, Object> entry) {
final FieldDescriptorType descriptor = entry.getKey();
private void mergeFromField(final Map.Entry<T, Object> entry) {
final T descriptor = entry.getKey();
Object otherValue = entry.getValue();
if (otherValue instanceof LazyField) {
otherValue = ((LazyField) otherValue).getValue();
@ -532,7 +542,6 @@ final class FieldSet<
descriptor
.internalMergeFrom(((MessageLite) value).toBuilder(), (MessageLite) otherValue)
.build();
fields.put(descriptor, value);
}
} else {
@ -567,10 +576,10 @@ final class FieldSet<
/** See {@link Message#writeTo(CodedOutputStream)}. */
public void writeTo(final CodedOutputStream output) throws IOException {
for (int i = 0; i < fields.getNumArrayEntries(); i++) {
final Map.Entry<FieldDescriptorType, Object> entry = fields.getArrayEntryAt(i);
final Map.Entry<T, Object> entry = fields.getArrayEntryAt(i);
writeField(entry.getKey(), entry.getValue(), output);
}
for (final Map.Entry<FieldDescriptorType, Object> entry : fields.getOverflowEntries()) {
for (final Map.Entry<T, Object> entry : fields.getOverflowEntries()) {
writeField(entry.getKey(), entry.getValue(), output);
}
}
@ -580,15 +589,14 @@ final class FieldSet<
for (int i = 0; i < fields.getNumArrayEntries(); i++) {
writeMessageSetTo(fields.getArrayEntryAt(i), output);
}
for (final Map.Entry<FieldDescriptorType, Object> entry : fields.getOverflowEntries()) {
for (final Map.Entry<T, Object> entry : fields.getOverflowEntries()) {
writeMessageSetTo(entry, output);
}
}
private void writeMessageSetTo(
final Map.Entry<FieldDescriptorType, Object> entry, final CodedOutputStream output)
private void writeMessageSetTo(final Map.Entry<T, Object> entry, final CodedOutputStream output)
throws IOException {
final FieldDescriptorType descriptor = entry.getKey();
final T descriptor = entry.getKey();
if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE
&& !descriptor.isRepeated()
&& !descriptor.isPacked()) {
@ -750,10 +758,10 @@ final class FieldSet<
public int getSerializedSize() {
int size = 0;
for (int i = 0; i < fields.getNumArrayEntries(); i++) {
final Map.Entry<FieldDescriptorType, Object> entry = fields.getArrayEntryAt(i);
final Map.Entry<T, Object> entry = fields.getArrayEntryAt(i);
size += computeFieldSize(entry.getKey(), entry.getValue());
}
for (final Map.Entry<FieldDescriptorType, Object> entry : fields.getOverflowEntries()) {
for (final Map.Entry<T, Object> entry : fields.getOverflowEntries()) {
size += computeFieldSize(entry.getKey(), entry.getValue());
}
return size;
@ -765,14 +773,14 @@ final class FieldSet<
for (int i = 0; i < fields.getNumArrayEntries(); i++) {
size += getMessageSetSerializedSize(fields.getArrayEntryAt(i));
}
for (final Map.Entry<FieldDescriptorType, Object> entry : fields.getOverflowEntries()) {
for (final Map.Entry<T, Object> entry : fields.getOverflowEntries()) {
size += getMessageSetSerializedSize(entry);
}
return size;
}
private int getMessageSetSerializedSize(final Map.Entry<FieldDescriptorType, Object> entry) {
final FieldDescriptorType descriptor = entry.getKey();
private int getMessageSetSerializedSize(final Map.Entry<T, Object> entry) {
final T descriptor = entry.getKey();
Object value = entry.getValue();
if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE
&& !descriptor.isRepeated()
@ -904,4 +912,385 @@ final class FieldSet<
return computeElementSize(type, number, value);
}
}
/**
* A FieldSet Builder that accept a {@link MessageLite.Builder} as a field value. This is useful
* for implementing methods in {@link MessageLite.Builder}.
*/
static final class Builder<T extends FieldDescriptorLite<T>> {
private SmallSortedMap<T, Object> fields;
private boolean hasLazyField;
private boolean isMutable;
private boolean hasNestedBuilders;
private Builder() {
this(SmallSortedMap.<T>newFieldMap(DEFAULT_FIELD_MAP_ARRAY_SIZE));
}
private Builder(SmallSortedMap<T, Object> fields) {
this.fields = fields;
this.isMutable = true;
}
/** Creates the FieldSet */
public FieldSet<T> build() {
if (fields.isEmpty()) {
return FieldSet.emptySet();
}
isMutable = false;
SmallSortedMap<T, Object> fieldsForBuild = fields;
if (hasNestedBuilders) {
// Make a copy of the fields map with all Builders replaced by Message.
fieldsForBuild = cloneAllFieldsMap(fields, /* copyList */ false);
replaceBuilders(fieldsForBuild);
}
FieldSet<T> fieldSet = new FieldSet<>(fieldsForBuild);
fieldSet.hasLazyField = hasLazyField;
return fieldSet;
}
private static <T extends FieldDescriptorLite<T>> void replaceBuilders(
SmallSortedMap<T, Object> fieldMap) {
for (int i = 0; i < fieldMap.getNumArrayEntries(); i++) {
replaceBuilders(fieldMap.getArrayEntryAt(i));
}
for (Map.Entry<T, Object> entry : fieldMap.getOverflowEntries()) {
replaceBuilders(entry);
}
}
private static <T extends FieldDescriptorLite<T>> void replaceBuilders(
Map.Entry<T, Object> entry) {
entry.setValue(replaceBuilders(entry.getKey(), entry.getValue()));
}
private static <T extends FieldDescriptorLite<T>> Object replaceBuilders(
T descriptor, Object value) {
if (value == null) {
return value;
}
if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
if (descriptor.isRepeated()) {
if (!(value instanceof List)) {
throw new IllegalStateException(
"Repeated field should contains a List but actually contains type: "
+ value.getClass());
}
@SuppressWarnings("unchecked") // We just check that value is an instance of List above.
List<Object> list = (List<Object>) value;
for (int i = 0; i < list.size(); i++) {
Object oldElement = list.get(i);
Object newElement = replaceBuilder(oldElement);
if (newElement != oldElement) {
// If the list contains a Message.Builder, then make a copy of that list and then
// modify the Message.Builder into a Message and return the new list. This way, the
// existing Message.Builder will still be able to modify the inner fields of the
// original FieldSet.Builder.
if (list == value) {
list = new ArrayList<>(list);
}
list.set(i, newElement);
}
}
return list;
} else {
return replaceBuilder(value);
}
}
return value;
}
private static Object replaceBuilder(Object value) {
return (value instanceof MessageLite.Builder) ? ((MessageLite.Builder) value).build() : value;
}
/** Returns a new Builder using the fields from {@code fieldSet}. */
public static <T extends FieldDescriptorLite<T>> Builder<T> fromFieldSet(FieldSet<T> fieldSet) {
Builder<T> builder = new Builder<T>(cloneAllFieldsMap(fieldSet.fields, /* copyList */ true));
builder.hasLazyField = fieldSet.hasLazyField;
return builder;
}
// =================================================================
/** Get a simple map containing all the fields. */
public Map<T, Object> getAllFields() {
if (hasLazyField) {
SmallSortedMap<T, Object> result = cloneAllFieldsMap(fields, /* copyList */ false);
if (fields.isImmutable()) {
result.makeImmutable();
} else {
replaceBuilders(result);
}
return result;
}
return fields.isImmutable() ? fields : Collections.unmodifiableMap(fields);
}
/** Useful for implementing {@link Message#hasField(Descriptors.FieldDescriptor)}. */
public boolean hasField(final T descriptor) {
if (descriptor.isRepeated()) {
throw new IllegalArgumentException("hasField() can only be called on non-repeated fields.");
}
return fields.get(descriptor) != null;
}
/**
* Useful for implementing {@link Message#getField(Descriptors.FieldDescriptor)}. This method
* returns {@code null} if the field is not set; in this case it is up to the caller to fetch
* the field's default value.
*/
public Object getField(final T descriptor) {
Object value = getFieldAllowBuilders(descriptor);
return replaceBuilders(descriptor, value);
}
/** Same as {@link #getField(F)}, but allow a {@link MessageLite.Builder} to be returned. */
Object getFieldAllowBuilders(final T descriptor) {
Object o = fields.get(descriptor);
if (o instanceof LazyField) {
return ((LazyField) o).getValue();
}
return o;
}
private void ensureIsMutable() {
if (!isMutable) {
fields = cloneAllFieldsMap(fields, /* copyList */ true);
isMutable = true;
}
}
/**
* Useful for implementing {@link Message.Builder#setField(Descriptors.FieldDescriptor,
* Object)}.
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public void setField(final T descriptor, Object value) {
ensureIsMutable();
if (descriptor.isRepeated()) {
if (!(value instanceof List)) {
throw new IllegalArgumentException(
"Wrong object type used with protocol message reflection.");
}
// Wrap the contents in a new list so that the caller cannot change
// the list's contents after setting it.
final List newList = new ArrayList();
newList.addAll((List) value);
for (final Object element : newList) {
verifyType(descriptor.getLiteType(), element);
hasNestedBuilders = hasNestedBuilders || element instanceof MessageLite.Builder;
}
value = newList;
} else {
verifyType(descriptor.getLiteType(), value);
}
if (value instanceof LazyField) {
hasLazyField = true;
}
hasNestedBuilders = hasNestedBuilders || value instanceof MessageLite.Builder;
fields.put(descriptor, value);
}
/** Useful for implementing {@link Message.Builder#clearField(Descriptors.FieldDescriptor)}. */
public void clearField(final T descriptor) {
ensureIsMutable();
fields.remove(descriptor);
if (fields.isEmpty()) {
hasLazyField = false;
}
}
/**
* Useful for implementing {@link Message#getRepeatedFieldCount(Descriptors.FieldDescriptor)}.
*/
public int getRepeatedFieldCount(final T descriptor) {
if (!descriptor.isRepeated()) {
throw new IllegalArgumentException(
"getRepeatedField() can only be called on repeated fields.");
}
final Object value = getField(descriptor);
if (value == null) {
return 0;
} else {
return ((List<?>) value).size();
}
}
/**
* Useful for implementing {@link Message#getRepeatedField(Descriptors.FieldDescriptor, int)}.
*/
public Object getRepeatedField(final T descriptor, final int index) {
if (hasNestedBuilders) {
ensureIsMutable();
}
Object value = getRepeatedFieldAllowBuilders(descriptor, index);
return replaceBuilder(value);
}
/**
* Same as {@link #getRepeatedField(F, int)}, but allow a {@link MessageLite.Builder} to be
* returned.
*/
Object getRepeatedFieldAllowBuilders(final T descriptor, final int index) {
if (!descriptor.isRepeated()) {
throw new IllegalArgumentException(
"getRepeatedField() can only be called on repeated fields.");
}
final Object value = getFieldAllowBuilders(descriptor);
if (value == null) {
throw new IndexOutOfBoundsException();
} else {
return ((List<?>) value).get(index);
}
}
/**
* Useful for implementing {@link Message.Builder#setRepeatedField(Descriptors.FieldDescriptor,
* int, Object)}.
*/
@SuppressWarnings("unchecked")
public void setRepeatedField(final T descriptor, final int index, final Object value) {
ensureIsMutable();
if (!descriptor.isRepeated()) {
throw new IllegalArgumentException(
"getRepeatedField() can only be called on repeated fields.");
}
hasNestedBuilders = hasNestedBuilders || value instanceof MessageLite.Builder;
final Object list = getField(descriptor);
if (list == null) {
throw new IndexOutOfBoundsException();
}
verifyType(descriptor.getLiteType(), value);
((List<Object>) list).set(index, value);
}
/**
* Useful for implementing {@link Message.Builder#addRepeatedField(Descriptors.FieldDescriptor,
* Object)}.
*/
@SuppressWarnings("unchecked")
public void addRepeatedField(final T descriptor, final Object value) {
ensureIsMutable();
if (!descriptor.isRepeated()) {
throw new IllegalArgumentException(
"addRepeatedField() can only be called on repeated fields.");
}
hasNestedBuilders = hasNestedBuilders || value instanceof MessageLite.Builder;
verifyType(descriptor.getLiteType(), value);
final Object existingValue = getField(descriptor);
List<Object> list;
if (existingValue == null) {
list = new ArrayList<>();
fields.put(descriptor, list);
} else {
list = (List<Object>) existingValue;
}
list.add(value);
}
/**
* Verifies that the given object is of the correct type to be a valid value for the given
* field. (For repeated fields, this checks if the object is the right type to be one element of
* the field.)
*
* @throws IllegalArgumentException The value is not of the right type.
*/
private static void verifyType(final WireFormat.FieldType type, final Object value) {
if (!FieldSet.isValidType(type, value)) {
// Builder can accept Message.Builder values even though FieldSet will reject.
if (type.getJavaType() == WireFormat.JavaType.MESSAGE
&& value instanceof MessageLite.Builder) {
return;
}
throw new IllegalArgumentException(
"Wrong object type used with protocol message reflection.");
}
}
/**
* See {@link Message#isInitialized()}. Note: Since {@code FieldSet} itself does not have any
* way of knowing about required fields that aren't actually present in the set, it is up to the
* caller to check that all required fields are present.
*/
public boolean isInitialized() {
for (int i = 0; i < fields.getNumArrayEntries(); i++) {
if (!FieldSet.isInitialized(fields.getArrayEntryAt(i))) {
return false;
}
}
for (final Map.Entry<T, Object> entry : fields.getOverflowEntries()) {
if (!FieldSet.isInitialized(entry)) {
return false;
}
}
return true;
}
/**
* Like {@link Message.Builder#mergeFrom(Message)}, but merges from another {@link FieldSet}.
*/
public void mergeFrom(final FieldSet<T> other) {
ensureIsMutable();
for (int i = 0; i < other.fields.getNumArrayEntries(); i++) {
mergeFromField(other.fields.getArrayEntryAt(i));
}
for (final Map.Entry<T, Object> entry : other.fields.getOverflowEntries()) {
mergeFromField(entry);
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
private void mergeFromField(final Map.Entry<T, Object> entry) {
final T descriptor = entry.getKey();
Object otherValue = entry.getValue();
if (otherValue instanceof LazyField) {
otherValue = ((LazyField) otherValue).getValue();
}
if (descriptor.isRepeated()) {
Object value = getField(descriptor);
if (value == null) {
value = new ArrayList();
}
for (Object element : (List) otherValue) {
((List) value).add(FieldSet.cloneIfMutable(element));
}
fields.put(descriptor, value);
} else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
Object value = getField(descriptor);
if (value == null) {
fields.put(descriptor, FieldSet.cloneIfMutable(otherValue));
} else {
// Merge the messages.
if (value instanceof MessageLite.Builder) {
descriptor.internalMergeFrom((MessageLite.Builder) value, (MessageLite) otherValue);
} else {
value =
descriptor
.internalMergeFrom(((MessageLite) value).toBuilder(), (MessageLite) otherValue)
.build();
fields.put(descriptor, value);
}
}
} else {
fields.put(descriptor, cloneIfMutable(otherValue));
}
}
}
}

@ -1363,7 +1363,7 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
extends Builder<BuilderType>
implements ExtendableMessageOrBuilder<MessageType> {
private FieldSet<FieldDescriptor> extensions = FieldSet.emptySet();
private FieldSet.Builder<FieldDescriptor> extensions;
protected ExtendableBuilder() {}
@ -1374,18 +1374,18 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
// For immutable message conversion.
void internalSetExtensionSet(FieldSet<FieldDescriptor> extensions) {
this.extensions = extensions;
this.extensions = FieldSet.Builder.fromFieldSet(extensions);
}
@Override
public BuilderType clear() {
extensions = FieldSet.emptySet();
extensions = null;
return super.clear();
}
private void ensureExtensionsIsMutable() {
if (extensions.isImmutable()) {
extensions = extensions.clone();
if (extensions == null) {
extensions = FieldSet.newBuilder();
}
}
@ -1408,7 +1408,7 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
Extension<MessageType, Type> extension = checkNotLite(extensionLite);
verifyExtensionContainingType(extension);
return extensions.hasField(extension.getDescriptor());
return extensions == null ? false : extensions.hasField(extension.getDescriptor());
}
/** Get the number of elements in a repeated extension. */
@ -1419,7 +1419,7 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
verifyExtensionContainingType(extension);
final FieldDescriptor descriptor = extension.getDescriptor();
return extensions.getRepeatedFieldCount(descriptor);
return extensions == null ? 0 : extensions.getRepeatedFieldCount(descriptor);
}
/** Get the value of an extension. */
@ -1429,7 +1429,7 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
verifyExtensionContainingType(extension);
FieldDescriptor descriptor = extension.getDescriptor();
final Object value = extensions.getField(descriptor);
final Object value = extensions == null ? null : extensions.getField(descriptor);
if (value == null) {
if (descriptor.isRepeated()) {
return (Type) Collections.emptyList();
@ -1453,8 +1453,11 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
verifyExtensionContainingType(extension);
FieldDescriptor descriptor = extension.getDescriptor();
return (Type) extension.singularFromReflectionType(
extensions.getRepeatedField(descriptor, index));
if (extensions == null) {
throw new IndexOutOfBoundsException();
}
return (Type)
extension.singularFromReflectionType(extensions.getRepeatedField(descriptor, index));
}
/** Set the value of an extension. */
@ -1605,7 +1608,7 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
/** Called by subclasses to check if all extensions are initialized. */
protected boolean extensionsAreInitialized() {
return extensions.isInitialized();
return extensions == null ? true : extensions.isInitialized();
}
/**
@ -1613,8 +1616,9 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
* building the message.
*/
private FieldSet<FieldDescriptor> buildExtensions() {
extensions.makeImmutable();
return extensions;
return extensions == null
? (FieldSet<FieldDescriptor>) FieldSet.emptySet()
: extensions.build();
}
@Override
@ -1628,7 +1632,9 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
@Override
public Map<FieldDescriptor, Object> getAllFields() {
final Map<FieldDescriptor, Object> result = super.getAllFieldsMutable();
if (extensions != null) {
result.putAll(extensions.getAllFields());
}
return Collections.unmodifiableMap(result);
}
@ -1636,7 +1642,7 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
public Object getField(final FieldDescriptor field) {
if (field.isExtension()) {
verifyContainingType(field);
final Object value = extensions.getField(field);
final Object value = extensions == null ? null : extensions.getField(field);
if (value == null) {
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
// Lacking an ExtensionRegistry, we have no way to determine the
@ -1653,11 +1659,44 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
}
}
@Override
public Message.Builder getFieldBuilder(final FieldDescriptor field) {
if (field.isExtension()) {
verifyContainingType(field);
if (field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) {
throw new UnsupportedOperationException(
"getFieldBuilder() called on a non-Message type.");
}
ensureExtensionsIsMutable();
final Object value = extensions.getFieldAllowBuilders(field);
if (value == null) {
Message.Builder builder = DynamicMessage.newBuilder(field.getMessageType());
extensions.setField(field, builder);
onChanged();
return builder;
} else {
if (value instanceof Message.Builder) {
return (Message.Builder) value;
} else if (value instanceof Message) {
Message.Builder builder = ((Message) value).toBuilder();
extensions.setField(field, builder);
onChanged();
return builder;
} else {
throw new UnsupportedOperationException(
"getRepeatedFieldBuilder() called on a non-Message type.");
}
}
} else {
return super.getFieldBuilder(field);
}
}
@Override
public int getRepeatedFieldCount(final FieldDescriptor field) {
if (field.isExtension()) {
verifyContainingType(field);
return extensions.getRepeatedFieldCount(field);
return extensions == null ? 0 : extensions.getRepeatedFieldCount(field);
} else {
return super.getRepeatedFieldCount(field);
}
@ -1668,17 +1707,46 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
final int index) {
if (field.isExtension()) {
verifyContainingType(field);
if (extensions == null) {
throw new IndexOutOfBoundsException();
}
return extensions.getRepeatedField(field, index);
} else {
return super.getRepeatedField(field, index);
}
}
@Override
public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, final int index) {
if (field.isExtension()) {
verifyContainingType(field);
ensureExtensionsIsMutable();
if (field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) {
throw new UnsupportedOperationException(
"getRepeatedFieldBuilder() called on a non-Message type.");
}
final Object value = extensions.getRepeatedFieldAllowBuilders(field, index);
if (value instanceof Message.Builder) {
return (Message.Builder) value;
} else if (value instanceof Message) {
Message.Builder builder = ((Message) value).toBuilder();
extensions.setRepeatedField(field, index, builder);
onChanged();
return builder;
} else {
throw new UnsupportedOperationException(
"getRepeatedFieldBuilder() called on a non-Message type.");
}
} else {
return super.getRepeatedFieldBuilder(field, index);
}
}
@Override
public boolean hasField(final FieldDescriptor field) {
if (field.isExtension()) {
verifyContainingType(field);
return extensions.hasField(field);
return extensions == null ? false : extensions.hasField(field);
} else {
return super.hasField(field);
}
@ -1749,10 +1817,12 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
}
protected final void mergeExtensionFields(final ExtendableMessage other) {
if (other.extensions != null) {
ensureExtensionsIsMutable();
extensions.mergeFrom(other.extensions);
onChanged();
}
}
private void verifyContainingType(final FieldDescriptor field) {
if (field.getContainingType() != getDescriptorForType()) {

@ -32,9 +32,10 @@ package com.google.protobuf;
import com.google.protobuf.Internal.ProtobufList;
import java.util.Arrays;
import java.util.RandomAccess;
/** Implements {@link ProtobufList} for non-primitive and {@link String} types. */
final class ProtobufArrayList<E> extends AbstractProtobufList<E> {
final class ProtobufArrayList<E> extends AbstractProtobufList<E> implements RandomAccess {
private static final ProtobufArrayList<Object> EMPTY_LIST =
new ProtobufArrayList<Object>(new Object[0], 0);

@ -113,8 +113,8 @@ public final class TextFormat {
}
/**
* Generates a human readable form of the field, useful for debugging and other purposes, with no
* newline characters.
* Generates a human readable form of the field, useful for debugging and other purposes, with
* no newline characters.
*
* @deprecated Use {@code printer().shortDebugString(FieldDescriptor, Object)}
*/
@ -122,10 +122,10 @@ public final class TextFormat {
public static String shortDebugString(final FieldDescriptor field, final Object value) {
return printer().shortDebugString(field, value);
}
//
/**
* Generates a human readable form of the unknown fields, useful for debugging and other purposes,
* with no newline characters.
* Generates a human readable form of the unknown fields, useful for debugging and other
* purposes, with no newline characters.
*
* @deprecated Use {@code printer().shortDebugString(UnknownFieldSet)}
*/
@ -166,8 +166,8 @@ public final class TextFormat {
}
/**
* Same as {@code printToString()}, except that non-ASCII characters in string type fields are not
* escaped in backslash+octals.
* Same as {@code printToString()}, except that non-ASCII characters in string type fields are
* not escaped in backslash+octals.
*
* @deprecated Use {@code printer().escapingNonAscii(false).printToString(UnknownFieldSet)}
*/
@ -175,20 +175,21 @@ public final class TextFormat {
public static String printToUnicodeString(final UnknownFieldSet fields) {
return printer().escapingNonAscii(false).printToString(fields);
}
//
/** @deprecated Use {@code printer().printField(FieldDescriptor, Object, Appendable)} */
@Deprecated
public static void printField(
final FieldDescriptor field, final Object value, final Appendable output) throws IOException {
final FieldDescriptor field, final Object value, final Appendable output)
throws IOException {
printer().printField(field, value, output);
}
//
/** @deprecated Use {@code printer().printFieldToString(FieldDescriptor, Object)} */
@Deprecated
public static String printFieldToString(final FieldDescriptor field, final Object value) {
return printer().printFieldToString(field, value);
}
//
/**
* Outputs a unicode textual representation of the value of given field value.
*
@ -205,7 +206,8 @@ public final class TextFormat {
*/
@Deprecated
public static void printUnicodeFieldValue(
final FieldDescriptor field, final Object value, final Appendable output) throws IOException {
final FieldDescriptor field, final Object value, final Appendable output)
throws IOException {
printer().escapingNonAscii(false).printFieldValue(field, value, output);
}
@ -285,13 +287,16 @@ public final class TextFormat {
public static final class Printer {
// Printer instance which escapes non-ASCII characters.
private static final Printer DEFAULT = new Printer(true);
private static final Printer DEFAULT = new Printer(true, TypeRegistry.getEmptyTypeRegistry());
/** Whether to escape non ASCII characters with backslash and octal. */
private final boolean escapeNonAscii;
private Printer(boolean escapeNonAscii) {
private final TypeRegistry typeRegistry;
private Printer(boolean escapeNonAscii, TypeRegistry typeRegistry) {
this.escapeNonAscii = escapeNonAscii;
this.typeRegistry = typeRegistry;
}
/**
@ -304,7 +309,20 @@ public final class TextFormat {
* with the escape mode set to the given parameter.
*/
public Printer escapingNonAscii(boolean escapeNonAscii) {
return new Printer(escapeNonAscii);
return new Printer(escapeNonAscii, typeRegistry);
}
/**
* Creates a new {@link Printer} using the given typeRegistry. The new Printer clones all other
* configurations from the current {@link Printer}.
*
* @throws IllegalArgumentException if a registry is already set.
*/
public Printer usingTypeRegistry(TypeRegistry typeRegistry) {
if (this.typeRegistry != TypeRegistry.getEmptyTypeRegistry()) {
throw new IllegalArgumentException("Only one typeRegistry is allowed.");
}
return new Printer(escapeNonAscii, typeRegistry);
}
/**
@ -323,9 +341,66 @@ public final class TextFormat {
private void print(final MessageOrBuilder message, final TextGenerator generator)
throws IOException {
if (message.getDescriptorForType().getFullName().equals("google.protobuf.Any")
&& printAny(message, generator)) {
return;
}
printMessage(message, generator);
}
/**
* Attempt to print the 'google.protobuf.Any' message in a human-friendly format. Returns false
* if the message isn't a valid 'google.protobuf.Any' message (in which case the message should
* be rendered just like a regular message to help debugging).
*/
private boolean printAny(final MessageOrBuilder message, final TextGenerator generator)
throws IOException {
Descriptor messageType = message.getDescriptorForType();
FieldDescriptor typeUrlField = messageType.findFieldByNumber(1);
FieldDescriptor valueField = messageType.findFieldByNumber(2);
if (typeUrlField == null
|| typeUrlField.getType() != FieldDescriptor.Type.STRING
|| valueField == null
|| valueField.getType() != FieldDescriptor.Type.BYTES) {
// The message may look like an Any but isn't actually an Any message (might happen if the
// user tries to use DynamicMessage to construct an Any from incomplete Descriptor).
return false;
}
String typeUrl = (String) message.getField(typeUrlField);
// If type_url is not set, we will not be able to decode the content of the value, so just
// print out the Any like a regular message.
if (typeUrl.isEmpty()) {
return false;
}
Object value = message.getField(valueField);
Message.Builder contentBuilder = null;
try {
Descriptor contentType = typeRegistry.getDescriptorForTypeUrl(typeUrl);
if (contentType == null) {
return false;
}
contentBuilder = DynamicMessage.getDefaultInstance(contentType).newBuilderForType();
contentBuilder.mergeFrom((ByteString) value);
} catch (InvalidProtocolBufferException e) {
// The value of Any is malformed. We cannot print it out nicely, so fallback to printing out
// the type_url and value as bytes. Note that we fail open here to be consistent with
// text_format.cc, and also to allow a way for users to inspect the content of the broken
// message.
return false;
}
generator.print("[");
generator.print(typeUrl);
generator.print("] {");
generator.eol();
generator.indent();
print(contentBuilder, generator);
generator.outdent();
generator.print("}");
generator.eol();
return true;
}
public String printFieldToString(final FieldDescriptor field, final Object value) {
try {
final StringBuilder text = new StringBuilder();
@ -1382,6 +1457,7 @@ public final class TextFormat {
FORBID_SINGULAR_OVERWRITES
}
private final TypeRegistry typeRegistry;
private final boolean allowUnknownFields;
private final boolean allowUnknownEnumValues;
private final boolean allowUnknownExtensions;
@ -1389,11 +1465,13 @@ public final class TextFormat {
private TextFormatParseInfoTree.Builder parseInfoTreeBuilder;
private Parser(
TypeRegistry typeRegistry,
boolean allowUnknownFields,
boolean allowUnknownEnumValues,
boolean allowUnknownExtensions,
SingularOverwritePolicy singularOverwritePolicy,
TextFormatParseInfoTree.Builder parseInfoTreeBuilder) {
this.typeRegistry = typeRegistry;
this.allowUnknownFields = allowUnknownFields;
this.allowUnknownEnumValues = allowUnknownEnumValues;
this.allowUnknownExtensions = allowUnknownExtensions;
@ -1414,6 +1492,18 @@ public final class TextFormat {
private SingularOverwritePolicy singularOverwritePolicy =
SingularOverwritePolicy.ALLOW_SINGULAR_OVERWRITES;
private TextFormatParseInfoTree.Builder parseInfoTreeBuilder = null;
private TypeRegistry typeRegistry = TypeRegistry.getEmptyTypeRegistry();
/**
* Sets the TypeRegistry for resolving Any. If this is not set, TextFormat will not be able to
* parse Any unless Any is write as bytes.
*
* @throws IllegalArgumentException if a registry is already set.
*/
public Builder setTypeRegistry(TypeRegistry typeRegistry) {
this.typeRegistry = typeRegistry;
return this;
}
/**
* Set whether this parser will allow unknown fields. By default, an exception is thrown if an
@ -1452,6 +1542,7 @@ public final class TextFormat {
public Parser build() {
return new Parser(
typeRegistry,
allowUnknownFields,
allowUnknownEnumValues,
allowUnknownExtensions,
@ -1834,6 +1925,14 @@ public final class TextFormat {
endToken = "}";
}
// Try to parse human readable format of Any in the form: [type_url]: { ... }
if (field.getMessageType().getFullName().equals("google.protobuf.Any")
&& tokenizer.tryConsume("[")) {
value =
consumeAnyFieldValue(
tokenizer, extensionRegistry, field, parseTreeBuilder, unknownFields);
tokenizer.consume(endToken);
} else {
Message defaultInstance = (extension == null) ? null : extension.defaultInstance;
MessageReflection.MergeTarget subField =
target.newMergeTargetForField(field, defaultInstance);
@ -1846,6 +1945,8 @@ public final class TextFormat {
}
value = subField.finish();
}
} else {
switch (field.getType()) {
case INT32:
@ -1951,6 +2052,71 @@ public final class TextFormat {
}
}
private Object consumeAnyFieldValue(
final Tokenizer tokenizer,
final ExtensionRegistry extensionRegistry,
final FieldDescriptor field,
final TextFormatParseInfoTree.Builder parseTreeBuilder,
List<UnknownField> unknownFields)
throws ParseException {
// Try to parse human readable format of Any in the form: [type_url]: { ... }
StringBuilder typeUrlBuilder = new StringBuilder();
// Parse the type_url inside [].
while (true) {
typeUrlBuilder.append(tokenizer.consumeIdentifier());
if (tokenizer.tryConsume("]")) {
break;
}
if (tokenizer.tryConsume("/")) {
typeUrlBuilder.append("/");
} else if (tokenizer.tryConsume(".")) {
typeUrlBuilder.append(".");
} else {
throw tokenizer.parseExceptionPreviousToken("Expected a valid type URL.");
}
}
tokenizer.tryConsume(":");
final String anyEndToken;
if (tokenizer.tryConsume("<")) {
anyEndToken = ">";
} else {
tokenizer.consume("{");
anyEndToken = "}";
}
String typeUrl = typeUrlBuilder.toString();
Descriptor contentType = null;
try {
contentType = typeRegistry.getDescriptorForTypeUrl(typeUrl);
} catch (InvalidProtocolBufferException e) {
throw tokenizer.parseException("Invalid valid type URL. Found: " + typeUrl);
}
if (contentType == null) {
throw tokenizer.parseException(
"Unable to parse Any of type: "
+ typeUrl
+ ". Please make sure that the TypeRegistry contains the descriptors for the given"
+ " types.");
}
Message.Builder contentBuilder =
DynamicMessage.getDefaultInstance(contentType).newBuilderForType();
MessageReflection.BuilderAdapter contentTarget =
new MessageReflection.BuilderAdapter(contentBuilder);
while (!tokenizer.tryConsume(anyEndToken)) {
mergeField(tokenizer, extensionRegistry, contentTarget, parseTreeBuilder, unknownFields);
}
// Serialize the content and put it back into an Any. Note that we can't depend on Any here
// because of a cyclic dependency (java_proto_library for any_java_proto depends on the
// protobuf_impl), so we need to construct the Any using proto reflection.
Descriptor anyDescriptor = field.getMessageType();
Message.Builder anyBuilder =
DynamicMessage.getDefaultInstance(anyDescriptor).newBuilderForType();
anyBuilder.setField(anyDescriptor.findFieldByName("type_url"), typeUrlBuilder.toString());
anyBuilder.setField(
anyDescriptor.findFieldByName("value"), contentBuilder.build().toByteString());
return anyBuilder.build();
}
/** Skips the next field including the field's name and value. */
private void skipField(Tokenizer tokenizer) throws ParseException {

@ -0,0 +1,160 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FileDescriptor;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
/**
* A TypeRegistry is used to resolve Any messages. You must provide a TypeRegistry containing all
* message types used in Any message fields.
*/
public class TypeRegistry {
private static final Logger logger = Logger.getLogger(TypeRegistry.class.getName());
private static class EmptyTypeRegistryHolder {
private static final TypeRegistry EMPTY =
new TypeRegistry(Collections.<String, Descriptor>emptyMap());
}
public static TypeRegistry getEmptyTypeRegistry() {
return EmptyTypeRegistryHolder.EMPTY;
}
public static Builder newBuilder() {
return new Builder();
}
/**
* Find a type by its full name. Returns null if it cannot be found in this {@link TypeRegistry}.
*/
public Descriptor find(String name) {
return types.get(name);
}
/**
* Find a type by its typeUrl. Returns null if it cannot be found in this {@link TypeRegistry}.
*/
/* @Nullable */
public final Descriptor getDescriptorForTypeUrl(String typeUrl)
throws InvalidProtocolBufferException {
return find(getTypeName(typeUrl));
}
private final Map<String, Descriptor> types;
TypeRegistry(Map<String, Descriptor> types) {
this.types = types;
}
private static String getTypeName(String typeUrl) throws InvalidProtocolBufferException {
String[] parts = typeUrl.split("/");
if (parts.length == 1) {
throw new InvalidProtocolBufferException("Invalid type url found: " + typeUrl);
}
return parts[parts.length - 1];
}
/** A Builder is used to build {@link TypeRegistry}. */
public static final class Builder {
private Builder() {}
/**
* Adds a message type and all types defined in the same .proto file as well as all transitively
* imported .proto files to this {@link Builder}.
*/
public Builder add(Descriptor messageType) {
if (types == null) {
throw new IllegalStateException("A TypeRegistry.Builder can only be used once.");
}
addFile(messageType.getFile());
return this;
}
/**
* Adds message types and all types defined in the same .proto file as well as all transitively
* imported .proto files to this {@link Builder}.
*/
public Builder add(Iterable<Descriptor> messageTypes) {
if (types == null) {
throw new IllegalStateException("A TypeRegistry.Builder can only be used once.");
}
for (Descriptor type : messageTypes) {
addFile(type.getFile());
}
return this;
}
/** Builds a {@link TypeRegistry}. This method can only be called once for one Builder. */
public TypeRegistry build() {
TypeRegistry result = new TypeRegistry(types);
// Make sure the built {@link TypeRegistry} is immutable.
types = null;
return result;
}
private void addFile(FileDescriptor file) {
// Skip the file if it's already added.
if (!files.add(file.getFullName())) {
return;
}
for (FileDescriptor dependency : file.getDependencies()) {
addFile(dependency);
}
for (Descriptor message : file.getMessageTypes()) {
addMessage(message);
}
}
private void addMessage(Descriptor message) {
for (Descriptor nestedType : message.getNestedTypes()) {
addMessage(nestedType);
}
if (types.containsKey(message.getFullName())) {
logger.warning("Type " + message.getFullName() + " is added multiple times.");
return;
}
types.put(message.getFullName(), message);
}
private final Set<String> files = new HashSet<>();
private Map<String, Descriptor> types = new HashMap<>();
}
}

@ -115,6 +115,160 @@ public class GeneratedMessageTest extends TestCase {
GeneratedMessageV3.setAlwaysUseFieldBuildersForTesting(false);
}
public void testGetFieldBuilderForExtensionField() {
TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
Message.Builder fieldBuilder =
builder.getFieldBuilder(UnittestProto.optionalNestedMessageExtension.getDescriptor());
int expected = 7432;
FieldDescriptor field =
NestedMessage.getDescriptor().findFieldByNumber(NestedMessage.BB_FIELD_NUMBER);
fieldBuilder.setField(field, expected);
assertEquals(
expected,
builder.build().getExtension(UnittestProto.optionalNestedMessageExtension).getBb());
// fieldBuilder still updates the builder after builder build() has been called.
expected += 100;
fieldBuilder.setField(field, expected);
assertEquals(
expected,
builder.build().getExtension(UnittestProto.optionalNestedMessageExtension).getBb());
}
public void testGetFieldBuilderWithExistingMessage() {
TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
builder.setExtension(
UnittestProto.optionalNestedMessageExtension,
NestedMessage.newBuilder().setBb(123).build());
Message.Builder fieldBuilder =
builder.getFieldBuilder(UnittestProto.optionalNestedMessageExtension.getDescriptor());
int expected = 7432;
FieldDescriptor field =
NestedMessage.getDescriptor().findFieldByNumber(NestedMessage.BB_FIELD_NUMBER);
fieldBuilder.setField(field, expected);
assertEquals(
expected,
builder.build().getExtension(UnittestProto.optionalNestedMessageExtension).getBb());
// fieldBuilder still updates the builder after builder build() has been called.
expected += 100;
fieldBuilder.setField(field, expected);
assertEquals(
expected,
builder.build().getExtension(UnittestProto.optionalNestedMessageExtension).getBb());
}
public void testGetFieldBuilderWithExistingBuilder() {
TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
NestedMessage.Builder nestedMessageBuilder = NestedMessage.newBuilder().setBb(123);
builder.setField(
UnittestProto.optionalNestedMessageExtension.getDescriptor(), nestedMessageBuilder);
Message.Builder fieldBuilder =
builder.getFieldBuilder(UnittestProto.optionalNestedMessageExtension.getDescriptor());
int expected = 7432;
FieldDescriptor field =
NestedMessage.getDescriptor().findFieldByNumber(NestedMessage.BB_FIELD_NUMBER);
fieldBuilder.setField(field, expected);
assertEquals(
expected,
builder.build().getExtension(UnittestProto.optionalNestedMessageExtension).getBb());
// Existing nestedMessageBuilder will also update builder.
expected += 100;
nestedMessageBuilder.setBb(expected);
assertEquals(
expected,
builder.build().getExtension(UnittestProto.optionalNestedMessageExtension).getBb());
// fieldBuilder still updates the builder.
expected += 100;
fieldBuilder.setField(field, expected);
assertEquals(
expected,
builder.build().getExtension(UnittestProto.optionalNestedMessageExtension).getBb());
}
public void testGetRepeatedFieldBuilderForExtensionField() {
TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
builder.addExtension(
UnittestProto.repeatedNestedMessageExtension,
NestedMessage.newBuilder().setBb(123).build());
Message.Builder fieldBuilder =
builder.getRepeatedFieldBuilder(
UnittestProto.repeatedNestedMessageExtension.getDescriptor(), 0);
int expected = 7432;
FieldDescriptor field =
NestedMessage.getDescriptor().findFieldByNumber(NestedMessage.BB_FIELD_NUMBER);
fieldBuilder.setField(field, expected);
assertEquals(
expected,
builder.build().getExtension(UnittestProto.repeatedNestedMessageExtension, 0).getBb());
// fieldBuilder still updates the builder after builder build() has been called.
expected += 100;
fieldBuilder.setField(field, expected);
assertEquals(
expected,
builder.build().getExtension(UnittestProto.repeatedNestedMessageExtension, 0).getBb());
}
public void testGetRepeatedFieldBuilderForExistingBuilder() {
TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
NestedMessage.Builder nestedMessageBuilder = NestedMessage.newBuilder().setBb(123);
builder.addRepeatedField(
UnittestProto.repeatedNestedMessageExtension.getDescriptor(), nestedMessageBuilder);
Message.Builder fieldBuilder =
builder.getRepeatedFieldBuilder(
UnittestProto.repeatedNestedMessageExtension.getDescriptor(), 0);
int expected = 7432;
FieldDescriptor field =
NestedMessage.getDescriptor().findFieldByNumber(NestedMessage.BB_FIELD_NUMBER);
fieldBuilder.setField(field, expected);
assertEquals(
expected,
builder.build().getExtension(UnittestProto.repeatedNestedMessageExtension, 0).getBb());
// Existing nestedMessageBuilder will also update builder.
expected += 100;
nestedMessageBuilder.setBb(expected);
assertEquals(
expected,
builder.build().getExtension(UnittestProto.repeatedNestedMessageExtension, 0).getBb());
// fieldBuilder still updates the builder.
expected += 100;
fieldBuilder.setField(field, expected);
assertEquals(
expected,
builder.build().getExtension(UnittestProto.repeatedNestedMessageExtension, 0).getBb());
}
public void testGetExtensionFieldOutOfBound() {
TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
try {
builder.getRepeatedField(UnittestProto.repeatedNestedMessageExtension.getDescriptor(), 0);
fail("Expected IndexOutOfBoundsException to be thrown");
} catch (IndexOutOfBoundsException expected) {
}
try {
builder.getExtension(UnittestProto.repeatedNestedMessageExtension, 0);
fail("Expected IndexOutOfBoundsException to be thrown");
} catch (IndexOutOfBoundsException expected) {
}
TestAllExtensions extensionsMessage = builder.build();
try {
extensionsMessage.getRepeatedField(
UnittestProto.repeatedNestedMessageExtension.getDescriptor(), 0);
fail("Expected IndexOutOfBoundsException to be thrown");
} catch (IndexOutOfBoundsException expected) {
}
try {
extensionsMessage.getExtension(UnittestProto.repeatedNestedMessageExtension, 0);
fail("Expected IndexOutOfBoundsException to be thrown");
} catch (IndexOutOfBoundsException expected) {
}
}
public void testDefaultInstance() throws Exception {
assertSame(
TestAllTypes.getDefaultInstance(),

@ -30,6 +30,7 @@
package com.google.protobuf;
import protobuf_unittest.Engine;
import protobuf_unittest.Vehicle;
import protobuf_unittest.Wheel;
import java.util.ArrayList;
@ -64,7 +65,7 @@ public class NestedBuildersTest extends TestCase {
for (int i = 0; i < 4; i++) {
vehicleBuilder.getWheelBuilder(i).setRadius(5).setWidth(i + 10);
}
vehicleBuilder.getEngineBuilder().setLiters(20);
Engine.Builder engineBuilder = vehicleBuilder.getEngineBuilder().setLiters(20);
vehicle = vehicleBuilder.build();
for (int i = 0; i < 4; i++) {
@ -74,6 +75,9 @@ public class NestedBuildersTest extends TestCase {
}
assertEquals(20, vehicle.getEngine().getLiters());
assertTrue(vehicle.hasEngine());
engineBuilder.setLiters(50);
assertEquals(50, vehicleBuilder.getEngine().getLiters());
}
public void testMessagesAreCached() {

@ -33,9 +33,14 @@ package com.google.protobuf;
import static com.google.protobuf.TestUtil.TEST_REQUIRED_INITIALIZED;
import static com.google.protobuf.TestUtil.TEST_REQUIRED_UNINITIALIZED;
import com.google.protobuf.DescriptorProtos.DescriptorProto;
import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Descriptors.FileDescriptor;
import com.google.protobuf.TextFormat.Parser.SingularOverwritePolicy;
import any_test.AnyTestProto.TestAny;
import map_test.MapTestProto.TestMap;
import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
@ -48,6 +53,7 @@ import protobuf_unittest.UnittestProto.TestOneof2;
import protobuf_unittest.UnittestProto.TestRequired;
import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet;
import java.io.StringReader;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;
import junit.framework.TestCase;
@ -506,6 +512,191 @@ public class TextFormatTest extends TestCase {
assertEquals(2, builder.getOptionalInt64());
}
public void testPrintAny_customBuiltTypeRegistry() throws Exception {
TestAny testAny =
TestAny.newBuilder()
.setValue(
Any.newBuilder()
.setTypeUrl("type.googleapis.com/" + TestAllTypes.getDescriptor().getFullName())
.setValue(
TestAllTypes.newBuilder().setOptionalInt32(12345).build().toByteString())
.build())
.build();
String actual =
TextFormat.printer()
.usingTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build())
.printToString(testAny);
String expected =
"value {\n"
+ " [type.googleapis.com/protobuf_unittest.TestAllTypes] {\n"
+ " optional_int32: 12345\n"
+ " }\n"
+ "}\n";
assertEquals(expected, actual);
}
private static Descriptor createDescriptorForAny(FieldDescriptorProto... fields)
throws Exception {
FileDescriptor fileDescriptor =
FileDescriptor.buildFrom(
FileDescriptorProto.newBuilder()
.setName("any.proto")
.setPackage("google.protobuf")
.setSyntax("proto3")
.addMessageType(
DescriptorProto.newBuilder()
.setName("Any")
.addAllField(Arrays.asList(fields)))
.build(),
new FileDescriptor[0]);
return fileDescriptor.getMessageTypes().get(0);
}
public void testPrintAny_anyWithDynamicMessage() throws Exception {
Descriptor descriptor =
createDescriptorForAny(
FieldDescriptorProto.newBuilder()
.setName("type_url")
.setNumber(1)
.setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
.setType(FieldDescriptorProto.Type.TYPE_STRING)
.build(),
FieldDescriptorProto.newBuilder()
.setName("value")
.setNumber(2)
.setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
.setType(FieldDescriptorProto.Type.TYPE_BYTES)
.build());
DynamicMessage testAny =
DynamicMessage.newBuilder(descriptor)
.setField(
descriptor.findFieldByNumber(1),
"type.googleapis.com/" + TestAllTypes.getDescriptor().getFullName())
.setField(
descriptor.findFieldByNumber(2),
TestAllTypes.newBuilder().setOptionalInt32(12345).build().toByteString())
.build();
String actual =
TextFormat.printer()
.usingTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build())
.printToString(testAny);
String expected =
"[type.googleapis.com/protobuf_unittest.TestAllTypes] {\n"
+ " optional_int32: 12345\n"
+ "}\n";
assertEquals(expected, actual);
}
public void testPrintAny_anyFromWithNoValueField() throws Exception {
Descriptor descriptor =
createDescriptorForAny(
FieldDescriptorProto.newBuilder()
.setName("type_url")
.setNumber(1)
.setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
.setType(FieldDescriptorProto.Type.TYPE_STRING)
.build());
DynamicMessage testAny =
DynamicMessage.newBuilder(descriptor)
.setField(
descriptor.findFieldByNumber(1),
"type.googleapis.com/" + TestAllTypes.getDescriptor().getFullName())
.build();
String actual =
TextFormat.printer()
.usingTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build())
.printToString(testAny);
String expected = "type_url: \"type.googleapis.com/protobuf_unittest.TestAllTypes\"\n";
assertEquals(expected, actual);
}
public void testPrintAny_anyFromWithNoTypeUrlField() throws Exception {
Descriptor descriptor =
createDescriptorForAny(
FieldDescriptorProto.newBuilder()
.setName("value")
.setNumber(2)
.setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
.setType(FieldDescriptorProto.Type.TYPE_BYTES)
.build());
DynamicMessage testAny =
DynamicMessage.newBuilder(descriptor)
.setField(
descriptor.findFieldByNumber(2),
TestAllTypes.newBuilder().setOptionalInt32(12345).build().toByteString())
.build();
String actual =
TextFormat.printer()
.usingTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build())
.printToString(testAny);
String expected = "value: \"\\b\\271`\"\n";
assertEquals(expected, actual);
}
public void testPrintAny_anyWithInvalidFieldType() throws Exception {
Descriptor descriptor =
createDescriptorForAny(
FieldDescriptorProto.newBuilder()
.setName("type_url")
.setNumber(1)
.setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
.setType(FieldDescriptorProto.Type.TYPE_STRING)
.build(),
FieldDescriptorProto.newBuilder()
.setName("value")
.setNumber(2)
.setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
.setType(FieldDescriptorProto.Type.TYPE_STRING)
.build());
DynamicMessage testAny =
DynamicMessage.newBuilder(descriptor)
.setField(
descriptor.findFieldByNumber(1),
"type.googleapis.com/" + TestAllTypes.getDescriptor().getFullName())
.setField(descriptor.findFieldByNumber(2), "test")
.build();
String actual =
TextFormat.printer()
.usingTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build())
.printToString(testAny);
String expected =
"type_url: \"type.googleapis.com/protobuf_unittest.TestAllTypes\"\n" + "value: \"test\"\n";
assertEquals(expected, actual);
}
public void testMergeAny_customBuiltTypeRegistry() throws Exception {
TestAny.Builder builder = TestAny.newBuilder();
TextFormat.Parser.newBuilder()
.setTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build())
.build()
.merge(
"value: {\n"
+ "[type.googleapis.com/protobuf_unittest.TestAllTypes] {\n"
+ "optional_int32: 12345\n"
+ "optional_nested_message {\n"
+ " bb: 123\n"
+ "}\n"
+ "}\n"
+ "}",
builder);
assertEquals(
TestAny.newBuilder()
.setValue(
Any.newBuilder()
.setTypeUrl("type.googleapis.com/" + TestAllTypes.getDescriptor().getFullName())
.setValue(
TestAllTypes.newBuilder()
.setOptionalInt32(12345)
.setOptionalNestedMessage(
TestAllTypes.NestedMessage.newBuilder().setBb(123))
.build()
.toByteString())
.build())
.build(),
builder.build());
}
private void assertParseError(String error, String text) {
// Test merge().

@ -0,0 +1,70 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import com.google.protobuf.Descriptors.Descriptor;
import protobuf_unittest.UnittestProto;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public final class TypeRegistryTest {
@Test
public void findDescriptorByFullName() throws Exception {
Descriptor descriptor = UnittestProto.TestAllTypes.getDescriptor();
assertNull(TypeRegistry.getEmptyTypeRegistry().find(descriptor.getFullName()));
assertSame(
descriptor,
TypeRegistry.newBuilder().add(descriptor).build().find(descriptor.getFullName()));
}
@Test
public void findDescriptorByTypeUrl() throws Exception {
Descriptor descriptor = UnittestProto.TestAllTypes.getDescriptor();
assertNull(
TypeRegistry.getEmptyTypeRegistry()
.getDescriptorForTypeUrl("type.googleapis.com/" + descriptor.getFullName()));
assertSame(
descriptor,
TypeRegistry.newBuilder()
.add(descriptor)
.build()
.getDescriptorForTypeUrl("type.googleapis.com/" + descriptor.getFullName()));
}
}

@ -36,8 +36,6 @@ package protobuf_unittest;
message Proto1 {
option experimental_java_message_interface =
"com.google.protobuf.ExtraInterfaces.HasBoolValue";
option experimental_java_interface_extends =
"com.google.protobuf.ExtraInterfaces.HasByteValue";
option experimental_java_message_interface =
"com.google.protobuf.ExtraInterfaces.HasStringValue<Proto1>";
option experimental_java_builder_interface =

@ -224,6 +224,7 @@
<exclude>TextFormatParseLocationTest.java</exclude>
<exclude>TextFormatTest.java</exclude>
<exclude>TestUtil.java</exclude>
<exclude>TypeRegistryTest.java</exclude>
<exclude>UnknownEnumValueTest.java</exclude>
<exclude>UnknownFieldSetLiteTest.java</exclude>
<exclude>UnknownFieldSetTest.java</exclude>

@ -108,15 +108,22 @@ public class JsonFormat {
*/
public static Printer printer() {
return new Printer(
TypeRegistry.getEmptyTypeRegistry(), false, Collections.<FieldDescriptor>emptySet(),
false, false, false, false);
com.google.protobuf.TypeRegistry.getEmptyTypeRegistry(),
TypeRegistry.getEmptyTypeRegistry(),
/* alwaysOutputDefaultValueFields */ false,
/* includingDefaultValueFields */ Collections.<FieldDescriptor>emptySet(),
/* preservingProtoFieldNames */ false,
/* omittingInsignificantWhitespace */ false,
/* printingEnumsAsInts */ false,
/* sortingMapKeys */ false);
}
/**
* A Printer converts protobuf message to JSON format.
*/
public static class Printer {
private final TypeRegistry registry;
private final com.google.protobuf.TypeRegistry registry;
private final TypeRegistry oldRegistry;
// NOTE: There are 3 states for these *defaultValueFields variables:
// 1) Default - alwaysOutput is false & including is empty set. Fields only output if they are
// set to non-default values.
@ -133,7 +140,8 @@ public class JsonFormat {
private final boolean sortingMapKeys;
private Printer(
TypeRegistry registry,
com.google.protobuf.TypeRegistry registry,
TypeRegistry oldRegistry,
boolean alwaysOutputDefaultValueFields,
Set<FieldDescriptor> includingDefaultValueFields,
boolean preservingProtoFieldNames,
@ -141,6 +149,7 @@ public class JsonFormat {
boolean printingEnumsAsInts,
boolean sortingMapKeys) {
this.registry = registry;
this.oldRegistry = oldRegistry;
this.alwaysOutputDefaultValueFields = alwaysOutputDefaultValueFields;
this.includingDefaultValueFields = includingDefaultValueFields;
this.preservingProtoFieldNames = preservingProtoFieldNames;
@ -150,17 +159,41 @@ public class JsonFormat {
}
/**
* Creates a new {@link Printer} using the given registry. The new Printer
* clones all other configurations from the current {@link Printer}.
* Creates a new {@link Printer} using the given registry. The new Printer clones all other
* configurations from the current {@link Printer}.
*
* @throws IllegalArgumentException if a registry is already set.
*/
public Printer usingTypeRegistry(TypeRegistry registry) {
if (this.registry != TypeRegistry.getEmptyTypeRegistry()) {
public Printer usingTypeRegistry(TypeRegistry oldRegistry) {
if (this.oldRegistry != TypeRegistry.getEmptyTypeRegistry()
|| this.registry != com.google.protobuf.TypeRegistry.getEmptyTypeRegistry()) {
throw new IllegalArgumentException("Only one registry is allowed.");
}
return new Printer(
com.google.protobuf.TypeRegistry.getEmptyTypeRegistry(),
oldRegistry,
alwaysOutputDefaultValueFields,
includingDefaultValueFields,
preservingProtoFieldNames,
omittingInsignificantWhitespace,
printingEnumsAsInts,
sortingMapKeys);
}
/**
* Creates a new {@link Printer} using the given registry. The new Printer clones all other
* configurations from the current {@link Printer}.
*
* @throws IllegalArgumentException if a registry is already set.
*/
public Printer usingTypeRegistry(com.google.protobuf.TypeRegistry registry) {
if (this.oldRegistry != TypeRegistry.getEmptyTypeRegistry()
|| this.registry != com.google.protobuf.TypeRegistry.getEmptyTypeRegistry()) {
throw new IllegalArgumentException("Only one registry is allowed.");
}
return new Printer(
registry,
oldRegistry,
alwaysOutputDefaultValueFields,
includingDefaultValueFields,
preservingProtoFieldNames,
@ -179,6 +212,7 @@ public class JsonFormat {
checkUnsetIncludingDefaultValueFields();
return new Printer(
registry,
oldRegistry,
true,
Collections.<FieldDescriptor>emptySet(),
preservingProtoFieldNames,
@ -197,6 +231,7 @@ public class JsonFormat {
checkUnsetPrintingEnumsAsInts();
return new Printer(
registry,
oldRegistry,
alwaysOutputDefaultValueFields,
Collections.<FieldDescriptor>emptySet(),
preservingProtoFieldNames,
@ -226,6 +261,7 @@ public class JsonFormat {
checkUnsetIncludingDefaultValueFields();
return new Printer(
registry,
oldRegistry,
false,
Collections.unmodifiableSet(new HashSet<>(fieldsToAlwaysOutput)),
preservingProtoFieldNames,
@ -250,6 +286,7 @@ public class JsonFormat {
public Printer preservingProtoFieldNames() {
return new Printer(
registry,
oldRegistry,
alwaysOutputDefaultValueFields,
includingDefaultValueFields,
true,
@ -279,6 +316,7 @@ public class JsonFormat {
public Printer omittingInsignificantWhitespace() {
return new Printer(
registry,
oldRegistry,
alwaysOutputDefaultValueFields,
includingDefaultValueFields,
preservingProtoFieldNames,
@ -302,6 +340,7 @@ public class JsonFormat {
public Printer sortingMapKeys() {
return new Printer(
registry,
oldRegistry,
alwaysOutputDefaultValueFields,
includingDefaultValueFields,
preservingProtoFieldNames,
@ -322,6 +361,7 @@ public class JsonFormat {
// mobile.
new PrinterImpl(
registry,
oldRegistry,
alwaysOutputDefaultValueFields,
includingDefaultValueFields,
preservingProtoFieldNames,
@ -354,37 +394,66 @@ public class JsonFormat {
* Creates a {@link Parser} with default configuration.
*/
public static Parser parser() {
return new Parser(TypeRegistry.getEmptyTypeRegistry(), false, Parser.DEFAULT_RECURSION_LIMIT);
return new Parser(
com.google.protobuf.TypeRegistry.getEmptyTypeRegistry(),
TypeRegistry.getEmptyTypeRegistry(),
false,
Parser.DEFAULT_RECURSION_LIMIT);
}
/**
* A Parser parses JSON to protobuf message.
*/
public static class Parser {
private final TypeRegistry registry;
private final com.google.protobuf.TypeRegistry registry;
private final TypeRegistry oldRegistry;
private final boolean ignoringUnknownFields;
private final int recursionLimit;
// The default parsing recursion limit is aligned with the proto binary parser.
private static final int DEFAULT_RECURSION_LIMIT = 100;
private Parser(TypeRegistry registry, boolean ignoreUnknownFields, int recursionLimit) {
private Parser(
com.google.protobuf.TypeRegistry registry,
TypeRegistry oldRegistry,
boolean ignoreUnknownFields,
int recursionLimit) {
this.registry = registry;
this.oldRegistry = oldRegistry;
this.ignoringUnknownFields = ignoreUnknownFields;
this.recursionLimit = recursionLimit;
}
/**
* Creates a new {@link Parser} using the given registry. The new Parser
* clones all other configurations from this Parser.
* Creates a new {@link Parser} using the given registry. The new Parser clones all other
* configurations from this Parser.
*
* @throws IllegalArgumentException if a registry is already set.
*/
public Parser usingTypeRegistry(TypeRegistry oldRegistry) {
if (this.oldRegistry != TypeRegistry.getEmptyTypeRegistry()
|| this.registry != com.google.protobuf.TypeRegistry.getEmptyTypeRegistry()) {
throw new IllegalArgumentException("Only one registry is allowed.");
}
return new Parser(
com.google.protobuf.TypeRegistry.getEmptyTypeRegistry(),
oldRegistry,
ignoringUnknownFields,
recursionLimit);
}
/**
* Creates a new {@link Parser} using the given registry. The new Parser clones all other
* configurations from this Parser.
*
* @throws IllegalArgumentException if a registry is already set.
*/
public Parser usingTypeRegistry(TypeRegistry registry) {
if (this.registry != TypeRegistry.getEmptyTypeRegistry()) {
public Parser usingTypeRegistry(com.google.protobuf.TypeRegistry registry) {
if (this.oldRegistry != TypeRegistry.getEmptyTypeRegistry()
|| this.registry != com.google.protobuf.TypeRegistry.getEmptyTypeRegistry()) {
throw new IllegalArgumentException("Only one registry is allowed.");
}
return new Parser(registry, ignoringUnknownFields, recursionLimit);
return new Parser(registry, oldRegistry, ignoringUnknownFields, recursionLimit);
}
/**
@ -392,7 +461,7 @@ public class JsonFormat {
* encountered. The new Parser clones all other configurations from this Parser.
*/
public Parser ignoringUnknownFields() {
return new Parser(this.registry, true, recursionLimit);
return new Parser(this.registry, oldRegistry, true, recursionLimit);
}
/**
@ -404,7 +473,8 @@ public class JsonFormat {
public void merge(String json, Message.Builder builder) throws InvalidProtocolBufferException {
// TODO(xiaofeng): Investigate the allocation overhead and optimize for
// mobile.
new ParserImpl(registry, ignoringUnknownFields, recursionLimit).merge(json, builder);
new ParserImpl(registry, oldRegistry, ignoringUnknownFields, recursionLimit)
.merge(json, builder);
}
/**
@ -417,12 +487,13 @@ public class JsonFormat {
public void merge(Reader json, Message.Builder builder) throws IOException {
// TODO(xiaofeng): Investigate the allocation overhead and optimize for
// mobile.
new ParserImpl(registry, ignoringUnknownFields, recursionLimit).merge(json, builder);
new ParserImpl(registry, oldRegistry, ignoringUnknownFields, recursionLimit)
.merge(json, builder);
}
// For testing only.
Parser usingRecursionLimit(int recursionLimit) {
return new Parser(registry, ignoringUnknownFields, recursionLimit);
return new Parser(registry, oldRegistry, ignoringUnknownFields, recursionLimit);
}
}
@ -478,7 +549,7 @@ public class JsonFormat {
@CanIgnoreReturnValue
public Builder add(Descriptor messageType) {
if (types == null) {
throw new IllegalStateException("A TypeRegistry.Builer can only be used once.");
throw new IllegalStateException("A TypeRegistry.Builder can only be used once.");
}
addFile(messageType.getFile());
return this;
@ -641,7 +712,8 @@ public class JsonFormat {
* A Printer converts protobuf messages to JSON format.
*/
private static final class PrinterImpl {
private final TypeRegistry registry;
private final com.google.protobuf.TypeRegistry registry;
private final TypeRegistry oldRegistry;
private final boolean alwaysOutputDefaultValueFields;
private final Set<FieldDescriptor> includingDefaultValueFields;
private final boolean preservingProtoFieldNames;
@ -658,7 +730,8 @@ public class JsonFormat {
}
PrinterImpl(
TypeRegistry registry,
com.google.protobuf.TypeRegistry registry,
TypeRegistry oldRegistry,
boolean alwaysOutputDefaultValueFields,
Set<FieldDescriptor> includingDefaultValueFields,
boolean preservingProtoFieldNames,
@ -667,6 +740,7 @@ public class JsonFormat {
boolean printingEnumsAsInts,
boolean sortingMapKeys) {
this.registry = registry;
this.oldRegistry = oldRegistry;
this.alwaysOutputDefaultValueFields = alwaysOutputDefaultValueFields;
this.includingDefaultValueFields = includingDefaultValueFields;
this.preservingProtoFieldNames = preservingProtoFieldNames;
@ -806,9 +880,12 @@ public class JsonFormat {
}
String typeUrl = (String) message.getField(typeUrlField);
Descriptor type = registry.getDescriptorForTypeUrl(typeUrl);
if (type == null) {
type = oldRegistry.getDescriptorForTypeUrl(typeUrl);
if (type == null) {
throw new InvalidProtocolBufferException("Cannot find type for url: " + typeUrl);
}
}
ByteString content = (ByteString) message.getField(valueField);
Message contentMessage =
DynamicMessage.getDefaultInstance(type).getParserForType().parseFrom(content);
@ -1218,14 +1295,20 @@ public class JsonFormat {
}
private static class ParserImpl {
private final TypeRegistry registry;
private final com.google.protobuf.TypeRegistry registry;
private final TypeRegistry oldRegistry;
private final JsonParser jsonParser;
private final boolean ignoringUnknownFields;
private final int recursionLimit;
private int currentDepth;
ParserImpl(TypeRegistry registry, boolean ignoreUnknownFields, int recursionLimit) {
ParserImpl(
com.google.protobuf.TypeRegistry registry,
TypeRegistry oldRegistry,
boolean ignoreUnknownFields,
int recursionLimit) {
this.registry = registry;
this.oldRegistry = oldRegistry;
this.ignoringUnknownFields = ignoreUnknownFields;
this.jsonParser = new JsonParser();
this.recursionLimit = recursionLimit;
@ -1447,9 +1530,12 @@ public class JsonFormat {
}
String typeUrl = typeUrlElement.getAsString();
Descriptor contentType = registry.getDescriptorForTypeUrl(typeUrl);
if (contentType == null) {
contentType = oldRegistry.getDescriptorForTypeUrl(typeUrl);
if (contentType == null) {
throw new InvalidProtocolBufferException("Cannot resolve type: " + typeUrl);
}
}
builder.setField(typeUrlField, typeUrl);
Message.Builder contentBuilder =
DynamicMessage.getDefaultInstance(contentType).newBuilderForType();

@ -152,6 +152,16 @@ public class JsonFormatTest extends TestCase {
assertEquals(message.toString(), parsedMessage.toString());
}
private void assertRoundTripEquals(Message message, com.google.protobuf.TypeRegistry registry)
throws Exception {
JsonFormat.Printer printer = JsonFormat.printer().usingTypeRegistry(registry);
JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(registry);
Message.Builder builder = message.newBuilderForType();
parser.merge(printer.print(message), builder);
Message parsedMessage = builder.build();
assertEquals(message.toString(), parsedMessage.toString());
}
private String toJsonString(Message message) throws IOException {
return JsonFormat.printer().print(message);
}
@ -850,6 +860,45 @@ public class JsonFormatTest extends TestCase {
}
public void testAnyFieldsWithCustomAddedTypeRegistry() throws Exception {
TestAllTypes content = TestAllTypes.newBuilder().setOptionalInt32(1234).build();
TestAny message = TestAny.newBuilder().setAnyValue(Any.pack(content)).build();
com.google.protobuf.TypeRegistry registry =
com.google.protobuf.TypeRegistry.newBuilder().add(content.getDescriptorForType()).build();
JsonFormat.Printer printer = JsonFormat.printer().usingTypeRegistry(registry);
assertEquals(
"{\n"
+ " \"anyValue\": {\n"
+ " \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
+ " \"optionalInt32\": 1234\n"
+ " }\n"
+ "}",
printer.print(message));
assertRoundTripEquals(message, registry);
TestAny messageWithDefaultAnyValue =
TestAny.newBuilder().setAnyValue(Any.getDefaultInstance()).build();
assertEquals("{\n" + " \"anyValue\": {}\n" + "}", printer.print(messageWithDefaultAnyValue));
assertRoundTripEquals(messageWithDefaultAnyValue, registry);
// Well-known types have a special formatting when embedded in Any.
//
// 1. Any in Any.
Any anyMessage = Any.pack(Any.pack(content));
assertEquals(
"{\n"
+ " \"@type\": \"type.googleapis.com/google.protobuf.Any\",\n"
+ " \"value\": {\n"
+ " \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
+ " \"optionalInt32\": 1234\n"
+ " }\n"
+ "}",
printer.print(anyMessage));
assertRoundTripEquals(anyMessage, registry);
}
public void testAnyFields() throws Exception {
TestAllTypes content = TestAllTypes.newBuilder().setOptionalInt32(1234).build();
TestAny message = TestAny.newBuilder().setAnyValue(Any.pack(content)).build();
@ -1136,7 +1185,7 @@ public class JsonFormatTest extends TestCase {
Any.Builder builder = Any.newBuilder();
mergeFromJson(
"{\n"
+ " \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
+ " \"@type\": \"type.googleapis.com/json_test.UnexpectedTypes\",\n"
+ " \"optionalInt32\": 12345\n"
+ "}",
builder);

@ -246,20 +246,6 @@ jspb.BinaryDecoder = function(opt_bytes, opt_start, opt_length) {
*/
this.cursor_ = 0;
/**
* Temporary storage for the low 32 bits of 64-bit data types that we're
* decoding.
* @private {number}
*/
this.tempLow_ = 0;
/**
* Temporary storage for the high 32 bits of 64-bit data types that we're
* decoding.
* @private {number}
*/
this.tempHigh_ = 0;
/**
* Set to true if this decoder encountered an error due to corrupt data.
* @private {boolean}
@ -442,9 +428,9 @@ jspb.BinaryDecoder.prototype.getError = function() {
/**
* Reads an unsigned varint from the binary stream and stores it as a split
* 64-bit integer. Since this does not convert the value to a number, no
* precision is lost.
* Reads an unsigned varint from the binary stream and invokes the conversion
* function with the value in two signed 32 bit integers to produce the result.
* Since this does not convert the value to a number, no precision is lost.
*
* It's possible for an unsigned varint to be incorrectly encoded - more than
* 64 bits' worth of data could be present. If this happens, this method will
@ -454,52 +440,72 @@ jspb.BinaryDecoder.prototype.getError = function() {
* details on the format, see
* https://developers.google.com/protocol-buffers/docs/encoding
*
* @private
* @param {function(number, number): T} convert Conversion function to produce
* the result value, takes parameters (lowBits, highBits).
* @return {T}
* @template T
*/
jspb.BinaryDecoder.prototype.readSplitVarint64_ = function() {
var temp;
jspb.BinaryDecoder.prototype.readSplitVarint64 = function(convert) {
var temp = 128;
var lowBits = 0;
var highBits = 0;
// Read the first four bytes of the varint, stopping at the terminator if we
// see it.
for (var i = 0; i < 4; i++) {
for (var i = 0; i < 4 && temp >= 128; i++) {
temp = this.bytes_[this.cursor_++];
lowBits |= (temp & 0x7F) << (i * 7);
if (temp < 128) {
this.tempLow_ = lowBits >>> 0;
this.tempHigh_ = 0;
return;
}
}
if (temp >= 128) {
// Read the fifth byte, which straddles the low and high dwords.
temp = this.bytes_[this.cursor_++];
lowBits |= (temp & 0x7F) << 28;
highBits |= (temp & 0x7F) >> 4;
if (temp < 128) {
this.tempLow_ = lowBits >>> 0;
this.tempHigh_ = highBits >>> 0;
return;
}
if (temp >= 128) {
// Read the sixth through tenth byte.
for (var i = 0; i < 5; i++) {
for (var i = 0; i < 5 && temp >= 128; i++) {
temp = this.bytes_[this.cursor_++];
highBits |= (temp & 0x7F) << (i * 7 + 3);
if (temp < 128) {
this.tempLow_ = lowBits >>> 0;
this.tempHigh_ = highBits >>> 0;
return;
}
}
if (temp < 128) {
return convert(lowBits >>> 0, highBits >>> 0);
}
// If we did not see the terminator, the encoding was invalid.
goog.asserts.fail('Failed to read varint, encoding is invalid.');
this.error_ = true;
};
/**
* Reads a 64-bit fixed-width value from the stream and invokes the conversion
* function with the value in two signed 32 bit integers to produce the result.
* Since this does not convert the value to a number, no precision is lost.
*
* @param {function(number, number): T} convert Conversion function to produce
* the result value, takes parameters (lowBits, highBits).
* @return {T}
* @template T
*/
jspb.BinaryDecoder.prototype.readSplitFixed64 = function(convert) {
var bytes = this.bytes_;
var cursor = this.cursor_;
this.cursor_ += 8;
var lowBits = 0;
var highBits = 0;
for (var i = cursor + 7; i >= cursor; i--) {
lowBits = (lowBits << 8) | bytes[i];
highBits = (highBits << 8) | bytes[i + 4];
}
return convert(lowBits, highBits);
};
/**
* Skips over a varint in the block without decoding it.
*/
@ -668,8 +674,7 @@ jspb.BinaryDecoder.prototype.readZigzagVarint32 = function() {
* integer exceeds 2^53.
*/
jspb.BinaryDecoder.prototype.readUnsignedVarint64 = function() {
this.readSplitVarint64_();
return jspb.utils.joinUint64(this.tempLow_, this.tempHigh_);
return this.readSplitVarint64(jspb.utils.joinUint64);
};
@ -680,8 +685,7 @@ jspb.BinaryDecoder.prototype.readUnsignedVarint64 = function() {
* @return {string} The decoded unsigned varint as a decimal string.
*/
jspb.BinaryDecoder.prototype.readUnsignedVarint64String = function() {
this.readSplitVarint64_();
return jspb.utils.joinUnsignedDecimalString(this.tempLow_, this.tempHigh_);
return this.readSplitVarint64(jspb.utils.joinUnsignedDecimalString);
};
@ -694,8 +698,7 @@ jspb.BinaryDecoder.prototype.readUnsignedVarint64String = function() {
* integer exceeds 2^53.
*/
jspb.BinaryDecoder.prototype.readSignedVarint64 = function() {
this.readSplitVarint64_();
return jspb.utils.joinInt64(this.tempLow_, this.tempHigh_);
return this.readSplitVarint64(jspb.utils.joinInt64);
};
@ -706,8 +709,7 @@ jspb.BinaryDecoder.prototype.readSignedVarint64 = function() {
* @return {string} The decoded signed varint as a decimal string.
*/
jspb.BinaryDecoder.prototype.readSignedVarint64String = function() {
this.readSplitVarint64_();
return jspb.utils.joinSignedDecimalString(this.tempLow_, this.tempHigh_);
return this.readSplitVarint64(jspb.utils.joinSignedDecimalString);
};
@ -725,8 +727,7 @@ jspb.BinaryDecoder.prototype.readSignedVarint64String = function() {
* integer exceeds 2^53.
*/
jspb.BinaryDecoder.prototype.readZigzagVarint64 = function() {
this.readSplitVarint64_();
return jspb.utils.joinZigzag64(this.tempLow_, this.tempHigh_);
return this.readSplitVarint64(jspb.utils.joinZigzag64);
};
@ -1039,8 +1040,7 @@ jspb.BinaryDecoder.prototype.readBytes = function(length) {
* @return {string} The hash value.
*/
jspb.BinaryDecoder.prototype.readVarintHash64 = function() {
this.readSplitVarint64_();
return jspb.utils.joinHash64(this.tempLow_, this.tempHigh_);
return this.readSplitVarint64(jspb.utils.joinHash64);
};

@ -45,6 +45,7 @@ goog.require('goog.testing.asserts');
goog.require('jspb.BinaryConstants');
goog.require('jspb.BinaryDecoder');
goog.require('jspb.BinaryEncoder');
goog.require('jspb.utils');
/**
@ -172,11 +173,9 @@ describe('binaryDecoderTest', function() {
});
/**
* Tests reading 64-bit integers as hash strings.
*/
it('testHashStrings', function() {
var encoder = new jspb.BinaryEncoder();
describe('varint64', function() {
var /** !jspb.BinaryEncoder */ encoder;
var /** !jspb.BinaryDecoder */ decoder;
var hashA = String.fromCharCode(0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00);
@ -186,6 +185,8 @@ describe('binaryDecoderTest', function() {
0x87, 0x65, 0x43, 0x21);
var hashD = String.fromCharCode(0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF);
beforeEach(function() {
encoder = new jspb.BinaryEncoder();
encoder.writeVarintHash64(hashA);
encoder.writeVarintHash64(hashB);
@ -197,8 +198,10 @@ describe('binaryDecoderTest', function() {
encoder.writeFixedHash64(hashC);
encoder.writeFixedHash64(hashD);
var decoder = jspb.BinaryDecoder.alloc(encoder.end());
decoder = jspb.BinaryDecoder.alloc(encoder.end());
});
it('reads 64-bit integers as hash strings', function() {
assertEquals(hashA, decoder.readVarintHash64());
assertEquals(hashB, decoder.readVarintHash64());
assertEquals(hashC, decoder.readVarintHash64());
@ -210,6 +213,28 @@ describe('binaryDecoderTest', function() {
assertEquals(hashD, decoder.readFixedHash64());
});
it('reads split 64 bit integers', function() {
function hexJoin(bitsLow, bitsHigh) {
return `0x${(bitsHigh >>> 0).toString(16)}:0x${
(bitsLow >>> 0).toString(16)}`;
}
function hexJoinHash(hash64) {
jspb.utils.splitHash64(hash64);
return hexJoin(jspb.utils.split64Low, jspb.utils.split64High);
}
expect(decoder.readSplitVarint64(hexJoin)).toEqual(hexJoinHash(hashA));
expect(decoder.readSplitVarint64(hexJoin)).toEqual(hexJoinHash(hashB));
expect(decoder.readSplitVarint64(hexJoin)).toEqual(hexJoinHash(hashC));
expect(decoder.readSplitVarint64(hexJoin)).toEqual(hexJoinHash(hashD));
expect(decoder.readSplitFixed64(hexJoin)).toEqual(hexJoinHash(hashA));
expect(decoder.readSplitFixed64(hexJoin)).toEqual(hexJoinHash(hashB));
expect(decoder.readSplitFixed64(hexJoin)).toEqual(hexJoinHash(hashC));
expect(decoder.readSplitFixed64(hexJoin)).toEqual(hexJoinHash(hashD));
});
});
/**
* Tests reading and writing large strings
*/

@ -954,6 +954,23 @@ jspb.BinaryReader.prototype.readVarintHash64 = function() {
};
/**
* Reads a 64-bit varint field from the stream and invokes `convert` to produce
* the return value, or throws an error if the next field in the stream is not
* of the correct wire type.
*
* @param {function(number, number): T} convert Conversion function to produce
* the result value, takes parameters (lowBits, highBits).
* @return {T}
* @template T
*/
jspb.BinaryReader.prototype.readSplitVarint64 = function(convert) {
goog.asserts.assert(
this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
return this.decoder_.readSplitVarint64(convert);
};
/**
* Reads a 64-bit varint or fixed64 field from the stream and returns it as a
* 8-character Unicode string for use as a hash table key, or throws an error
@ -968,6 +985,23 @@ jspb.BinaryReader.prototype.readFixedHash64 = function() {
};
/**
* Reads a 64-bit fixed64 field from the stream and invokes `convert`
* to produce the return value, or throws an error if the next field in the
* stream is not of the correct wire type.
*
* @param {function(number, number): T} convert Conversion function to produce
* the result value, takes parameters (lowBits, highBits).
* @return {T}
* @template T
*/
jspb.BinaryReader.prototype.readSplitFixed64 = function(convert) {
goog.asserts.assert(
this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64);
return this.decoder_.readSplitFixed64(convert);
};
/**
* Reads a packed scalar field using the supplied raw reader function.
* @param {function(this:jspb.BinaryDecoder)} decodeMethod

@ -407,6 +407,26 @@ describe('binaryReaderTest', function() {
-6, '08 8B 80 80 80 80 80 80 80 80 00');
});
/**
* Tests reading 64-bit integers as split values.
*/
it('handles split 64 fields', function() {
var writer = new jspb.BinaryWriter();
writer.writeInt64String(1, '4294967296');
writer.writeSfixed64String(2, '4294967298');
var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
function rejoin(lowBits, highBits) {
return highBits * 2 ** 32 + (lowBits >>> 0);
}
reader.nextField();
expect(reader.getFieldNumber()).toEqual(1);
expect(reader.readSplitVarint64(rejoin)).toEqual(0x100000000);
reader.nextField();
expect(reader.getFieldNumber()).toEqual(2);
expect(reader.readSplitFixed64(rejoin)).toEqual(0x100000002);
});
/**
* Tests 64-bit fields that are handled as strings.

@ -428,7 +428,6 @@ jspb.utils.joinHash64 = function(bitsLow, bitsHigh) {
return String.fromCharCode(a, b, c, d, e, f, g, h);
};
/**
* Individual digits for number->string conversion.
* @const {!Array<string>}
@ -438,6 +437,11 @@ jspb.utils.DIGITS = [
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
];
/** @const @private {number} '0' */
jspb.utils.ZERO_CHAR_CODE_ = 48;
/** @const @private {number} 'a' */
jspb.utils.A_CHAR_CODE_ = 97;
/**
* Losslessly converts a 64-bit unsigned integer in 32:32 split representation
@ -487,27 +491,20 @@ jspb.utils.joinUnsignedDecimalString = function(bitsLow, bitsHigh) {
digitB %= base;
}
// Convert base-1e7 digits to base-10, omitting leading zeroes.
var table = jspb.utils.DIGITS;
var start = false;
var result = '';
function emit(digit) {
var temp = base;
for (var i = 0; i < 7; i++) {
temp /= 10;
var decimalDigit = ((digit / temp) % 10) >>> 0;
if ((decimalDigit == 0) && !start) continue;
start = true;
result += table[decimalDigit];
// Convert base-1e7 digits to base-10, with optional leading zeroes.
function decimalFrom1e7(digit1e7, needLeadingZeros) {
var partial = digit1e7 ? String(digit1e7) : '';
if (needLeadingZeros) {
return '0000000'.slice(partial.length) + partial;
}
return partial;
}
if (digitC || start) emit(digitC);
if (digitB || start) emit(digitB);
if (digitA || start) emit(digitA);
return result;
return decimalFrom1e7(digitC, /*needLeadingZeros=*/ 0) +
decimalFrom1e7(digitB, /*needLeadingZeros=*/ digitC) +
// If the final 1e7 digit didn't need leading zeros, we would have
// returned via the trivial code path at the top.
decimalFrom1e7(digitA, /*needLeadingZeros=*/ 1);
};
@ -605,7 +602,7 @@ jspb.utils.decimalStringToHash64 = function(dec) {
// For each decimal digit, set result to 10*result + digit.
for (var i = 0; i < dec.length; i++) {
muladd(10, jspb.utils.DIGITS.indexOf(dec[i]));
muladd(10, dec.charCodeAt(i) - jspb.utils.ZERO_CHAR_CODE_);
}
// If there's a minus sign, convert into two's complement.
@ -627,6 +624,28 @@ jspb.utils.splitDecimalString = function(value) {
jspb.utils.splitHash64(jspb.utils.decimalStringToHash64(value));
};
/**
* @param {number} nibble A 4-bit integer.
* @return {string}
* @private
*/
jspb.utils.toHexDigit_ = function(nibble) {
return String.fromCharCode(
nibble < 10 ? jspb.utils.ZERO_CHAR_CODE_ + nibble :
jspb.utils.A_CHAR_CODE_ - 10 + nibble);
};
/**
* @param {number} hexCharCode
* @return {number}
* @private
*/
jspb.utils.fromHexCharCode_ = function(hexCharCode) {
if (hexCharCode >= jspb.utils.A_CHAR_CODE_) {
return hexCharCode - jspb.utils.A_CHAR_CODE_ + 10;
}
return hexCharCode - jspb.utils.ZERO_CHAR_CODE_;
};
/**
* Converts an 8-character hash string into its hexadecimal representation.
@ -640,8 +659,8 @@ jspb.utils.hash64ToHexString = function(hash) {
for (var i = 0; i < 8; i++) {
var c = hash.charCodeAt(7 - i);
temp[i * 2 + 2] = jspb.utils.DIGITS[c >> 4];
temp[i * 2 + 3] = jspb.utils.DIGITS[c & 0xF];
temp[i * 2 + 2] = jspb.utils.toHexDigit_(c >> 4);
temp[i * 2 + 3] = jspb.utils.toHexDigit_(c & 0xF);
}
var result = temp.join('');
@ -662,8 +681,8 @@ jspb.utils.hexStringToHash64 = function(hex) {
var result = '';
for (var i = 0; i < 8; i++) {
var hi = jspb.utils.DIGITS.indexOf(hex[i * 2 + 2]);
var lo = jspb.utils.DIGITS.indexOf(hex[i * 2 + 3]);
var hi = jspb.utils.fromHexCharCode_(hex.charCodeAt(i * 2 + 2));
var lo = jspb.utils.fromHexCharCode_(hex.charCodeAt(i * 2 + 3));
result = String.fromCharCode(hi * 16 + lo) + result;
}

@ -38,7 +38,6 @@
goog.require('goog.crypt');
goog.require('goog.crypt.base64');
goog.require('goog.testing.asserts');
goog.require('jspb.BinaryConstants');
goog.require('jspb.BinaryWriter');
goog.require('jspb.utils');
@ -82,36 +81,36 @@ describe('binaryUtilsTest', function() {
// Check some magic numbers.
var result =
jspb.utils.joinUnsignedDecimalString(0x89e80001, 0x8ac72304);
assertEquals('10000000000000000001', result);
expect(result).toEqual('10000000000000000001');
result = jspb.utils.joinUnsignedDecimalString(0xacd05f15, 0x1b69b4b);
assertEquals('123456789123456789', result);
expect(result).toEqual('123456789123456789');
result = jspb.utils.joinUnsignedDecimalString(0xeb1f0ad2, 0xab54a98c);
assertEquals('12345678901234567890', result);
expect(result).toEqual('12345678901234567890');
result = jspb.utils.joinUnsignedDecimalString(0xe3b70cb1, 0x891087b8);
assertEquals('9876543210987654321', result);
expect(result).toEqual('9876543210987654321');
// Check limits.
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00000000);
assertEquals('0', result);
expect(result).toEqual('0');
result = jspb.utils.joinUnsignedDecimalString(0xFFFFFFFF, 0xFFFFFFFF);
assertEquals('18446744073709551615', result);
expect(result).toEqual('18446744073709551615');
// Check each bit of the low dword.
for (var i = 0; i < 32; i++) {
var low = (1 << i) >>> 0;
result = jspb.utils.joinUnsignedDecimalString(low, 0);
assertEquals('' + Math.pow(2, i), result);
expect(result).toEqual('' + Math.pow(2, i));
}
// Check the first 20 bits of the high dword.
for (var i = 0; i < 20; i++) {
var high = (1 << i) >>> 0;
result = jspb.utils.joinUnsignedDecimalString(0, high);
assertEquals('' + Math.pow(2, 32 + i), result);
expect(result).toEqual('' + Math.pow(2, 32 + i));
}
// V8's internal double-to-string conversion is inaccurate for values above
@ -119,40 +118,40 @@ describe('binaryUtilsTest', function() {
// manually against the correct string representations of 2^N.
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00100000);
assertEquals('4503599627370496', result);
expect(result).toEqual('4503599627370496');
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00200000);
assertEquals('9007199254740992', result);
expect(result).toEqual('9007199254740992');
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00400000);
assertEquals('18014398509481984', result);
expect(result).toEqual('18014398509481984');
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00800000);
assertEquals('36028797018963968', result);
expect(result).toEqual('36028797018963968');
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x01000000);
assertEquals('72057594037927936', result);
expect(result).toEqual('72057594037927936');
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x02000000);
assertEquals('144115188075855872', result);
expect(result).toEqual('144115188075855872');
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x04000000);
assertEquals('288230376151711744', result);
expect(result).toEqual('288230376151711744');
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x08000000);
assertEquals('576460752303423488', result);
expect(result).toEqual('576460752303423488');
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x10000000);
assertEquals('1152921504606846976', result);
expect(result).toEqual('1152921504606846976');
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x20000000);
assertEquals('2305843009213693952', result);
expect(result).toEqual('2305843009213693952');
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x40000000);
assertEquals('4611686018427387904', result);
expect(result).toEqual('4611686018427387904');
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x80000000);
assertEquals('9223372036854775808', result);
expect(result).toEqual('9223372036854775808');
});
@ -164,38 +163,38 @@ describe('binaryUtilsTest', function() {
var convert = jspb.utils.hash64ToDecimalString;
result = convert(toHashString(0x00000000, 0x00000000), false);
assertEquals('0', result);
expect(result).toEqual('0');
result = convert(toHashString(0x00000000, 0x00000000), true);
assertEquals('0', result);
expect(result).toEqual('0');
result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF), false);
assertEquals('18446744073709551615', result);
expect(result).toEqual('18446744073709551615');
result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF), true);
assertEquals('-1', result);
expect(result).toEqual('-1');
result = convert(toHashString(0x00000000, 0x80000000), false);
assertEquals('9223372036854775808', result);
expect(result).toEqual('9223372036854775808');
result = convert(toHashString(0x00000000, 0x80000000), true);
assertEquals('-9223372036854775808', result);
expect(result).toEqual('-9223372036854775808');
result = convert(toHashString(0xacd05f15, 0x01b69b4b), false);
assertEquals('123456789123456789', result);
expect(result).toEqual('123456789123456789');
result = convert(toHashString(~0xacd05f15 + 1, ~0x01b69b4b), true);
assertEquals('-123456789123456789', result);
expect(result).toEqual('-123456789123456789');
// And converting arrays of hashes should work the same way.
result = jspb.utils.hash64ArrayToDecimalStrings([
toHashString(0xFFFFFFFF, 0xFFFFFFFF),
toHashString(0x00000000, 0x80000000),
toHashString(0xacd05f15, 0x01b69b4b)], false);
assertEquals(3, result.length);
assertEquals('18446744073709551615', result[0]);
assertEquals('9223372036854775808', result[1]);
assertEquals('123456789123456789', result[2]);
expect(result.length).toEqual(3);
expect(result[0]).toEqual('18446744073709551615');
expect(result[1]).toEqual('9223372036854775808');
expect(result[2]).toEqual('123456789123456789');
});
/*
@ -206,32 +205,32 @@ describe('binaryUtilsTest', function() {
var convert = jspb.utils.decimalStringToHash64;
result = convert('0');
assertEquals(goog.crypt.byteArrayToString(
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), result);
expect(result).toEqual(goog.crypt.byteArrayToString(
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]));
result = convert('-1');
assertEquals(goog.crypt.byteArrayToString(
[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result);
expect(result).toEqual(goog.crypt.byteArrayToString(
[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]));
result = convert('18446744073709551615');
assertEquals(goog.crypt.byteArrayToString(
[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result);
expect(result).toEqual(goog.crypt.byteArrayToString(
[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]));
result = convert('9223372036854775808');
assertEquals(goog.crypt.byteArrayToString(
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), result);
expect(result).toEqual(goog.crypt.byteArrayToString(
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]));
result = convert('-9223372036854775808');
assertEquals(goog.crypt.byteArrayToString(
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), result);
expect(result).toEqual(goog.crypt.byteArrayToString(
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]));
result = convert('123456789123456789');
assertEquals(goog.crypt.byteArrayToString(
[0x15, 0x5F, 0xD0, 0xAC, 0x4B, 0x9B, 0xB6, 0x01]), result);
expect(result).toEqual(goog.crypt.byteArrayToString(
[0x15, 0x5F, 0xD0, 0xAC, 0x4B, 0x9B, 0xB6, 0x01]));
result = convert('-123456789123456789');
assertEquals(goog.crypt.byteArrayToString(
[0xEB, 0xA0, 0x2F, 0x53, 0xB4, 0x64, 0x49, 0xFE]), result);
expect(result).toEqual(goog.crypt.byteArrayToString(
[0xEB, 0xA0, 0x2F, 0x53, 0xB4, 0x64, 0x49, 0xFE]));
});
/**
@ -242,13 +241,13 @@ describe('binaryUtilsTest', function() {
var convert = jspb.utils.hash64ToHexString;
result = convert(toHashString(0x00000000, 0x00000000));
assertEquals('0x0000000000000000', result);
expect(result).toEqual('0x0000000000000000');
result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF));
assertEquals('0xffffffffffffffff', result);
expect(result).toEqual('0xffffffffffffffff');
result = convert(toHashString(0x12345678, 0x9ABCDEF0));
assertEquals('0x9abcdef012345678', result);
expect(result).toEqual('0x9abcdef012345678');
});
@ -260,22 +259,22 @@ describe('binaryUtilsTest', function() {
var convert = jspb.utils.hexStringToHash64;
result = convert('0x0000000000000000');
assertEquals(goog.crypt.byteArrayToString(
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), result);
expect(result).toEqual(goog.crypt.byteArrayToString(
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]));
result = convert('0xffffffffffffffff');
assertEquals(goog.crypt.byteArrayToString(
[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result);
expect(result).toEqual(goog.crypt.byteArrayToString(
[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]));
// Hex string is big-endian, hash string is little-endian.
result = convert('0x123456789ABCDEF0');
assertEquals(goog.crypt.byteArrayToString(
[0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]), result);
expect(result).toEqual(goog.crypt.byteArrayToString(
[0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]));
// Capitalization should not matter.
result = convert('0x0000abcdefABCDEF');
assertEquals(goog.crypt.byteArrayToString(
[0xEF, 0xCD, 0xAB, 0xEF, 0xCD, 0xAB, 0x00, 0x00]), result);
expect(result).toEqual(goog.crypt.byteArrayToString(
[0xEF, 0xCD, 0xAB, 0xEF, 0xCD, 0xAB, 0x00, 0x00]));
});
@ -288,25 +287,25 @@ describe('binaryUtilsTest', function() {
var convert = jspb.utils.numberToHash64;
result = convert(0x0000000000000);
assertEquals('0x0000000000000000', jspb.utils.hash64ToHexString(result));
expect(jspb.utils.hash64ToHexString(result)).toEqual('0x0000000000000000');
result = convert(0xFFFFFFFFFFFFF);
assertEquals('0x000fffffffffffff', jspb.utils.hash64ToHexString(result));
expect(jspb.utils.hash64ToHexString(result)).toEqual('0x000fffffffffffff');
result = convert(0x123456789ABCD);
assertEquals('0x000123456789abcd', jspb.utils.hash64ToHexString(result));
expect(jspb.utils.hash64ToHexString(result)).toEqual('0x000123456789abcd');
result = convert(0xDCBA987654321);
assertEquals('0x000dcba987654321', jspb.utils.hash64ToHexString(result));
expect(jspb.utils.hash64ToHexString(result)).toEqual('0x000dcba987654321');
// 53 bits of precision should not be truncated.
result = convert(0x10000000000001);
assertEquals('0x0010000000000001', jspb.utils.hash64ToHexString(result));
expect(jspb.utils.hash64ToHexString(result)).toEqual('0x0010000000000001');
// 54 bits of precision should be truncated.
result = convert(0x20000000000001);
assertNotEquals(
'0x0020000000000001', jspb.utils.hash64ToHexString(result));
expect(jspb.utils.hash64ToHexString(result))
.not.toEqual('0x0020000000000001');
});
@ -322,15 +321,15 @@ describe('binaryUtilsTest', function() {
// come back out of the string unchanged.
for (var i = 0; i < 65536; i++) {
strings[i] = 'a' + String.fromCharCode(i) + 'a';
if (3 != strings[i].length) throw 'fail!';
if (i != strings[i].charCodeAt(1)) throw 'fail!';
expect(strings[i].length).toEqual(3);
expect(strings[i].charCodeAt(1)).toEqual(i);
}
// Each unicode character should compare equal to itself and not equal to a
// different unicode character.
for (var i = 0; i < 65536; i++) {
if (strings[i] != strings[i]) throw 'fail!';
if (strings[i] == strings[(i + 1) % 65536]) throw 'fail!';
expect(strings[i] == strings[i]).toEqual(true);
expect(strings[i] == strings[(i + 1) % 65536]).toEqual(false);
}
});
@ -345,10 +344,9 @@ describe('binaryUtilsTest', function() {
// NaN.
jspb.utils.splitFloat32(NaN);
if (!isNaN(jspb.utils.joinFloat32(jspb.utils.split64Low,
jspb.utils.split64High))) {
throw 'fail!';
}
expect(isNaN(jspb.utils.joinFloat32(
jspb.utils.split64Low, jspb.utils.split64High)))
.toEqual(true);
/**
* @param {number} x
@ -359,10 +357,9 @@ describe('binaryUtilsTest', function() {
if (goog.isDef(opt_bits)) {
if (opt_bits != jspb.utils.split64Low) throw 'fail!';
}
if (truncate(x) != jspb.utils.joinFloat32(jspb.utils.split64Low,
jspb.utils.split64High)) {
throw 'fail!';
}
expect(truncate(x))
.toEqual(jspb.utils.joinFloat32(
jspb.utils.split64Low, jspb.utils.split64High));
}
// Positive and negative infinity.
@ -411,10 +408,9 @@ describe('binaryUtilsTest', function() {
// NaN.
jspb.utils.splitFloat64(NaN);
if (!isNaN(jspb.utils.joinFloat64(jspb.utils.split64Low,
jspb.utils.split64High))) {
throw 'fail!';
}
expect(isNaN(jspb.utils.joinFloat64(
jspb.utils.split64Low, jspb.utils.split64High)))
.toEqual(true);
/**
* @param {number} x
@ -429,10 +425,9 @@ describe('binaryUtilsTest', function() {
if (goog.isDef(opt_lowBits)) {
if (opt_lowBits != jspb.utils.split64Low) throw 'fail!';
}
if (x != jspb.utils.joinFloat64(jspb.utils.split64Low,
jspb.utils.split64High)) {
throw 'fail!';
}
expect(
jspb.utils.joinFloat64(jspb.utils.split64Low, jspb.utils.split64High))
.toEqual(x);
}
// Positive and negative infinity.
@ -487,8 +482,8 @@ describe('binaryUtilsTest', function() {
// We should have two more varints than we started with - one for the field
// tag, one for the packed length.
assertEquals(values.length + 2,
jspb.utils.countVarints(buffer, 0, buffer.length));
expect(jspb.utils.countVarints(buffer, 0, buffer.length))
.toEqual(values.length + 2);
});
@ -506,8 +501,8 @@ describe('binaryUtilsTest', function() {
writer.writeString(2, 'terminator');
var buffer = new Uint8Array(writer.getResultBuffer());
assertEquals(count,
jspb.utils.countVarintFields(buffer, 0, buffer.length, 1));
expect(jspb.utils.countVarintFields(buffer, 0, buffer.length, 1))
.toEqual(count);
writer = new jspb.BinaryWriter();
@ -519,8 +514,8 @@ describe('binaryUtilsTest', function() {
writer.writeString(2, 'terminator');
buffer = new Uint8Array(writer.getResultBuffer());
assertEquals(count,
jspb.utils.countVarintFields(buffer, 0, buffer.length, 123456789));
expect(jspb.utils.countVarintFields(buffer, 0, buffer.length, 123456789))
.toEqual(count);
});
@ -538,8 +533,8 @@ describe('binaryUtilsTest', function() {
writer.writeString(2, 'terminator');
var buffer = new Uint8Array(writer.getResultBuffer());
assertEquals(count,
jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 1));
expect(jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 1))
.toEqual(count);
writer = new jspb.BinaryWriter();
@ -551,8 +546,8 @@ describe('binaryUtilsTest', function() {
writer.writeString(2, 'terminator');
buffer = new Uint8Array(writer.getResultBuffer());
assertEquals(count,
jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 123456789));
expect(jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 123456789))
.toEqual(count);
});
@ -570,8 +565,8 @@ describe('binaryUtilsTest', function() {
writer.writeString(2, 'terminator');
var buffer = new Uint8Array(writer.getResultBuffer());
assertEquals(count,
jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 1));
expect(jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 1))
.toEqual(count);
writer = new jspb.BinaryWriter();
@ -583,8 +578,8 @@ describe('binaryUtilsTest', function() {
writer.writeString(2, 'terminator');
buffer = new Uint8Array(writer.getResultBuffer());
assertEquals(count,
jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 123456789));
expect(jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 123456789))
.toEqual(count);
});
@ -602,8 +597,8 @@ describe('binaryUtilsTest', function() {
writer.writeString(2, 'terminator');
var buffer = new Uint8Array(writer.getResultBuffer());
assertEquals(count,
jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 1));
expect(jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 1))
.toEqual(count);
writer = new jspb.BinaryWriter();
@ -615,8 +610,8 @@ describe('binaryUtilsTest', function() {
writer.writeString(2, 'terminator');
buffer = new Uint8Array(writer.getResultBuffer());
assertEquals(count,
jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 123456789));
expect(jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 123456789))
.toEqual(count);
});
@ -624,9 +619,10 @@ describe('binaryUtilsTest', function() {
* Tests byte format for debug strings.
*/
it('testDebugBytesToTextFormat', function() {
assertEquals('""', jspb.utils.debugBytesToTextFormat(null));
assertEquals('"\\x00\\x10\\xff"',
jspb.utils.debugBytesToTextFormat([0, 16, 255]));
expect(jspb.utils.debugBytesToTextFormat(null)).toEqual('""');
expect(jspb.utils.debugBytesToTextFormat([
0, 16, 255
])).toEqual('"\\x00\\x10\\xff"');
});
@ -647,15 +643,15 @@ describe('binaryUtilsTest', function() {
var sourceString = goog.crypt.byteArrayToString(sourceData);
function check(result) {
assertEquals(Uint8Array, result.constructor);
assertEquals(sourceData.length, result.length);
expect(result.constructor).toEqual(Uint8Array);
expect(result.length).toEqual(sourceData.length);
for (var i = 0; i < result.length; i++) {
assertEquals(sourceData[i], result[i]);
expect(result[i]).toEqual(sourceData[i]);
}
}
// Converting Uint8Arrays into Uint8Arrays should be a no-op.
assertEquals(sourceBytes, convert(sourceBytes));
expect(convert(sourceBytes)).toEqual(sourceBytes);
// Converting Array<numbers> into Uint8Arrays should work.
check(convert(sourceData));

@ -886,6 +886,32 @@ jspb.BinaryWriter.prototype.writeVarintHash64 = function(field, value) {
};
/**
* Writes a 64-bit field to the buffer as a fixed64.
* @param {number} field The field number.
* @param {number} lowBits The low 32 bits.
* @param {number} highBits The high 32 bits.
*/
jspb.BinaryWriter.prototype.writeSplitFixed64 = function(
field, lowBits, highBits) {
this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64);
this.encoder_.writeSplitFixed64(lowBits, highBits);
};
/**
* Writes a 64-bit field to the buffer as a varint.
* @param {number} field The field number.
* @param {number} lowBits The low 32 bits.
* @param {number} highBits The high 32 bits.
*/
jspb.BinaryWriter.prototype.writeSplitVarint64 = function(
field, lowBits, highBits) {
this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
this.encoder_.writeSplitVarint64(lowBits, highBits);
};
/**
* Writes an array of numbers to the buffer as a repeated 32-bit int field.
* @param {number} field The field number.
@ -926,6 +952,40 @@ jspb.BinaryWriter.prototype.writeRepeatedInt64 = function(field, value) {
};
/**
* Writes an array of 64-bit values to the buffer as a fixed64.
* @param {number} field The field number.
* @param {?Array<T>} value The value.
* @param {function(T): number} lo Function to get low bits.
* @param {function(T): number} hi Function to get high bits.
* @template T
*/
jspb.BinaryWriter.prototype.writeRepeatedSplitFixed64 = function(
field, value, lo, hi) {
if (value == null) return;
for (var i = 0; i < value.length; i++) {
this.writeSplitFixed64(field, lo(value[i]), hi(value[i]));
}
};
/**
* Writes an array of 64-bit values to the buffer as a varint.
* @param {number} field The field number.
* @param {?Array<T>} value The value.
* @param {function(T): number} lo Function to get low bits.
* @param {function(T): number} hi Function to get high bits.
* @template T
*/
jspb.BinaryWriter.prototype.writeRepeatedSplitVarint64 = function(
field, value, lo, hi) {
if (value == null) return;
for (var i = 0; i < value.length; i++) {
this.writeSplitVarint64(field, lo(value[i]), hi(value[i]));
}
};
/**
* Writes an array of numbers formatted as strings to the buffer as a repeated
* 64-bit int field.
@ -1313,6 +1373,44 @@ jspb.BinaryWriter.prototype.writePackedInt64 = function(field, value) {
};
/**
* Writes an array of 64-bit values to the buffer as a fixed64.
* @param {number} field The field number.
* @param {?Array<T>} value The value.
* @param {function(T): number} lo Function to get low bits.
* @param {function(T): number} hi Function to get high bits.
* @template T
*/
jspb.BinaryWriter.prototype.writePackedSplitFixed64 = function(
field, value, lo, hi) {
if (value == null) return;
var bookmark = this.beginDelimited_(field);
for (var i = 0; i < value.length; i++) {
this.encoder_.writeSplitFixed64(lo(value[i]), hi(value[i]));
}
this.endDelimited_(bookmark);
};
/**
* Writes an array of 64-bit values to the buffer as a varint.
* @param {number} field The field number.
* @param {?Array<T>} value The value.
* @param {function(T): number} lo Function to get low bits.
* @param {function(T): number} hi Function to get high bits.
* @template T
*/
jspb.BinaryWriter.prototype.writePackedSplitVarint64 = function(
field, value, lo, hi) {
if (value == null) return;
var bookmark = this.beginDelimited_(field);
for (var i = 0; i < value.length; i++) {
this.encoder_.writeSplitVarint64(lo(value[i]), hi(value[i]));
}
this.endDelimited_(bookmark);
};
/**
* Writes an array of numbers represented as strings to the buffer as a packed
* 64-bit int field.

@ -40,6 +40,7 @@
goog.require('goog.crypt');
goog.require('goog.testing.asserts');
goog.require('jspb.BinaryReader');
goog.require('jspb.BinaryWriter');
@ -130,4 +131,74 @@ describe('binaryWriterTest', function() {
assertEquals('CgF/', writer.getResultBase64String(false));
assertEquals('CgF_', writer.getResultBase64String(true));
});
it('writes split 64 fields', function() {
var writer = new jspb.BinaryWriter();
writer.writeSplitVarint64(1, 0x1, 0x2);
writer.writeSplitVarint64(1, 0xFFFFFFFF, 0xFFFFFFFF);
writer.writeSplitFixed64(2, 0x1, 0x2);
writer.writeSplitFixed64(2, 0xFFFFFFF0, 0xFFFFFFFF);
function lo(i) {
return i + 1;
}
function hi(i) {
return i + 2;
}
writer.writeRepeatedSplitVarint64(3, [0, 1, 2], lo, hi);
writer.writeRepeatedSplitFixed64(4, [0, 1, 2], lo, hi);
writer.writePackedSplitVarint64(5, [0, 1, 2], lo, hi);
writer.writePackedSplitFixed64(6, [0, 1, 2], lo, hi);
function bitsAsArray(lowBits, highBits) {
return [lowBits >>> 0, highBits >>> 0];
}
var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
reader.nextField();
expect(reader.getFieldNumber()).toEqual(1);
expect(reader.readSplitVarint64(bitsAsArray)).toEqual([0x1, 0x2]);
reader.nextField();
expect(reader.getFieldNumber()).toEqual(1);
expect(reader.readSplitVarint64(bitsAsArray)).toEqual([
0xFFFFFFFF, 0xFFFFFFFF
]);
reader.nextField();
expect(reader.getFieldNumber()).toEqual(2);
expect(reader.readSplitFixed64(bitsAsArray)).toEqual([0x1, 0x2]);
reader.nextField();
expect(reader.getFieldNumber()).toEqual(2);
expect(reader.readSplitFixed64(bitsAsArray)).toEqual([
0xFFFFFFF0, 0xFFFFFFFF
]);
for (let i = 0; i < 3; i++) {
reader.nextField();
expect(reader.getFieldNumber()).toEqual(3);
expect(reader.readSplitVarint64(bitsAsArray)).toEqual([i + 1, i + 2]);
}
for (let i = 0; i < 3; i++) {
reader.nextField();
expect(reader.getFieldNumber()).toEqual(4);
expect(reader.readSplitFixed64(bitsAsArray)).toEqual([i + 1, i + 2]);
}
reader.nextField();
expect(reader.getFieldNumber()).toEqual(5);
expect(reader.readPackedInt64String()).toEqual([
String(2 * 2 ** 32 + 1),
String(3 * 2 ** 32 + 2),
String(4 * 2 ** 32 + 3),
]);
reader.nextField();
expect(reader.getFieldNumber()).toEqual(6);
expect(reader.readPackedFixed64String()).toEqual([
String(2 * 2 ** 32 + 1),
String(3 * 2 ** 32 + 2),
String(4 * 2 ** 32 + 3),
]);
});
});

@ -465,11 +465,15 @@ jspb.Map.prototype.serializeBinary = function(
* entries with unset keys is required for maps to be backwards compatible
* with the repeated message representation described here: goo.gl/zuoLAC
*
* @param {V=} opt_defaultValue
* The default value for the type of map values.
*
*/
jspb.Map.deserializeBinary = function(map, reader, keyReaderFn, valueReaderFn,
opt_valueReaderCallback, opt_defaultKey) {
opt_valueReaderCallback, opt_defaultKey,
opt_defaultValue) {
var key = opt_defaultKey;
var value = undefined;
var value = opt_defaultValue;
while (reader.nextField()) {
if (reader.isEndGroup()) {

@ -104,7 +104,7 @@ jspb.ExtensionFieldInfo = function(fieldNumber, fieldName, ctor, toObjectFn,
/**
* Stores binary-related information for a single extension field.
* @param {!jspb.ExtensionFieldInfo<T>} fieldInfo
* @param {function(this:jspb.BinaryReader,number,?)} binaryReaderFn
* @param {function(this:jspb.BinaryReader,number,?,?)} binaryReaderFn
* @param {function(this:jspb.BinaryWriter,number,?)
* |function(this:jspb.BinaryWriter,number,?,?,?,?,?)} binaryWriterFn
* @param {function(?,?)=} opt_binaryMessageSerializeFn
@ -976,153 +976,186 @@ jspb.Message.getMapField = function(msg, fieldNumber, noLazyCreate,
/**
* Sets the value of a non-extension field.
* @param {!jspb.Message} msg A jspb proto.
* @param {T} msg A jspb proto.
* @param {number} fieldNumber The field number.
* @param {string|number|boolean|Uint8Array|Array|undefined} value New value
* @return {T} return msg
* @template T
* @protected
*/
jspb.Message.setField = function(msg, fieldNumber, value) {
// TODO(b/35241823): replace this with a bounded generic when available
goog.asserts.assertInstanceof(msg, jspb.Message);
if (fieldNumber < msg.pivot_) {
msg.array[jspb.Message.getIndex_(msg, fieldNumber)] = value;
} else {
jspb.Message.maybeInitEmptyExtensionObject_(msg);
msg.extensionObject_[fieldNumber] = value;
}
return msg;
};
/**
* Sets the value of a non-extension integer field of a proto3
* @param {!jspb.Message} msg A jspb proto.
* @param {T} msg A jspb proto.
* @param {number} fieldNumber The field number.
* @param {number} value New value
* @return {T} return msg
* @template T
* @protected
*/
jspb.Message.setProto3IntField = function(msg, fieldNumber, value) {
jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, 0);
return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, 0);
};
/**
* Sets the value of a non-extension floating point field of a proto3
* @param {!jspb.Message} msg A jspb proto.
* @param {T} msg A jspb proto.
* @param {number} fieldNumber The field number.
* @param {number} value New value
* @return {T} return msg
* @template T
* @protected
*/
jspb.Message.setProto3FloatField = function(msg, fieldNumber, value) {
jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, 0.0);
return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, 0.0);
};
/**
* Sets the value of a non-extension boolean field of a proto3
* @param {!jspb.Message} msg A jspb proto.
* @param {T} msg A jspb proto.
* @param {number} fieldNumber The field number.
* @param {boolean} value New value
* @return {T} return msg
* @template T
* @protected
*/
jspb.Message.setProto3BooleanField = function(msg, fieldNumber, value) {
jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, false);
return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, false);
};
/**
* Sets the value of a non-extension String field of a proto3
* @param {!jspb.Message} msg A jspb proto.
* @param {T} msg A jspb proto.
* @param {number} fieldNumber The field number.
* @param {string} value New value
* @return {T} return msg
* @template T
* @protected
*/
jspb.Message.setProto3StringField = function(msg, fieldNumber, value) {
jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, "");
return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, '');
};
/**
* Sets the value of a non-extension Bytes field of a proto3
* @param {!jspb.Message} msg A jspb proto.
* @param {T} msg A jspb proto.
* @param {number} fieldNumber The field number.
* @param {!Uint8Array|string} value New value
* @return {T} return msg
* @template T
* @protected
*/
jspb.Message.setProto3BytesField = function(msg, fieldNumber, value) {
jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, "");
return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, '');
};
/**
* Sets the value of a non-extension enum field of a proto3
* @param {!jspb.Message} msg A jspb proto.
* @param {T} msg A jspb proto.
* @param {number} fieldNumber The field number.
* @param {number} value New value
* @return {T} return msg
* @template T
* @protected
*/
jspb.Message.setProto3EnumField = function(msg, fieldNumber, value) {
jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, 0);
return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, 0);
};
/**
* Sets the value of a non-extension int field of a proto3 that has jstype set
* to String.
* @param {!jspb.Message} msg A jspb proto.
* @param {T} msg A jspb proto.
* @param {number} fieldNumber The field number.
* @param {string} value New value
* @return {T} return msg
* @template T
* @protected
*/
jspb.Message.setProto3StringIntField = function(msg, fieldNumber, value) {
jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, "0");
return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, '0');
};
/**
* Sets the value of a non-extension primitive field, with proto3 (non-nullable
* primitives) semantics of ignoring values that are equal to the type's
* default.
* @param {!jspb.Message} msg A jspb proto.
* @param {T} msg A jspb proto.
* @param {number} fieldNumber The field number.
* @param {!Uint8Array|string|number|boolean|undefined} value New value
* @param {!Uint8Array|string|number|boolean} defaultValue The default value.
* @return {T} return msg
* @template T
* @private
*/
jspb.Message.setFieldIgnoringDefault_ = function(
msg, fieldNumber, value, defaultValue) {
// TODO(b/35241823): replace this with a bounded generic when available
goog.asserts.assertInstanceof(msg, jspb.Message);
if (value !== defaultValue) {
jspb.Message.setField(msg, fieldNumber, value);
} else {
msg.array[jspb.Message.getIndex_(msg, fieldNumber)] = null;
}
return msg;
};
/**
* Adds a value to a repeated, primitive field.
* @param {!jspb.Message} msg A jspb proto.
* @param {T} msg A jspb proto.
* @param {number} fieldNumber The field number.
* @param {string|number|boolean|!Uint8Array} value New value
* @param {number=} opt_index Index where to put new value.
* @return {T} return msg
* @template T
* @protected
*/
jspb.Message.addToRepeatedField = function(msg, fieldNumber, value, opt_index) {
// TODO(b/35241823): replace this with a bounded generic when available
goog.asserts.assertInstanceof(msg, jspb.Message);
var arr = jspb.Message.getRepeatedField(msg, fieldNumber);
if (opt_index != undefined) {
arr.splice(opt_index, 0, value);
} else {
arr.push(value);
}
return msg;
};
/**
* Sets the value of a field in a oneof union and clears all other fields in
* the union.
* @param {!jspb.Message} msg A jspb proto.
* @param {T} msg A jspb proto.
* @param {number} fieldNumber The field number.
* @param {!Array<number>} oneof The fields belonging to the union.
* @param {string|number|boolean|Uint8Array|Array|undefined} value New value
* @return {T} return msg
* @template T
* @protected
*/
jspb.Message.setOneofField = function(msg, fieldNumber, oneof, value) {
// TODO(b/35241823): replace this with a bounded generic when available
goog.asserts.assertInstanceof(msg, jspb.Message);
var currentCase = jspb.Message.computeOneofCase(msg, oneof);
if (currentCase && currentCase !== fieldNumber && value !== undefined) {
if (msg.wrappers_ && currentCase in msg.wrappers_) {
@ -1130,7 +1163,7 @@ jspb.Message.setOneofField = function(msg, fieldNumber, oneof, value) {
}
jspb.Message.setField(msg, currentCase, undefined);
}
jspb.Message.setField(msg, fieldNumber, value);
return jspb.Message.setField(msg, fieldNumber, value);
};
@ -1244,48 +1277,61 @@ jspb.Message.wrapRepeatedField_ = function(msg, ctor, fieldNumber) {
/**
* Sets a proto field and syncs it to the backing array.
* @param {!jspb.Message} msg A jspb proto.
* @param {T} msg A jspb proto.
* @param {number} fieldNumber The field number.
* @param {?jspb.Message|?jspb.Map|undefined} value A new value for this proto
* field.
* @return {T} the msg
* @template T
* @protected
*/
jspb.Message.setWrapperField = function(msg, fieldNumber, value) {
// TODO(b/35241823): replace this with a bounded generic when available
goog.asserts.assertInstanceof(msg, jspb.Message);
if (!msg.wrappers_) {
msg.wrappers_ = {};
}
var data = value ? value.toArray() : value;
msg.wrappers_[fieldNumber] = value;
jspb.Message.setField(msg, fieldNumber, data);
return jspb.Message.setField(msg, fieldNumber, data);
};
/**
* Sets a proto field in a oneof union and syncs it to the backing array.
* @param {!jspb.Message} msg A jspb proto.
* @param {T} msg A jspb proto.
* @param {number} fieldNumber The field number.
* @param {!Array<number>} oneof The fields belonging to the union.
* @param {jspb.Message|undefined} value A new value for this proto field.
* @return {T} the msg
* @template T
* @protected
*/
jspb.Message.setOneofWrapperField = function(msg, fieldNumber, oneof, value) {
// TODO(b/35241823): replace this with a bounded generic when available
goog.asserts.assertInstanceof(msg, jspb.Message);
if (!msg.wrappers_) {
msg.wrappers_ = {};
}
var data = value ? value.toArray() : value;
msg.wrappers_[fieldNumber] = value;
jspb.Message.setOneofField(msg, fieldNumber, oneof, data);
return jspb.Message.setOneofField(msg, fieldNumber, oneof, data);
};
/**
* Sets a repeated proto field and syncs it to the backing array.
* @param {!jspb.Message} msg A jspb proto.
* @param {T} msg A jspb proto.
* @param {number} fieldNumber The field number.
* @param {Array<!jspb.Message>|undefined} value An array of protos.
* @return {T} the msg
* @template T
* @protected
*/
jspb.Message.setRepeatedWrapperField = function(msg, fieldNumber, value) {
// TODO(b/35241823): replace this with a bounded generic when available
goog.asserts.assertInstanceof(msg, jspb.Message);
if (!msg.wrappers_) {
msg.wrappers_ = {};
}
@ -1294,7 +1340,7 @@ jspb.Message.setRepeatedWrapperField = function(msg, fieldNumber, value) {
data[i] = value[i].toArray();
}
msg.wrappers_[fieldNumber] = value;
jspb.Message.setField(msg, fieldNumber, data);
return jspb.Message.setField(msg, fieldNumber, data);
};

@ -118,6 +118,7 @@ goog.require('proto.jspb.test.TestReservedNamesExtension');
goog.require('proto.jspb.test.ExtensionMessage');
goog.require('proto.jspb.test.TestExtensionsMessage');
goog.require('proto.jspb.test.TestAllowAliasEnum');
describe('Message test suite', function() {
var stubs = new goog.testing.PropertyReplacer();

@ -28,6 +28,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// LINT: LEGACY_NAMES
// Author: mwr@google.com (Mark Rawling)
syntax = "proto2";
@ -311,3 +312,11 @@ message Deeply {
}
enum TestAllowAliasEnum {
option allow_alias = true;
TEST_ALLOW_ALIAS_DEFAULT = 0;
VALUE1 = 1;
value1 = 1;
}

@ -3,11 +3,28 @@
# Build file to set up and run tests
set -ex
# Install the latest Bazel version available
use_bazel.sh latest
bazel version
# Print bazel testlogs to stdout when tests failed.
function print_test_logs {
# TODO(yannic): Only print logs of failing tests.
testlogs_dir=$(bazel info bazel-testlogs)
testlogs=$(find "${testlogs_dir}" -name "*.log")
for log in $testlogs; do
cat "${log}"
done
}
# Change to repo root
cd $(dirname $0)/../../..
git submodule update --init --recursive
bazel test :protobuf_test --copt=-Werror --host_copt=-Werror
trap print_test_logs EXIT
bazel test :build_files_updated_unittest :protobuf_test --copt=-Werror --host_copt=-Werror
trap - EXIT
cd examples
bazel build :all

@ -50,7 +50,6 @@ build_artifact_version() {
}
build_artifact_version 2.7
build_artifact_version 3.4
build_artifact_version 3.5
build_artifact_version 3.6
build_artifact_version 3.7

@ -51,7 +51,6 @@ build_artifact_version() {
}
build_artifact_version 2.7
build_artifact_version 3.4
build_artifact_version 3.5
build_artifact_version 3.6
build_artifact_version 3.7

@ -77,7 +77,7 @@ typedef GPB_ENUM(GPBDuration_FieldNumber) {
* if (duration.seconds < 0 && duration.nanos > 0) {
* duration.seconds += 1;
* duration.nanos -= 1000000000;
* } else if (durations.seconds > 0 && duration.nanos < 0) {
* } else if (duration.seconds > 0 && duration.nanos < 0) {
* duration.seconds -= 1;
* duration.nanos += 1000000000;
* }

@ -5,7 +5,7 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
def protobuf_deps():
"""Loads common dependencies needed to compile the protobuf library."""
if "zlib" not in native.existing_rules():
if not native.existing_rule("zlib"):
http_archive(
name = "zlib",
build_file = "@com_google_protobuf//:third_party/zlib.BUILD",
@ -14,10 +14,34 @@ def protobuf_deps():
urls = ["https://zlib.net/zlib-1.2.11.tar.gz"],
)
if "six" not in native.existing_rules():
if not native.existing_rule("six"):
http_archive(
name = "six",
build_file = "@//:six.BUILD",
sha256 = "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a",
urls = ["https://pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz#md5=34eed507548117b2ab523ab14b2f8b55"],
)
if not native.existing_rule("rules_cc"):
http_archive(
name = "rules_cc",
sha256 = "29daf0159f0cf552fcff60b49d8bcd4f08f08506d2da6e41b07058ec50cfeaec",
strip_prefix = "rules_cc-b7fe9697c0c76ab2fd431a891dbb9a6a32ed7c3e",
urls = ["https://github.com/bazelbuild/rules_cc/archive/b7fe9697c0c76ab2fd431a891dbb9a6a32ed7c3e.tar.gz"],
)
if not native.existing_rule("rules_java"):
http_archive(
name = "rules_java",
sha256 = "f5a3e477e579231fca27bf202bb0e8fbe4fc6339d63b38ccb87c2760b533d1c3",
strip_prefix = "rules_java-981f06c3d2bd10225e85209904090eb7b5fb26bd",
urls = ["https://github.com/bazelbuild/rules_java/archive/981f06c3d2bd10225e85209904090eb7b5fb26bd.tar.gz"],
)
if not native.existing_rule("rules_proto"):
http_archive(
name = "rules_proto",
sha256 = "88b0a90433866b44bb4450d4c30bc5738b8c4f9c9ba14e9661deb123f56a833d",
strip_prefix = "rules_proto-b0cc14be5da05168b01db282fe93bdf17aa2b9f4",
urls = ["https://github.com/bazelbuild/rules_proto/archive/b0cc14be5da05168b01db282fe93bdf17aa2b9f4.tar.gz"],
)

@ -1998,6 +1998,13 @@ class Proto3Test(unittest.TestCase):
m1.MergeFrom(m2)
self.assertEqual(10, m2.map_int32_foreign_message[123].c)
# Test merge maps within different message types.
m1 = map_unittest_pb2.TestMap()
m2 = map_unittest_pb2.TestMessageMap()
m2.map_int32_message[123].optional_int32 = 10
m1.map_int32_all_types.MergeFrom(m2.map_int32_message)
self.assertEqual(10, m1.map_int32_all_types[123].optional_int32)
def testMergeFromBadType(self):
msg = map_unittest_pb2.TestMap()
with self.assertRaisesRegexp(

@ -620,7 +620,7 @@ class _FieldProperty(property):
def _AddPropertiesForRepeatedField(field, cls):
"""Adds a public property for a "repeated" protocol message field. Clients
can use this property to get the value of the field, which will be either a
_RepeatedScalarFieldContainer or _RepeatedCompositeFieldContainer (see
RepeatedScalarFieldContainer or RepeatedCompositeFieldContainer (see
below).
Note that when clients add values to these containers, we perform

@ -722,10 +722,10 @@ def _SetStructValue(struct_value, value):
struct_value.string_value = value
elif isinstance(value, _INT_OR_FLOAT):
struct_value.number_value = value
elif isinstance(value, dict):
elif isinstance(value, (dict, Struct)):
struct_value.struct_value.Clear()
struct_value.struct_value.update(value)
elif isinstance(value, list):
elif isinstance(value, (list, ListValue)):
struct_value.list_value.Clear()
struct_value.list_value.extend(value)
else:

@ -871,6 +871,15 @@ class StructTest(unittest.TestCase):
self.assertEqual([6, True, False, None, inner_struct],
list(struct['key5'].items()))
def testStructAssignment(self):
# Tests struct assignment from another struct
s1 = struct_pb2.Struct()
s2 = struct_pb2.Struct()
for value in [1, 'a', [1], ['a'], {'a': 'b'}]:
s1['x'] = value
s2['x'] = s1['x']
self.assertEqual(s1['x'], s2['x'])
def testMergeFrom(self):
struct = struct_pb2.Struct()
struct_class = struct.__class__

@ -343,9 +343,8 @@ PyObject* MapReflectionFriend::MergeFrom(PyObject* _self, PyObject* arg) {
const Reflection* other_reflection = other_message->GetReflection();
internal::MapFieldBase* field = reflection->MutableMapData(
message, self->parent_field_descriptor);
const internal::MapFieldBase* other_field =
other_reflection->GetMapData(*other_message,
self->parent_field_descriptor);
const internal::MapFieldBase* other_field = other_reflection->GetMapData(
*other_message, other_map->parent_field_descriptor);
field->MergeFrom(*other_field);
self->version++;
Py_RETURN_NONE;

@ -47,7 +47,6 @@
#endif
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/io/strtod.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <google/protobuf/descriptor.pb.h>
@ -63,14 +62,17 @@
#include <google/protobuf/pyext/message_factory.h>
#include <google/protobuf/pyext/repeated_composite_container.h>
#include <google/protobuf/pyext/repeated_scalar_container.h>
#include <google/protobuf/pyext/unknown_fields.h>
#include <google/protobuf/pyext/safe_numerics.h>
#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
#include <google/protobuf/pyext/unknown_fields.h>
#include <google/protobuf/util/message_differencer.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/io/strtod.h>
#include <google/protobuf/stubs/map_util.h>
// clang-format off
#include <google/protobuf/port_def.inc>
// clang-format on
#if PY_MAJOR_VERSION >= 3
#define PyInt_AsLong PyLong_AsLong

@ -71,6 +71,9 @@ static VALUE table_key(Map* self, VALUE key,
case UPB_TYPE_BYTES:
case UPB_TYPE_STRING:
// Strings: use string content directly.
if (TYPE(key) == T_SYMBOL) {
key = rb_id2str(SYM2ID(key));
}
Check_Type(key, T_STRING);
key = native_slot_encode_and_freeze_string(self->key_type, key);
*out_key = RSTRING_PTR(key);
@ -397,6 +400,11 @@ VALUE Map_index_set(VALUE _self, VALUE key, VALUE value) {
void* mem;
key = table_key(self, key, keybuf, &keyval, &length);
if (TYPE(value) == T_HASH) {
VALUE args[1] = { value };
value = rb_class_new_instance(1, args, self->value_type_class);
}
mem = value_memory(&v);
native_slot_set("", self->value_type, self->value_type_class, mem, value);

@ -192,7 +192,7 @@ static int extract_method_call(VALUE method_name, MessageHeader* self,
// Find the field name
char wrapper_field_name[name_len - 8];
strncpy(wrapper_field_name, name, name_len - 9);
wrapper_field_name[name_len - 7] = '\0';
wrapper_field_name[name_len - 9] = '\0';
// Check if field exists and is a wrapper type
const upb_oneofdef* test_o_wrapper;
@ -220,7 +220,7 @@ static int extract_method_call(VALUE method_name, MessageHeader* self,
// Find enum field name
char enum_name[name_len - 5];
strncpy(enum_name, name, name_len - 6);
enum_name[name_len - 4] = '\0';
enum_name[name_len - 6] = '\0';
// Check if enum field exists
const upb_oneofdef* test_o_enum;

@ -204,6 +204,20 @@ module BasicTest
end
end
def test_map_field_with_symbol
m = MapMessage.new
assert m.map_string_int32 == {}
assert m.map_string_msg == {}
m = MapMessage.new(
:map_string_int32 => {a: 1, "b" => 2},
:map_string_msg => {a: TestMessage2.new(:foo => 1),
b: TestMessage2.new(:foo => 10)})
assert_equal 1, m.map_string_int32[:a]
assert_equal 2, m.map_string_int32[:b]
assert_equal 10, m.map_string_msg[:b].foo
end
def test_map_inspect
m = MapMessage.new(
:map_string_int32 => {"a" => 1, "b" => 2},

@ -139,4 +139,58 @@ class TestWellKnownTypes < Test::Unit::TestCase
assert any.is(Google::Protobuf::Timestamp)
assert_equal ts, any.unpack(Google::Protobuf::Timestamp)
end
def test_struct_init
s = Google::Protobuf::Struct.new(fields: {'a' => Google::Protobuf::Value.new({number_value: 4.4})})
assert_equal 4.4, s['a']
s = Google::Protobuf::Struct.new(fields: {'a' => {number_value: 2.2}})
assert_equal 2.2, s['a']
s = Google::Protobuf::Struct.new(fields: {a: {number_value: 1.1}})
assert_equal 1.1, s[:a]
end
def test_struct_nested_init
s = Google::Protobuf::Struct.new(
fields: {
'a' => {string_value: 'A'},
'b' => {struct_value: {
fields: {
'x' => {list_value: {values: [{number_value: 1.0}, {string_value: "ok"}]}},
'y' => {bool_value: true}}}
},
'c' => {struct_value: {}}
}
)
assert_equal 'A', s['a']
assert_equal 'A', s[:a]
expected_b_x = [Google::Protobuf::Value.new(number_value: 1.0), Google::Protobuf::Value.new(string_value: "ok")]
assert_equal expected_b_x, s['b']['x'].values
assert_equal expected_b_x, s[:b][:x].values
assert_equal expected_b_x, s['b'][:x].values
assert_equal expected_b_x, s[:b]['x'].values
assert_equal true, s['b']['y']
assert_equal true, s[:b][:y]
assert_equal true, s[:b]['y']
assert_equal true, s['b'][:y]
assert_equal Google::Protobuf::Struct.new, s['c']
assert_equal Google::Protobuf::Struct.new, s[:c]
s = Google::Protobuf::Struct.new(
fields: {
a: {string_value: 'Eh'},
b: {struct_value: {
fields: {
y: {bool_value: false}}}
}
}
)
assert_equal 'Eh', s['a']
assert_equal 'Eh', s[:a]
assert_equal false, s['b']['y']
assert_equal false, s[:b][:y]
assert_equal false, s['b'][:y]
assert_equal false, s[:b]['y']
end
end

@ -105,6 +105,7 @@ nobase_include_HEADERS = \
google/protobuf/has_bits.h \
google/protobuf/implicit_weak_message.h \
google/protobuf/inlined_string_field.h \
google/protobuf/io/io_win32.h \
google/protobuf/map_entry.h \
google/protobuf/map_entry_lite.h \
google/protobuf/map_field.h \
@ -184,7 +185,6 @@ libprotobuf_lite_la_SOURCES = \
google/protobuf/stubs/int128.cc \
google/protobuf/stubs/int128.h \
google/protobuf/io/io_win32.cc \
google/protobuf/io/io_win32.h \
google/protobuf/stubs/map_util.h \
google/protobuf/stubs/mathutil.h \
google/protobuf/stubs/status.cc \
@ -213,7 +213,6 @@ libprotobuf_lite_la_SOURCES = \
google/protobuf/repeated_field.cc \
google/protobuf/wire_format_lite.cc \
google/protobuf/io/coded_stream.cc \
google/protobuf/io/coded_stream_inl.h \
google/protobuf/io/strtod.cc \
google/protobuf/io/zero_copy_stream.cc \
google/protobuf/io/zero_copy_stream_impl.cc \
@ -728,6 +727,9 @@ protobuf_test_CPPFLAGS = -I$(GOOGLETEST_SRC_DIR)/include \
# since test_util.cc takes forever to compile with optimization (with GCC).
# See configure.ac for more info.
protobuf_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
# Doesn't pass on Windows with MSVC
NON_MSVC_TEST_SOURCES = \
google/protobuf/compiler/command_line_interface_unittest.cc
protobuf_test_SOURCES = \
google/protobuf/stubs/bytestream_unittest.cc \
google/protobuf/stubs/common_unittest.cc \
@ -773,7 +775,6 @@ protobuf_test_SOURCES = \
google/protobuf/io/zero_copy_stream_unittest.cc \
google/protobuf/compiler/annotation_test_util.h \
google/protobuf/compiler/annotation_test_util.cc \
google/protobuf/compiler/command_line_interface_unittest.cc \
google/protobuf/compiler/importer_unittest.cc \
google/protobuf/compiler/mock_code_generator.cc \
google/protobuf/compiler/mock_code_generator.h \
@ -805,6 +806,7 @@ protobuf_test_SOURCES = \
google/protobuf/util/message_differencer_unittest.cc \
google/protobuf/util/time_util_test.cc \
google/protobuf/util/type_resolver_util_test.cc \
$(NON_MSVC_TEST_SOURCES) \
$(COMMON_TEST_SOURCES)
nodist_protobuf_test_SOURCES = $(protoc_outputs)
$(am_protobuf_test_OBJECTS): unittest_proto_middleman

@ -32,7 +32,7 @@ static void InitDefaultsscc_info_Any_google_2fprotobuf_2fany_2eproto() {
}
PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Any_google_2fprotobuf_2fany_2eproto =
{{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsscc_info_Any_google_2fprotobuf_2fany_2eproto}, {}};
{{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Any_google_2fprotobuf_2fany_2eproto}, {}};
static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fany_2eproto[1];
static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto = nullptr;
@ -125,11 +125,11 @@ Any::Any(const Any& from)
_any_metadata_(&type_url_, &value_) {
_internal_metadata_.MergeFrom(from._internal_metadata_);
type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
if (!from.type_url().empty()) {
if (!from._internal_type_url().empty()) {
type_url_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.type_url_);
}
value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
if (!from.value().empty()) {
if (!from._internal_value().empty()) {
value_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.value_);
}
// @@protoc_insertion_point(copy_constructor:google.protobuf.Any)
@ -182,14 +182,14 @@ const char* Any::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::intern
// string type_url = 1;
case 1:
if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) {
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(mutable_type_url(), ptr, ctx, "google.protobuf.Any.type_url");
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(_internal_mutable_type_url(), ptr, ctx, "google.protobuf.Any.type_url");
CHK_(ptr);
} else goto handle_unusual;
continue;
// bytes value = 2;
case 2:
if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) {
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(mutable_value(), ptr, ctx);
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(_internal_mutable_value(), ptr, ctx);
CHK_(ptr);
} else goto handle_unusual;
continue;
@ -227,9 +227,9 @@ bool Any::MergePartialFromCodedStream(
case 1: {
if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (10 & 0xFF)) {
DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
input, this->mutable_type_url()));
input, this->_internal_mutable_type_url()));
DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
this->type_url().data(), static_cast<int>(this->type_url().length()),
this->_internal_type_url().data(), static_cast<int>(this->_internal_type_url().length()),
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE,
"google.protobuf.Any.type_url"));
} else {
@ -242,7 +242,7 @@ bool Any::MergePartialFromCodedStream(
case 2: {
if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (18 & 0xFF)) {
DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadBytes(
input, this->mutable_value()));
input, this->_internal_mutable_value()));
} else {
goto handle_unusual;
}
@ -279,17 +279,17 @@ failure:
// string type_url = 1;
if (this->type_url().size() > 0) {
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
this->type_url().data(), static_cast<int>(this->type_url().length()),
this->_internal_type_url().data(), static_cast<int>(this->_internal_type_url().length()),
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Any.type_url");
target = stream->WriteStringMaybeAliased(
1, this->type_url(), target);
1, this->_internal_type_url(), target);
}
// bytes value = 2;
if (this->value().size() > 0) {
target = stream->WriteBytesMaybeAliased(
2, this->value(), target);
2, this->_internal_value(), target);
}
if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
@ -312,14 +312,14 @@ size_t Any::ByteSizeLong() const {
if (this->type_url().size() > 0) {
total_size += 1 +
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
this->type_url());
this->_internal_type_url());
}
// bytes value = 2;
if (this->value().size() > 0) {
total_size += 1 +
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize(
this->value());
this->_internal_value());
}
if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {

@ -206,6 +206,11 @@ class PROTOBUF_EXPORT Any :
std::string* mutable_type_url();
std::string* release_type_url();
void set_allocated_type_url(std::string* type_url);
private:
const std::string& _internal_type_url() const;
void _internal_set_type_url(const std::string& value);
std::string* _internal_mutable_type_url();
public:
// bytes value = 2;
void clear_value();
@ -217,6 +222,11 @@ class PROTOBUF_EXPORT Any :
std::string* mutable_value();
std::string* release_value();
void set_allocated_value(std::string* value);
private:
const std::string& _internal_value() const;
void _internal_set_value(const std::string& value);
std::string* _internal_mutable_value();
public:
// @@protoc_insertion_point(class_scope:google.protobuf.Any)
private:
@ -246,12 +256,22 @@ inline void Any::clear_type_url() {
}
inline const std::string& Any::type_url() const {
// @@protoc_insertion_point(field_get:google.protobuf.Any.type_url)
return type_url_.GetNoArena();
return _internal_type_url();
}
inline void Any::set_type_url(const std::string& value) {
_internal_set_type_url(value);
// @@protoc_insertion_point(field_set:google.protobuf.Any.type_url)
}
inline std::string* Any::mutable_type_url() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Any.type_url)
return _internal_mutable_type_url();
}
inline const std::string& Any::_internal_type_url() const {
return type_url_.GetNoArena();
}
inline void Any::_internal_set_type_url(const std::string& value) {
type_url_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value);
// @@protoc_insertion_point(field_set:google.protobuf.Any.type_url)
}
inline void Any::set_type_url(std::string&& value) {
@ -271,9 +291,8 @@ inline void Any::set_type_url(const char* value, size_t size) {
::std::string(reinterpret_cast<const char*>(value), size));
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.type_url)
}
inline std::string* Any::mutable_type_url() {
inline std::string* Any::_internal_mutable_type_url() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Any.type_url)
return type_url_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
}
inline std::string* Any::release_type_url() {
@ -297,12 +316,22 @@ inline void Any::clear_value() {
}
inline const std::string& Any::value() const {
// @@protoc_insertion_point(field_get:google.protobuf.Any.value)
return value_.GetNoArena();
return _internal_value();
}
inline void Any::set_value(const std::string& value) {
_internal_set_value(value);
// @@protoc_insertion_point(field_set:google.protobuf.Any.value)
}
inline std::string* Any::mutable_value() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Any.value)
return _internal_mutable_value();
}
inline const std::string& Any::_internal_value() const {
return value_.GetNoArena();
}
inline void Any::_internal_set_value(const std::string& value) {
value_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value);
// @@protoc_insertion_point(field_set:google.protobuf.Any.value)
}
inline void Any::set_value(std::string&& value) {
@ -322,9 +351,8 @@ inline void Any::set_value(const void* value, size_t size) {
::std::string(reinterpret_cast<const char*>(value), size));
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.value)
}
inline std::string* Any::mutable_value() {
inline std::string* Any::_internal_mutable_value() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Any.value)
return value_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
}
inline std::string* Any::release_value() {

@ -35,7 +35,6 @@
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace internal {

@ -33,7 +33,6 @@
#include <gtest/gtest.h>
namespace google {
namespace protobuf {
namespace {

@ -44,7 +44,7 @@ static void InitDefaultsscc_info_Api_google_2fprotobuf_2fapi_2eproto() {
}
PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<4> scc_info_Api_google_2fprotobuf_2fapi_2eproto =
{{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 4, InitDefaultsscc_info_Api_google_2fprotobuf_2fapi_2eproto}, {
{{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 4, 0, InitDefaultsscc_info_Api_google_2fprotobuf_2fapi_2eproto}, {
&scc_info_Method_google_2fprotobuf_2fapi_2eproto.base,
&scc_info_Option_google_2fprotobuf_2ftype_2eproto.base,
&scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto.base,
@ -62,7 +62,7 @@ static void InitDefaultsscc_info_Method_google_2fprotobuf_2fapi_2eproto() {
}
PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Method_google_2fprotobuf_2fapi_2eproto =
{{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsscc_info_Method_google_2fprotobuf_2fapi_2eproto}, {
{{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_Method_google_2fprotobuf_2fapi_2eproto}, {
&scc_info_Option_google_2fprotobuf_2ftype_2eproto.base,}};
static void InitDefaultsscc_info_Mixin_google_2fprotobuf_2fapi_2eproto() {
@ -77,7 +77,7 @@ static void InitDefaultsscc_info_Mixin_google_2fprotobuf_2fapi_2eproto() {
}
PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Mixin_google_2fprotobuf_2fapi_2eproto =
{{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsscc_info_Mixin_google_2fprotobuf_2fapi_2eproto}, {}};
{{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Mixin_google_2fprotobuf_2fapi_2eproto}, {}};
static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fapi_2eproto[3];
static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto = nullptr;
@ -208,11 +208,11 @@ Api::Api(const Api& from)
mixins_(from.mixins_) {
_internal_metadata_.MergeFrom(from._internal_metadata_);
name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
if (!from.name().empty()) {
if (!from._internal_name().empty()) {
name_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.name_);
}
version_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
if (!from.version().empty()) {
if (!from._internal_version().empty()) {
version_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.version_);
}
if (from.has_source_context()) {
@ -283,7 +283,7 @@ const char* Api::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::intern
// string name = 1;
case 1:
if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) {
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(mutable_name(), ptr, ctx, "google.protobuf.Api.name");
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(_internal_mutable_name(), ptr, ctx, "google.protobuf.Api.name");
CHK_(ptr);
} else goto handle_unusual;
continue;
@ -296,7 +296,7 @@ const char* Api::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::intern
ptr = ctx->ParseMessage(add_methods(), ptr);
CHK_(ptr);
if (!ctx->DataAvailable(ptr)) break;
} while (::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad<::PROTOBUF_NAMESPACE_ID::uint8>(ptr) == 18);
} while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr));
} else goto handle_unusual;
continue;
// repeated .google.protobuf.Option options = 3;
@ -308,13 +308,13 @@ const char* Api::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::intern
ptr = ctx->ParseMessage(add_options(), ptr);
CHK_(ptr);
if (!ctx->DataAvailable(ptr)) break;
} while (::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad<::PROTOBUF_NAMESPACE_ID::uint8>(ptr) == 26);
} while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr));
} else goto handle_unusual;
continue;
// string version = 4;
case 4:
if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) {
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(mutable_version(), ptr, ctx, "google.protobuf.Api.version");
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(_internal_mutable_version(), ptr, ctx, "google.protobuf.Api.version");
CHK_(ptr);
} else goto handle_unusual;
continue;
@ -334,7 +334,7 @@ const char* Api::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::intern
ptr = ctx->ParseMessage(add_mixins(), ptr);
CHK_(ptr);
if (!ctx->DataAvailable(ptr)) break;
} while (::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad<::PROTOBUF_NAMESPACE_ID::uint8>(ptr) == 50);
} while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<50>(ptr));
} else goto handle_unusual;
continue;
// .google.protobuf.Syntax syntax = 7;
@ -379,9 +379,9 @@ bool Api::MergePartialFromCodedStream(
case 1: {
if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (10 & 0xFF)) {
DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
input, this->mutable_name()));
input, this->_internal_mutable_name()));
DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), static_cast<int>(this->name().length()),
this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE,
"google.protobuf.Api.name"));
} else {
@ -416,9 +416,9 @@ bool Api::MergePartialFromCodedStream(
case 4: {
if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (34 & 0xFF)) {
DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
input, this->mutable_version()));
input, this->_internal_mutable_version()));
DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
this->version().data(), static_cast<int>(this->version().length()),
this->_internal_version().data(), static_cast<int>(this->_internal_version().length()),
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE,
"google.protobuf.Api.version"));
} else {
@ -493,24 +493,24 @@ failure:
// string name = 1;
if (this->name().size() > 0) {
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), static_cast<int>(this->name().length()),
this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Api.name");
target = stream->WriteStringMaybeAliased(
1, this->name(), target);
1, this->_internal_name(), target);
}
// repeated .google.protobuf.Method methods = 2;
for (auto it = this->methods().pointer_begin(),
end = this->methods().pointer_end(); it < end; ++it) {
for (auto it = this->methods_.pointer_begin(),
end = this->methods_.pointer_end(); it < end; ++it) {
stream->EnsureSpace(&target);
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
InternalWriteMessageToArray(2, **it, target, stream);
}
// repeated .google.protobuf.Option options = 3;
for (auto it = this->options().pointer_begin(),
end = this->options().pointer_end(); it < end; ++it) {
for (auto it = this->options_.pointer_begin(),
end = this->options_.pointer_end(); it < end; ++it) {
stream->EnsureSpace(&target);
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
InternalWriteMessageToArray(3, **it, target, stream);
@ -519,11 +519,11 @@ failure:
// string version = 4;
if (this->version().size() > 0) {
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
this->version().data(), static_cast<int>(this->version().length()),
this->_internal_version().data(), static_cast<int>(this->_internal_version().length()),
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Api.version");
target = stream->WriteStringMaybeAliased(
4, this->version(), target);
4, this->_internal_version(), target);
}
// .google.protobuf.SourceContext source_context = 5;
@ -535,8 +535,8 @@ failure:
}
// repeated .google.protobuf.Mixin mixins = 6;
for (auto it = this->mixins().pointer_begin(),
end = this->mixins().pointer_end(); it < end; ++it) {
for (auto it = this->mixins_.pointer_begin(),
end = this->mixins_.pointer_end(); it < end; ++it) {
stream->EnsureSpace(&target);
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
InternalWriteMessageToArray(6, **it, target, stream);
@ -566,50 +566,38 @@ size_t Api::ByteSizeLong() const {
(void) cached_has_bits;
// repeated .google.protobuf.Method methods = 2;
{
unsigned int count = static_cast<unsigned int>(this->methods_size());
total_size += 1UL * count;
for (unsigned int i = 0; i < count; i++) {
total_size += 1UL * this->methods_size();
for (const auto& msg : this->methods_) {
total_size +=
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
this->methods(static_cast<int>(i)));
}
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg);
}
// repeated .google.protobuf.Option options = 3;
{
unsigned int count = static_cast<unsigned int>(this->options_size());
total_size += 1UL * count;
for (unsigned int i = 0; i < count; i++) {
total_size += 1UL * this->options_size();
for (const auto& msg : this->options_) {
total_size +=
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
this->options(static_cast<int>(i)));
}
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg);
}
// repeated .google.protobuf.Mixin mixins = 6;
{
unsigned int count = static_cast<unsigned int>(this->mixins_size());
total_size += 1UL * count;
for (unsigned int i = 0; i < count; i++) {
total_size += 1UL * this->mixins_size();
for (const auto& msg : this->mixins_) {
total_size +=
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
this->mixins(static_cast<int>(i)));
}
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg);
}
// string name = 1;
if (this->name().size() > 0) {
total_size += 1 +
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
this->name());
this->_internal_name());
}
// string version = 4;
if (this->version().size() > 0) {
total_size += 1 +
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
this->version());
this->_internal_version());
}
// .google.protobuf.SourceContext source_context = 5;
@ -696,9 +684,9 @@ bool Api::IsInitialized() const {
void Api::InternalSwap(Api* other) {
using std::swap;
_internal_metadata_.Swap(&other->_internal_metadata_);
CastToBase(&methods_)->InternalSwap(CastToBase(&other->methods_));
CastToBase(&options_)->InternalSwap(CastToBase(&other->options_));
CastToBase(&mixins_)->InternalSwap(CastToBase(&other->mixins_));
methods_.InternalSwap(&other->methods_);
options_.InternalSwap(&other->options_);
mixins_.InternalSwap(&other->mixins_);
name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
GetArenaNoVirtual());
version_.Swap(&other->version_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
@ -734,15 +722,15 @@ Method::Method(const Method& from)
options_(from.options_) {
_internal_metadata_.MergeFrom(from._internal_metadata_);
name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
if (!from.name().empty()) {
if (!from._internal_name().empty()) {
name_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.name_);
}
request_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
if (!from.request_type_url().empty()) {
if (!from._internal_request_type_url().empty()) {
request_type_url_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.request_type_url_);
}
response_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
if (!from.response_type_url().empty()) {
if (!from._internal_response_type_url().empty()) {
response_type_url_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.response_type_url_);
}
::memcpy(&request_streaming_, &from.request_streaming_,
@ -808,14 +796,14 @@ const char* Method::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::int
// string name = 1;
case 1:
if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) {
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(mutable_name(), ptr, ctx, "google.protobuf.Method.name");
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(_internal_mutable_name(), ptr, ctx, "google.protobuf.Method.name");
CHK_(ptr);
} else goto handle_unusual;
continue;
// string request_type_url = 2;
case 2:
if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) {
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(mutable_request_type_url(), ptr, ctx, "google.protobuf.Method.request_type_url");
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(_internal_mutable_request_type_url(), ptr, ctx, "google.protobuf.Method.request_type_url");
CHK_(ptr);
} else goto handle_unusual;
continue;
@ -829,7 +817,7 @@ const char* Method::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::int
// string response_type_url = 4;
case 4:
if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) {
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(mutable_response_type_url(), ptr, ctx, "google.protobuf.Method.response_type_url");
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(_internal_mutable_response_type_url(), ptr, ctx, "google.protobuf.Method.response_type_url");
CHK_(ptr);
} else goto handle_unusual;
continue;
@ -849,7 +837,7 @@ const char* Method::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::int
ptr = ctx->ParseMessage(add_options(), ptr);
CHK_(ptr);
if (!ctx->DataAvailable(ptr)) break;
} while (::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad<::PROTOBUF_NAMESPACE_ID::uint8>(ptr) == 50);
} while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<50>(ptr));
} else goto handle_unusual;
continue;
// .google.protobuf.Syntax syntax = 7;
@ -894,9 +882,9 @@ bool Method::MergePartialFromCodedStream(
case 1: {
if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (10 & 0xFF)) {
DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
input, this->mutable_name()));
input, this->_internal_mutable_name()));
DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), static_cast<int>(this->name().length()),
this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE,
"google.protobuf.Method.name"));
} else {
@ -909,9 +897,9 @@ bool Method::MergePartialFromCodedStream(
case 2: {
if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (18 & 0xFF)) {
DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
input, this->mutable_request_type_url()));
input, this->_internal_mutable_request_type_url()));
DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
this->request_type_url().data(), static_cast<int>(this->request_type_url().length()),
this->_internal_request_type_url().data(), static_cast<int>(this->_internal_request_type_url().length()),
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE,
"google.protobuf.Method.request_type_url"));
} else {
@ -937,9 +925,9 @@ bool Method::MergePartialFromCodedStream(
case 4: {
if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (34 & 0xFF)) {
DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
input, this->mutable_response_type_url()));
input, this->_internal_mutable_response_type_url()));
DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
this->response_type_url().data(), static_cast<int>(this->response_type_url().length()),
this->_internal_response_type_url().data(), static_cast<int>(this->_internal_response_type_url().length()),
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE,
"google.protobuf.Method.response_type_url"));
} else {
@ -1016,21 +1004,21 @@ failure:
// string name = 1;
if (this->name().size() > 0) {
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), static_cast<int>(this->name().length()),
this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Method.name");
target = stream->WriteStringMaybeAliased(
1, this->name(), target);
1, this->_internal_name(), target);
}
// string request_type_url = 2;
if (this->request_type_url().size() > 0) {
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
this->request_type_url().data(), static_cast<int>(this->request_type_url().length()),
this->_internal_request_type_url().data(), static_cast<int>(this->_internal_request_type_url().length()),
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Method.request_type_url");
target = stream->WriteStringMaybeAliased(
2, this->request_type_url(), target);
2, this->_internal_request_type_url(), target);
}
// bool request_streaming = 3;
@ -1042,11 +1030,11 @@ failure:
// string response_type_url = 4;
if (this->response_type_url().size() > 0) {
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
this->response_type_url().data(), static_cast<int>(this->response_type_url().length()),
this->_internal_response_type_url().data(), static_cast<int>(this->_internal_response_type_url().length()),
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Method.response_type_url");
target = stream->WriteStringMaybeAliased(
4, this->response_type_url(), target);
4, this->_internal_response_type_url(), target);
}
// bool response_streaming = 5;
@ -1056,8 +1044,8 @@ failure:
}
// repeated .google.protobuf.Option options = 6;
for (auto it = this->options().pointer_begin(),
end = this->options().pointer_end(); it < end; ++it) {
for (auto it = this->options_.pointer_begin(),
end = this->options_.pointer_end(); it < end; ++it) {
stream->EnsureSpace(&target);
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
InternalWriteMessageToArray(6, **it, target, stream);
@ -1087,35 +1075,31 @@ size_t Method::ByteSizeLong() const {
(void) cached_has_bits;
// repeated .google.protobuf.Option options = 6;
{
unsigned int count = static_cast<unsigned int>(this->options_size());
total_size += 1UL * count;
for (unsigned int i = 0; i < count; i++) {
total_size += 1UL * this->options_size();
for (const auto& msg : this->options_) {
total_size +=
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
this->options(static_cast<int>(i)));
}
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg);
}
// string name = 1;
if (this->name().size() > 0) {
total_size += 1 +
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
this->name());
this->_internal_name());
}
// string request_type_url = 2;
if (this->request_type_url().size() > 0) {
total_size += 1 +
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
this->request_type_url());
this->_internal_request_type_url());
}
// string response_type_url = 4;
if (this->response_type_url().size() > 0) {
total_size += 1 +
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
this->response_type_url());
this->_internal_response_type_url());
}
// bool request_streaming = 3;
@ -1210,7 +1194,7 @@ bool Method::IsInitialized() const {
void Method::InternalSwap(Method* other) {
using std::swap;
_internal_metadata_.Swap(&other->_internal_metadata_);
CastToBase(&options_)->InternalSwap(CastToBase(&other->options_));
options_.InternalSwap(&other->options_);
name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
GetArenaNoVirtual());
request_type_url_.Swap(&other->request_type_url_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(),
@ -1245,11 +1229,11 @@ Mixin::Mixin(const Mixin& from)
_internal_metadata_(nullptr) {
_internal_metadata_.MergeFrom(from._internal_metadata_);
name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
if (!from.name().empty()) {
if (!from._internal_name().empty()) {
name_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.name_);
}
root_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
if (!from.root().empty()) {
if (!from._internal_root().empty()) {
root_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.root_);
}
// @@protoc_insertion_point(copy_constructor:google.protobuf.Mixin)
@ -1302,14 +1286,14 @@ const char* Mixin::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::inte
// string name = 1;
case 1:
if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) {
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(mutable_name(), ptr, ctx, "google.protobuf.Mixin.name");
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(_internal_mutable_name(), ptr, ctx, "google.protobuf.Mixin.name");
CHK_(ptr);
} else goto handle_unusual;
continue;
// string root = 2;
case 2:
if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) {
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(mutable_root(), ptr, ctx, "google.protobuf.Mixin.root");
ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(_internal_mutable_root(), ptr, ctx, "google.protobuf.Mixin.root");
CHK_(ptr);
} else goto handle_unusual;
continue;
@ -1347,9 +1331,9 @@ bool Mixin::MergePartialFromCodedStream(
case 1: {
if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (10 & 0xFF)) {
DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
input, this->mutable_name()));
input, this->_internal_mutable_name()));
DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), static_cast<int>(this->name().length()),
this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE,
"google.protobuf.Mixin.name"));
} else {
@ -1362,9 +1346,9 @@ bool Mixin::MergePartialFromCodedStream(
case 2: {
if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (18 & 0xFF)) {
DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString(
input, this->mutable_root()));
input, this->_internal_mutable_root()));
DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
this->root().data(), static_cast<int>(this->root().length()),
this->_internal_root().data(), static_cast<int>(this->_internal_root().length()),
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE,
"google.protobuf.Mixin.root"));
} else {
@ -1403,21 +1387,21 @@ failure:
// string name = 1;
if (this->name().size() > 0) {
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
this->name().data(), static_cast<int>(this->name().length()),
this->_internal_name().data(), static_cast<int>(this->_internal_name().length()),
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Mixin.name");
target = stream->WriteStringMaybeAliased(
1, this->name(), target);
1, this->_internal_name(), target);
}
// string root = 2;
if (this->root().size() > 0) {
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
this->root().data(), static_cast<int>(this->root().length()),
this->_internal_root().data(), static_cast<int>(this->_internal_root().length()),
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
"google.protobuf.Mixin.root");
target = stream->WriteStringMaybeAliased(
2, this->root(), target);
2, this->_internal_root(), target);
}
if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
@ -1440,14 +1424,14 @@ size_t Mixin::ByteSizeLong() const {
if (this->name().size() > 0) {
total_size += 1 +
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
this->name());
this->_internal_name());
}
// string root = 2;
if (this->root().size() > 0) {
total_size += 1 +
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
this->root());
this->_internal_root());
}
if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {

@ -238,6 +238,11 @@ class PROTOBUF_EXPORT Api :
std::string* mutable_name();
std::string* release_name();
void set_allocated_name(std::string* name);
private:
const std::string& _internal_name() const;
void _internal_set_name(const std::string& value);
std::string* _internal_mutable_name();
public:
// string version = 4;
void clear_version();
@ -249,9 +254,17 @@ class PROTOBUF_EXPORT Api :
std::string* mutable_version();
std::string* release_version();
void set_allocated_version(std::string* version);
private:
const std::string& _internal_version() const;
void _internal_set_version(const std::string& value);
std::string* _internal_mutable_version();
public:
// .google.protobuf.SourceContext source_context = 5;
bool has_source_context() const;
private:
bool _internal_has_source_context() const;
public:
void clear_source_context();
const PROTOBUF_NAMESPACE_ID::SourceContext& source_context() const;
PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context();
@ -420,6 +433,11 @@ class PROTOBUF_EXPORT Method :
std::string* mutable_name();
std::string* release_name();
void set_allocated_name(std::string* name);
private:
const std::string& _internal_name() const;
void _internal_set_name(const std::string& value);
std::string* _internal_mutable_name();
public:
// string request_type_url = 2;
void clear_request_type_url();
@ -431,6 +449,11 @@ class PROTOBUF_EXPORT Method :
std::string* mutable_request_type_url();
std::string* release_request_type_url();
void set_allocated_request_type_url(std::string* request_type_url);
private:
const std::string& _internal_request_type_url() const;
void _internal_set_request_type_url(const std::string& value);
std::string* _internal_mutable_request_type_url();
public:
// string response_type_url = 4;
void clear_response_type_url();
@ -442,6 +465,11 @@ class PROTOBUF_EXPORT Method :
std::string* mutable_response_type_url();
std::string* release_response_type_url();
void set_allocated_response_type_url(std::string* response_type_url);
private:
const std::string& _internal_response_type_url() const;
void _internal_set_response_type_url(const std::string& value);
std::string* _internal_mutable_response_type_url();
public:
// bool request_streaming = 3;
void clear_request_streaming();
@ -599,6 +627,11 @@ class PROTOBUF_EXPORT Mixin :
std::string* mutable_name();
std::string* release_name();
void set_allocated_name(std::string* name);
private:
const std::string& _internal_name() const;
void _internal_set_name(const std::string& value);
std::string* _internal_mutable_name();
public:
// string root = 2;
void clear_root();
@ -610,6 +643,11 @@ class PROTOBUF_EXPORT Mixin :
std::string* mutable_root();
std::string* release_root();
void set_allocated_root(std::string* root);
private:
const std::string& _internal_root() const;
void _internal_set_root(const std::string& value);
std::string* _internal_mutable_root();
public:
// @@protoc_insertion_point(class_scope:google.protobuf.Mixin)
private:
@ -638,12 +676,22 @@ inline void Api::clear_name() {
}
inline const std::string& Api::name() const {
// @@protoc_insertion_point(field_get:google.protobuf.Api.name)
return name_.GetNoArena();
return _internal_name();
}
inline void Api::set_name(const std::string& value) {
_internal_set_name(value);
// @@protoc_insertion_point(field_set:google.protobuf.Api.name)
}
inline std::string* Api::mutable_name() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Api.name)
return _internal_mutable_name();
}
inline const std::string& Api::_internal_name() const {
return name_.GetNoArena();
}
inline void Api::_internal_set_name(const std::string& value) {
name_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value);
// @@protoc_insertion_point(field_set:google.protobuf.Api.name)
}
inline void Api::set_name(std::string&& value) {
@ -663,9 +711,8 @@ inline void Api::set_name(const char* value, size_t size) {
::std::string(reinterpret_cast<const char*>(value), size));
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Api.name)
}
inline std::string* Api::mutable_name() {
inline std::string* Api::_internal_mutable_name() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Api.name)
return name_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
}
inline std::string* Api::release_name() {
@ -746,12 +793,22 @@ inline void Api::clear_version() {
}
inline const std::string& Api::version() const {
// @@protoc_insertion_point(field_get:google.protobuf.Api.version)
return version_.GetNoArena();
return _internal_version();
}
inline void Api::set_version(const std::string& value) {
_internal_set_version(value);
// @@protoc_insertion_point(field_set:google.protobuf.Api.version)
}
inline std::string* Api::mutable_version() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Api.version)
return _internal_mutable_version();
}
inline const std::string& Api::_internal_version() const {
return version_.GetNoArena();
}
inline void Api::_internal_set_version(const std::string& value) {
version_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value);
// @@protoc_insertion_point(field_set:google.protobuf.Api.version)
}
inline void Api::set_version(std::string&& value) {
@ -771,9 +828,8 @@ inline void Api::set_version(const char* value, size_t size) {
::std::string(reinterpret_cast<const char*>(value), size));
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Api.version)
}
inline std::string* Api::mutable_version() {
inline std::string* Api::_internal_mutable_version() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Api.version)
return version_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
}
inline std::string* Api::release_version() {
@ -890,12 +946,22 @@ inline void Method::clear_name() {
}
inline const std::string& Method::name() const {
// @@protoc_insertion_point(field_get:google.protobuf.Method.name)
return name_.GetNoArena();
return _internal_name();
}
inline void Method::set_name(const std::string& value) {
_internal_set_name(value);
// @@protoc_insertion_point(field_set:google.protobuf.Method.name)
}
inline std::string* Method::mutable_name() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Method.name)
return _internal_mutable_name();
}
inline const std::string& Method::_internal_name() const {
return name_.GetNoArena();
}
inline void Method::_internal_set_name(const std::string& value) {
name_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value);
// @@protoc_insertion_point(field_set:google.protobuf.Method.name)
}
inline void Method::set_name(std::string&& value) {
@ -915,9 +981,8 @@ inline void Method::set_name(const char* value, size_t size) {
::std::string(reinterpret_cast<const char*>(value), size));
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.name)
}
inline std::string* Method::mutable_name() {
inline std::string* Method::_internal_mutable_name() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Method.name)
return name_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
}
inline std::string* Method::release_name() {
@ -941,12 +1006,22 @@ inline void Method::clear_request_type_url() {
}
inline const std::string& Method::request_type_url() const {
// @@protoc_insertion_point(field_get:google.protobuf.Method.request_type_url)
return request_type_url_.GetNoArena();
return _internal_request_type_url();
}
inline void Method::set_request_type_url(const std::string& value) {
_internal_set_request_type_url(value);
// @@protoc_insertion_point(field_set:google.protobuf.Method.request_type_url)
}
inline std::string* Method::mutable_request_type_url() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Method.request_type_url)
return _internal_mutable_request_type_url();
}
inline const std::string& Method::_internal_request_type_url() const {
return request_type_url_.GetNoArena();
}
inline void Method::_internal_set_request_type_url(const std::string& value) {
request_type_url_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value);
// @@protoc_insertion_point(field_set:google.protobuf.Method.request_type_url)
}
inline void Method::set_request_type_url(std::string&& value) {
@ -966,9 +1041,8 @@ inline void Method::set_request_type_url(const char* value, size_t size) {
::std::string(reinterpret_cast<const char*>(value), size));
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.request_type_url)
}
inline std::string* Method::mutable_request_type_url() {
inline std::string* Method::_internal_mutable_request_type_url() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Method.request_type_url)
return request_type_url_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
}
inline std::string* Method::release_request_type_url() {
@ -1006,12 +1080,22 @@ inline void Method::clear_response_type_url() {
}
inline const std::string& Method::response_type_url() const {
// @@protoc_insertion_point(field_get:google.protobuf.Method.response_type_url)
return response_type_url_.GetNoArena();
return _internal_response_type_url();
}
inline void Method::set_response_type_url(const std::string& value) {
_internal_set_response_type_url(value);
// @@protoc_insertion_point(field_set:google.protobuf.Method.response_type_url)
}
inline std::string* Method::mutable_response_type_url() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Method.response_type_url)
return _internal_mutable_response_type_url();
}
inline const std::string& Method::_internal_response_type_url() const {
return response_type_url_.GetNoArena();
}
inline void Method::_internal_set_response_type_url(const std::string& value) {
response_type_url_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value);
// @@protoc_insertion_point(field_set:google.protobuf.Method.response_type_url)
}
inline void Method::set_response_type_url(std::string&& value) {
@ -1031,9 +1115,8 @@ inline void Method::set_response_type_url(const char* value, size_t size) {
::std::string(reinterpret_cast<const char*>(value), size));
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.response_type_url)
}
inline std::string* Method::mutable_response_type_url() {
inline std::string* Method::_internal_mutable_response_type_url() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Method.response_type_url)
return response_type_url_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
}
inline std::string* Method::release_response_type_url() {
@ -1116,12 +1199,22 @@ inline void Mixin::clear_name() {
}
inline const std::string& Mixin::name() const {
// @@protoc_insertion_point(field_get:google.protobuf.Mixin.name)
return name_.GetNoArena();
return _internal_name();
}
inline void Mixin::set_name(const std::string& value) {
_internal_set_name(value);
// @@protoc_insertion_point(field_set:google.protobuf.Mixin.name)
}
inline std::string* Mixin::mutable_name() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.name)
return _internal_mutable_name();
}
inline const std::string& Mixin::_internal_name() const {
return name_.GetNoArena();
}
inline void Mixin::_internal_set_name(const std::string& value) {
name_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value);
// @@protoc_insertion_point(field_set:google.protobuf.Mixin.name)
}
inline void Mixin::set_name(std::string&& value) {
@ -1141,9 +1234,8 @@ inline void Mixin::set_name(const char* value, size_t size) {
::std::string(reinterpret_cast<const char*>(value), size));
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Mixin.name)
}
inline std::string* Mixin::mutable_name() {
inline std::string* Mixin::_internal_mutable_name() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.name)
return name_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
}
inline std::string* Mixin::release_name() {
@ -1167,12 +1259,22 @@ inline void Mixin::clear_root() {
}
inline const std::string& Mixin::root() const {
// @@protoc_insertion_point(field_get:google.protobuf.Mixin.root)
return root_.GetNoArena();
return _internal_root();
}
inline void Mixin::set_root(const std::string& value) {
_internal_set_root(value);
// @@protoc_insertion_point(field_set:google.protobuf.Mixin.root)
}
inline std::string* Mixin::mutable_root() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.root)
return _internal_mutable_root();
}
inline const std::string& Mixin::_internal_root() const {
return root_.GetNoArena();
}
inline void Mixin::_internal_set_root(const std::string& value) {
root_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value);
// @@protoc_insertion_point(field_set:google.protobuf.Mixin.root)
}
inline void Mixin::set_root(std::string&& value) {
@ -1192,9 +1294,8 @@ inline void Mixin::set_root(const char* value, size_t size) {
::std::string(reinterpret_cast<const char*>(value), size));
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Mixin.root)
}
inline std::string* Mixin::mutable_root() {
inline std::string* Mixin::_internal_mutable_root() {
// @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.root)
return root_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
}
inline std::string* Mixin::release_root() {

@ -50,9 +50,9 @@ using type_info = ::type_info;
#include <typeinfo>
#endif
#include <google/protobuf/port.h>
#include <type_traits>
#include <google/protobuf/arena_impl.h>
#include <google/protobuf/port.h>
#include <google/protobuf/port_def.inc>

@ -70,7 +70,6 @@
#include <google/protobuf/compiler/plugin.pb.h>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/io/io_win32.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
@ -79,8 +78,7 @@
#include <google/protobuf/text_format.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/io/io_win32.h>
#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/stubs/stl_util.h>

@ -45,22 +45,21 @@
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/testing/file.h>
#include <google/protobuf/testing/file.h>
#include <google/protobuf/testing/file.h>
#include <google/protobuf/compiler/mock_code_generator.h>
#include <google/protobuf/compiler/subprocess.h>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/compiler/command_line_interface.h>
#include <google/protobuf/test_util2.h>
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/io/io_win32.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/testing/file.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
#include <google/protobuf/io/io_win32.h>
#include <google/protobuf/stubs/strutil.h>

@ -39,8 +39,6 @@
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {

@ -38,7 +38,6 @@
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
#include <google/protobuf/compiler/cpp/cpp_string_field.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/cpp/cpp_enum_field.h>

@ -51,8 +51,6 @@
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/port_def.inc>
namespace google {
@ -440,17 +438,22 @@ void FileGenerator::GenerateSourceIncludes(io::Printer* printer) {
void FileGenerator::GenerateSourceDefaultInstance(int idx,
io::Printer* printer) {
Formatter format(printer, variables_);
MessageGenerator* generator = message_generators_[idx].get();
format(
"class $1$ {\n"
" public:\n"
" ::$proto_ns$::internal::ExplicitlyConstructed<$2$> _instance;\n",
DefaultInstanceType(message_generators_[idx]->descriptor_, options_),
message_generators_[idx]->classname_);
DefaultInstanceType(generator->descriptor_, options_),
generator->classname_);
format.Indent();
message_generators_[idx]->GenerateExtraDefaultFields(printer);
generator->GenerateExtraDefaultFields(printer);
format.Outdent();
format("} $1$;\n",
DefaultInstanceName(message_generators_[idx]->descriptor_, options_));
format("} $1$;\n", DefaultInstanceName(generator->descriptor_, options_));
if (options_.lite_implicit_weak_fields) {
format("$1$DefaultTypeInternal* $2$ = &$3$;\n", generator->classname_,
DefaultInstancePtr(generator->descriptor_, options_),
DefaultInstanceName(generator->descriptor_, options_));
}
}
// A list of things defined in one .pb.cc file that we need to reference from
@ -513,21 +516,45 @@ void FileGenerator::GenerateInternalForwardDeclarations(
}
for (auto scc : Sorted(refs.weak_sccs)) {
// We do things a little bit differently for proto1-style weak fields versus
// lite implicit weak fields, even though they are trying to accomplish
// similar things. We need to support implicit weak fields on iOS, and the
// Apple linker only supports weak definitions, not weak declarations. For
// that reason we need a pointer type which we can weakly define to be null.
// However, code size considerations prevent us from using the same approach
// for proto1-style weak fields.
if (options_.lite_implicit_weak_fields) {
format("extern ::$proto_ns$::internal::SCCInfo<$1$> $2$;\n",
scc->children.size(), SccInfoSymbol(scc, options_));
format(
"__attribute__((weak)) ::$proto_ns$::internal::SCCInfo<$1$>*\n"
" $2$ = nullptr;\n",
scc->children.size(), SccInfoPtrSymbol(scc, options_));
} else {
format(
"extern __attribute__((weak)) ::$proto_ns$::internal::SCCInfo<$1$> "
"$2$;\n",
scc->children.size(), SccInfoSymbol(scc, options_));
}
}
{
NamespaceOpener ns(format);
for (auto instance : Sorted(refs.weak_default_instances)) {
ns.ChangeTo(Namespace(instance, options_));
if (options_.lite_implicit_weak_fields) {
format("extern $1$ $2$;\n", DefaultInstanceType(instance, options_),
DefaultInstanceName(instance, options_));
format("__attribute__((weak)) $1$* $2$ = nullptr;\n",
DefaultInstanceType(instance, options_),
DefaultInstancePtr(instance, options_));
} else {
format("extern __attribute__((weak)) $1$ $2$;\n",
DefaultInstanceType(instance, options_),
DefaultInstanceName(instance, options_));
}
}
}
for (auto file : Sorted(refs.weak_reflection_files)) {
format(
@ -555,7 +582,8 @@ void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* printer) {
GenerateInternalForwardDeclarations(refs, printer);
if (IsSCCRepresentative(message_generators_[idx]->descriptor_)) {
GenerateInitForSCC(GetSCC(message_generators_[idx]->descriptor_), printer);
GenerateInitForSCC(GetSCC(message_generators_[idx]->descriptor_), refs,
printer);
}
{ // package namespace
@ -649,7 +677,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
// Now generate the InitDefaults for each SCC.
for (auto scc : sccs_) {
GenerateInitForSCC(scc, printer);
GenerateInitForSCC(scc, refs, printer);
}
if (HasDescriptorMethods(file_, options_)) {
@ -904,7 +932,9 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) {
}
}
void FileGenerator::GenerateInitForSCC(const SCC* scc, io::Printer* printer) {
void FileGenerator::GenerateInitForSCC(const SCC* scc,
const CrossFileReferences& refs,
io::Printer* printer) {
Formatter format(printer, variables_);
// We use static and not anonymous namespace because symbol names are
// substantially shorter.
@ -954,17 +984,46 @@ void FileGenerator::GenerateInitForSCC(const SCC* scc, io::Printer* printer) {
format.Outdent();
format("}\n\n");
// If we are using lite implicit weak fields then we need to distinguish
// between regular SCC dependencies and ones that we need to reference weakly
// through an extra pointer indirection.
std::vector<const SCC*> regular_sccs;
std::vector<const SCC*> implicit_weak_sccs;
for (const SCC* child : scc->children) {
if (options_.lite_implicit_weak_fields &&
refs.weak_sccs.find(child) != refs.weak_sccs.end()) {
implicit_weak_sccs.push_back(child);
} else {
regular_sccs.push_back(child);
}
}
format(
"$dllexport_decl $::$proto_ns$::internal::SCCInfo<$1$> $2$ =\n"
" "
"{{ATOMIC_VAR_INIT(::$proto_ns$::internal::SCCInfoBase::kUninitialized), "
"$1$, InitDefaults$2$}, {",
"$3$, $4$, InitDefaults$2$}, {",
scc->children.size(), // 1
SccInfoSymbol(scc, options_));
for (const SCC* child : scc->children) {
SccInfoSymbol(scc, options_), regular_sccs.size(),
implicit_weak_sccs.size());
for (const SCC* child : regular_sccs) {
format("\n &$1$.base,", SccInfoSymbol(child, options_));
}
for (const SCC* child : implicit_weak_sccs) {
format(
"\n reinterpret_cast<::$proto_ns$::internal::SCCInfoBase**>("
"\n &$1$),",
SccInfoPtrSymbol(child, options_));
}
format("}};\n\n");
if (options_.lite_implicit_weak_fields) {
format(
"$dllexport_decl $::$proto_ns$::internal::SCCInfo<$1$>*\n"
" $2$ = &$3$;\n\n",
scc->children.size(), SccInfoPtrSymbol(scc, options_),
SccInfoSymbol(scc, options_));
}
}
void FileGenerator::GenerateTables(io::Printer* printer) {

@ -113,7 +113,8 @@ class FileGenerator {
void GenerateSourceIncludes(io::Printer* printer);
void GenerateSourceDefaultInstance(int idx, io::Printer* printer);
void GenerateInitForSCC(const SCC* scc, io::Printer* printer);
void GenerateInitForSCC(const SCC* scc, const CrossFileReferences& refs,
io::Printer* printer);
void GenerateTables(io::Printer* printer);
void GenerateReflectionInitializationCode(io::Printer* printer);

@ -45,8 +45,6 @@
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
namespace google {
namespace protobuf {
namespace compiler {

@ -44,7 +44,6 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/compiler/scc.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
@ -52,8 +51,6 @@
#include <google/protobuf/wire_format_lite.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/stubs/hash.h>
#include <google/protobuf/port_def.inc>
@ -204,6 +201,10 @@ void SetIntVar(const Options& options, const std::string& type,
(*variables)[type] = IntTypeName(options, type);
}
bool HasInternalAccessors(const FieldOptions::CType ctype) {
return ctype == FieldOptions::STRING;
}
} // namespace
void SetCommonVars(const Options& options,
@ -373,12 +374,22 @@ std::string DefaultInstanceName(const Descriptor* descriptor,
return "_" + ClassName(descriptor, false) + "_default_instance_";
}
std::string DefaultInstancePtr(const Descriptor* descriptor,
const Options& options) {
return DefaultInstanceName(descriptor, options) + "ptr_";
}
std::string QualifiedDefaultInstanceName(const Descriptor* descriptor,
const Options& options) {
return QualifiedFileLevelSymbol(
descriptor->file(), DefaultInstanceName(descriptor, options), options);
}
std::string QualifiedDefaultInstancePtr(const Descriptor* descriptor,
const Options& options) {
return QualifiedDefaultInstanceName(descriptor, options) + "ptr_";
}
std::string DescriptorTableName(const FileDescriptor* file,
const Options& options) {
return UniqueName("descriptor_table", file, options);
@ -1125,7 +1136,7 @@ bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options,
MessageSCCAnalyzer* scc_analyzer) {
return UsingImplicitWeakFields(field->file(), options) &&
field->type() == FieldDescriptor::TYPE_MESSAGE &&
!field->is_required() && !field->is_map() &&
!field->is_required() && !field->is_map() && !field->is_extension() &&
field->containing_oneof() == nullptr &&
!IsWellKnownMessage(field->message_type()->file()) &&
field->message_type()->file()->name() !=
@ -1479,7 +1490,8 @@ class ParseLoopGenerator {
name = "StringPieceParser" + utf8;
break;
}
format_("ptr = $pi_ns$::Inline$1$($2$_$3$(), ptr, ctx$4$);\n", name,
format_("ptr = $pi_ns$::Inline$1$($2$$3$_$4$(), ptr, ctx$5$);\n", name,
HasInternalAccessors(ctype) ? "_internal_" : "",
field->is_repeated() && !field->is_packable() ? "add" : "mutable",
FieldName(field), field_name);
}
@ -1551,10 +1563,9 @@ class ParseLoopGenerator {
FieldName(field));
} else {
format_(
"ptr = ctx->ParseMessage("
"CastToBase(&$1$_)->AddWeak(reinterpret_cast<const "
"::$proto_ns$::MessageLite*>(&$2$::_$3$_default_instance_)), "
"ptr);\n",
"ptr = ctx->ParseMessage($1$_.AddWeak(reinterpret_cast<const "
"::$proto_ns$::MessageLite*>($2$::_$3$_default_instance_ptr_)"
"), ptr);\n",
FieldName(field), Namespace(field->message_type(), options_),
ClassName(field->message_type()));
}
@ -1757,12 +1768,11 @@ class ParseLoopGenerator {
}
GenerateFieldBody(wiretype, field);
if (is_repeat) {
string type = tag_size == 2 ? "uint16" : "uint8";
format_.Outdent();
format_(
" if (!ctx->DataAvailable(ptr)) break;\n"
"} while ($pi_ns$::UnalignedLoad<$1$>(ptr) == $2$);\n",
IntTypeName(options_, type), SmallVarintValue(tag));
"} while ($pi_ns$::ExpectTag<$1$>(ptr));\n",
tag);
}
format_.Outdent();
if (fallback_tag) {

@ -49,7 +49,6 @@
#include <google/protobuf/port.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/port_def.inc>
namespace google {
@ -133,10 +132,19 @@ std::string DefaultInstanceType(const Descriptor* descriptor,
std::string DefaultInstanceName(const Descriptor* descriptor,
const Options& options);
// Non-qualified name of the default instance pointer. This is used only for
// implicit weak fields, where we need an extra indirection.
std::string DefaultInstancePtr(const Descriptor* descriptor,
const Options& options);
// Fully qualified name of the default_instance of this message.
std::string QualifiedDefaultInstanceName(const Descriptor* descriptor,
const Options& options);
// Fully qualified name of the default instance pointer.
std::string QualifiedDefaultInstancePtr(const Descriptor* descriptor,
const Options& options);
// DescriptorTable variable name.
std::string DescriptorTableName(const FileDescriptor* file,
const Options& options);
@ -549,6 +557,11 @@ inline std::string SccInfoSymbol(const SCC* scc, const Options& options) {
scc->GetRepresentative(), options);
}
inline std::string SccInfoPtrSymbol(const SCC* scc, const Options& options) {
return UniqueName("scc_info_ptr_" + ClassName(scc->GetRepresentative()),
scc->GetRepresentative(), options);
}
void ListAllFields(const Descriptor* d,
std::vector<const FieldDescriptor*>* fields);
void ListAllFields(const FileDescriptor* d,

@ -55,8 +55,6 @@
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/stubs/hash.h>
@ -738,7 +736,12 @@ void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) {
if (field->is_repeated()) {
format("$deprecated_attr$int ${1$$name$_size$}$() const;\n", field);
} else if (HasHasMethod(field)) {
format("$deprecated_attr$bool ${1$has_$name$$}$() const;\n", field);
format(
"$deprecated_attr$bool ${1$has_$name$$}$() const;\n"
"private:\n"
"bool _internal_has_$name$() const;\n"
"public:\n",
field);
} else if (HasPrivateHasMethod(field)) {
format(
"private:\n"
@ -800,9 +803,12 @@ void MessageGenerator::GenerateSingularFieldHasBits(
format.Set("has_mask",
strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
format(
"inline bool $classname$::_internal_has_$name$() const {\n"
" return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n"
"}\n"
"inline bool $classname$::has_$name$() const {\n"
"$annotate_accessor$"
" return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n"
" return _internal_has_$name$();\n"
"}\n");
} else {
// Message fields have a has_$name$() method.
@ -849,13 +855,28 @@ void MessageGenerator::GenerateOneofMemberHasBits(const FieldDescriptor* field,
// Oneofs also have has_$name$() but only as a private helper
// method, so that generated code is slightly cleaner (vs. comparing
// _oneof_case_[index] against a constant everywhere).
//
// If has_$name$() is private, there is no need to add an internal accessor.
// Only annotate public accessors.
if (HasPrivateHasMethod(field)) {
format(
"inline bool $classname$::has_$name$() const {\n"
"$annotate_accessor$"
" return $oneof_name$_case() == k$field_name$;\n"
"}\n");
} else {
format(
"inline bool $classname$::_internal_has_$name$() const {\n"
" return $oneof_name$_case() == k$field_name$;\n"
"}\n"
"inline void $classname$::set_has_$name$() {\n"
"inline bool $classname$::has_$name$() const {\n"
"$annotate_accessor$"
" return _internal_has_$name$();\n"
"}\n");
}
// set_has_$name$() for oneof fields is always private; hence should not be
// annotated.
format(
"inline void $classname$::set_has_$name$() {\n"
" _oneof_case_[$oneof_index$] = k$field_name$;\n"
"}\n");
}
@ -918,8 +939,12 @@ void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* printer) {
format(
"inline int $classname$::$name$_size() const {\n"
"$annotate_accessor$"
" return $name$_.size();\n"
"}\n");
" return $name$_$1$.size();\n"
"}\n",
IsImplicitWeakField(field, options_, scc_analyzer_) &&
field->message_type()
? ".weak"
: "");
} else if (field->containing_oneof()) {
format.Set("field_name", UnderscoresToCamelCase(field->name(), true));
format.Set("oneof_name", field->containing_oneof()->name());
@ -1943,10 +1968,18 @@ void MessageGenerator::GenerateDefaultInstanceInitializer(
options_)); // 1
continue;
}
if (IsImplicitWeakField(field, options_, scc_analyzer_)) {
format(
"$package_ns$::$name$_ = reinterpret_cast<$1$*>(\n"
" $2$);\n",
FieldMessageTypeName(field, options_),
QualifiedDefaultInstancePtr(field->message_type(), options_));
} else {
format(
"$package_ns$::$name$_ = const_cast< $1$*>(\n"
" $1$::internal_default_instance());\n",
FieldMessageTypeName(field, options_));
}
} else if (field->containing_oneof() &&
HasDescriptorMethods(descriptor_->file(), options_)) {
field_generators_.get(field).GenerateConstructorCode(printer);
@ -4295,7 +4328,9 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
if (field->is_repeated()) {
if (IsImplicitWeakField(field, options_, scc_analyzer_)) {
format(
"if (!::$proto_ns$::internal::AllAreInitializedWeak(this->$1$_))"
"if "
"(!::$proto_ns$::internal::AllAreInitializedWeak(this->$1$_.weak)"
")"
" return false;\n",
FieldName(field));
} else {

@ -62,6 +62,8 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
(*variables)["type"] + "*", (*variables)["name"] + "_", implicit_weak);
(*variables)["type_default_instance"] =
QualifiedDefaultInstanceName(descriptor->message_type(), options);
(*variables)["type_default_instance_ptr"] =
QualifiedDefaultInstancePtr(descriptor->message_type(), options);
(*variables)["type_reference_function"] =
implicit_weak
? (" " + ReferenceFunctionName(descriptor->message_type(), options) +
@ -149,47 +151,40 @@ void MessageFieldGenerator::GenerateInlineAccessorDefinitions(
format(
"inline const $type$& $classname$::$name$() const {\n"
"$annotate_accessor$"
"$type_reference_function$"
" const $type$* p = $casted_member$;\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return p != nullptr ? *p : *reinterpret_cast<const $type$*>(\n"
" &$type_default_instance$);\n"
"}\n");
format(
"inline $type$* $classname$::$release_name$() {\n"
"$annotate_accessor$"
" // @@protoc_insertion_point(field_release:$full_name$)\n"
"$type_reference_function$"
" $clear_hasbit$\n"
" $type$* temp = $casted_member$;\n");
if (SupportsArenas(descriptor_)) {
format(
"inline $type$* $classname$::$release_name$() {\n"
" auto temp = unsafe_arena_release_$name$();\n"
" if (GetArenaNoVirtual() != nullptr) {\n"
" temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n"
" }\n");
}
format(
" $name$_ = nullptr;\n"
" }\n"
" return temp;\n"
"}\n");
if (SupportsArenas(descriptor_)) {
"}\n"
"inline $type$* $classname$::unsafe_arena_release_$name$() {\n");
} else {
format("inline $type$* $classname$::$release_name$() {\n");
}
format(
"inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
"$annotate_accessor$"
" // "
"@@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
" // @@protoc_insertion_point(field_release:$full_name$)\n"
"$type_reference_function$"
" $clear_hasbit$\n"
" $type$* temp = $casted_member$;\n"
" $name$_ = nullptr;\n"
" return temp;\n"
"}\n");
}
format(
"inline $type$* $classname$::mutable_$name$() {\n"
"$annotate_accessor$"
"$type_reference_function$"
" $set_hasbit$\n"
" if ($name$_ == nullptr) {\n"
" auto* p = CreateMaybeMessage<$type$>(GetArenaNoVirtual());\n");
@ -283,9 +278,9 @@ void MessageFieldGenerator::GenerateInternalAccessorDefinitions(
" const $classname$* msg) {\n"
" if (msg->$name$_ != nullptr) {\n"
" return *msg->$name$_;\n"
" } else if (&$type_default_instance$ != nullptr) {\n"
" } else if ($type_default_instance_ptr$ != nullptr) {\n"
" return *reinterpret_cast<const ::$proto_ns$::MessageLite*>(\n"
" &$type_default_instance$);\n"
" $type_default_instance_ptr$);\n"
" } else {\n"
" return "
"*::$proto_ns$::internal::ImplicitWeakMessage::default_instance();\n"
@ -300,14 +295,14 @@ void MessageFieldGenerator::GenerateInternalAccessorDefinitions(
}
format(
" if (msg->$name$_ == nullptr) {\n"
" if (&$type_default_instance$ == nullptr) {\n"
" if ($type_default_instance_ptr$ == nullptr) {\n"
" msg->$name$_ = ::$proto_ns$::Arena::CreateMessage<\n"
" ::$proto_ns$::internal::ImplicitWeakMessage>(\n"
" msg->GetArenaNoVirtual());\n"
" } else {\n"
" msg->$name$_ = reinterpret_cast<const "
"::$proto_ns$::MessageLite*>(\n"
" &$type_default_instance$)->New("
" $type_default_instance_ptr$)->New("
"msg->GetArenaNoVirtual());\n"
" }\n"
" }\n"
@ -322,13 +317,13 @@ void MessageFieldGenerator::GenerateInternalAccessorDefinitions(
}
format(
" if (msg->$name$_ == nullptr) {\n"
" if (&$type_default_instance$ == nullptr) {\n"
" if ($type_default_instance_ptr$ == nullptr) {\n"
" msg->$name$_ = "
"new ::$proto_ns$::internal::ImplicitWeakMessage;\n"
" } else {\n"
" msg->$name$_ = "
"reinterpret_cast<const ::$proto_ns$::MessageLite*>(\n"
" &$type_default_instance$)->New();\n"
" $type_default_instance_ptr$)->New();\n"
" }\n"
" }\n"
" return msg->$name$_;\n"
@ -637,7 +632,11 @@ RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
void RepeatedMessageFieldGenerator::GeneratePrivateMembers(
io::Printer* printer) const {
Formatter format(printer, variables_);
if (implicit_weak_field_) {
format("::$proto_ns$::WeakRepeatedPtrField< $type$ > $name$_;\n");
} else {
format("::$proto_ns$::RepeatedPtrField< $type$ > $name$_;\n");
}
}
void RepeatedMessageFieldGenerator::GenerateAccessorDeclarations(
@ -657,20 +656,22 @@ void RepeatedMessageFieldGenerator::GenerateAccessorDeclarations(
void RepeatedMessageFieldGenerator::GenerateInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
format.Set("weak", implicit_weak_field_ ? ".weak" : "");
format(
"inline $type$* $classname$::mutable_$name$(int index) {\n"
"$annotate_accessor$"
// TODO(dlj): move insertion points
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
"$type_reference_function$"
" return $name$_.Mutable(index);\n"
" return $name$_$weak$.Mutable(index);\n"
"}\n"
"inline ::$proto_ns$::RepeatedPtrField< $type$ >*\n"
"$classname$::mutable_$name$() {\n"
"$annotate_accessor$"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
"$type_reference_function$"
" return &$name$_;\n"
" return &$name$_$weak$;\n"
"}\n");
if (options_.safe_boundary_check) {
@ -678,7 +679,7 @@ void RepeatedMessageFieldGenerator::GenerateInlineAccessorDefinitions(
"inline const $type$& $classname$::$name$(int index) const {\n"
"$annotate_accessor$"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_.InternalCheckedGet(index,\n"
" return $name$_$weak$.InternalCheckedGet(index,\n"
" *reinterpret_cast<const $type$*>(&$type_default_instance$));\n"
"}\n");
} else {
@ -687,7 +688,7 @@ void RepeatedMessageFieldGenerator::GenerateInlineAccessorDefinitions(
"$annotate_accessor$"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
"$type_reference_function$"
" return $name$_.Get(index);\n"
" return $name$_$weak$.Get(index);\n"
"}\n");
}
@ -695,7 +696,7 @@ void RepeatedMessageFieldGenerator::GenerateInlineAccessorDefinitions(
"inline $type$* $classname$::add_$name$() {\n"
"$annotate_accessor$"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
" return $name$_.Add();\n"
" return $name$_$weak$.Add();\n"
"}\n");
format(
@ -704,39 +705,26 @@ void RepeatedMessageFieldGenerator::GenerateInlineAccessorDefinitions(
"$annotate_accessor$"
" // @@protoc_insertion_point(field_list:$full_name$)\n"
"$type_reference_function$"
" return $name$_;\n"
" return $name$_$weak$;\n"
"}\n");
}
void RepeatedMessageFieldGenerator::GenerateClearingCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
if (implicit_weak_field_) {
format(
"CastToBase(&$name$_)->Clear<"
"::$proto_ns$::internal::ImplicitWeakTypeHandler<$type$>>();\n");
} else {
format("$name$_.Clear();\n");
}
}
void RepeatedMessageFieldGenerator::GenerateMergingCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
if (implicit_weak_field_) {
format(
"CastToBase(&$name$_)->MergeFrom<"
"::$proto_ns$::internal::ImplicitWeakTypeHandler<$type$>>(CastToBase("
"from.$name$_));\n");
} else {
format("$name$_.MergeFrom(from.$name$_);\n");
}
}
void RepeatedMessageFieldGenerator::GenerateSwappingCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("CastToBase(&$name$_)->InternalSwap(CastToBase(&other->$name$_));\n");
format("$name$_.InternalSwap(&other->$name$_);\n");
}
void RepeatedMessageFieldGenerator::GenerateConstructorCode(
@ -751,9 +739,9 @@ void RepeatedMessageFieldGenerator::GenerateMergeFromCodedStream(
if (implicit_weak_field_) {
format(
"DO_(::$proto_ns$::internal::WireFormatLite::"
"ReadMessage(input, CastToBase(&$name$_)->AddWeak(\n"
"ReadMessage(input, $name$_.AddWeak(\n"
" reinterpret_cast<const ::$proto_ns$::MessageLite*>(\n"
" &$type_default_instance$))));\n");
" $type_default_instance_ptr$))));\n");
} else {
format(
"DO_(::$proto_ns$::internal::WireFormatLite::"
@ -770,55 +758,25 @@ void RepeatedMessageFieldGenerator::GenerateMergeFromCodedStream(
void RepeatedMessageFieldGenerator::GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const {
Formatter format(printer, variables_);
if (implicit_weak_field_) {
format(
"for (unsigned int i = 0,\n"
" n = static_cast<unsigned int>(this->$name$_size()); i < n; i++) "
"{\n"
" stream->EnsureSpace(&target);\n"
" target = ::$proto_ns$::internal::WireFormatLite::\n"
" InternalWrite$declared_type$ToArray(\n"
" $number$,\n"
" CastToBase($name$_).Get<"
"::$proto_ns$::internal::ImplicitWeakTypeHandler<$type$>>("
"static_cast<int>(i)), target, stream);\n"
"}\n");
} else {
format(
"for (auto it = this->$name$().pointer_begin(),\n"
" end = this->$name$().pointer_end(); it < end; ++it) {\n"
"for (auto it = this->$name$_.pointer_begin(),\n"
" end = this->$name$_.pointer_end(); it < end; ++it) {\n"
" stream->EnsureSpace(&target);\n"
" target = ::$proto_ns$::internal::WireFormatLite::\n"
" InternalWrite$declared_type$ToArray($number$, **it, target, "
"stream);\n"
"}\n");
}
}
void RepeatedMessageFieldGenerator::GenerateByteSize(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"{\n"
" unsigned int count = static_cast<unsigned "
"int>(this->$name$_size());\n");
format.Indent();
format(
"total_size += $tag_size$UL * count;\n"
"for (unsigned int i = 0; i < count; i++) {\n"
"total_size += $tag_size$UL * this->$name$_size();\n"
"for (const auto& msg : this->$name$_) {\n"
" total_size +=\n"
" ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n");
if (implicit_weak_field_) {
format(
" CastToBase($name$_).Get<"
"::$proto_ns$::internal::ImplicitWeakTypeHandler<$type$>>("
"static_cast<int>(i)));\n");
} else {
format(" this->$name$(static_cast<int>(i)));\n");
}
format("}\n");
format.Outdent();
format("}\n");
" ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(msg);\n"
"}\n");
}
} // namespace cpp

@ -38,7 +38,6 @@
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {

@ -39,7 +39,6 @@
#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {
@ -197,6 +196,12 @@ void StringFieldGenerator::GenerateAccessorDeclarations(
descriptor_);
}
}
format(
"private:\n"
"const std::string& _internal_$name$() const;\n"
"void _internal_set_$name$(const std::string& value);\n"
"std::string* _internal_mutable_$name$();\n"
"public:\n");
if (unknown_ctype) {
format.Outdent();
@ -208,18 +213,31 @@ void StringFieldGenerator::GenerateAccessorDeclarations(
void StringFieldGenerator::GenerateInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
if (SupportsArenas(descriptor_)) {
format(
"inline const std::string& $classname$::$name$() const {\n"
"$annotate_accessor$"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_.Get();\n"
" return _internal_$name$();\n"
"}\n"
"inline void $classname$::set_$name$(const std::string& value) {\n"
"$annotate_accessor$"
" _internal_set_$name$(value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
"inline std::string* $classname$::mutable_$name$() {\n"
"$annotate_accessor$"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return _internal_mutable_$name$();\n"
"}\n");
if (SupportsArenas(descriptor_)) {
format(
"inline const std::string& $classname$::_internal_$name$() const {\n"
" return $name$_.Get();\n"
"}\n"
"inline void $classname$::_internal_set_$name$(const std::string& "
"value) {\n"
" $set_hasbit$\n"
" $name$_.Set$lite$($default_variable$, value, GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
"inline void $classname$::set_$name$(std::string&& value) {\n"
"$annotate_accessor$"
@ -257,10 +275,8 @@ void StringFieldGenerator::GenerateInlineAccessorDefinitions(
"GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
"inline std::string* $classname$::mutable_$name$() {\n"
"$annotate_accessor$"
"inline std::string* $classname$::_internal_mutable_$name$() {\n"
" $set_hasbit$\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_.Mutable($default_variable$, GetArenaNoVirtual());\n"
"}\n"
"inline std::string* $classname$::$release_name$() {\n"
@ -324,16 +340,13 @@ void StringFieldGenerator::GenerateInlineAccessorDefinitions(
} else {
// No-arena case.
format(
"inline const std::string& $classname$::$name$() const {\n"
"$annotate_accessor$"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
"inline const std::string& $classname$::_internal_$name$() const {\n"
" return $name$_.GetNoArena();\n"
"}\n"
"inline void $classname$::set_$name$(const std::string& value) {\n"
"$annotate_accessor$"
"inline void $classname$::_internal_set_$name$(const std::string& "
"value) {\n"
" $set_hasbit$\n"
" $name$_.SetNoArena($default_variable$, value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
"inline void $classname$::set_$name$(std::string&& value) {\n"
"$annotate_accessor$"
@ -368,10 +381,8 @@ void StringFieldGenerator::GenerateInlineAccessorDefinitions(
" $string_piece$(reinterpret_cast<const char*>(value), size));\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
"inline std::string* $classname$::mutable_$name$() {\n"
"$annotate_accessor$"
"inline std::string* $classname$::_internal_mutable_$name$() {\n"
" $set_hasbit$\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_.MutableNoArena($default_variable$);\n"
"}\n"
"inline std::string* $classname$::$release_name$() {\n"
@ -500,7 +511,7 @@ void StringFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
Formatter format(printer, variables_);
if (SupportsArenas(descriptor_) || descriptor_->containing_oneof() != NULL) {
// TODO(gpike): improve this
format("set_$name$(from.$name$());\n");
format("_internal_set_$name$(from._internal_$name$());\n");
} else {
format(
"$set_hasbit$\n"
@ -537,9 +548,9 @@ void StringFieldGenerator::GenerateCopyConstructorCode(
GenerateConstructorCode(printer);
if (HasFieldPresence(descriptor_->file())) {
format("if (from.has_$name$()) {\n");
format("if (from._internal_has_$name$()) {\n");
} else {
format("if (!from.$name$().empty()) {\n");
format("if (!from._internal_$name$().empty()) {\n");
}
format.Indent();
@ -547,7 +558,7 @@ void StringFieldGenerator::GenerateCopyConstructorCode(
if (SupportsArenas(descriptor_) || descriptor_->containing_oneof() != NULL) {
// TODO(gpike): improve this
format(
"$name$_.Set$lite$($default_variable$, from.$name$(),\n"
"$name$_.Set$lite$($default_variable$, from._internal_$name$(),\n"
" GetArenaNoVirtual());\n");
} else {
format("$name$_.AssignWithDefault($default_variable$, from.$name$_);\n");
@ -612,18 +623,19 @@ void StringFieldGenerator::GenerateMergeFromCodedStream(
" $name$_.UnsafeSetTaggedPointer(str);\n"
"} else {\n"
" DO_(::$proto_ns$::internal::WireFormatLite::Read$declared_type$(\n"
" input, this->mutable_$name$()));\n"
" input, this->_internal_mutable_$name$()));\n"
"}\n");
} else {
format(
"DO_(::$proto_ns$::internal::WireFormatLite::Read$declared_type$(\n"
" input, this->mutable_$name$()));\n");
" input, this->_internal_mutable_$name$()));\n");
}
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
GenerateUtf8CheckCodeForString(
descriptor_, options_, true,
"this->$name$().data(), static_cast<int>(this->$name$().length()),\n",
"this->_internal_$name$().data(), "
"static_cast<int>(this->_internal_$name$().length()),\n",
format);
}
}
@ -638,12 +650,13 @@ void StringFieldGenerator::GenerateSerializeWithCachedSizesToArray(
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
GenerateUtf8CheckCodeForString(
descriptor_, options_, false,
"this->$name$().data(), static_cast<int>(this->$name$().length()),\n",
"this->_internal_$name$().data(), "
"static_cast<int>(this->_internal_$name$().length()),\n",
format);
}
format(
"target = stream->Write$declared_type$MaybeAliased(\n"
" $number$, this->$name$(), target);\n");
" $number$, this->_internal_$name$(), target);\n");
}
void StringFieldGenerator::GenerateByteSize(io::Printer* printer) const {
@ -651,7 +664,7 @@ void StringFieldGenerator::GenerateByteSize(io::Printer* printer) const {
format(
"total_size += $tag_size$ +\n"
" ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
" this->$name$());\n");
" this->_internal_$name$());\n");
}
uint32 StringFieldGenerator::CalculateFieldTag() const {
@ -666,6 +679,13 @@ StringOneofFieldGenerator::StringOneofFieldGenerator(
inlined_ = false;
SetCommonOneofFieldVariables(descriptor, &variables_);
variables_["field_name"] = UnderscoresToCamelCase(descriptor->name(), true);
variables_["oneof_index"] =
StrCat(descriptor->containing_oneof()->index());
// has_$name$() for oneof fields is private if has_bit is not present. In that
// case, use _has_$name$() instead of _internal_has_$name$().
variables_["internal"] =
HasFieldPresence(descriptor->file()) ? "_internal_" : "";
}
StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
@ -673,26 +693,39 @@ StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
if (SupportsArenas(descriptor_)) {
format(
"inline const std::string& $classname$::$name$() const {\n"
"$annotate_accessor$"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" if (has_$name$()) {\n"
" return _internal_$name$();\n"
"}\n"
"inline void $classname$::set_$name$(const std::string& value) {\n"
"$annotate_accessor$"
" _internal_set_$name$(value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
"inline std::string* $classname$::mutable_$name$() {\n"
"$annotate_accessor$"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return _internal_mutable_$name$();\n"
"}\n");
if (SupportsArenas(descriptor_)) {
format(
"inline const std::string& $classname$::_internal_$name$() const {\n"
" if ($internal$has_$name$()) {\n"
" return $field_member$.Get();\n"
" }\n"
" return *$default_variable$;\n"
"}\n"
"inline void $classname$::set_$name$(const std::string& value) {\n"
"$annotate_accessor$"
" if (!has_$name$()) {\n"
"inline void $classname$::_internal_set_$name$(const std::string& "
"value) {\n"
" if (!$internal$has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" $field_member$.UnsafeSetDefault($default_variable$);\n"
" }\n"
" $field_member$.Set$lite$($default_variable$, value,\n"
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
"inline void $classname$::set_$name$(std::string&& value) {\n"
"$annotate_accessor$"
@ -748,16 +781,14 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
"inline std::string* $classname$::mutable_$name$() {\n"
"$annotate_accessor$"
" if (!has_$name$()) {\n"
"inline std::string* $classname$::_internal_mutable_$name$() {\n"
" if (!$internal$has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" $field_member$.UnsafeSetDefault($default_variable$);\n"
" }\n"
" return $field_member$.Mutable($default_variable$,\n"
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
"}\n"
"inline std::string* $classname$::$release_name$() {\n"
"$annotate_accessor$"
@ -816,24 +847,20 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
} else {
// No-arena case.
format(
"inline const std::string& $classname$::$name$() const {\n"
"$annotate_accessor$"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" if (has_$name$()) {\n"
"inline const std::string& $classname$::_internal_$name$() const {\n"
" if ($internal$has_$name$()) {\n"
" return $field_member$.GetNoArena();\n"
" }\n"
" return *$default_variable$;\n"
"}\n"
"inline void $classname$::set_$name$(const std::string& value) {\n"
"$annotate_accessor$"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
" if (!has_$name$()) {\n"
"inline void $classname$::_internal_set_$name$(const std::string& "
"value) {\n"
" if (!$internal$has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" $field_member$.UnsafeSetDefault($default_variable$);\n"
" }\n"
" $field_member$.SetNoArena($default_variable$, value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
"inline void $classname$::set_$name$(std::string&& value) {\n"
"$annotate_accessor$"
@ -885,14 +912,12 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
" reinterpret_cast<const char*>(value), size));\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
"inline std::string* $classname$::mutable_$name$() {\n"
"$annotate_accessor$"
" if (!has_$name$()) {\n"
"inline std::string* $classname$::_internal_mutable_$name$() {\n"
" if (!$internal$has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" $field_member$.UnsafeSetDefault($default_variable$);\n"
" }\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $field_member$.MutableNoArena($default_variable$);\n"
"}\n"
"inline std::string* $classname$::$release_name$() {\n"
@ -979,18 +1004,19 @@ void StringOneofFieldGenerator::GenerateMergeFromCodedStream(
" $field_member$.UnsafeSetTaggedPointer(new_value);\n"
"} else {\n"
" DO_(::$proto_ns$::internal::WireFormatLite::Read$declared_type$(\n"
" input, this->mutable_$name$()));\n"
" input, this->_internal_mutable_$name$()));\n"
"}\n");
} else {
format(
"DO_(::$proto_ns$::internal::WireFormatLite::Read$declared_type$(\n"
" input, this->mutable_$name$()));\n");
" input, this->_internal_mutable_$name$()));\n");
}
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
GenerateUtf8CheckCodeForString(
descriptor_, options_, true,
"this->$name$().data(), static_cast<int>(this->$name$().length()),\n",
"this->_internal_$name$().data(), "
"static_cast<int>(this->_internal_$name$().length()),\n",
format);
}
}
@ -1064,7 +1090,10 @@ void RepeatedStringFieldGenerator::GenerateAccessorDeclarations(
"const;\n"
"$deprecated_attr$::$proto_ns$::RepeatedPtrField<std::string>* "
"${1$mutable_$name$$}$()"
";\n",
";\n"
"private:\n"
"std::string* _internal_add_$name$();\n"
"public:\n",
descriptor_);
if (unknown_ctype) {
@ -1077,6 +1106,12 @@ void RepeatedStringFieldGenerator::GenerateAccessorDeclarations(
void RepeatedStringFieldGenerator::GenerateInlineAccessorDefinitions(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"inline std::string* $classname$::add_$name$() {\n"
"$annotate_accessor$"
" // @@protoc_insertion_point(field_add_mutable:$full_name$)\n"
" return _internal_add_$name$();\n"
"}\n");
if (options_.safe_boundary_check) {
format(
"inline const std::string& $classname$::$name$(int index) const {\n"
@ -1135,9 +1170,7 @@ void RepeatedStringFieldGenerator::GenerateInlineAccessorDefinitions(
" reinterpret_cast<const char*>(value), size);\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
"inline std::string* $classname$::add_$name$() {\n"
"$annotate_accessor$"
" // @@protoc_insertion_point(field_add_mutable:$full_name$)\n"
"inline std::string* $classname$::_internal_add_$name$() {\n"
" return $name$_.Add();\n"
"}\n"
"inline void $classname$::add_$name$(const std::string& value) {\n"
@ -1200,7 +1233,7 @@ void RepeatedStringFieldGenerator::GenerateMergingCode(
void RepeatedStringFieldGenerator::GenerateSwappingCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format("$name$_.InternalSwap(CastToBase(&other->$name$_));\n");
format("$name$_.InternalSwap(&other->$name$_);\n");
}
void RepeatedStringFieldGenerator::GenerateConstructorCode(
@ -1219,12 +1252,12 @@ void RepeatedStringFieldGenerator::GenerateMergeFromCodedStream(
Formatter format(printer, variables_);
format(
"DO_(::$proto_ns$::internal::WireFormatLite::Read$declared_type$(\n"
" input, this->add_$name$()));\n");
" input, this->_internal_add_$name$()));\n");
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
GenerateUtf8CheckCodeForString(
descriptor_, options_, true,
"this->$name$(this->$name$_size() - 1).data(),\n"
"static_cast<int>(this->$name$(this->$name$_size() - 1).length()),\n",
"$name$_.Get($name$_.size() - 1).data(),\n"
"static_cast<int>($name$_.Get($name$_.size() - 1).length()),\n",
format);
}
}
@ -1233,8 +1266,8 @@ void RepeatedStringFieldGenerator::GenerateSerializeWithCachedSizesToArray(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"for (auto it = this->$name$().pointer_begin(),\n"
" end = this->$name$().pointer_end(); it < end; ++it) {\n"
"for (auto it = $field_member$.pointer_begin(),\n"
" end = $field_member$.pointer_end(); it < end; ++it) {\n"
" const auto& s = **it;\n");
// format("for (const std::string& s : this->$name$()) {\n");
format.Indent();
@ -1254,11 +1287,11 @@ void RepeatedStringFieldGenerator::GenerateByteSize(
Formatter format(printer, variables_);
format(
"total_size += $tag_size$ *\n"
" ::$proto_ns$::internal::FromIntSize(this->$name$_size());\n"
"for (int i = 0, n = this->$name$_size(); i < n; i++) {\n"
" ::$proto_ns$::internal::FromIntSize($name$_.size());\n"
"for (int i = 0, n = $name$_.size(); i < n; i++) {\n"
" total_size += "
"::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
" this->$name$(i));\n"
" $name$_.Get(i));\n"
"}\n");
}

@ -57,7 +57,7 @@ void WriteDocCommentBodyImpl(io::Printer* printer, SourceLocation location) {
comments = StringReplace(comments, "&", "&amp;", true);
comments = StringReplace(comments, "<", "&lt;", true);
std::vector<string> lines;
SplitStringAllowEmpty(comments, "\n", &lines);
lines = Split(comments, "\n", false);
// TODO: We really should work out which part to put in the summary and which to put in the remarks...
// but that needs to be part of a bigger effort to understand the markdown better anyway.
printer->Print("/// <summary>\n");

@ -36,7 +36,7 @@
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
#include <string>
#include <google/protobuf/stubs/port.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/compiler/code_generator.h>

@ -39,7 +39,7 @@
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__
#include <string>
#include <google/protobuf/stubs/port.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/port_def.inc>

@ -213,7 +213,7 @@ void ReflectionClassGenerator::WriteDescriptor(io::Printer* printer) {
for (int i = 0; i < file_->extension_count(); i++) {
extensions.push_back(GetFullExtensionName(file_->extension(i)));
}
printer->Print("new pb::Extension[] { $extensions$ }, ", "extensions", JoinStrings(extensions, ", "));
printer->Print("new pb::Extension[] { $extensions$ }, ", "extensions", Join(extensions, ", "));
}
else {
printer->Print("null, ");
@ -264,7 +264,7 @@ void ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descript
for (int i = 0; i < descriptor->field_count(); i++) {
fields.push_back(GetPropertyName(descriptor->field(i)));
}
printer->Print("new[]{ \"$fields$\" }, ", "fields", JoinStrings(fields, "\", \""));
printer->Print("new[]{ \"$fields$\" }, ", "fields", Join(fields, "\", \""));
}
else {
printer->Print("null, ");
@ -276,7 +276,7 @@ void ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descript
for (int i = 0; i < descriptor->oneof_decl_count(); i++) {
oneofs.push_back(UnderscoresToCamelCase(descriptor->oneof_decl(i)->name(), true));
}
printer->Print("new[]{ \"$oneofs$\" }, ", "oneofs", JoinStrings(oneofs, "\", \""));
printer->Print("new[]{ \"$oneofs$\" }, ", "oneofs", Join(oneofs, "\", \""));
}
else {
printer->Print("null, ");
@ -288,7 +288,7 @@ void ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descript
for (int i = 0; i < descriptor->enum_type_count(); i++) {
enums.push_back(GetClassName(descriptor->enum_type(i)));
}
printer->Print("new[]{ typeof($enums$) }, ", "enums", JoinStrings(enums, "), typeof("));
printer->Print("new[]{ typeof($enums$) }, ", "enums", Join(enums, "), typeof("));
}
else {
printer->Print("null, ");
@ -300,7 +300,7 @@ void ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descript
for (int i = 0; i < descriptor->extension_count(); i++) {
extensions.push_back(GetFullExtensionName(descriptor->extension(i)));
}
printer->Print("new pb::Extension[] { $extensions$ }, ", "extensions", JoinStrings(extensions, ", "));
printer->Print("new pb::Extension[] { $extensions$ }, ", "extensions", Join(extensions, ", "));
}
else {
printer->Print("null, ");

@ -46,14 +46,11 @@
#include <memory>
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/compiler/parser.h>
#include <google/protobuf/io/io_win32.h>
#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/io/io_win32.h>
#ifdef _WIN32
#include <ctype.h>

@ -35,7 +35,6 @@
#include <google/protobuf/compiler/java/java_name_resolver.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/map_util.h>
namespace google {

@ -174,7 +174,8 @@ void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) {
void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) {
// We start the comment with the main body based on the comments from the
// .proto file (if present). We then continue with the field declaration, e.g.:
// .proto file (if present). We then continue with the field declaration,
// e.g.:
// optional string foo = 5;
// And then we end with the javadoc tags if applicable.
// If the field is a group, the debug string might end with {.
@ -211,16 +212,16 @@ void WriteFieldAccessorDocComment(io::Printer* printer,
break;
// Repeated
case LIST_COUNT:
printer->Print(" * @return The number of $name$(s).\n", "name",
printer->Print(" * @return The count of $name$.\n", "name",
field->camelcase_name());
break;
case LIST_GETTER:
printer->Print(" * @return A list containing the $name$(s).\n", "name",
printer->Print(" * @return A list containing the $name$.\n", "name",
field->camelcase_name());
break;
case LIST_INDEXED_GETTER:
printer->Print(" * @param index The index of the element to return.\n");
printer->Print(" * @return The $name$(s) at the given index.\n", "name",
printer->Print(" * @return The $name$ at the given index.\n", "name",
field->camelcase_name());
break;
case LIST_INDEXED_SETTER:
@ -233,7 +234,7 @@ void WriteFieldAccessorDocComment(io::Printer* printer,
field->camelcase_name());
break;
case LIST_MULTI_ADDER:
printer->Print(" * @param values The $name$(s) to add.\n", "name",
printer->Print(" * @param values The $name$ to add.\n", "name",
field->camelcase_name());
break;
}
@ -256,11 +257,14 @@ void WriteFieldEnumValueAccessorDocComment(io::Printer* printer,
// Should never happen
break;
case GETTER:
printer->Print(" * @return The enum value for $name$.\n", "name",
printer->Print(
" * @return The enum numeric value on the wire for $name$.\n", "name",
field->camelcase_name());
break;
case SETTER:
printer->Print(" * @param value The enum value for $name$ to set.\n",
printer->Print(
" * @param value The enum numeric value on the wire for $name$ to "
"set.\n",
"name", field->camelcase_name());
break;
case CLEARER:
@ -271,26 +275,36 @@ void WriteFieldEnumValueAccessorDocComment(io::Printer* printer,
// Should never happen
break;
case LIST_GETTER:
printer->Print(" * @return A list containing the enum values for "
"$name$(s).\n", "name", field->camelcase_name());
printer->Print(
" * @return A list containing the enum numeric values on the wire "
"for $name$.\n",
"name", field->camelcase_name());
break;
case LIST_INDEXED_GETTER:
printer->Print(" * @param index The index of the value to return.\n");
printer->Print(" * @return The enum value of the $name$ at the given "
"index.\n", "name", field->camelcase_name());
printer->Print(
" * @return The enum numeric value on the wire of $name$ at the "
"given index.\n",
"name", field->camelcase_name());
break;
case LIST_INDEXED_SETTER:
printer->Print(" * @param index The index to set the value at.\n");
printer->Print(" * @param value The enum value of the $name$ to set.\n",
printer->Print(
" * @param value The enum numeric value on the wire for $name$ to "
"set.\n",
"name", field->camelcase_name());
break;
case LIST_ADDER:
printer->Print(" * @param value The enum value of the $name$ to add.\n",
printer->Print(
" * @param value The enum numeric value on the wire for $name$ to "
"add.\n",
"name", field->camelcase_name());
break;
case LIST_MULTI_ADDER:
printer->Print(" * @param values The enum values of the $name$(s) to "
"add.\n", "name", field->camelcase_name());
printer->Print(
" * @param values The enum numeric values on the wire for $name$ to "
"add.\n",
"name", field->camelcase_name());
break;
}
if (builder) {
@ -316,8 +330,8 @@ void WriteFieldStringBytesAccessorDocComment(io::Printer* printer,
field->camelcase_name());
break;
case SETTER:
printer->Print(" * @param value The bytes for $name$ to set.\n",
"name", field->camelcase_name());
printer->Print(" * @param value The bytes for $name$ to set.\n", "name",
field->camelcase_name());
break;
case CLEARER:
// Print nothing
@ -327,7 +341,7 @@ void WriteFieldStringBytesAccessorDocComment(io::Printer* printer,
// Should never happen
break;
case LIST_GETTER:
printer->Print(" * @return A list containing the bytes for $name$(s).\n",
printer->Print(" * @return A list containing the bytes for $name$.\n",
"name", field->camelcase_name());
break;
case LIST_INDEXED_GETTER:
@ -345,7 +359,7 @@ void WriteFieldStringBytesAccessorDocComment(io::Printer* printer,
"name", field->camelcase_name());
break;
case LIST_MULTI_ADDER:
printer->Print(" * @param values The bytes of the $name$(s) to add.\n",
printer->Print(" * @param values The bytes of the $name$ to add.\n",
"name", field->camelcase_name());
break;
}

@ -53,7 +53,6 @@ namespace compiler {
namespace java {
enum FieldAccessorType {
HAZZER,
GETTER,
SETTER,
@ -65,7 +64,6 @@ enum FieldAccessorType {
LIST_INDEXED_SETTER,
LIST_ADDER,
LIST_MULTI_ADDER
};
void WriteMessageDocComment(io::Printer* printer, const Descriptor* message);

@ -44,7 +44,6 @@
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {
@ -175,8 +174,9 @@ void EnumGenerator::Generate(io::Printer* printer) {
"}\n"
"\n"
"/**\n"
" * @param value The number of the enum to look for.\n"
" * @return The enum associated with the given number.\n"
" * @param value The numeric wire value of the corresponding enum "
"entry.\n"
" * @return The enum associated with the given numeric wire value.\n"
" * @deprecated Use {@link #forNumber(int)} instead.\n"
" */\n"
"@java.lang.Deprecated\n"
@ -184,6 +184,11 @@ void EnumGenerator::Generate(io::Printer* printer) {
" return forNumber(value);\n"
"}\n"
"\n"
"/**\n"
" * @param value The numeric wire value of the corresponding enum "
"entry.\n"
" * @return The enum associated with the given numeric wire value.\n"
" */\n"
"public static $classname$ forNumber(int value) {\n"
" switch (value) {\n",
"classname", descriptor_->name());

@ -46,7 +46,6 @@
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {

@ -46,7 +46,6 @@
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {

@ -43,7 +43,6 @@
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/map_util.h>
namespace google {

@ -41,7 +41,6 @@
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {

@ -55,7 +55,6 @@
#include <google/protobuf/stubs/substitute.h>
namespace google {
namespace protobuf {
namespace compiler {

@ -54,7 +54,6 @@
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {

@ -44,9 +44,6 @@
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/stubs/hash.h> // for hash<T *>
namespace google {

@ -55,8 +55,6 @@
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
namespace google {
namespace protobuf {
namespace compiler {

@ -53,8 +53,6 @@
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
namespace google {
namespace protobuf {
namespace compiler {

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

Loading…
Cancel
Save