PROTOBUF_SYNC_PIPER
pull/8076/head
Joshua Haberman 4 years ago
commit 5c028d6cf4
  1. 1
      BUILD
  2. 42
      CHANGES.txt
  3. 4
      Protobuf.podspec
  4. 3
      cmake/CMakeLists.txt
  5. 1
      cmake/extract_includes.bat.in
  6. 4
      cmake/install.cmake
  7. 3
      cmake/libprotobuf-lite.cmake
  8. 4
      cmake/libprotobuf.cmake
  9. 12
      cmake/protobuf-module.cmake.in
  10. 20
      conformance/Makefile.am
  11. 12
      conformance/conformance_cpp.cc
  12. 2
      conformance/failure_list_php_c.txt
  13. 4
      conformance/failure_list_php_c_32.txt
  14. 3
      conformance/text_format_conformance_suite.cc
  15. 36
      conformance/text_format_failure_list_python_2.7.txt
  16. 30
      conformance/text_format_failure_list_python_cpp_2.7.txt
  17. 2
      csharp/Google.Protobuf.Tools.nuspec
  18. 56
      csharp/src/Google.Protobuf.Benchmarks/ByteStringBenchmark.cs
  19. 170
      csharp/src/Google.Protobuf.Test/ByteStringTest.cs
  20. 19
      csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
  21. 1
      csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
  22. 22
      csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs
  23. 145
      csharp/src/Google.Protobuf/ByteString.cs
  24. 64
      csharp/src/Google.Protobuf/ByteStringAsync.cs
  25. 3
      csharp/src/Google.Protobuf/Google.Protobuf.csproj
  26. 2
      csharp/src/Google.Protobuf/IBufferMessage.cs
  27. 10
      csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs
  28. 81
      csharp/src/Google.Protobuf/UnsafeByteOperations.cs
  29. 4
      docs/options.md
  30. 8
      editors/proto.vim
  31. 2
      java/bom/pom.xml
  32. 2
      java/core/pom.xml
  33. 42
      java/core/src/main/java/com/google/protobuf/FieldSet.java
  34. 25
      java/core/src/main/java/com/google/protobuf/TextFormat.java
  35. 2
      java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
  36. 24
      java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
  37. 86
      java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
  38. 24
      java/core/src/test/java/com/google/protobuf/MapLiteTest.java
  39. 24
      java/core/src/test/java/com/google/protobuf/MapTest.java
  40. 4
      java/core/src/test/java/com/google/protobuf/TestUtil.java
  41. 4
      java/core/src/test/java/com/google/protobuf/TestUtilLite.java
  42. 2
      java/lite/pom.xml
  43. 2
      java/pom.xml
  44. 2
      java/util/pom.xml
  45. 29
      java/util/src/main/java/com/google/protobuf/util/Durations.java
  46. 28
      java/util/src/main/java/com/google/protobuf/util/Timestamps.java
  47. 9
      js/binary/reader.js
  48. 125
      objectivec/GPBMessage.m
  49. 9
      objectivec/GPBUtilities.m
  50. 4
      objectivec/GPBUtilities_PackagePrivate.h
  51. 2
      objectivec/Tests/CocoaPods/iOSCocoaPodsTester/Podfile-framework
  52. 2
      objectivec/Tests/CocoaPods/iOSCocoaPodsTester/Podfile-static
  53. 4
      php/ext/google/protobuf/config.m4
  54. 106
      php/ext/google/protobuf/def.c
  55. 6
      php/ext/google/protobuf/def.h
  56. 62
      php/ext/google/protobuf/make-preload.php
  57. 386
      php/ext/google/protobuf/message.c
  58. 75
      php/ext/google/protobuf/package.xml
  59. 2502
      php/ext/google/protobuf/php-upb.c
  60. 754
      php/ext/google/protobuf/php-upb.h
  61. 36
      php/ext/google/protobuf/protobuf.c
  62. 2
      php/ext/google/protobuf/protobuf.h
  63. 3232
      php/ext/google/protobuf/wkt.inc
  64. 13
      php/generate_descriptor_protos.sh
  65. 6
      php/prepare_c_extension.sh
  66. 18
      php/src/GPBMetadata/Google/Protobuf/Any.php
  67. 51
      php/src/GPBMetadata/Google/Protobuf/Api.php
  68. 19
      php/src/GPBMetadata/Google/Protobuf/Duration.php
  69. 18
      php/src/GPBMetadata/Google/Protobuf/FieldMask.php
  70. 17
      php/src/GPBMetadata/Google/Protobuf/GPBEmpty.php
  71. 19
      php/src/GPBMetadata/Google/Protobuf/SourceContext.php
  72. BIN
      php/src/GPBMetadata/Google/Protobuf/Struct.php
  73. 19
      php/src/GPBMetadata/Google/Protobuf/Timestamp.php
  74. BIN
      php/src/GPBMetadata/Google/Protobuf/Type.php
  75. 45
      php/src/GPBMetadata/Google/Protobuf/Wrappers.php
  76. 101
      php/src/Google/Protobuf/Any.php
  77. 20
      php/src/Google/Protobuf/Api.php
  78. 2
      php/src/Google/Protobuf/BoolValue.php
  79. 2
      php/src/Google/Protobuf/BytesValue.php
  80. 2
      php/src/Google/Protobuf/DoubleValue.php
  81. 6
      php/src/Google/Protobuf/Duration.php
  82. 18
      php/src/Google/Protobuf/Enum.php
  83. 4
      php/src/Google/Protobuf/EnumValue.php
  84. 22
      php/src/Google/Protobuf/Field.php
  85. 1
      php/src/Google/Protobuf/Field/Cardinality.php
  86. 1
      php/src/Google/Protobuf/Field/Kind.php
  87. 42
      php/src/Google/Protobuf/FieldMask.php
  88. 2
      php/src/Google/Protobuf/FloatValue.php
  89. 2
      php/src/Google/Protobuf/Int32Value.php
  90. 2
      php/src/Google/Protobuf/Int64Value.php
  91. 86
      php/src/Google/Protobuf/Internal/AnyBase.php
  92. 32
      php/src/Google/Protobuf/Internal/TimestampBase.php
  93. 12
      php/src/Google/Protobuf/Method.php
  94. 4
      php/src/Google/Protobuf/Mixin.php
  95. 16
      php/src/Google/Protobuf/Option.php
  96. 2
      php/src/Google/Protobuf/SourceContext.php
  97. 2
      php/src/Google/Protobuf/StringValue.php
  98. 1
      php/src/Google/Protobuf/Syntax.php
  99. 68
      php/src/Google/Protobuf/Timestamp.php
  100. 18
      php/src/Google/Protobuf/Type.php
  101. Some files were not shown because too many files have changed in this diff Show More

@ -164,6 +164,7 @@ cc_library(
# AUTOGEN(protobuf_lite_srcs)
"src/google/protobuf/any_lite.cc",
"src/google/protobuf/arena.cc",
"src/google/protobuf/arenastring.cc",
"src/google/protobuf/extension_set.cc",
"src/google/protobuf/generated_enum_util.cc",
"src/google/protobuf/generated_message_table_driven_lite.cc",

@ -1,12 +1,15 @@
Unreleased Changes
2020-11-11 version 3.14.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
Protocol Compiler
* The proto compiler no longer requires a .proto filename when it is not
generating code.
* Added flag `--deterministic_output` to `protoc --encode=...`.
* Fixed deadlock when using google.protobuf.Any embedded in aggregate options.
C++
* Arenas are now unconditionally enabled. cc_enable_arenas no longer has
any effect.
* Removed inlined string support, which is incompatible with arenas.
* Fix a memory corruption bug in reflection when mixing optional and
non-optional fields.
* Make SpaceUsed() calculation more thorough for map fields.
@ -20,18 +23,55 @@ Unreleased Changes
* When running under ASAN, skip a test that makes huge allocations.
* Fixed a crash that could happen when creating more than 256 extensions in
a single message.
* Fix a crash in BuildFile when passing in invalid descriptor proto.
* Parser security fix when operating with CodedInputStream.
* Warn against the use of AllowUnknownExtension.
* Migrated to C++11 for-range loops instead of index-based loops where
possible. This fixes a lot of warnings when compiling with -Wsign-compare.
* Fix segment fault for proto3 optional (#7805)
* Adds a CMake option to build `libprotoc` separately (#7949)
Java
* Bugfix in mergeFrom() when a oneof has multiple message fields.
* Fix RopeByteString.RopeInputStream.read() returning -1 when told to read
0 bytes when not at EOF.
* Redefine remove(Object) on primitive repeated field Lists to avoid
autoboxing.
* Support "\u" escapes in textformat string literals.
* Trailing empty spaces are no longer ignored for FieldMask.
* Fix FieldMaskUtil.subtract to recursively remove mask.
* Mark enums with `@java.lang.Deprecated` if the proto enum has option
`deprecated = true;`.
* Adding forgotten duration.proto to the lite library (#7738)
Python
* Print google.protobuf.NullValue as null instead of "NULL_VALUE" when it is
used outside WKT Value/Struct.
* Fix bug occurring when attempting to deep copy an enum type in python 3.
* Add a setuptools extension for generating Python protobufs (#7783)
* Remove uses of pkg_resources in non-namespace packages. (#7902)
* [bazel/py] Omit google/__init__.py from the Protobuf runtime. (#7908)
* Removed the unnecessary setuptools package dependency for Python package (#7511)
* Fix PyUnknownFields memory leak (#7928)
PHP
* Added support for "==" to the PHP C extension (#7883)
* Added `==` operators for Map and Array. (#7900)
* Native C well-known types (#7944)
* Optimized away hex2bin() call in generated code (#8006)
* New version of upb, and a new hash function wyhash in third_party. (#8000)
* add missing hasOneof method to check presence of oneof fields (#8003)
Go:
* Update go_package options to reference google.golang.org/protobuf module.
C#:
* annotate ByteString.CopyFrom(ReadOnlySpan<byte>) as SecuritySafeCritical (#7701)
* Fix C# optional field reflection when there are regular fields too (#7705)
* Fix parsing negative Int32Value that crosses segment boundary (#8035)
Javascript:
* JS: parse (un)packed fields conditionally (#7379)
2020-07-14 version 3.13.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)

@ -5,7 +5,7 @@
# dependent projects use the :git notation to refer to the library.
Pod::Spec.new do |s|
s.name = 'Protobuf'
s.version = '3.13.0'
s.version = '3.14.0'
s.summary = 'Protocol Buffers v.3 runtime library for Objective-C.'
s.homepage = 'https://github.com/protocolbuffers/protobuf'
s.license = '3-Clause BSD License'
@ -34,7 +34,7 @@ Pod::Spec.new do |s|
s.user_target_xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1' }
s.pod_target_xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1' }
s.ios.deployment_target = '7.0'
s.ios.deployment_target = '9.0'
s.osx.deployment_target = '10.9'
s.tvos.deployment_target = '9.0'
s.watchos.deployment_target = '2.0'

@ -44,6 +44,7 @@ option(protobuf_BUILD_TESTS "Build tests" ON)
option(protobuf_BUILD_CONFORMANCE "Build conformance tests" OFF)
option(protobuf_BUILD_EXAMPLES "Build examples" OFF)
option(protobuf_BUILD_PROTOC_BINARIES "Build libprotoc and protoc compiler" ON)
option(protobuf_BUILD_LIBPROTOC "Build libprotoc" OFF)
if (BUILD_SHARED_LIBS)
set(protobuf_BUILD_SHARED_LIBS_DEFAULT ON)
else (BUILD_SHARED_LIBS)
@ -64,8 +65,6 @@ include(protobuf-options.cmake)
# Overrides for option dependencies
if (protobuf_BUILD_PROTOC_BINARIES OR protobuf_BUILD_TESTS)
set(protobuf_BUILD_LIBPROTOC ON)
else()
set(protobuf_BUILD_LIBPROTOC OFF)
endif ()
# Path to main configure script
set(protobuf_CONFIGURE_SCRIPT "../configure.ac")

@ -87,7 +87,6 @@ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\bytestream.h" i
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\callback.h" include\google\protobuf\stubs\callback.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\casts.h" include\google\protobuf\stubs\casts.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\common.h" include\google\protobuf\stubs\common.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\fastmem.h" include\google\protobuf\stubs\fastmem.h
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

@ -6,9 +6,9 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/protobuf-lite.pc.cmake
${CMAKE_CURRENT_BINARY_DIR}/protobuf-lite.pc @ONLY)
set(_protobuf_libraries libprotobuf-lite libprotobuf)
if (protobuf_BUILD_PROTOC_BINARIES)
if (protobuf_BUILD_LIBPROTOC)
list(APPEND _protobuf_libraries libprotoc)
endif (protobuf_BUILD_PROTOC_BINARIES)
endif (protobuf_BUILD_LIBPROTOC)
foreach(_library ${_protobuf_libraries})
set_property(TARGET ${_library}

@ -69,6 +69,9 @@ target_link_libraries(libprotobuf-lite ${CMAKE_THREAD_LIBS_INIT})
if(protobuf_LINK_LIBATOMIC)
target_link_libraries(libprotobuf-lite atomic)
endif()
if(${CMAKE_SYSTEM_NAME} STREQUAL "Android")
target_link_libraries(libprotobuf-lite log)
endif()
target_include_directories(libprotobuf-lite PUBLIC ${protobuf_source_dir}/src)
if(MSVC AND protobuf_BUILD_SHARED_LIBS)
target_compile_definitions(libprotobuf-lite

@ -2,7 +2,6 @@ set(libprotobuf_files
${protobuf_source_dir}/src/google/protobuf/any.cc
${protobuf_source_dir}/src/google/protobuf/any.pb.cc
${protobuf_source_dir}/src/google/protobuf/api.pb.cc
${protobuf_source_dir}/src/google/protobuf/arenastring.cc
${protobuf_source_dir}/src/google/protobuf/compiler/importer.cc
${protobuf_source_dir}/src/google/protobuf/compiler/parser.cc
${protobuf_source_dir}/src/google/protobuf/descriptor.cc
@ -122,6 +121,9 @@ endif()
if(protobuf_LINK_LIBATOMIC)
target_link_libraries(libprotobuf atomic)
endif()
if(${CMAKE_SYSTEM_NAME} STREQUAL "Android")
target_link_libraries(libprotobuf log)
endif()
target_include_directories(libprotobuf PUBLIC ${protobuf_source_dir}/src)
if(MSVC AND protobuf_BUILD_SHARED_LIBS)
target_compile_definitions(libprotobuf

@ -97,6 +97,10 @@ function(_protobuf_find_libraries name filename)
else()
get_target_property(${name}_LIBRARY_RELEASE protobuf::lib${filename}
LOCATION_RELEASE)
get_target_property(${name}_LIBRARY_RELWITHDEBINFO protobuf::lib${filename}
LOCATION_RELWITHDEBINFO)
get_target_property(${name}_LIBRARY_MINSIZEREL protobuf::lib${filename}
LOCATION_MINSIZEREL)
get_target_property(${name}_LIBRARY_DEBUG protobuf::lib${filename}
LOCATION_DEBUG)
@ -146,6 +150,14 @@ get_target_property(Protobuf_INCLUDE_DIRS protobuf::libprotobuf
# Set the protoc Executable
get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
IMPORTED_LOCATION_RELEASE)
if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
IMPORTED_LOCATION_RELWITHDEBINFO)
endif()
if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
IMPORTED_LOCATION_MINSIZEREL)
endif()
if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc
IMPORTED_LOCATION_DEBUG)

@ -333,7 +333,7 @@ conformance-php-c:
# Targets for actually running tests.
test_cpp: protoc_middleman conformance-test-runner conformance-cpp
./conformance-test-runner --enforce_recommended --failure_list failure_list_cpp.txt ./conformance-cpp
./conformance-test-runner --enforce_recommended --failure_list failure_list_cpp.txt --text_format_failure_list text_format_failure_list_cpp.txt ./conformance-cpp
test_java: protoc_middleman conformance-test-runner conformance-java
./conformance-test-runner --enforce_recommended --failure_list failure_list_java.txt --text_format_failure_list text_format_failure_list_java.txt ./conformance-java
@ -359,10 +359,24 @@ test_php_c_32: protoc_middleman conformance-test-runner conformance-php-c $(othe
# These depend on library paths being properly set up. The easiest way to
# run them is to just use "tox" from the python dir.
test_python: protoc_middleman conformance-test-runner
./conformance-test-runner --enforce_recommended --failure_list failure_list_python.txt --text_format_failure_list text_format_failure_list_python.txt ./conformance_python.py
VERSION="$(shell python --version 2>&1)"; \
if [[ "$$VERSION" == "Python 2.7"* ]]; then \
echo "Using Python 2.7 failure list."; \
./conformance-test-runner --enforce_recommended --failure_list failure_list_python.txt --text_format_failure_list text_format_failure_list_python_2.7.txt ./conformance_python.py; \
else \
echo "Using Python >2.7 failure list."; \
./conformance-test-runner --enforce_recommended --failure_list failure_list_python.txt --text_format_failure_list text_format_failure_list_python.txt ./conformance_python.py; \
fi
test_python_cpp: protoc_middleman conformance-test-runner
./conformance-test-runner --enforce_recommended --failure_list failure_list_python_cpp.txt ./conformance_python.py
VERSION="$(shell python --version 2>&1)"; \
if [[ "$$VERSION" == "Python 2.7"* ]]; then \
echo "Using Python 2.7 failure list."; \
./conformance-test-runner --enforce_recommended --failure_list failure_list_python_cpp.txt --text_format_failure_list text_format_failure_list_python_cpp_2.7.txt ./conformance_python.py; \
else \
echo "Using Python >2.7 failure list."; \
./conformance-test-runner --enforce_recommended --failure_list failure_list_python_cpp.txt --text_format_failure_list text_format_failure_list_python_cpp.txt ./conformance_python.py; \
fi
test_nodejs: protoc_middleman conformance-test-runner $(other_language_protoc_outputs)
NODE_PATH=../js:. ./conformance-test-runner --enforce_recommended --failure_list failure_list_js.txt ./conformance_nodejs.js

@ -36,6 +36,7 @@
#include <google/protobuf/text_format.h>
#include <google/protobuf/util/json_util.h>
#include <google/protobuf/util/type_resolver_util.h>
#include <google/protobuf/stubs/status.h>
#include "conformance.pb.h"
#include <google/protobuf/test_messages_proto2.pb.h>
#include <google/protobuf/test_messages_proto3.pb.h>
@ -125,9 +126,9 @@ void DoTest(const ConformanceRequest& request, ConformanceResponse* response) {
options.ignore_unknown_fields =
(request.test_category() ==
conformance::JSON_IGNORE_UNKNOWN_PARSING_TEST);
Status status = JsonToBinaryString(type_resolver, *type_url,
request.json_payload(), &proto_binary,
options);
util::Status status =
JsonToBinaryString(type_resolver, *type_url, request.json_payload(),
&proto_binary, options);
if (!status.ok()) {
response->set_parse_error(string("Parse error: ") +
std::string(status.error_message()));
@ -179,8 +180,9 @@ void DoTest(const ConformanceRequest& request, ConformanceResponse* response) {
case conformance::JSON: {
string proto_binary;
GOOGLE_CHECK(test_message->SerializeToString(&proto_binary));
Status status = BinaryToJsonString(type_resolver, *type_url, proto_binary,
response->mutable_json_payload());
util::Status status =
BinaryToJsonString(type_resolver, *type_url, proto_binary,
response->mutable_json_payload());
if (!status.ok()) {
response->set_serialize_error(
string("Failed to serialize JSON output: ") +

@ -1,4 +1,2 @@
Recommended.Proto2.JsonInput.FieldNameExtension.Validator
Recommended.Proto3.JsonInput.NullValueInOtherOneofNewFormat.Validator
Recommended.Proto3.JsonInput.NullValueInOtherOneofOldFormat.Validator
Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator

@ -1,4 +0,0 @@
Recommended.Proto2.JsonInput.FieldNameExtension.Validator
Recommended.Proto3.JsonInput.NullValueInOtherOneofNewFormat.Validator
Recommended.Proto3.JsonInput.NullValueInOtherOneofOldFormat.Validator
Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator

@ -259,8 +259,7 @@ void TextFormatConformanceTestSuite::RunSuiteImpl() {
"optional_float: 18446744073709551616");
// String literals x {Strings, Bytes}
for (const auto& field_type :
std::vector<const std::string>{"String", "Bytes"}) {
for (const auto& field_type : std::vector<std::string>{"String", "Bytes"}) {
const std::string field_name =
field_type == "String" ? "optional_string" : "optional_bytes";
RunValidTextFormatTest(

@ -0,0 +1,36 @@
# This is the list of text format conformance tests that are known to fail right
# now.
# TODO: These should be fixed.
Required.Proto3.TextFormatInput.FloatFieldMaxValue.ProtobufOutput
Required.Proto3.TextFormatInput.FloatFieldMaxValue.TextFormatOutput
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.ProtobufOutput
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.TextFormatOutput
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.ProtobufOutput
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.TextFormatOutput
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.ProtobufOutput
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.TextFormatOutput
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.ProtobufOutput
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.TextFormatOutput
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString
Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes
Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString
Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes
Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput
Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeBytes
Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeString

@ -0,0 +1,30 @@
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.ProtobufOutput
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.TextFormatOutput
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.ProtobufOutput
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.TextFormatOutput
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.ProtobufOutput
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.TextFormatOutput
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.ProtobufOutput
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.TextFormatOutput
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString
Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes
Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString
Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes
Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput
Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeBytes
Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeString

@ -5,7 +5,7 @@
<title>Google Protocol Buffers tools</title>
<summary>Tools for Protocol Buffers - Google's data interchange format.</summary>
<description>See project site for more info.</description>
<version>3.13.0</version>
<version>3.14.0</version>
<authors>Google Inc.</authors>
<owners>protobuf-packages</owners>
<licenseUrl>https://github.com/protocolbuffers/protobuf/blob/master/LICENSE</licenseUrl>

@ -1,6 +1,7 @@
#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
// Copyright 2019 Google Inc. All rights reserved.
// https://github.com/protocolbuffers/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@ -27,20 +28,45 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
#ifndef PHP_PROTOBUF_BUNDLED_PHP_H_
#define PHP_PROTOBUF_BUNDLED_PHP_H_
using BenchmarkDotNet.Attributes;
// We embed PHP source code into the binary for things we don't want to
// implement in C. This struct serves as a table of contents for all of
// the embedded files.
typedef struct {
const char *filename;
const char *contents;
} BundledPhp_File;
namespace Google.Protobuf.Benchmarks
{
/// <summary>
/// Benchmarks using ByteString.
/// </summary>
[MemoryDiagnoser]
public class ByteStringBenchmark
{
private const int Zero = 0;
private const int Kilobyte = 1024;
private const int _128Kilobytes = 1024 * 128;
private const int Megabyte = 1024 * 1024;
private const int _10Megabytes = 1024 * 1024 * 10;
// An array of all the embedded file structs. This array is terminated with a
// {NULL, NULL} entry.
extern BundledPhp_File *bundled_files;
byte[] byteBuffer;
#endif // PHP_PROTOBUF_BUNDLED_PHP_H_
[GlobalSetup]
public void GlobalSetup()
{
byteBuffer = new byte[PayloadSize];
}
[Params(Zero, Kilobyte, _128Kilobytes, Megabyte, _10Megabytes)]
public int PayloadSize { get; set; }
[Benchmark]
public ByteString CopyFrom()
{
return ByteString.CopyFrom(byteBuffer);
}
[Benchmark]
public ByteString UnsafeWrap()
{
return UnsafeByteOperations.UnsafeWrap(byteBuffer);
}
}
}

@ -34,6 +34,13 @@ using System;
using System.Text;
using NUnit.Framework;
using System.IO;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Buffers;
using System.Runtime.InteropServices;
using System.Threading;
using System.Runtime.CompilerServices;
#if !NET35
using System.Threading.Tasks;
#endif
@ -54,6 +61,7 @@ namespace Google.Protobuf
EqualityTester.AssertInequality(b1, b3);
EqualityTester.AssertInequality(b1, b4);
EqualityTester.AssertInequality(b1, null);
EqualityTester.AssertEquality(ByteString.Empty, ByteString.Empty);
#pragma warning disable 1718 // Deliberately calling ==(b1, b1) and !=(b1, b1)
Assert.IsTrue(b1 == b1);
Assert.IsTrue(b1 == b2);
@ -63,6 +71,7 @@ namespace Google.Protobuf
Assert.IsTrue((ByteString) null == null);
Assert.IsFalse(b1 != b1);
Assert.IsFalse(b1 != b2);
Assert.IsTrue(ByteString.Empty == ByteString.Empty);
#pragma warning disable 1718
Assert.IsTrue(b1 != b3);
Assert.IsTrue(b1 != b4);
@ -110,6 +119,18 @@ namespace Google.Protobuf
Assert.AreEqual(10, bs[0]);
}
[Test]
public void CopyFromReadOnlySpanCopiesContents()
{
byte[] data = new byte[1];
data[0] = 10;
ReadOnlySpan<byte> byteSpan = data;
var bs = ByteString.CopyFrom(byteSpan);
Assert.AreEqual(10, bs[0]);
data[0] = 5;
Assert.AreEqual(10, bs[0]);
}
[Test]
public void ToByteArrayCopiesContents()
{
@ -142,6 +163,84 @@ namespace Google.Protobuf
Assert.AreEqual(3, bs[1]);
}
[Test]
public void CopyTo()
{
byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
ByteString bs = ByteString.CopyFrom(data);
byte[] dest = new byte[data.Length];
bs.CopyTo(dest, 0);
CollectionAssert.AreEqual(data, dest);
}
[Test]
public void GetEnumerator()
{
byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
ByteString bs = ByteString.CopyFrom(data);
IEnumerator<byte> genericEnumerator = bs.GetEnumerator();
Assert.IsTrue(genericEnumerator.MoveNext());
Assert.AreEqual(0, genericEnumerator.Current);
IEnumerator enumerator = ((IEnumerable)bs).GetEnumerator();
Assert.IsTrue(enumerator.MoveNext());
Assert.AreEqual(0, enumerator.Current);
// Call via LINQ
CollectionAssert.AreEqual(bs.Span.ToArray(), bs.ToArray());
}
[Test]
public void UnsafeWrap()
{
byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
ByteString bs = UnsafeByteOperations.UnsafeWrap(data.AsMemory(2, 3));
ReadOnlySpan<byte> s = bs.Span;
Assert.AreEqual(3, s.Length);
Assert.AreEqual(2, s[0]);
Assert.AreEqual(3, s[1]);
Assert.AreEqual(4, s[2]);
// Check that the value is not a copy
data[2] = byte.MaxValue;
Assert.AreEqual(byte.MaxValue, s[0]);
}
[Test]
public void WriteToStream()
{
byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
ByteString bs = ByteString.CopyFrom(data);
MemoryStream ms = new MemoryStream();
bs.WriteTo(ms);
CollectionAssert.AreEqual(data, ms.ToArray());
}
[Test]
public void WriteToStream_Stackalloc()
{
byte[] data = Encoding.UTF8.GetBytes("Hello world");
Span<byte> s = stackalloc byte[data.Length];
data.CopyTo(s);
MemoryStream ms = new MemoryStream();
using (UnmanagedMemoryManager<byte> manager = new UnmanagedMemoryManager<byte>(s))
{
ByteString bs = ByteString.AttachBytes(manager.Memory);
bs.WriteTo(ms);
}
CollectionAssert.AreEqual(data, ms.ToArray());
}
[Test]
public void ToStringUtf8()
{
@ -156,6 +255,21 @@ namespace Google.Protobuf
Assert.AreEqual("\u20ac", bs.ToString(Encoding.Unicode));
}
[Test]
public void ToString_Stackalloc()
{
byte[] data = Encoding.UTF8.GetBytes("Hello world");
Span<byte> s = stackalloc byte[data.Length];
data.CopyTo(s);
using (UnmanagedMemoryManager<byte> manager = new UnmanagedMemoryManager<byte>(s))
{
ByteString bs = ByteString.AttachBytes(manager.Memory);
Assert.AreEqual("Hello world", bs.ToString(Encoding.UTF8));
}
}
[Test]
public void FromBase64_WithText()
{
@ -172,6 +286,29 @@ namespace Google.Protobuf
Assert.AreSame(ByteString.Empty, ByteString.FromBase64(""));
}
[Test]
public void ToBase64_Array()
{
ByteString bs = ByteString.CopyFrom(Encoding.UTF8.GetBytes("Hello world"));
Assert.AreEqual("SGVsbG8gd29ybGQ=", bs.ToBase64());
}
[Test]
public void ToBase64_Stackalloc()
{
byte[] data = Encoding.UTF8.GetBytes("Hello world");
Span<byte> s = stackalloc byte[data.Length];
data.CopyTo(s);
using (UnmanagedMemoryManager<byte> manager = new UnmanagedMemoryManager<byte>(s))
{
ByteString bs = ByteString.AttachBytes(manager.Memory);
Assert.AreEqual("SGVsbG8gd29ybGQ=", bs.ToBase64());
}
}
[Test]
public void FromStream_Seekable()
{
@ -249,5 +386,38 @@ namespace Google.Protobuf
var copied = byteString.Memory.ToArray();
CollectionAssert.AreEqual(byteString, copied);
}
// Create Memory<byte> from non-array source.
// Use by ByteString tests that have optimized path for array backed Memory<byte>.
private sealed unsafe class UnmanagedMemoryManager<T> : MemoryManager<T> where T : unmanaged
{
private readonly T* _pointer;
private readonly int _length;
public UnmanagedMemoryManager(Span<T> span)
{
fixed (T* ptr = &MemoryMarshal.GetReference(span))
{
_pointer = ptr;
_length = span.Length;
}
}
public override Span<T> GetSpan() => new Span<T>(_pointer, _length);
public override MemoryHandle Pin(int elementIndex = 0)
{
if (elementIndex < 0 || elementIndex >= _length)
{
throw new ArgumentOutOfRangeException(nameof(elementIndex));
}
return new MemoryHandle(_pointer + elementIndex);
}
public override void Unpin() { }
protected override void Dispose(bool disposing) { }
}
}
}

@ -343,6 +343,25 @@ namespace Google.Protobuf
}
}
[Test]
public void ReadInt32Wrapper_VariableBlockSizes()
{
byte[] rawBytes = new byte[] { 202, 1, 11, 8, 254, 255, 255, 255, 255, 255, 255, 255, 255, 1 };
for (int blockSize = 1; blockSize <= rawBytes.Length; blockSize++)
{
ReadOnlySequence<byte> data = ReadOnlySequenceFactory.CreateWithContent(rawBytes, blockSize);
AssertReadFromParseContext(data, (ref ParseContext ctx) =>
{
ctx.ReadTag();
var value = ParsingPrimitivesWrappers.ReadInt32Wrapper(ref ctx);
Assert.AreEqual(-2, value);
}, true);
}
}
[Test]
public void ReadHugeBlob()
{

@ -6,6 +6,7 @@
<SignAssembly>true</SignAssembly>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<IsPackable>False</IsPackable>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>

@ -87,6 +87,28 @@ namespace Google.Protobuf.WellKnownTypes
});
}
[Test]
public void NegativeSingleValues()
{
var message = new TestWellKnownTypes
{
FloatField = -12.5f,
DoubleField = -12.25d,
Int32Field = -1,
Int64Field = -2
};
MessageParsingHelpers.AssertWritingMessage(message);
MessageParsingHelpers.AssertRoundtrip(TestWellKnownTypes.Parser, message, parsed =>
{
Assert.AreEqual(-12.5f, parsed.FloatField);
Assert.AreEqual(-12.25d, parsed.DoubleField);
Assert.AreEqual(-1, parsed.Int32Field);
Assert.AreEqual(-2L, parsed.Int64Field);
});
}
[Test]
public void NonNullDefaultIsPreservedThroughSerialization()
{

@ -34,6 +34,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
#if !NET35
@ -49,40 +50,36 @@ namespace Google.Protobuf
/// <summary>
/// Immutable array of bytes.
/// </summary>
[SecuritySafeCritical]
public sealed class ByteString : IEnumerable<byte>, IEquatable<ByteString>
{
private static readonly ByteString empty = new ByteString(new byte[0]);
private readonly byte[] bytes;
private readonly ReadOnlyMemory<byte> bytes;
/// <summary>
/// Unsafe operations that can cause IO Failure and/or other catastrophic side-effects.
/// Internal use only. Ensure that the provided memory is not mutated and belongs to this instance.
/// </summary>
internal static class Unsafe
internal static ByteString AttachBytes(ReadOnlyMemory<byte> bytes)
{
/// <summary>
/// Constructs a new ByteString from the given byte array. The array is
/// *not* copied, and must not be modified after this constructor is called.
/// </summary>
internal static ByteString FromBytes(byte[] bytes)
{
return new ByteString(bytes);
}
return new ByteString(bytes);
}
/// <summary>
/// Internal use only. Ensure that the provided array is not mutated and belongs to this instance.
/// Internal use only. Ensure that the provided memory is not mutated and belongs to this instance.
/// This method encapsulates converting array to memory. Reduces need for SecuritySafeCritical
/// in .NET Framework.
/// </summary>
internal static ByteString AttachBytes(byte[] bytes)
{
return new ByteString(bytes);
return AttachBytes(bytes.AsMemory());
}
/// <summary>
/// Constructs a new ByteString from the given byte array. The array is
/// Constructs a new ByteString from the given memory. The memory is
/// *not* copied, and must not be modified after this constructor is called.
/// </summary>
private ByteString(byte[] bytes)
private ByteString(ReadOnlyMemory<byte> bytes)
{
this.bytes = bytes;
}
@ -111,18 +108,13 @@ namespace Google.Protobuf
get { return Length == 0; }
}
#if GOOGLE_PROTOBUF_SUPPORT_SYSTEM_MEMORY
/// <summary>
/// Provides read-only access to the data of this <see cref="ByteString"/>.
/// No data is copied so this is the most efficient way of accessing.
/// </summary>
public ReadOnlySpan<byte> Span
{
[SecuritySafeCritical]
get
{
return new ReadOnlySpan<byte>(bytes);
}
get { return bytes.Span; }
}
/// <summary>
@ -131,13 +123,8 @@ namespace Google.Protobuf
/// </summary>
public ReadOnlyMemory<byte> Memory
{
[SecuritySafeCritical]
get
{
return new ReadOnlyMemory<byte>(bytes);
}
get { return bytes; }
}
#endif
/// <summary>
/// Converts this <see cref="ByteString"/> into a byte array.
@ -146,7 +133,7 @@ namespace Google.Protobuf
/// <returns>A byte array with the same data as this <c>ByteString</c>.</returns>
public byte[] ToByteArray()
{
return (byte[]) bytes.Clone();
return bytes.ToArray();
}
/// <summary>
@ -155,7 +142,16 @@ namespace Google.Protobuf
/// <returns>A base64 representation of this <c>ByteString</c>.</returns>
public string ToBase64()
{
return Convert.ToBase64String(bytes);
if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment))
{
// Fast path. ByteString was created with an array, so pass the underlying array.
return Convert.ToBase64String(segment.Array, segment.Offset, segment.Count);
}
else
{
// Slow path. BytesString is not an array. Convert memory and pass result to ToBase64String.
return Convert.ToBase64String(bytes.ToArray());
}
}
/// <summary>
@ -199,21 +195,10 @@ namespace Google.Protobuf
/// <param name="stream">The stream to copy into a ByteString.</param>
/// <param name="cancellationToken">The cancellation token to use when reading from the stream, if any.</param>
/// <returns>A ByteString with content read from the given stream.</returns>
public async static Task<ByteString> FromStreamAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken))
public static Task<ByteString> FromStreamAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken))
{
ProtoPreconditions.CheckNotNull(stream, nameof(stream));
int capacity = stream.CanSeek ? checked((int) (stream.Length - stream.Position)) : 0;
var memoryStream = new MemoryStream(capacity);
// We have to specify the buffer size here, as there's no overload accepting the cancellation token
// alone. But it's documented to use 81920 by default if not specified.
await stream.CopyToAsync(memoryStream, 81920, cancellationToken);
#if NETSTANDARD1_1 || NETSTANDARD2_0
byte[] bytes = memoryStream.ToArray();
#else
// Avoid an extra copy if we can.
byte[] bytes = memoryStream.Length == memoryStream.Capacity ? memoryStream.GetBuffer() : memoryStream.ToArray();
#endif
return AttachBytes(bytes);
return ByteStringAsync.FromStreamAsyncCore(stream, cancellationToken);
}
#endif
@ -239,7 +224,6 @@ namespace Google.Protobuf
return new ByteString(portion);
}
#if GOOGLE_PROTOBUF_SUPPORT_SYSTEM_MEMORY
/// <summary>
/// Constructs a <see cref="ByteString" /> from a read only span. The contents
/// are copied, so further modifications to the span will not
@ -249,7 +233,6 @@ namespace Google.Protobuf
{
return new ByteString(bytes.ToArray());
}
#endif
/// <summary>
/// Creates a new <see cref="ByteString" /> by encoding the specified text with
@ -273,7 +256,7 @@ namespace Google.Protobuf
/// </summary>
public byte this[int index]
{
get { return bytes[index]; }
get { return bytes.Span[index]; }
}
/// <summary>
@ -287,7 +270,18 @@ namespace Google.Protobuf
/// <returns>The result of decoding the binary data with the given decoding.</returns>
public string ToString(Encoding encoding)
{
return encoding.GetString(bytes, 0, bytes.Length);
if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment))
{
// Fast path. ByteString was created with an array.
return encoding.GetString(segment.Array, segment.Offset, segment.Count);
}
else
{
// Slow path. BytesString is not an array. Convert memory and pass result to GetString.
// TODO: Consider using GetString overload that takes a pointer.
byte[] array = bytes.ToArray();
return encoding.GetString(array, 0, array.Length);
}
}
/// <summary>
@ -307,9 +301,10 @@ namespace Google.Protobuf
/// Returns an iterator over the bytes in this <see cref="ByteString"/>.
/// </summary>
/// <returns>An iterator over the bytes in this object.</returns>
[SecuritySafeCritical]
public IEnumerator<byte> GetEnumerator()
{
return ((IEnumerable<byte>) bytes).GetEnumerator();
return MemoryMarshal.ToEnumerable(bytes).GetEnumerator();
}
/// <summary>
@ -327,7 +322,17 @@ namespace Google.Protobuf
public CodedInputStream CreateCodedInput()
{
// We trust CodedInputStream not to reveal the provided byte array or modify it
return new CodedInputStream(bytes);
if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment) && segment.Count == bytes.Length)
{
// Fast path. ByteString was created with a complete array.
return new CodedInputStream(segment.Array);
}
else
{
// Slow path. BytesString is not an array, or is a slice of an array.
// Convert memory and pass result to WriteRawBytes.
return new CodedInputStream(bytes.ToArray());
}
}
/// <summary>
@ -346,18 +351,8 @@ namespace Google.Protobuf
{
return false;
}
if (lhs.bytes.Length != rhs.bytes.Length)
{
return false;
}
for (int i = 0; i < lhs.Length; i++)
{
if (rhs.bytes[i] != lhs.bytes[i])
{
return false;
}
}
return true;
return lhs.bytes.Span.SequenceEqual(rhs.bytes.Span);
}
/// <summary>
@ -376,6 +371,7 @@ namespace Google.Protobuf
/// </summary>
/// <param name="obj">The object to compare this with.</param>
/// <returns><c>true</c> if <paramref name="obj"/> refers to an equal <see cref="ByteString"/>; <c>false</c> otherwise.</returns>
[SecuritySafeCritical]
public override bool Equals(object obj)
{
return this == (obj as ByteString);
@ -386,12 +382,15 @@ namespace Google.Protobuf
/// will return the same hash code.
/// </summary>
/// <returns>A hash code for this object.</returns>
[SecuritySafeCritical]
public override int GetHashCode()
{
ReadOnlySpan<byte> b = bytes.Span;
int ret = 23;
foreach (byte b in bytes)
for (int i = 0; i < b.Length; i++)
{
ret = (ret * 31) + b;
ret = (ret * 31) + b[i];
}
return ret;
}
@ -406,20 +405,12 @@ namespace Google.Protobuf
return this == other;
}
/// <summary>
/// Used internally by CodedOutputStream to avoid creating a copy for the write
/// </summary>
internal void WriteRawBytesTo(CodedOutputStream outputStream)
{
outputStream.WriteRawBytes(bytes, 0, bytes.Length);
}
/// <summary>
/// Copies the entire byte array to the destination array provided at the offset specified.
/// </summary>
public void CopyTo(byte[] array, int position)
{
ByteArray.Copy(bytes, 0, array, position, bytes.Length);
bytes.CopyTo(array.AsMemory(position));
}
/// <summary>
@ -427,7 +418,17 @@ namespace Google.Protobuf
/// </summary>
public void WriteTo(Stream outputStream)
{
outputStream.Write(bytes, 0, bytes.Length);
if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment))
{
// Fast path. ByteString was created with an array, so pass the underlying array.
outputStream.Write(segment.Array, segment.Offset, segment.Count);
}
else
{
// Slow path. BytesString is not an array. Convert memory and pass result to WriteRawBytes.
var array = bytes.ToArray();
outputStream.Write(array, 0, array.Length);
}
}
}
}

@ -0,0 +1,64 @@
#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace Google.Protobuf
{
/// <summary>
/// SecuritySafeCritical attribute can not be placed on types with async methods.
/// This class has ByteString's async methods so it can be marked with SecuritySafeCritical.
/// </summary>
internal static class ByteStringAsync
{
#if !NET35
internal static async Task<ByteString> FromStreamAsyncCore(Stream stream, CancellationToken cancellationToken)
{
int capacity = stream.CanSeek ? checked((int)(stream.Length - stream.Position)) : 0;
var memoryStream = new MemoryStream(capacity);
// We have to specify the buffer size here, as there's no overload accepting the cancellation token
// alone. But it's documented to use 81920 by default if not specified.
await stream.CopyToAsync(memoryStream, 81920, cancellationToken);
#if NETSTANDARD1_1
byte[] bytes = memoryStream.ToArray();
#else
// Avoid an extra copy if we can.
byte[] bytes = memoryStream.Length == memoryStream.Capacity ? memoryStream.GetBuffer() : memoryStream.ToArray();
#endif
return ByteString.AttachBytes(bytes);
}
#endif
}
}

@ -4,7 +4,7 @@
<Description>C# runtime library for Protocol Buffers - Google's data interchange format.</Description>
<Copyright>Copyright 2015, Google Inc.</Copyright>
<AssemblyTitle>Google Protocol Buffers</AssemblyTitle>
<VersionPrefix>3.13.0</VersionPrefix>
<VersionPrefix>3.14.0</VersionPrefix>
<!-- C# 7.2 is required for Span/BufferWriter/ReadOnlySequence -->
<LangVersion>7.2</LangVersion>
<Authors>Google Inc.</Authors>
@ -19,7 +19,6 @@
<PackageLicenseUrl>https://github.com/protocolbuffers/protobuf/blob/master/LICENSE</PackageLicenseUrl>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/protocolbuffers/protobuf.git</RepositoryUrl>
<DefineConstants>$(DefineConstants);GOOGLE_PROTOBUF_SUPPORT_SYSTEM_MEMORY</DefineConstants>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<!-- Include PDB in the built .nupkg -->
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>

@ -32,7 +32,6 @@
namespace Google.Protobuf
{
#if GOOGLE_PROTOBUF_SUPPORT_SYSTEM_MEMORY
/// <summary>
/// Interface for a Protocol Buffers message, supporting
/// parsing from <see cref="ParseContext"/> and writing to <see cref="WriteContext"/>.
@ -51,5 +50,4 @@ namespace Google.Protobuf
/// </summary>
void InternalWriteTo(ref WriteContext ctx);
}
#endif
}

@ -160,8 +160,11 @@ namespace Google.Protobuf
internal static uint? ReadUInt32Wrapper(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
{
// length:1 + tag:1 + value:5(varint32-max) = 7 bytes
if (state.bufferPos + 7 <= state.bufferSize)
// field=1, type=varint = tag of 8
const int expectedTag = 8;
// length:1 + tag:1 + value:10(varint64-max) = 12 bytes
// Value can be 64 bits for negative integers
if (state.bufferPos + 12 <= state.bufferSize)
{
// The entire wrapper message is already contained in `buffer`.
int pos0 = state.bufferPos;
@ -177,8 +180,7 @@ namespace Google.Protobuf
return ReadUInt32WrapperSlow(ref buffer, ref state);
}
int finalBufferPos = state.bufferPos + length;
// field=1, type=varint = tag of 8
if (buffer[state.bufferPos++] != 8)
if (buffer[state.bufferPos++] != expectedTag)
{
state.bufferPos = pos0;
return ReadUInt32WrapperSlow(ref buffer, ref state);

@ -0,0 +1,81 @@
#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Security;
namespace Google.Protobuf
{
/// <summary>
/// Provides a number of unsafe byte operations to be used by advanced applications with high performance
/// requirements. These methods are referred to as "unsafe" due to the fact that they potentially expose
/// the backing buffer of a <see cref="ByteString"/> to the application.
/// </summary>
/// <remarks>
/// <para>
/// The methods in this class should only be called if it is guaranteed that the buffer backing the
/// <see cref="ByteString"/> will never change! Mutation of a <see cref="ByteString"/> can lead to unexpected
/// and undesirable consequences in your application, and will likely be difficult to debug. Proceed with caution!
/// </para>
/// <para>
/// This can have a number of significant side affects that have spooky-action-at-a-distance-like behavior. In
/// particular, if the bytes value changes out from under a Protocol Buffer:
/// </para>
/// <list type="bullet">
/// <item>
/// <description>serialization may throw</description>
/// </item>
/// <item>
/// <description>serialization may succeed but the wrong bytes may be written out</description>
/// </item>
/// <item>
/// <description>objects that are normally immutable (such as ByteString) are no longer immutable</description>
/// </item>
/// <item>
/// <description>hashCode may be incorrect</description>
/// </item>
/// </list>
/// </remarks>
[SecuritySafeCritical]
public static class UnsafeByteOperations
{
/// <summary>
/// Constructs a new <see cref="ByteString" /> from the given bytes. The bytes are not copied,
/// and must not be modified while the <see cref="ByteString" /> is in use.
/// This API is experimental and subject to change.
/// </summary>
public static ByteString UnsafeWrap(ReadOnlyMemory<byte> bytes)
{
return ByteString.AttachBytes(bytes);
}
}
}

@ -93,8 +93,8 @@ with info about your project (name and website) so we can add an entry for you.
* Website: https://github.com/protobuf-c/protobuf-c
* Extensions: 1019
1. ScalePB
* Website: http://trueaccord.github.io/ScalaPB/
1. ScalaPB
* Website: https://scalapb.github.io/
* Extensions: 1020
1. protoc-gen-bq-schema

@ -69,10 +69,10 @@ syn keyword pbBool true false
syn match pbInt /-\?\<\d\+\>/
syn match pbInt /\<0[xX]\x+\>/
syn match pbFloat /\<-\?\d*\(\.\d*\)\?/
syn region pbComment start="\/\*" end="\*\/" contains=@pbCommentGrp
syn region pbComment start="//" skip="\\$" end="$" keepend contains=@pbCommentGrp
syn region pbString start=/"/ skip=/\\./ end=/"/
syn region pbString start=/'/ skip=/\\./ end=/'/
syn region pbComment start="\/\*" end="\*\/" contains=@pbCommentGrp,@Spell
syn region pbComment start="//" skip="\\$" end="$" keepend contains=@pbCommentGrp,@Spell
syn region pbString start=/"/ skip=/\\./ end=/"/ contains=@Spell
syn region pbString start=/'/ skip=/\\./ end=/'/ contains=@Spell
if version >= 508 || !exists("did_proto_syn_inits")
if version < 508

@ -4,7 +4,7 @@
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-bom</artifactId>
<version>3.13.0</version>
<version>3.14.0</version>
<packaging>pom</packaging>
<name>Protocol Buffers [BOM]</name>

@ -4,7 +4,7 @@
<parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
<version>3.13.0</version>
<version>3.14.0</version>
</parent>
<artifactId>protobuf-java</artifactId>

@ -119,7 +119,6 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
}
/** Make this FieldSet immutable from this point forward. */
@SuppressWarnings("unchecked")
public void makeImmutable() {
if (isImmutable) {
return;
@ -286,11 +285,11 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
final List newList = new ArrayList();
newList.addAll((List) value);
for (final Object element : newList) {
verifyType(descriptor.getLiteType(), element);
verifyType(descriptor, element);
}
value = newList;
} else {
verifyType(descriptor.getLiteType(), value);
verifyType(descriptor, value);
}
if (value instanceof LazyField) {
@ -354,7 +353,7 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
throw new IndexOutOfBoundsException();
}
verifyType(descriptor.getLiteType(), value);
verifyType(descriptor, value);
((List<Object>) list).set(index, value);
}
@ -369,7 +368,7 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
"addRepeatedField() can only be called on repeated fields.");
}
verifyType(descriptor.getLiteType(), value);
verifyType(descriptor, value);
final Object existingValue = getField(descriptor);
List<Object> list;
@ -390,8 +389,8 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
*
* @throws IllegalArgumentException The value is not of the right type.
*/
private void verifyType(final WireFormat.FieldType type, final Object value) {
if (!isValidType(type, value)) {
private void verifyType(final T descriptor, final Object value) {
if (!isValidType(descriptor.getLiteType(), 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
@ -400,10 +399,16 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
// 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.");
String.format(
"Wrong object type used with protocol message reflection.\n"
+ "Field number: %d, field java type: %s, value type: %s\n",
descriptor.getNumber(),
descriptor.getLiteType().getJavaType(),
value.getClass().getName()));
}
}
private static boolean isValidType(final WireFormat.FieldType type, final Object value) {
checkNotNull(value);
switch (type.getJavaType()) {
@ -1081,12 +1086,12 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
final List newList = new ArrayList();
newList.addAll((List) value);
for (final Object element : newList) {
verifyType(descriptor.getLiteType(), element);
verifyType(descriptor, element);
hasNestedBuilders = hasNestedBuilders || element instanceof MessageLite.Builder;
}
value = newList;
} else {
verifyType(descriptor.getLiteType(), value);
verifyType(descriptor, value);
}
if (value instanceof LazyField) {
@ -1172,7 +1177,7 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
throw new IndexOutOfBoundsException();
}
verifyType(descriptor.getLiteType(), value);
verifyType(descriptor, value);
((List<Object>) list).set(index, value);
}
@ -1190,7 +1195,7 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
hasNestedBuilders = hasNestedBuilders || value instanceof MessageLite.Builder;
verifyType(descriptor.getLiteType(), value);
verifyType(descriptor, value);
final Object existingValue = getField(descriptor);
List<Object> list;
@ -1211,15 +1216,20 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
*
* @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)) {
private void verifyType(final T descriptor, final Object value) {
if (!FieldSet.isValidType(descriptor.getLiteType(), value)) {
// Builder can accept Message.Builder values even though FieldSet will reject.
if (type.getJavaType() == WireFormat.JavaType.MESSAGE
if (descriptor.getLiteType().getJavaType() == WireFormat.JavaType.MESSAGE
&& value instanceof MessageLite.Builder) {
return;
}
throw new IllegalArgumentException(
"Wrong object type used with protocol message reflection.");
String.format(
"Wrong object type used with protocol message reflection.\n"
+ "Field number: %d, field java type: %s, value type: %s\n",
descriptor.getNumber(),
descriptor.getLiteType().getJavaType(),
value.getClass().getName()));
}
}

@ -61,6 +61,7 @@ public final class TextFormat {
private static final Logger logger = Logger.getLogger(TextFormat.class.getName());
/**
* Outputs a textual representation of the Protocol Message supplied into the parameter output.
* (This representation is the new version of the classic "ProtocolPrinter" output from the
@ -727,9 +728,9 @@ public final class TextFormat {
// Groups must be serialized with their original capitalization.
generator.print(field.getMessageType().getName());
} else {
generator.print(field.getName());
generator.print(field.getName());
}
}
}
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
generator.print(" {");
@ -1811,16 +1812,16 @@ public final class TextFormat {
extension = target.findExtensionByName(extensionRegistry, name.toString());
if (extension == null) {
String message =
(tokenizer.getPreviousLine() + 1)
+ ":"
+ (tokenizer.getPreviousColumn() + 1)
+ ":\t"
+ type.getFullName()
+ ".["
+ name
+ "]";
unknownFields.add(new UnknownField(message, UnknownField.Type.EXTENSION));
String message =
(tokenizer.getPreviousLine() + 1)
+ ":"
+ (tokenizer.getPreviousColumn() + 1)
+ ":\t"
+ type.getFullName()
+ ".["
+ name
+ "]";
unknownFields.add(new UnknownField(message, UnknownField.Type.EXTENSION));
} else {
if (extension.descriptor.getContainingType() != type) {
throw tokenizer.parseExceptionPreviousToken(

@ -388,7 +388,7 @@ final class UnsafeUtil {
}
if (Android.isOnAndroidDevice()) {
return true;
return false;
}
clazz.getMethod("getByte", long.class);
clazz.getMethod("putByte", long.class, byte.class);

@ -184,17 +184,17 @@ public final class MapForProto2LiteTest extends TestCase {
}
private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) {
assertEquals(0, testMapOrBuilder.getInt32ToInt32Field().size());
assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldMap().size());
assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldCount());
assertEquals(0, testMapOrBuilder.getInt32ToStringField().size());
assertEquals(0, testMapOrBuilder.getInt32ToStringFieldMap().size());
assertEquals(0, testMapOrBuilder.getInt32ToStringFieldCount());
assertEquals(0, testMapOrBuilder.getInt32ToBytesField().size());
assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldMap().size());
assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldCount());
assertEquals(0, testMapOrBuilder.getInt32ToEnumField().size());
assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldMap().size());
assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldCount());
assertEquals(0, testMapOrBuilder.getInt32ToMessageField().size());
assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldMap().size());
assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldCount());
assertEquals(0, testMapOrBuilder.getStringToInt32Field().size());
assertEquals(0, testMapOrBuilder.getStringToInt32FieldMap().size());
assertEquals(0, testMapOrBuilder.getStringToInt32FieldCount());
}
@ -226,13 +226,13 @@ public final class MapForProto2LiteTest extends TestCase {
}
private void assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder) {
assertImmutable(testMapOrBuilder.getInt32ToInt32Field(), 1, 2);
assertImmutable(testMapOrBuilder.getInt32ToStringField(), 1, "2");
assertImmutable(testMapOrBuilder.getInt32ToBytesField(), 1, TestUtil.toBytes("2"));
assertImmutable(testMapOrBuilder.getInt32ToEnumField(), 1, TestMap.EnumValue.FOO);
assertImmutable(testMapOrBuilder.getInt32ToInt32FieldMap(), 1, 2);
assertImmutable(testMapOrBuilder.getInt32ToStringFieldMap(), 1, "2");
assertImmutable(testMapOrBuilder.getInt32ToBytesFieldMap(), 1, TestUtil.toBytes("2"));
assertImmutable(testMapOrBuilder.getInt32ToEnumFieldMap(), 1, TestMap.EnumValue.FOO);
assertImmutable(
testMapOrBuilder.getInt32ToMessageField(), 1, MessageValue.getDefaultInstance());
assertImmutable(testMapOrBuilder.getStringToInt32Field(), "1", 2);
testMapOrBuilder.getInt32ToMessageFieldMap(), 1, MessageValue.getDefaultInstance());
assertImmutable(testMapOrBuilder.getStringToInt32FieldMap(), "1", 2);
}
private <K, V> void assertImmutable(Map<K, V> map, K key, V value) {

@ -128,35 +128,35 @@ public class MapForProto2Test extends TestCase {
}
private void assertMapValuesSet(TestMapOrBuilder message) {
assertEquals(3, message.getInt32ToInt32Field().size());
assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
assertEquals(22, message.getInt32ToInt32Field().get(2).intValue());
assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
assertEquals(3, message.getInt32ToStringField().size());
assertEquals("11", message.getInt32ToStringField().get(1));
assertEquals("22", message.getInt32ToStringField().get(2));
assertEquals("33", message.getInt32ToStringField().get(3));
assertEquals(3, message.getInt32ToBytesField().size());
assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
assertEquals(3, message.getInt32ToEnumField().size());
assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
assertEquals(3, message.getInt32ToMessageField().size());
assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
assertEquals(3, message.getStringToInt32Field().size());
assertEquals(11, message.getStringToInt32Field().get("1").intValue());
assertEquals(22, message.getStringToInt32Field().get("2").intValue());
assertEquals(33, message.getStringToInt32Field().get("3").intValue());
assertEquals(3, message.getInt32ToInt32FieldMap().size());
assertEquals(11, message.getInt32ToInt32FieldMap().get(1).intValue());
assertEquals(22, message.getInt32ToInt32FieldMap().get(2).intValue());
assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue());
assertEquals(3, message.getInt32ToStringFieldMap().size());
assertEquals("11", message.getInt32ToStringFieldMap().get(1));
assertEquals("22", message.getInt32ToStringFieldMap().get(2));
assertEquals("33", message.getInt32ToStringFieldMap().get(3));
assertEquals(3, message.getInt32ToBytesFieldMap().size());
assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesFieldMap().get(1));
assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesFieldMap().get(2));
assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3));
assertEquals(3, message.getInt32ToEnumFieldMap().size());
assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(1));
assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(2));
assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3));
assertEquals(3, message.getInt32ToMessageFieldMap().size());
assertEquals(11, message.getInt32ToMessageFieldMap().get(1).getValue());
assertEquals(22, message.getInt32ToMessageFieldMap().get(2).getValue());
assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue());
assertEquals(3, message.getStringToInt32FieldMap().size());
assertEquals(11, message.getStringToInt32FieldMap().get("1").intValue());
assertEquals(22, message.getStringToInt32FieldMap().get("2").intValue());
assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue());
}
private void updateMapValuesUsingMutableMap(TestMap.Builder builder) {
@ -268,17 +268,17 @@ public class MapForProto2Test extends TestCase {
}
private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) {
assertEquals(0, testMapOrBuilder.getInt32ToInt32Field().size());
assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldMap().size());
assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldCount());
assertEquals(0, testMapOrBuilder.getInt32ToStringField().size());
assertEquals(0, testMapOrBuilder.getInt32ToStringFieldMap().size());
assertEquals(0, testMapOrBuilder.getInt32ToStringFieldCount());
assertEquals(0, testMapOrBuilder.getInt32ToBytesField().size());
assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldMap().size());
assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldCount());
assertEquals(0, testMapOrBuilder.getInt32ToEnumField().size());
assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldMap().size());
assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldCount());
assertEquals(0, testMapOrBuilder.getInt32ToMessageField().size());
assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldMap().size());
assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldCount());
assertEquals(0, testMapOrBuilder.getStringToInt32Field().size());
assertEquals(0, testMapOrBuilder.getStringToInt32FieldMap().size());
assertEquals(0, testMapOrBuilder.getStringToInt32FieldCount());
}
@ -293,13 +293,13 @@ public class MapForProto2Test extends TestCase {
}
private void assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder) {
assertImmutable(testMapOrBuilder.getInt32ToInt32Field(), 1, 2);
assertImmutable(testMapOrBuilder.getInt32ToStringField(), 1, "2");
assertImmutable(testMapOrBuilder.getInt32ToBytesField(), 1, TestUtil.toBytes("2"));
assertImmutable(testMapOrBuilder.getInt32ToEnumField(), 1, TestMap.EnumValue.FOO);
assertImmutable(testMapOrBuilder.getInt32ToInt32FieldMap(), 1, 2);
assertImmutable(testMapOrBuilder.getInt32ToStringFieldMap(), 1, "2");
assertImmutable(testMapOrBuilder.getInt32ToBytesFieldMap(), 1, TestUtil.toBytes("2"));
assertImmutable(testMapOrBuilder.getInt32ToEnumFieldMap(), 1, TestMap.EnumValue.FOO);
assertImmutable(
testMapOrBuilder.getInt32ToMessageField(), 1, MessageValue.getDefaultInstance());
assertImmutable(testMapOrBuilder.getStringToInt32Field(), "1", 2);
testMapOrBuilder.getInt32ToMessageFieldMap(), 1, MessageValue.getDefaultInstance());
assertImmutable(testMapOrBuilder.getStringToInt32FieldMap(), "1", 2);
}
private <K, V> void assertImmutable(Map<K, V> map, K key, V value) {
@ -874,8 +874,8 @@ public class MapForProto2Test extends TestCase {
ByteString data = builder.build().toByteString();
TestRecursiveMap message = TestRecursiveMap.parseFrom(data);
assertEquals(2, message.getRecursiveMapField().get(1).getValue());
assertEquals(4, message.getRecursiveMapField().get(3).getValue());
assertEquals(2, message.getRecursiveMapFieldMap().get(1).getValue());
assertEquals(4, message.getRecursiveMapFieldMap().get(3).getValue());
}
public void testIterationOrder() throws Exception {

@ -191,17 +191,17 @@ public final class MapLiteTest extends TestCase {
}
private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) {
assertEquals(0, testMapOrBuilder.getInt32ToInt32Field().size());
assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldMap().size());
assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldCount());
assertEquals(0, testMapOrBuilder.getInt32ToStringField().size());
assertEquals(0, testMapOrBuilder.getInt32ToStringFieldMap().size());
assertEquals(0, testMapOrBuilder.getInt32ToStringFieldCount());
assertEquals(0, testMapOrBuilder.getInt32ToBytesField().size());
assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldMap().size());
assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldCount());
assertEquals(0, testMapOrBuilder.getInt32ToEnumField().size());
assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldMap().size());
assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldCount());
assertEquals(0, testMapOrBuilder.getInt32ToMessageField().size());
assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldMap().size());
assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldCount());
assertEquals(0, testMapOrBuilder.getStringToInt32Field().size());
assertEquals(0, testMapOrBuilder.getStringToInt32FieldMap().size());
assertEquals(0, testMapOrBuilder.getStringToInt32FieldCount());
}
@ -232,13 +232,13 @@ public final class MapLiteTest extends TestCase {
}
private void assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder) {
assertImmutable(testMapOrBuilder.getInt32ToInt32Field(), 1, 2);
assertImmutable(testMapOrBuilder.getInt32ToStringField(), 1, "2");
assertImmutable(testMapOrBuilder.getInt32ToBytesField(), 1, TestUtil.toBytes("2"));
assertImmutable(testMapOrBuilder.getInt32ToEnumField(), 1, TestMap.EnumValue.FOO);
assertImmutable(testMapOrBuilder.getInt32ToInt32FieldMap(), 1, 2);
assertImmutable(testMapOrBuilder.getInt32ToStringFieldMap(), 1, "2");
assertImmutable(testMapOrBuilder.getInt32ToBytesFieldMap(), 1, TestUtil.toBytes("2"));
assertImmutable(testMapOrBuilder.getInt32ToEnumFieldMap(), 1, TestMap.EnumValue.FOO);
assertImmutable(
testMapOrBuilder.getInt32ToMessageField(), 1, MessageValue.getDefaultInstance());
assertImmutable(testMapOrBuilder.getStringToInt32Field(), "1", 2);
testMapOrBuilder.getInt32ToMessageFieldMap(), 1, MessageValue.getDefaultInstance());
assertImmutable(testMapOrBuilder.getStringToInt32FieldMap(), "1", 2);
}
private <K, V> void assertImmutable(Map<K, V> map, K key, V value) {

@ -271,17 +271,17 @@ public class MapTest extends TestCase {
}
private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) {
assertEquals(0, testMapOrBuilder.getInt32ToInt32Field().size());
assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldMap().size());
assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldCount());
assertEquals(0, testMapOrBuilder.getInt32ToStringField().size());
assertEquals(0, testMapOrBuilder.getInt32ToStringFieldMap().size());
assertEquals(0, testMapOrBuilder.getInt32ToStringFieldCount());
assertEquals(0, testMapOrBuilder.getInt32ToBytesField().size());
assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldMap().size());
assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldCount());
assertEquals(0, testMapOrBuilder.getInt32ToEnumField().size());
assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldMap().size());
assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldCount());
assertEquals(0, testMapOrBuilder.getInt32ToMessageField().size());
assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldMap().size());
assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldCount());
assertEquals(0, testMapOrBuilder.getStringToInt32Field().size());
assertEquals(0, testMapOrBuilder.getStringToInt32FieldMap().size());
assertEquals(0, testMapOrBuilder.getStringToInt32FieldCount());
}
@ -296,13 +296,13 @@ public class MapTest extends TestCase {
}
private void assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder) {
assertImmutable(testMapOrBuilder.getInt32ToInt32Field(), 1, 2);
assertImmutable(testMapOrBuilder.getInt32ToStringField(), 1, "2");
assertImmutable(testMapOrBuilder.getInt32ToBytesField(), 1, TestUtil.toBytes("2"));
assertImmutable(testMapOrBuilder.getInt32ToEnumField(), 1, TestMap.EnumValue.FOO);
assertImmutable(testMapOrBuilder.getInt32ToInt32FieldMap(), 1, 2);
assertImmutable(testMapOrBuilder.getInt32ToStringFieldMap(), 1, "2");
assertImmutable(testMapOrBuilder.getInt32ToBytesFieldMap(), 1, TestUtil.toBytes("2"));
assertImmutable(testMapOrBuilder.getInt32ToEnumFieldMap(), 1, TestMap.EnumValue.FOO);
assertImmutable(
testMapOrBuilder.getInt32ToMessageField(), 1, MessageValue.getDefaultInstance());
assertImmutable(testMapOrBuilder.getStringToInt32Field(), "1", 2);
testMapOrBuilder.getInt32ToMessageFieldMap(), 1, MessageValue.getDefaultInstance());
assertImmutable(testMapOrBuilder.getStringToInt32FieldMap(), "1", 2);
}
private <K, V> void assertImmutable(Map<K, V> map, K key, V value) {

@ -260,8 +260,8 @@ public final class TestUtil {
TestRequired.newBuilder().setA(1).setB(2).setC(3).build();
/** Helper to convert a String to ByteString. */
static ByteString toBytes(String str) {
return ByteString.copyFrom(str.getBytes(Internal.UTF_8));
public static ByteString toBytes(String str) {
return ByteString.copyFromUtf8(str);
}
// BEGIN FULL-RUNTIME

@ -142,8 +142,8 @@ public final class TestUtilLite {
private TestUtilLite() {}
/** Helper to convert a String to ByteString. */
static ByteString toBytes(String str) {
return ByteString.copyFrom(str.getBytes(Internal.UTF_8));
public static ByteString toBytes(String str) {
return ByteString.copyFromUtf8(str);
}
/**

@ -4,7 +4,7 @@
<parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
<version>3.13.0</version>
<version>3.14.0</version>
</parent>
<artifactId>protobuf-javalite</artifactId>

@ -4,7 +4,7 @@
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
<version>3.13.0</version>
<version>3.14.0</version>
<packaging>pom</packaging>
<name>Protocol Buffers [Parent]</name>

@ -4,7 +4,7 @@
<parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
<version>3.13.0</version>
<version>3.14.0</version>
</parent>
<artifactId>protobuf-java-util</artifactId>

@ -44,6 +44,7 @@ import static com.google.protobuf.util.Timestamps.NANOS_PER_SECOND;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.protobuf.Duration;
import java.io.Serializable;
import java.text.ParseException;
import java.util.Comparator;
@ -72,23 +73,25 @@ public final class Durations {
private Durations() {}
private static final Comparator<Duration> COMPARATOR =
new Comparator<Duration>() {
@Override
public int compare(Duration d1, Duration d2) {
checkValid(d1);
checkValid(d2);
int secDiff = Long.compare(d1.getSeconds(), d2.getSeconds());
return (secDiff != 0) ? secDiff : Integer.compare(d1.getNanos(), d2.getNanos());
}
};
private static enum DurationComparator implements Comparator<Duration>, Serializable {
INSTANCE;
@Override
public int compare(Duration d1, Duration d2) {
checkValid(d1);
checkValid(d2);
int secDiff = Long.compare(d1.getSeconds(), d2.getSeconds());
return (secDiff != 0) ? secDiff : Integer.compare(d1.getNanos(), d2.getNanos());
}
}
/**
* Returns a {@link Comparator} for {@link Duration}s which sorts in increasing chronological
* order. Nulls and invalid {@link Duration}s are not allowed (see {@link #isValid}).
* order. Nulls and invalid {@link Duration}s are not allowed (see {@link #isValid}). The returned
* comparator is serializable.
*/
public static Comparator<Duration> comparator() {
return COMPARATOR;
return DurationComparator.INSTANCE;
}
/**
@ -99,7 +102,7 @@ public final class Durations {
* and a value greater than {@code 0} if {@code x > y}
*/
public static int compare(Duration x, Duration y) {
return COMPARATOR.compare(x, y);
return DurationComparator.INSTANCE.compare(x, y);
}
/**

@ -39,6 +39,7 @@ import static com.google.common.math.LongMath.checkedSubtract;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.protobuf.Duration;
import com.google.protobuf.Timestamp;
import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Comparator;
@ -100,24 +101,25 @@ public final class Timestamps {
private Timestamps() {}
private static final Comparator<Timestamp> COMPARATOR =
new Comparator<Timestamp>() {
@Override
public int compare(Timestamp t1, Timestamp t2) {
checkValid(t1);
checkValid(t2);
int secDiff = Long.compare(t1.getSeconds(), t2.getSeconds());
return (secDiff != 0) ? secDiff : Integer.compare(t1.getNanos(), t2.getNanos());
}
};
private static enum TimestampComparator implements Comparator<Timestamp>, Serializable {
INSTANCE;
@Override
public int compare(Timestamp t1, Timestamp t2) {
checkValid(t1);
checkValid(t2);
int secDiff = Long.compare(t1.getSeconds(), t2.getSeconds());
return (secDiff != 0) ? secDiff : Integer.compare(t1.getNanos(), t2.getNanos());
}
}
/**
* Returns a {@link Comparator} for {@link Timestamp Timestamps} which sorts in increasing
* chronological order. Nulls and invalid {@link Timestamp Timestamps} are not allowed (see
* {@link #isValid}).
* {@link #isValid}). The returned comparator is serializable.
*/
public static Comparator<Timestamp> comparator() {
return COMPARATOR;
return TimestampComparator.INSTANCE;
}
/**
@ -128,7 +130,7 @@ public final class Timestamps {
* and a value greater than {@code 0} if {@code x > y}
*/
public static int compare(Timestamp x, Timestamp y) {
return COMPARATOR.compare(x, y);
return TimestampComparator.INSTANCE.compare(x, y);
}
/**

@ -207,6 +207,15 @@ jspb.BinaryReader.prototype.getWireType = function() {
};
/**
* @return {boolean} Whether the current wire type is a delimited field. Used to
* conditionally parse packed repeated fields.
*/
jspb.BinaryReader.prototype.isDelimited = function() {
return this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED;
};
/**
* @return {boolean} Whether the current wire type is an end-group tag. Used as
* an exit condition in decoder loops in generated code.

@ -71,6 +71,8 @@ static NSString *const kGPBDataCoderKey = @"GPBData";
@package
GPBUnknownFieldSet *unknownFields_;
NSMutableDictionary *extensionMap_;
// Readonly access to autocreatedExtensionMap_ is protected via
// readOnlySemaphore_.
NSMutableDictionary *autocreatedExtensionMap_;
// If the object was autocreated, we remember the creator so that if we get
@ -79,10 +81,10 @@ static NSString *const kGPBDataCoderKey = @"GPBData";
GPBFieldDescriptor *autocreatorField_;
GPBExtensionDescriptor *autocreatorExtension_;
// A lock to provide mutual exclusion from internal data that can be modified
// by *read* operations such as getters (autocreation of message fields and
// message extensions, not setting of values). Used to guarantee thread safety
// for concurrent reads on the message.
// Message can only be mutated from one thread. But some *readonly* operations
// modifify internal state because they autocreate things. The
// autocreatedExtensionMap_ is one such structure. Access during readonly
// operations is protected via this semaphore.
// NOTE: OSSpinLock may seem like a good fit here but Apple engineers have
// pointed out that they are vulnerable to live locking on iOS in cases of
// priority inversion:
@ -583,19 +585,30 @@ static id GetOrCreateArrayIvarWithField(GPBMessage *self,
// This is like GPBGetObjectIvarWithField(), but for arrays, it should
// only be used to wire the method into the class.
static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
if (!array) {
// Check again after getting the lock.
GPBPrepareReadOnlySemaphore(self);
dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER);
array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
if (!array) {
array = CreateArrayForField(field, self);
GPBSetAutocreatedRetainedObjectIvarWithField(self, field, array);
}
dispatch_semaphore_signal(self->readOnlySemaphore_);
uint8_t *storage = (uint8_t *)self->messageStorage_;
_Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset];
id array = atomic_load(typePtr);
if (array) {
return array;
}
return array;
id expected = nil;
id autocreated = CreateArrayForField(field, self);
if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) {
// Value was set, return it.
return autocreated;
}
// Some other thread set it, release the one created and return what got set.
if (GPBFieldDataTypeIsObject(field)) {
GPBAutocreatedArray *autoArray = autocreated;
autoArray->_autocreator = nil;
} else {
GPBInt32Array *gpbArray = autocreated;
gpbArray->_autocreator = nil;
}
[autocreated release];
return expected;
}
static id GetOrCreateMapIvarWithField(GPBMessage *self,
@ -613,19 +626,31 @@ static id GetOrCreateMapIvarWithField(GPBMessage *self,
// This is like GPBGetObjectIvarWithField(), but for maps, it should
// only be used to wire the method into the class.
static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
if (!dict) {
// Check again after getting the lock.
GPBPrepareReadOnlySemaphore(self);
dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER);
dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
if (!dict) {
dict = CreateMapForField(field, self);
GPBSetAutocreatedRetainedObjectIvarWithField(self, field, dict);
}
dispatch_semaphore_signal(self->readOnlySemaphore_);
uint8_t *storage = (uint8_t *)self->messageStorage_;
_Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset];
id dict = atomic_load(typePtr);
if (dict) {
return dict;
}
return dict;
id expected = nil;
id autocreated = CreateMapForField(field, self);
if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) {
// Value was set, return it.
return autocreated;
}
// Some other thread set it, release the one created and return what got set.
if ((field.mapKeyDataType == GPBDataTypeString) &&
GPBFieldDataTypeIsObject(field)) {
GPBAutocreatedDictionary *autoDict = autocreated;
autoDict->_autocreator = nil;
} else {
GPBInt32Int32Dictionary *gpbDict = autocreated;
gpbDict->_autocreator = nil;
}
[autocreated release];
return expected;
}
#endif // !defined(__clang_analyzer__)
@ -3337,30 +3362,34 @@ id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field) {
id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
NSCAssert(!GPBFieldIsMapOrArray(field), @"Shouldn't get here");
if (GPBGetHasIvarField(self, field)) {
uint8_t *storage = (uint8_t *)self->messageStorage_;
id *typePtr = (id *)&storage[field->description_->offset];
return *typePtr;
}
// Not set...
// Non messages (string/data), get their default.
if (!GPBFieldDataTypeIsMessage(field)) {
if (GPBGetHasIvarField(self, field)) {
uint8_t *storage = (uint8_t *)self->messageStorage_;
id *typePtr = (id *)&storage[field->description_->offset];
return *typePtr;
}
// Not set...non messages (string/data), get their default.
return field.defaultValue.valueMessage;
}
GPBPrepareReadOnlySemaphore(self);
dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER);
GPBMessage *result = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
if (!result) {
// For non repeated messages, create the object, set it and return it.
// This object will not initially be visible via GPBGetHasIvar, so
// we save its creator so it can become visible if it's mutated later.
result = GPBCreateMessageWithAutocreator(field.msgClass, self, field);
GPBSetAutocreatedRetainedObjectIvarWithField(self, field, result);
}
dispatch_semaphore_signal(self->readOnlySemaphore_);
return result;
uint8_t *storage = (uint8_t *)self->messageStorage_;
_Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset];
id msg = atomic_load(typePtr);
if (msg) {
return msg;
}
id expected = nil;
id autocreated = GPBCreateMessageWithAutocreator(field.msgClass, self, field);
if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) {
// Value was set, return it.
return autocreated;
}
// Some other thread set it, release the one created and return what got set.
GPBClearMessageAutocreator(autocreated);
[autocreated release];
return expected;
}
#pragma clang diagnostic pop

@ -504,15 +504,6 @@ static void GPBMaybeClearOneofPrivate(GPBMessage *self,
// Object types are handled slightly differently, they need to be released
// and retained.
void GPBSetAutocreatedRetainedObjectIvarWithField(
GPBMessage *self, GPBFieldDescriptor *field,
id __attribute__((ns_consumed)) value) {
uint8_t *storage = (uint8_t *)self->messageStorage_;
id *typePtr = (id *)&storage[field->description_->offset];
NSCAssert(*typePtr == NULL, @"Can't set autocreated object more than once.");
*typePtr = value;
}
void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self,
GPBFieldDescriptor *field) {
if (GPBGetHasIvarField(self, field)) {

@ -289,10 +289,6 @@ void GPBSetRetainedObjectIvarWithFieldPrivate(GPBMessage *self,
id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self,
GPBFieldDescriptor *field);
void GPBSetAutocreatedRetainedObjectIvarWithField(
GPBMessage *self, GPBFieldDescriptor *field,
id __attribute__((ns_consumed)) value);
// Clears and releases the autocreated message ivar, if it's autocreated. If
// it's not set as autocreated, this method does nothing.
void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self,

@ -1,5 +1,5 @@
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
platform :ios, '9.0'
install! 'cocoapods', :deterministic_uuids => false

@ -1,5 +1,5 @@
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
platform :ios, '9.0'
install! 'cocoapods', :deterministic_uuids => false

@ -4,7 +4,7 @@ if test "$PHP_PROTOBUF" != "no"; then
PHP_NEW_EXTENSION(
protobuf,
arena.c array.c bundled_php.c convert.c def.c map.c message.c names.c php-upb.c protobuf.c,
$ext_shared)
arena.c array.c convert.c def.c map.c message.c names.c php-upb.c protobuf.c,
$ext_shared, , -std=gnu99)
fi

@ -772,6 +772,7 @@ upb_symtab *DescriptorPool_GetSymbolTable() {
return intern->symtab;
}
/*
* DescriptorPool::getGeneratedPool()
*
@ -906,13 +907,38 @@ static void add_name_mappings(const upb_filedef *file) {
}
}
static void add_descriptor(DescriptorPool *pool,
const google_protobuf_FileDescriptorProto *file) {
upb_strview name = google_protobuf_FileDescriptorProto_name(file);
upb_status status;
const upb_filedef *file_def;
upb_status_clear(&status);
if (upb_symtab_lookupfile2(pool->symtab, name.data, name.size)) {
// Already added.
fprintf(stderr, "WARNING: file was already added\n");
return;
}
// The PHP code generator currently special-cases descriptor.proto. It
// doesn't add it as a dependency even if the proto file actually does
// depend on it.
if (depends_on_descriptor(file)) {
google_protobuf_FileDescriptorProto_getmsgdef(pool->symtab);
}
file_def = upb_symtab_addfile(pool->symtab, file, &status);
CheckUpbStatus(&status, "Unable to load descriptor");
add_name_mappings(file_def);
}
/*
* add_name_mappings()
* add_descriptor()
*
* Adds the given descriptor data to this DescriptorPool.
*/
static void add_descriptor(DescriptorPool *pool, const char *data,
int data_len, upb_arena *arena) {
static void add_descriptor_set(DescriptorPool *pool, const char *data,
int data_len, upb_arena *arena) {
size_t i, n;
google_protobuf_FileDescriptorSet *set;
const google_protobuf_FileDescriptorProto* const* files;
@ -928,27 +954,28 @@ static void add_descriptor(DescriptorPool *pool, const char *data,
for (i = 0; i < n; i++) {
const google_protobuf_FileDescriptorProto* file = files[i];
upb_strview name = google_protobuf_FileDescriptorProto_name(file);
upb_status status;
const upb_filedef *file_def;
upb_status_clear(&status);
if (upb_symtab_lookupfile2(pool->symtab, name.data, name.size)) {
// Already added.
continue;
}
add_descriptor(pool, file);
}
}
// The PHP code generator currently special-cases descriptor.proto. It
// doesn't add it as a dependency even if the proto file actually does
// depend on it.
if (depends_on_descriptor(file)) {
google_protobuf_FileDescriptorProto_getmsgdef(pool->symtab);
}
bool DescriptorPool_HasFile(const char *filename) {
DescriptorPool *intern = GetPool(get_generated_pool());
return upb_symtab_lookupfile(intern->symtab, filename) != NULL;
}
void DescriptorPool_AddDescriptor(const char *filename, const char *data,
int size) {
upb_arena *arena = upb_arena_new();
const google_protobuf_FileDescriptorProto *file =
google_protobuf_FileDescriptorProto_parse(data, size, arena);
file_def = upb_symtab_addfile(pool->symtab, file, &status);
CheckUpbStatus(&status, "Unable to load descriptor");
add_name_mappings(file_def);
if (!file) {
zend_error(E_ERROR, "Failed to parse binary descriptor for %s\n", filename);
return;
}
add_descriptor(GetPool(get_generated_pool()), file);
upb_arena_free(arena);
}
/*
@ -969,7 +996,7 @@ PHP_METHOD(DescriptorPool, internalAddGeneratedFile) {
}
arena = upb_arena_new();
add_descriptor(intern, data, data_len, arena);
add_descriptor_set(intern, data, data_len, arena);
upb_arena_free(arena);
}
@ -983,6 +1010,35 @@ static zend_function_entry DescriptorPool_methods[] = {
ZEND_FE_END
};
// -----------------------------------------------------------------------------
// InternalDescriptorPool
// -----------------------------------------------------------------------------
// For the C extension, Google\Protobuf\Internal\DescriptorPool is not a
// separate instantiable object, it just returns a
// Google\Protobuf\DescriptorPool.
zend_class_entry *InternalDescriptorPool_class_entry;
/*
* InternalDescriptorPool::getGeneratedPool()
*
* Returns the generated DescriptorPool. Note that this is identical to
* DescriptorPool::getGeneratedPool(), and in fact returns a DescriptorPool
* instance.
*/
PHP_METHOD(InternalDescriptorPool, getGeneratedPool) {
zval ret;
ZVAL_COPY(&ret, get_generated_pool());
RETURN_ZVAL(&ret, 0, 1);
}
static zend_function_entry InternalDescriptorPool_methods[] = {
PHP_ME(InternalDescriptorPool, getGeneratedPool, NULL,
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
ZEND_FE_END
};
// -----------------------------------------------------------------------------
// GPBType
// -----------------------------------------------------------------------------
@ -1044,7 +1100,7 @@ void Def_ModuleInit() {
h = &FieldDescriptor_object_handlers;
memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\DescriptorPool",
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\DescriptorPool",
DescriptorPool_methods);
DescriptorPool_class_entry = zend_register_internal_class(&tmp_ce);
DescriptorPool_class_entry->ce_flags |= ZEND_ACC_FINAL;
@ -1053,6 +1109,10 @@ void Def_ModuleInit() {
memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
h->dtor_obj = DescriptorPool_destructor;
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\DescriptorPool",
InternalDescriptorPool_methods);
InternalDescriptorPool_class_entry = zend_register_internal_class(&tmp_ce);
// GPBType.
#define STR(str) (str), strlen(str)
zend_class_entry class_type;

@ -49,6 +49,12 @@ upb_symtab *DescriptorPool_Steal(zval *zv);
upb_symtab *DescriptorPool_GetSymbolTable();
// Returns true if the global descriptor pool already has the given filename.
bool DescriptorPool_HasFile(const char *filename);
// Adds the given descriptor with the given filename to the global pool.
void DescriptorPool_AddDescriptor(const char *filename, const char *data, int size);
typedef struct Descriptor {
zend_object std;
const upb_msgdef *msgdef;

@ -1,62 +0,0 @@
<?php
$cwd = dirname($argv[0]) . "/../../../src";
chdir($cwd);
$cmd = "grep -r -l 'Generated by the protocol buffer' * | grep 'php$' | grep -v Internal";
$handle = popen($cmd, 'r');
$filenames = explode("\n", stream_get_contents($handle));
array_pop($filenames); // empty string after last '\n'
$filenames[] = "Google/Protobuf/DescriptorPool.php";
$output = "../ext/google/protobuf/bundled_php.c";
function stripSuffix($str, $suffix) {
return substr($str, 0, strlen($str) - strlen($suffix));
}
function toClassName($filename) {
# Google/Protobuf/BoolValue.php -> Google\\Protobuf\\BoolValue
$ret = stripSuffix($filename, ".php");
return str_replace("/", "\\\\", $ret);
}
function toCSymbolName($filename) {
# Google/Protobuf/BoolValue.php -> Google__Protobuf__BoolValue
$ret = stripSuffix($filename, ".php");
return str_replace("/", "__", $ret);
}
$f = fopen($output, "w");
fwrite($f, "#include \"bundled_php.h\"\n");
fwrite($f, "#include \"stdlib.h\"\n");
foreach ($filenames as $filename) {
print("Reading $filename...\n");
$contents = file_get_contents($filename);
$contents = substr($contents, 5); // Strip <?php
$c_symbol_name = toCSymbolName($filename);
fwrite($f, "static const char {$c_symbol_name}[] = {");
for ($i = 0; $i < strlen($contents); $i++) {
if ($i % 10 == 0) {
fwrite($f, "\n");
}
fprintf($f, " 0x%02x,", ord($contents[$i]));
}
fwrite($f, "0};\n");
}
fwrite($f, "static BundledPhp_File php[] = {\n");
foreach ($filenames as $filename) {
$class_name = toClassName($filename);
$c_symbol_name = toCSymbolName($filename);
fwrite($f, " {\"$class_name\", $c_symbol_name},\n");
}
fwrite($f, " {NULL, NULL}\n");
fwrite($f, "};\n");
fwrite($f, "BundledPhp_File *bundled_files = &php[0];\n");
fclose($f);
print("Wrote $output\n");
?>

@ -36,6 +36,7 @@
// This is not self-contained: it must be after other Zend includes.
#include <Zend/zend_exceptions.h>
#include <Zend/zend_inheritance.h>
#include "arena.h"
#include "array.h"
@ -108,6 +109,43 @@ static const upb_fielddef *get_field(Message *msg, PROTO_STR *member) {
return f;
}
static void Message_get(Message *intern, const upb_fielddef *f, zval *rv) {
upb_arena *arena = Arena_Get(&intern->arena);
if (upb_fielddef_ismap(f)) {
upb_mutmsgval msgval = upb_msg_mutable(intern->msg, f, arena);
MapField_GetPhpWrapper(rv, msgval.map, f, &intern->arena);
} else if (upb_fielddef_isseq(f)) {
upb_mutmsgval msgval = upb_msg_mutable(intern->msg, f, arena);
RepeatedField_GetPhpWrapper(rv, msgval.array, f, &intern->arena);
} else {
upb_msgval msgval = upb_msg_get(intern->msg, f);
const Descriptor *subdesc = Descriptor_GetFromFieldDef(f);
Convert_UpbToPhp(msgval, rv, upb_fielddef_type(f), subdesc, &intern->arena);
}
}
static bool Message_set(Message *intern, const upb_fielddef *f, zval *val) {
upb_arena *arena = Arena_Get(&intern->arena);
upb_msgval msgval;
if (upb_fielddef_ismap(f)) {
msgval.map_val = MapField_GetUpbMap(val, f, arena);
if (!msgval.map_val) return false;
} else if (upb_fielddef_isseq(f)) {
msgval.array_val = RepeatedField_GetUpbArray(val, f, arena);
if (!msgval.array_val) return false;
} else {
upb_fieldtype_t type = upb_fielddef_type(f);
const Descriptor *subdesc = Descriptor_GetFromFieldDef(f);
bool ok = Convert_PhpToUpb(val, &msgval, type, subdesc, arena);
if (!ok) return false;
}
upb_msg_set(intern->msg, f, msgval, arena);
return true;
}
static bool MessageEq(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m);
/**
@ -271,6 +309,7 @@ static void Message_unset_property(PROTO_VAL *obj, PROTO_STR *member,
upb_msg_clearfield(intern->msg, f);
}
/**
* Message_read_property()
*
@ -293,22 +332,9 @@ static zval *Message_read_property(PROTO_VAL *obj, PROTO_STR *member,
int type, void **cache_slot, zval *rv) {
Message* intern = PROTO_MSG_P(obj);
const upb_fielddef *f = get_field(intern, member);
upb_arena *arena = Arena_Get(&intern->arena);
if (!f) return NULL;
if (upb_fielddef_ismap(f)) {
upb_mutmsgval msgval = upb_msg_mutable(intern->msg, f, arena);
MapField_GetPhpWrapper(rv, msgval.map, f, &intern->arena);
} else if (upb_fielddef_isseq(f)) {
upb_mutmsgval msgval = upb_msg_mutable(intern->msg, f, arena);
RepeatedField_GetPhpWrapper(rv, msgval.array, f, &intern->arena);
} else {
upb_msgval msgval = upb_msg_get(intern->msg, f);
const Descriptor *subdesc = Descriptor_GetFromFieldDef(f);
Convert_UpbToPhp(msgval, rv, upb_fielddef_type(f), subdesc, &intern->arena);
}
Message_get(intern, f, rv);
return rv;
}
@ -337,37 +363,20 @@ static PROTO_RETURN_VAL Message_write_property(
PROTO_VAL *obj, PROTO_STR *member, zval *val, void **cache_slot) {
Message* intern = PROTO_MSG_P(obj);
const upb_fielddef *f = get_field(intern, member);
upb_arena *arena = Arena_Get(&intern->arena);
upb_msgval msgval;
if (!f) goto error;
if (upb_fielddef_ismap(f)) {
msgval.map_val = MapField_GetUpbMap(val, f, arena);
if (!msgval.map_val) goto error;
} else if (upb_fielddef_isseq(f)) {
msgval.array_val = RepeatedField_GetUpbArray(val, f, arena);
if (!msgval.array_val) goto error;
} else {
upb_fieldtype_t type = upb_fielddef_type(f);
const Descriptor *subdesc = Descriptor_GetFromFieldDef(f);
bool ok = Convert_PhpToUpb(val, &msgval, type, subdesc, arena);
if (!ok) goto error;
}
upb_msg_set(intern->msg, f, msgval, arena);
if (f && Message_set(intern, f, val)) {
#if PHP_VERSION_ID < 70400
return;
return;
#else
return val;
return val;
#endif
error:
} else {
#if PHP_VERSION_ID < 70400
return;
return;
#else
return &EG(error_zval);
return &EG(error_zval);
#endif
}
}
/**
@ -531,6 +540,12 @@ bool Message_InitFromPhp(upb_msg *msg, const upb_msgdef *m, zval *init,
}
}
static void Message_Initialize(Message *intern, const Descriptor *desc) {
intern->desc = desc;
intern->msg = upb_msg_new(desc->msgdef, Arena_Get(&intern->arena));
ObjCache_Add(intern->msg, &intern->std);
}
/**
* Message::__construct()
*
@ -540,13 +555,10 @@ bool Message_InitFromPhp(upb_msg *msg, const upb_msgdef *m, zval *init,
PHP_METHOD(Message, __construct) {
Message* intern = (Message*)Z_OBJ_P(getThis());
const Descriptor* desc = Descriptor_GetFromClassEntry(Z_OBJCE_P(getThis()));
const upb_msgdef *msgdef = desc->msgdef;
upb_arena *arena = Arena_Get(&intern->arena);
zval *init_arr = NULL;
intern->desc = desc;
intern->msg = upb_msg_new(msgdef, arena);
ObjCache_Add(intern->msg, &intern->std);
Message_Initialize(intern, desc);
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a!", &init_arr) == FAILURE) {
return;
@ -892,6 +904,39 @@ PHP_METHOD(Message, whichOneof) {
RETURN_STRING(field ? upb_fielddef_name(field) : "");
}
/**
* Message::hasOneof()
*
* Returns the presence of the given oneof field, given a field number. Called
* from generated code methods such as:
*
* public function hasDoubleValueOneof()
* {
* return $this->hasOneof(10);
* }
*
* @return boolean
*/
PHP_METHOD(Message, hasOneof) {
Message* intern = (Message*)Z_OBJ_P(getThis());
zend_long field_num;
const upb_fielddef* f;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &field_num) == FAILURE) {
return;
}
f = upb_msgdef_itof(intern->desc->msgdef, field_num);
if (!f || !upb_fielddef_realcontainingoneof(f)) {
php_error_docref(NULL, E_USER_ERROR,
"Internal error, no such oneof field %d\n",
(int)field_num);
}
RETVAL_BOOL(upb_msg_has(intern->msg, f));
}
/**
* Message::readOneof()
*
@ -1002,6 +1047,7 @@ static zend_function_entry Message_methods[] = {
PHP_ME(Message, mergeFrom, arginfo_mergeFrom, ZEND_ACC_PUBLIC)
PHP_ME(Message, readWrapperValue, arginfo_read, ZEND_ACC_PROTECTED)
PHP_ME(Message, writeWrapperValue, arginfo_write, ZEND_ACC_PROTECTED)
PHP_ME(Message, hasOneof, arginfo_read, ZEND_ACC_PROTECTED)
PHP_ME(Message, readOneof, arginfo_read, ZEND_ACC_PROTECTED)
PHP_ME(Message, writeOneof, arginfo_write, ZEND_ACC_PROTECTED)
PHP_ME(Message, whichOneof, arginfo_read, ZEND_ACC_PROTECTED)
@ -1009,6 +1055,260 @@ static zend_function_entry Message_methods[] = {
ZEND_FE_END
};
// Well-known types ////////////////////////////////////////////////////////////
static const char TYPE_URL_PREFIX[] = "type.googleapis.com/";
static upb_msgval Message_getval(Message *intern, const char *field_name) {
const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, field_name);
PBPHP_ASSERT(f);
return upb_msg_get(intern->msg, f);
}
static void Message_setval(Message *intern, const char *field_name,
upb_msgval val) {
const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, field_name);
PBPHP_ASSERT(f);
return upb_msg_set(intern->msg, f, val, Arena_Get(&intern->arena));
}
static upb_msgval StringVal(upb_strview view) {
upb_msgval ret;
ret.str_val = view;
return ret;
}
static bool TryStripUrlPrefix(upb_strview *str) {
size_t size = strlen(TYPE_URL_PREFIX);
if (str->size < size || memcmp(TYPE_URL_PREFIX, str->data, size) != 0) {
return false;
}
str->data += size;
str->size -= size;
return true;
}
static bool StrViewEq(upb_strview view, const char *str) {
size_t size = strlen(str);
return view.size == size && memcmp(view.data, str, size) == 0;
}
PHP_METHOD(google_protobuf_Any, unpack) {
Message* intern = (Message*)Z_OBJ_P(getThis());
upb_strview type_url = Message_getval(intern, "type_url").str_val;
upb_strview value = Message_getval(intern, "value").str_val;
upb_symtab *symtab = DescriptorPool_GetSymbolTable();
const upb_msgdef *m;
Descriptor *desc;
zval ret;
// Ensure that type_url has TYPE_URL_PREFIX as a prefix.
if (!TryStripUrlPrefix(&type_url)) {
zend_throw_exception(
NULL, "Type url needs to be type.googleapis.com/fully-qualified",
0 TSRMLS_CC);
return;
}
m = upb_symtab_lookupmsg2(symtab, type_url.data, type_url.size);
if (m == NULL) {
zend_throw_exception(
NULL, "Specified message in any hasn't been added to descriptor pool",
0 TSRMLS_CC);
return;
}
desc = Descriptor_GetFromMessageDef(m);
PBPHP_ASSERT(desc->class_entry->create_object == Message_create);
zend_object *obj = Message_create(desc->class_entry);
Message *msg = (Message*)obj;
Message_Initialize(msg, desc);
ZVAL_OBJ(&ret, obj);
// Get value.
if (!upb_decode(value.data, value.size, msg->msg,
upb_msgdef_layout(desc->msgdef), Arena_Get(&msg->arena))) {
zend_throw_exception_ex(NULL, 0, "Error occurred during parsing");
return;
}
// Fuse since the parsed message could alias "value".
upb_arena_fuse(Arena_Get(&intern->arena), Arena_Get(&msg->arena));
RETURN_ZVAL(&ret, 1, 0);
}
PHP_METHOD(google_protobuf_Any, pack) {
Message* intern = (Message*)Z_OBJ_P(getThis());
upb_arena *arena = Arena_Get(&intern->arena);
zval *val;
Message *msg;
upb_strview value;
upb_strview type_url;
const char *full_name;
char *buf;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &val) ==
FAILURE) {
return;
}
if (!instanceof_function(Z_OBJCE_P(val), message_ce)) {
zend_error(E_USER_ERROR, "Given value is not an instance of Message.");
return;
}
msg = (Message*)Z_OBJ_P(val);
// Serialize and set value.
value.data = upb_encode(msg->msg, upb_msgdef_layout(msg->desc->msgdef), arena,
&value.size);
Message_setval(intern, "value", StringVal(value));
// Set type url: type_url_prefix + fully_qualified_name
full_name = upb_msgdef_fullname(msg->desc->msgdef);
type_url.size = strlen(TYPE_URL_PREFIX) + strlen(full_name);
buf = upb_arena_malloc(arena, type_url.size + 1);
memcpy(buf, TYPE_URL_PREFIX, strlen(TYPE_URL_PREFIX));
memcpy(buf + strlen(TYPE_URL_PREFIX), full_name, strlen(full_name));
type_url.data = buf;
Message_setval(intern, "type_url", StringVal(type_url));
}
PHP_METHOD(google_protobuf_Any, is) {
Message* intern = (Message*)Z_OBJ_P(getThis());
upb_strview type_url = Message_getval(intern, "type_url").str_val;
zend_class_entry *klass = NULL;
const upb_msgdef *m;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "C", &klass) ==
FAILURE) {
return;
}
m = NameMap_GetMessage(klass);
if (m == NULL) {
RETURN_BOOL(false);
}
RETURN_BOOL(TryStripUrlPrefix(&type_url) &&
StrViewEq(type_url, upb_msgdef_fullname(m)));
}
PHP_METHOD(google_protobuf_Timestamp, fromDateTime) {
Message* intern = (Message*)Z_OBJ_P(getThis());
zval* datetime;
const char *classname = "\\DatetimeInterface";
zend_string *classname_str = zend_string_init(classname, strlen(classname), 0);
zend_class_entry *date_interface_ce = zend_lookup_class(classname_str);
if (date_interface_ce == NULL) {
zend_error(E_ERROR, "Make sure date extension is enabled.");
return;
}
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &datetime,
date_interface_ce) == FAILURE) {
zend_error(E_USER_ERROR, "Expect DatetimeInterface.");
return;
}
upb_msgval timestamp_seconds;
{
zval retval;
zval function_name;
ZVAL_STRING(&function_name, "date_timestamp_get");
if (call_user_function(EG(function_table), NULL, &function_name, &retval, 1,
datetime) == FAILURE ||
!Convert_PhpToUpb(&retval, &timestamp_seconds, UPB_TYPE_INT64, NULL,
NULL)) {
zend_error(E_ERROR, "Cannot get timestamp from DateTime.");
return;
}
zval_dtor(&retval);
zval_dtor(&function_name);
}
upb_msgval timestamp_nanos;
{
zval retval;
zval function_name;
zval format_string;
ZVAL_STRING(&function_name, "date_format");
ZVAL_STRING(&format_string, "u");
zval params[2] = {
*datetime,
format_string,
};
if (call_user_function(EG(function_table), NULL, &function_name, &retval, 2,
params) == FAILURE ||
!Convert_PhpToUpb(&retval, &timestamp_nanos, UPB_TYPE_INT32, NULL,
NULL)) {
zend_error(E_ERROR, "Cannot format DateTime.");
return;
}
timestamp_nanos.int32_val *= 1000;
zval_dtor(&retval);
zval_dtor(&function_name);
zval_dtor(&format_string);
}
Message_setval(intern, "seconds", timestamp_seconds);
Message_setval(intern, "nanos", timestamp_nanos);
RETURN_NULL();
}
PHP_METHOD(google_protobuf_Timestamp, toDateTime) {
Message* intern = (Message*)Z_OBJ_P(getThis());
upb_msgval seconds = Message_getval(intern, "seconds");
upb_msgval nanos = Message_getval(intern, "nanos");
// Get formatted time string.
char formatted_time[32];
snprintf(formatted_time, sizeof(formatted_time), "%" PRId64 ".%06" PRId32,
seconds.int64_val, nanos.int32_val / 1000);
// Create Datetime object.
zval datetime;
zval function_name;
zval format_string;
zval formatted_time_php;
ZVAL_STRING(&function_name, "date_create_from_format");
ZVAL_STRING(&format_string, "U.u");
ZVAL_STRING(&formatted_time_php, formatted_time);
zval params[2] = {
format_string,
formatted_time_php,
};
if (call_user_function(EG(function_table), NULL, &function_name, &datetime, 2,
params) == FAILURE) {
zend_error(E_ERROR, "Cannot create DateTime.");
return;
}
zval_dtor(&function_name);
zval_dtor(&format_string);
zval_dtor(&formatted_time_php);
ZVAL_OBJ(return_value, Z_OBJ(datetime));
}
#include "wkt.inc"
/**
* Message_ModuleInit()
*
@ -1033,4 +1333,6 @@ void Message_ModuleInit() {
h->unset_property = Message_unset_property;
h->get_properties = Message_get_properties;
h->get_property_ptr_ptr = Message_get_property_ptr_ptr;
WellKnownTypes_ModuleInit(); /* From wkt.inc. */
}

@ -10,18 +10,18 @@
<email>protobuf-opensource@google.com</email>
<active>yes</active>
</lead>
<date>2020-10-08</date>
<time>14:07:59</time>
<date>2020-11-12</date>
<time>14:06:40</time>
<version>
<release>3.13.0.1</release>
<api>3.13.0.1</api>
<release>3.14.0</release>
<api>3.14.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
<notes>GA release.</notes>
<notes>PHP protobuf</notes>
<contents>
<dir baseinstalldir="/" name="/">
<file baseinstalldir="/" name="config.m4" role="src"/>
@ -29,8 +29,6 @@
<file baseinstalldir="/" name="arena.h" role="src"/>
<file baseinstalldir="/" name="array.c" role="src"/>
<file baseinstalldir="/" name="array.h" role="src"/>
<file baseinstalldir="/" name="bundled_php.c" role="src"/>
<file baseinstalldir="/" name="bundled_php.h" role="src"/>
<file baseinstalldir="/" name="convert.c" role="src"/>
<file baseinstalldir="/" name="convert.h" role="src"/>
<file baseinstalldir="/" name="def.c" role="src"/>
@ -45,6 +43,9 @@
<file baseinstalldir="/" name="php-upb.h" role="src"/>
<file baseinstalldir="/" name="protobuf.c" role="src"/>
<file baseinstalldir="/" name="protobuf.h" role="src"/>
<file baseinstalldir="/" name="wkt.inc" role="src"/>
<file baseinstalldir="/" name="third_party/wyhash/wyhash.h" role="src"/>
<file baseinstalldir="/" name="third_party/wyhash/LICENSE" role="doc"/>
<file baseinstalldir="/" name="LICENSE" role="doc"/>
</dir>
</contents>
@ -689,5 +690,65 @@ G A release.
<license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
<notes>GA release.</notes>
</release>
<release>
<version>
<release>3.14.0RC1</release>
<api>3.14.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2020-11-05</date>
<time>13:39:47</time>
<license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
<notes>
</notes>
</release>
<release>
<version>
<release>3.14.0RC2</release>
<api>3.14.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2020-11-10</date>
<time>16:28:41</time>
<license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
<notes>
</notes>
</release>
<release>
<version>
<release>3.14.0RC3</release>
<api>3.14.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2020-11-11</date>
<time>10:35:18</time>
<license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
<notes>
</notes>
</release>
<release>
<version>
<release>3.14.0</release>
<api>3.14.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2020-11-12</date>
<time>14:06:40</time>
<license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
<notes>
</notes>
</release>
</changelog>
</package>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -35,7 +35,6 @@
#include "arena.h"
#include "array.h"
#include "bundled_php.h"
#include "convert.h"
#include "def.h"
#include "map.h"
@ -162,10 +161,6 @@ static PHP_RINIT_FUNCTION(protobuf) {
upb_symtab *symtab = PROTOBUF_G(saved_symtab);
DescriptorPool_CreateWithSymbolTable(&PROTOBUF_G(generated_pool), symtab);
// Set up autoloader for bundled sources.
zend_eval_string("spl_autoload_register('protobuf_internal_loadbundled');",
NULL, "autoload_register.php");
zend_hash_init(&PROTOBUF_G(object_cache), 64, NULL, NULL, 0);
zend_hash_init(&PROTOBUF_G(name_msg_cache), 64, NULL, NULL, 0);
zend_hash_init(&PROTOBUF_G(name_enum_cache), 64, NULL, NULL, 0);
@ -193,34 +188,6 @@ static PHP_RSHUTDOWN_FUNCTION(protobuf) {
return SUCCESS;
}
// -----------------------------------------------------------------------------
// Bundled PHP sources
// -----------------------------------------------------------------------------
// We bundle PHP sources for well-known types into the C extension. There is no
// need to implement these in C.
static PHP_FUNCTION(protobuf_internal_loadbundled) {
char *name = NULL;
zend_long size;
BundledPhp_File *file;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &size) != SUCCESS) {
return;
}
for (file = bundled_files; file->filename; file++) {
if (strcmp(file->filename, name) == 0) {
zend_eval_string((char*)file->contents, NULL, (char*)file->filename);
return;
}
}
}
ZEND_BEGIN_ARG_INFO_EX(arginfo_load_bundled_source, 0, 0, 1)
ZEND_ARG_INFO(0, class_name)
ZEND_END_ARG_INFO()
// -----------------------------------------------------------------------------
// Object Cache.
// -----------------------------------------------------------------------------
@ -303,7 +270,6 @@ const upb_enumdef *NameMap_GetEnum(zend_class_entry *ce) {
// -----------------------------------------------------------------------------
zend_function_entry protobuf_functions[] = {
PHP_FE(protobuf_internal_loadbundled, arginfo_load_bundled_source)
ZEND_FE_END
};
@ -345,7 +311,7 @@ zend_module_entry protobuf_module_entry = {
PHP_RINIT(protobuf), // request shutdown
PHP_RSHUTDOWN(protobuf), // request shutdown
NULL, // extension info
"3.13.0", // extension version
PHP_PROTOBUF_VERSION, // extension version
PHP_MODULE_GLOBALS(protobuf), // globals descriptor
PHP_GINIT(protobuf), // globals ctor
PHP_GSHUTDOWN(protobuf), // globals dtor

@ -69,7 +69,7 @@ const zval *get_generated_pool();
#define PROTO_STRLEN_P(obj) ZSTR_LEN(obj)
#endif
#define PHP_PROTOBUF_VERSION "3.13.0.1"
#define PHP_PROTOBUF_VERSION "3.14.0"
// ptr -> PHP object cache. This is a weak map that caches lazily-created
// wrapper objects around upb types:

File diff suppressed because it is too large Load Diff

@ -3,6 +3,8 @@
# Run this script to regenerate descriptor protos after the protocol compiler
# changes.
set -e
if test ! -e src/google/protobuf/stubs/common.h; then
cat >&2 << __EOF__
Could not find source code. Make sure you are running this script from the
@ -13,4 +15,15 @@ fi
pushd src
./protoc --php_out=internal:../php/src google/protobuf/descriptor.proto
./protoc --php_out=internal_generate_c_wkt:../php/src \
google/protobuf/any.proto \
google/protobuf/api.proto \
google/protobuf/duration.proto \
google/protobuf/empty.proto \
google/protobuf/field_mask.proto \
google/protobuf/source_context.proto \
google/protobuf/struct.proto \
google/protobuf/type.proto \
google/protobuf/timestamp.proto \
google/protobuf/wrappers.proto
popd

@ -0,0 +1,6 @@
# wyhash has to live in the base third_party directory.
# We copy it into the ext/google/protobuf directory for the build
# (and for the release to PECL).
mkdir -p ../ext/google/protobuf/third_party/wyhash
cp ../../third_party/wyhash/* ../ext/google/protobuf/third_party/wyhash

@ -14,15 +14,15 @@ class Any
if (static::$is_initialized == true) {
return;
}
$pool->internalAddGeneratedFile(hex2bin(
"0acd010a19676f6f676c652f70726f746f6275662f616e792e70726f746f" .
"120f676f6f676c652e70726f746f62756622260a03416e7912100a087479" .
"70655f75726c180120012809120d0a0576616c756518022001280c426f0a" .
"13636f6d2e676f6f676c652e70726f746f6275664208416e7950726f746f" .
"50015a256769746875622e636f6d2f676f6c616e672f70726f746f627566" .
"2f7074797065732f616e79a20203475042aa021e476f6f676c652e50726f" .
"746f6275662e57656c6c4b6e6f776e5479706573620670726f746f33"
));
$pool->internalAddGeneratedFile(
'
Ô
google/protobuf/any.protogoogle.protobuf"&
Any
type_url ( 
value ( Bv
com.google.protobufBAnyProtoPZ,google.golang.org/protobuf/types/known/anypb˘GPBŞGoogle.Protobuf.WellKnownTypesbproto3'
, true);
static::$is_initialized = true;
}

@ -16,32 +16,31 @@ class Api
}
\GPBMetadata\Google\Protobuf\SourceContext::initOnce();
\GPBMetadata\Google\Protobuf\Type::initOnce();
$pool->internalAddGeneratedFile(hex2bin(
"0ac8050a19676f6f676c652f70726f746f6275662f6170692e70726f746f" .
"120f676f6f676c652e70726f746f6275661a1a676f6f676c652f70726f74" .
"6f6275662f747970652e70726f746f2281020a03417069120c0a046e616d" .
"6518012001280912280a076d6574686f647318022003280b32172e676f6f" .
"676c652e70726f746f6275662e4d6574686f6412280a076f7074696f6e73" .
"18032003280b32172e676f6f676c652e70726f746f6275662e4f7074696f" .
"6e120f0a0776657273696f6e18042001280912360a0e736f757263655f63" .
"6f6e7465787418052001280b321e2e676f6f676c652e70726f746f627566" .
"2e536f75726365436f6e7465787412260a066d6978696e7318062003280b" .
"32162e676f6f676c652e70726f746f6275662e4d6978696e12270a067379" .
"6e74617818072001280e32172e676f6f676c652e70726f746f6275662e53" .
"796e74617822d5010a064d6574686f64120c0a046e616d65180120012809" .
"12180a10726571756573745f747970655f75726c18022001280912190a11" .
"726571756573745f73747265616d696e6718032001280812190a11726573" .
"706f6e73655f747970655f75726c180420012809121a0a12726573706f6e" .
"73655f73747265616d696e6718052001280812280a076f7074696f6e7318" .
"062003280b32172e676f6f676c652e70726f746f6275662e4f7074696f6e" .
"12270a0673796e74617818072001280e32172e676f6f676c652e70726f74" .
"6f6275662e53796e74617822230a054d6978696e120c0a046e616d651801" .
"20012809120c0a04726f6f7418022001280942750a13636f6d2e676f6f67" .
"6c652e70726f746f627566420841706950726f746f50015a2b676f6f676c" .
"652e676f6c616e672e6f72672f67656e70726f746f2f70726f746f627566" .
"2f6170693b617069a20203475042aa021e476f6f676c652e50726f746f62" .
"75662e57656c6c4b6e6f776e5479706573620670726f746f33"
));
$pool->internalAddGeneratedFile(
'
É
google/protobuf/api.protogoogle.protobufgoogle/protobuf/type.proto"<EFBFBD>
Api
name ( (
methods ( 2.google.protobuf.Method(
options ( 2.google.protobuf.Option
version ( 6
source_context ( 2.google.protobuf.SourceContext&
mixins ( 2.google.protobuf.Mixin\'
syntax (2.google.protobuf.Syntax"Ő
Method
name ( 
request_type_url ( 
request_streaming (
response_type_url ( 
response_streaming ((
options ( 2.google.protobuf.Option\'
syntax (2.google.protobuf.Syntax"#
Mixin
name ( 
root ( Bv
com.google.protobufBApiProtoPZ,google.golang.org/protobuf/types/known/apipb˘GPBŞGoogle.Protobuf.WellKnownTypesbproto3'
, true);
static::$is_initialized = true;
}

@ -14,16 +14,15 @@ class Duration
if (static::$is_initialized == true) {
return;
}
$pool->internalAddGeneratedFile(hex2bin(
"0ae3010a1e676f6f676c652f70726f746f6275662f6475726174696f6e2e" .
"70726f746f120f676f6f676c652e70726f746f627566222a0a0844757261" .
"74696f6e120f0a077365636f6e6473180120012803120d0a056e616e6f73" .
"180220012805427c0a13636f6d2e676f6f676c652e70726f746f62756642" .
"0d4475726174696f6e50726f746f50015a2a6769746875622e636f6d2f67" .
"6f6c616e672f70726f746f6275662f7074797065732f6475726174696f6e" .
"f80101a20203475042aa021e476f6f676c652e50726f746f6275662e5765" .
"6c6c4b6e6f776e5479706573620670726f746f33"
));
$pool->internalAddGeneratedFile(
'
ë
google/protobuf/duration.protogoogle.protobuf"*
Duration
seconds (
nanos (
com.google.protobufB DurationProtoPZ1google.golang.org/protobuf/types/known/durationpbø¢GPBªGoogle.Protobuf.WellKnownTypesbproto3'
, true);
static::$is_initialized = true;
}

@ -14,16 +14,14 @@ class FieldMask
if (static::$is_initialized == true) {
return;
}
$pool->internalAddGeneratedFile(hex2bin(
"0ae3010a20676f6f676c652f70726f746f6275662f6669656c645f6d6173" .
"6b2e70726f746f120f676f6f676c652e70726f746f627566221a0a094669" .
"656c644d61736b120d0a0570617468731801200328094289010a13636f6d" .
"2e676f6f676c652e70726f746f627566420e4669656c644d61736b50726f" .
"746f50015a39676f6f676c652e676f6c616e672e6f72672f67656e70726f" .
"746f2f70726f746f6275662f6669656c645f6d61736b3b6669656c645f6d" .
"61736ba20203475042aa021e476f6f676c652e50726f746f6275662e5765" .
"6c6c4b6e6f776e5479706573620670726f746f33"
));
$pool->internalAddGeneratedFile(
'
ß
google/protobuf/field_mask.protogoogle.protobuf"
FieldMask
paths ( B…
com.google.protobufBFieldMaskProtoPZ2google.golang.org/protobuf/types/known/fieldmaskpbř˘GPBŞGoogle.Protobuf.WellKnownTypesbproto3'
, true);
static::$is_initialized = true;
}

@ -14,15 +14,14 @@ class GPBEmpty
if (static::$is_initialized == true) {
return;
}
$pool->internalAddGeneratedFile(hex2bin(
"0ab7010a1b676f6f676c652f70726f746f6275662f656d7074792e70726f" .
"746f120f676f6f676c652e70726f746f62756622070a05456d7074794276" .
"0a13636f6d2e676f6f676c652e70726f746f627566420a456d7074795072" .
"6f746f50015a276769746875622e636f6d2f676f6c616e672f70726f746f" .
"6275662f7074797065732f656d707479f80101a20203475042aa021e476f" .
"6f676c652e50726f746f6275662e57656c6c4b6e6f776e54797065736206" .
"70726f746f33"
));
$pool->internalAddGeneratedFile(
'
ž
google/protobuf/empty.protogoogle.protobuf"
EmptyB}
com.google.protobufB
EmptyProtoPZ.google.golang.org/protobuf/types/known/emptypbř˘GPBŞGoogle.Protobuf.WellKnownTypesbproto3'
, true);
static::$is_initialized = true;
}

@ -14,17 +14,14 @@ class SourceContext
if (static::$is_initialized == true) {
return;
}
$pool->internalAddGeneratedFile(hex2bin(
"0afb010a24676f6f676c652f70726f746f6275662f736f757263655f636f" .
"6e746578742e70726f746f120f676f6f676c652e70726f746f6275662222" .
"0a0d536f75726365436f6e7465787412110a0966696c655f6e616d651801" .
"200128094295010a13636f6d2e676f6f676c652e70726f746f6275664212" .
"536f75726365436f6e7465787450726f746f50015a41676f6f676c652e67" .
"6f6c616e672e6f72672f67656e70726f746f2f70726f746f6275662f736f" .
"757263655f636f6e746578743b736f757263655f636f6e74657874a20203" .
"475042aa021e476f6f676c652e50726f746f6275662e57656c6c4b6e6f77" .
"6e5479706573620670726f746f33"
));
$pool->internalAddGeneratedFile(
'
ð
$google/protobuf/source_context.protogoogle.protobuf""
SourceContext
file_name ( BŠ
com.google.protobufBSourceContextProtoPZ6google.golang.org/protobuf/types/known/sourcecontextpb¢GPBªGoogle.Protobuf.WellKnownTypesbproto3'
, true);
static::$is_initialized = true;
}

@ -14,16 +14,15 @@ class Timestamp
if (static::$is_initialized == true) {
return;
}
$pool->internalAddGeneratedFile(hex2bin(
"0ae7010a1f676f6f676c652f70726f746f6275662f74696d657374616d70" .
"2e70726f746f120f676f6f676c652e70726f746f627566222b0a0954696d" .
"657374616d70120f0a077365636f6e6473180120012803120d0a056e616e" .
"6f73180220012805427e0a13636f6d2e676f6f676c652e70726f746f6275" .
"66420e54696d657374616d7050726f746f50015a2b6769746875622e636f" .
"6d2f676f6c616e672f70726f746f6275662f7074797065732f74696d6573" .
"74616d70f80101a20203475042aa021e476f6f676c652e50726f746f6275" .
"662e57656c6c4b6e6f776e5479706573620670726f746f33"
));
$pool->internalAddGeneratedFile(
'
ď
google/protobuf/timestamp.protogoogle.protobuf"+
Timestamp
seconds (
nanos (B…
com.google.protobufBTimestampProtoPZ2google.golang.org/protobuf/types/known/timestamppbř˘GPBŞGoogle.Protobuf.WellKnownTypesbproto3'
, true);
static::$is_initialized = true;
}

@ -14,23 +14,34 @@ class Wrappers
if (static::$is_initialized == true) {
return;
}
$pool->internalAddGeneratedFile(hex2bin(
"0abf030a1e676f6f676c652f70726f746f6275662f77726170706572732e" .
"70726f746f120f676f6f676c652e70726f746f627566221c0a0b446f7562" .
"6c6556616c7565120d0a0576616c7565180120012801221b0a0a466c6f61" .
"7456616c7565120d0a0576616c7565180120012802221b0a0a496e743634" .
"56616c7565120d0a0576616c7565180120012803221c0a0b55496e743634" .
"56616c7565120d0a0576616c7565180120012804221b0a0a496e74333256" .
"616c7565120d0a0576616c7565180120012805221c0a0b55496e74333256" .
"616c7565120d0a0576616c756518012001280d221a0a09426f6f6c56616c" .
"7565120d0a0576616c7565180120012808221c0a0b537472696e6756616c" .
"7565120d0a0576616c7565180120012809221b0a0a427974657356616c75" .
"65120d0a0576616c756518012001280c427c0a13636f6d2e676f6f676c65" .
"2e70726f746f627566420d577261707065727350726f746f50015a2a6769" .
"746875622e636f6d2f676f6c616e672f70726f746f6275662f7074797065" .
"732f7772617070657273f80101a20203475042aa021e476f6f676c652e50" .
"726f746f6275662e57656c6c4b6e6f776e5479706573620670726f746f33"
));
$pool->internalAddGeneratedFile(
'
Ç
google/protobuf/wrappers.protogoogle.protobuf"
DoubleValue
value ("
FloatValue
value ("
Int64Value
value ("
UInt64Value
value ("
Int32Value
value ("
UInt32Value
value ( "
BoolValue
value ("
StringValue
value ( "
BytesValue
value ( 
com.google.protobufB WrappersProtoPZ1google.golang.org/protobuf/types/known/wrapperspbø¢GPBªGoogle.Protobuf.WellKnownTypesbproto3'
, true);
static::$is_initialized = true;
}

@ -5,7 +5,6 @@
namespace Google\Protobuf;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\Message;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
@ -39,10 +38,13 @@ use Google\Protobuf\Internal\GPBUtil;
* ...
* Example 4: Pack and unpack a message in Go
* foo := &pb.Foo{...}
* any, err := ptypes.MarshalAny(foo)
* any, err := anypb.New(foo)
* if err != nil {
* ...
* }
* ...
* foo := &pb.Foo{}
* if err := ptypes.UnmarshalAny(any, foo); err != nil {
* if err := any.UnmarshalTo(foo); err != nil {
* ...
* }
* The pack methods provided by protobuf library will by default use
@ -76,11 +78,12 @@ use Google\Protobuf\Internal\GPBUtil;
*
* Generated from protobuf message <code>google.protobuf.Any</code>
*/
class Any extends \Google\Protobuf\Internal\Message
class Any extends \Google\Protobuf\Internal\AnyBase
{
/**
* A URL/resource name that uniquely identifies the type of the serialized
* protocol buffer message. The last segment of the URL's path must represent
* protocol buffer message. This string must contain at least
* one "/" character. The last segment of the URL's path must represent
* the fully qualified name of the type (as in
* `path/google.protobuf.Duration`). The name should be in a canonical form
* (e.g., leading "." is not accepted).
@ -104,15 +107,13 @@ class Any extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>string type_url = 1;</code>
*/
private $type_url = '';
protected $type_url = '';
/**
* Must be a valid serialized protocol buffer of the above specified type.
*
* Generated from protobuf field <code>bytes value = 2;</code>
*/
private $value = '';
const TYPE_URL_PREFIX = 'type.googleapis.com/';
protected $value = '';
/**
* Constructor.
@ -122,7 +123,8 @@ class Any extends \Google\Protobuf\Internal\Message
*
* @type string $type_url
* A URL/resource name that uniquely identifies the type of the serialized
* protocol buffer message. The last segment of the URL's path must represent
* protocol buffer message. This string must contain at least
* one "/" character. The last segment of the URL's path must represent
* the fully qualified name of the type (as in
* `path/google.protobuf.Duration`). The name should be in a canonical form
* (e.g., leading "." is not accepted).
@ -154,7 +156,8 @@ class Any extends \Google\Protobuf\Internal\Message
/**
* A URL/resource name that uniquely identifies the type of the serialized
* protocol buffer message. The last segment of the URL's path must represent
* protocol buffer message. This string must contain at least
* one "/" character. The last segment of the URL's path must represent
* the fully qualified name of the type (as in
* `path/google.protobuf.Duration`). The name should be in a canonical form
* (e.g., leading "." is not accepted).
@ -186,7 +189,8 @@ class Any extends \Google\Protobuf\Internal\Message
/**
* A URL/resource name that uniquely identifies the type of the serialized
* protocol buffer message. The last segment of the URL's path must represent
* protocol buffer message. This string must contain at least
* one "/" character. The last segment of the URL's path must represent
* the fully qualified name of the type (as in
* `path/google.protobuf.Duration`). The name should be in a canonical form
* (e.g., leading "." is not accepted).
@ -246,78 +250,5 @@ class Any extends \Google\Protobuf\Internal\Message
return $this;
}
/**
* This method will try to resolve the type_url in Any message to get the
* targeted message type. If failed, an error will be thrown. Otherwise,
* the method will create a message of the targeted type and fill it with
* the decoded value in Any.
* @return Message unpacked message
* @throws \Exception Type url needs to be type.googleapis.com/fully-qualified.
* @throws \Exception Class hasn't been added to descriptor pool.
* @throws \Exception cannot decode data in value field.
*/
public function unpack()
{
// Get fully qualified name from type url.
$url_prifix_len = strlen(GPBUtil::TYPE_URL_PREFIX);
if (substr($this->type_url, 0, $url_prifix_len) !=
GPBUtil::TYPE_URL_PREFIX) {
throw new \Exception(
"Type url needs to be type.googleapis.com/fully-qulified");
}
$fully_qualifed_name =
substr($this->type_url, $url_prifix_len);
// Create message according to fully qualified name.
$pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
$desc = $pool->getDescriptorByProtoName($fully_qualifed_name);
if (is_null($desc)) {
throw new \Exception("Class ".$fully_qualifed_name
." hasn't been added to descriptor pool");
}
$klass = $desc->getClass();
$msg = new $klass();
// Merge data into message.
$msg->mergeFromString($this->value);
return $msg;
}
/**
* The type_url will be created according to the given message’s type and
* the value is encoded data from the given message..
* @param message: A proto message.
*/
public function pack($msg)
{
if (!$msg instanceof Message) {
trigger_error("Given parameter is not a message instance.",
E_USER_ERROR);
return;
}
// Set value using serialized message.
$this->value = $msg->serializeToString();
// Set type url.
$pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
$desc = $pool->getDescriptorByClassName(get_class($msg));
$fully_qualifed_name = $desc->getFullName();
$this->type_url = GPBUtil::TYPE_URL_PREFIX . $fully_qualifed_name;
}
/**
* This method returns whether the type_url in any_message is corresponded
* to the given class.
* @param klass: The fully qualified PHP class name of a proto message type.
*/
public function is($klass)
{
$pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
$desc = $pool->getDescriptorByClassName($klass);
$fully_qualifed_name = $desc->getFullName();
$type_url = GPBUtil::TYPE_URL_PREFIX . $fully_qualifed_name;
return $this->type_url === $type_url;
}
}

@ -28,7 +28,7 @@ class Api extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>string name = 1;</code>
*/
private $name = '';
protected $name = '';
/**
* The methods of this interface, in unspecified order.
*
@ -62,14 +62,14 @@ class Api extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>string version = 4;</code>
*/
private $version = '';
protected $version = '';
/**
* Source context for the protocol buffer service represented by this
* message.
*
* Generated from protobuf field <code>.google.protobuf.SourceContext source_context = 5;</code>
*/
private $source_context = null;
protected $source_context = null;
/**
* Included interfaces. See [Mixin][].
*
@ -81,7 +81,7 @@ class Api extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>.google.protobuf.Syntax syntax = 7;</code>
*/
private $syntax = 0;
protected $syntax = 0;
/**
* Constructor.
@ -275,7 +275,17 @@ class Api extends \Google\Protobuf\Internal\Message
*/
public function getSourceContext()
{
return $this->source_context;
return isset($this->source_context) ? $this->source_context : null;
}
public function hasSourceContext()
{
return isset($this->source_context);
}
public function clearSourceContext()
{
unset($this->source_context);
}
/**

@ -21,7 +21,7 @@ class BoolValue extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>bool value = 1;</code>
*/
private $value = false;
protected $value = false;
/**
* Constructor.

@ -21,7 +21,7 @@ class BytesValue extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>bytes value = 1;</code>
*/
private $value = '';
protected $value = '';
/**
* Constructor.

@ -21,7 +21,7 @@ class DoubleValue extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>double value = 1;</code>
*/
private $value = 0.0;
protected $value = 0.0;
/**
* Constructor.

@ -25,7 +25,7 @@ use Google\Protobuf\Internal\GPBUtil;
* 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;
* }
@ -66,7 +66,7 @@ class Duration extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>int64 seconds = 1;</code>
*/
private $seconds = 0;
protected $seconds = 0;
/**
* Signed fractions of a second at nanosecond resolution of the span
* of time. Durations less than one second are represented with a 0
@ -77,7 +77,7 @@ class Duration extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>int32 nanos = 2;</code>
*/
private $nanos = 0;
protected $nanos = 0;
/**
* Constructor.

@ -20,7 +20,7 @@ class Enum extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>string name = 1;</code>
*/
private $name = '';
protected $name = '';
/**
* Enum value definitions.
*
@ -38,13 +38,13 @@ class Enum extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>.google.protobuf.SourceContext source_context = 4;</code>
*/
private $source_context = null;
protected $source_context = null;
/**
* The source syntax.
*
* Generated from protobuf field <code>.google.protobuf.Syntax syntax = 5;</code>
*/
private $syntax = 0;
protected $syntax = 0;
/**
* Constructor.
@ -155,7 +155,17 @@ class Enum extends \Google\Protobuf\Internal\Message
*/
public function getSourceContext()
{
return $this->source_context;
return isset($this->source_context) ? $this->source_context : null;
}
public function hasSourceContext()
{
return isset($this->source_context);
}
public function clearSourceContext()
{
unset($this->source_context);
}
/**

@ -20,13 +20,13 @@ class EnumValue extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>string name = 1;</code>
*/
private $name = '';
protected $name = '';
/**
* Enum value number.
*
* Generated from protobuf field <code>int32 number = 2;</code>
*/
private $number = 0;
protected $number = 0;
/**
* Protocol buffer options.
*

@ -20,45 +20,45 @@ class Field extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>.google.protobuf.Field.Kind kind = 1;</code>
*/
private $kind = 0;
protected $kind = 0;
/**
* The field cardinality.
*
* Generated from protobuf field <code>.google.protobuf.Field.Cardinality cardinality = 2;</code>
*/
private $cardinality = 0;
protected $cardinality = 0;
/**
* The field number.
*
* Generated from protobuf field <code>int32 number = 3;</code>
*/
private $number = 0;
protected $number = 0;
/**
* The field name.
*
* Generated from protobuf field <code>string name = 4;</code>
*/
private $name = '';
protected $name = '';
/**
* The field type URL, without the scheme, for message or enumeration
* types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`.
*
* Generated from protobuf field <code>string type_url = 6;</code>
*/
private $type_url = '';
protected $type_url = '';
/**
* The index of the field type in `Type.oneofs`, for message or enumeration
* types. The first type has index 1; zero means the type is not in the list.
*
* Generated from protobuf field <code>int32 oneof_index = 7;</code>
*/
private $oneof_index = 0;
protected $oneof_index = 0;
/**
* Whether to use alternative packed wire representation.
*
* Generated from protobuf field <code>bool packed = 8;</code>
*/
private $packed = false;
protected $packed = false;
/**
* The protocol buffer options.
*
@ -70,13 +70,13 @@ class Field extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>string json_name = 10;</code>
*/
private $json_name = '';
protected $json_name = '';
/**
* The string value of the default value of this field. Proto2 syntax only.
*
* Generated from protobuf field <code>string default_value = 11;</code>
*/
private $default_value = '';
protected $default_value = '';
/**
* Constructor.
@ -133,7 +133,7 @@ class Field extends \Google\Protobuf\Internal\Message
*/
public function setKind($var)
{
GPBUtil::checkEnum($var, \Google\Protobuf\Field_Kind::class);
GPBUtil::checkEnum($var, \Google\Protobuf\Field\Kind::class);
$this->kind = $var;
return $this;
@ -159,7 +159,7 @@ class Field extends \Google\Protobuf\Internal\Message
*/
public function setCardinality($var)
{
GPBUtil::checkEnum($var, \Google\Protobuf\Field_Cardinality::class);
GPBUtil::checkEnum($var, \Google\Protobuf\Field\Cardinality::class);
$this->cardinality = $var;
return $this;

@ -54,6 +54,7 @@ class Cardinality
return self::$valueToName[$value];
}
public static function value($name)
{
$const = __CLASS__ . '::' . strtoupper($name);

@ -159,6 +159,7 @@ class Kind
return self::$valueToName[$value];
}
public static function value($name)
{
$const = __CLASS__ . '::' . strtoupper($name);

@ -62,45 +62,39 @@ use Google\Protobuf\Internal\GPBUtil;
* and leave the others untouched. If a resource is passed in to
* describe the updated values, the API ignores the values of all
* fields not covered by the mask.
* If a repeated field is specified for an update operation, the existing
* repeated values in the target resource will be overwritten by the new values.
* Note that a repeated field is only allowed in the last position of a `paths`
* string.
* If a repeated field is specified for an update operation, new values will
* be appended to the existing repeated field in the target resource. Note that
* a repeated field is only allowed in the last position of a `paths` string.
* If a sub-message is specified in the last position of the field mask for an
* update operation, then the existing sub-message in the target resource is
* overwritten. Given the target message:
* update operation, then new value will be merged into the existing sub-message
* in the target resource.
* For example, given the target message:
* f {
* b {
* d : 1
* x : 2
* d: 1
* x: 2
* }
* c : 1
* c: [1]
* }
* And an update message:
* f {
* b {
* d : 10
* d: 10
* }
* c: [2]
* }
* then if the field mask is:
* paths: "f.b"
* paths: ["f.b", "f.c"]
* then the result will be:
* f {
* b {
* d : 10
* }
* c : 1
* }
* However, if the update mask was:
* paths: "f.b.d"
* then the result would be:
* f {
* b {
* d : 10
* x : 2
* d: 10
* x: 2
* }
* c : 1
* c: [1, 2]
* }
* An implementation may provide options to override this default behavior for
* repeated and message fields.
* In order to reset a field's value to the default, the field must
* be in the mask and set to the default value in the provided resource.
* Hence, in order to reset all fields of a resource, provide a default
@ -165,7 +159,7 @@ use Google\Protobuf\Internal\GPBUtil;
* ## Field Mask Verification
* The implementation of any API method which has a FieldMask type field in the
* request should verify the included field paths, and return an
* `INVALID_ARGUMENT` error if any path is duplicated or unmappable.
* `INVALID_ARGUMENT` error if any path is unmappable.
*
* Generated from protobuf message <code>google.protobuf.FieldMask</code>
*/

@ -21,7 +21,7 @@ class FloatValue extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>float value = 1;</code>
*/
private $value = 0.0;
protected $value = 0.0;
/**
* Constructor.

@ -21,7 +21,7 @@ class Int32Value extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>int32 value = 1;</code>
*/
private $value = 0;
protected $value = 0;
/**
* Constructor.

@ -21,7 +21,7 @@ class Int64Value extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>int64 value = 1;</code>
*/
private $value = 0;
protected $value = 0;
/**
* Constructor.

@ -0,0 +1,86 @@
<?php
namespace Google\Protobuf\Internal;
/**
* Base class for Google\Protobuf\Any, this contains hand-written convenience
* methods like pack() and unpack().
*/
class AnyBase extends \Google\Protobuf\Internal\Message
{
const TYPE_URL_PREFIX = 'type.googleapis.com/';
/**
* This method will try to resolve the type_url in Any message to get the
* targeted message type. If failed, an error will be thrown. Otherwise,
* the method will create a message of the targeted type and fill it with
* the decoded value in Any.
* @return Message unpacked message
* @throws \Exception Type url needs to be type.googleapis.com/fully-qualified.
* @throws \Exception Class hasn't been added to descriptor pool.
* @throws \Exception cannot decode data in value field.
*/
public function unpack()
{
// Get fully qualified name from type url.
$url_prifix_len = strlen(GPBUtil::TYPE_URL_PREFIX);
if (substr($this->type_url, 0, $url_prifix_len) !=
GPBUtil::TYPE_URL_PREFIX) {
throw new \Exception(
"Type url needs to be type.googleapis.com/fully-qulified");
}
$fully_qualifed_name =
substr($this->type_url, $url_prifix_len);
// Create message according to fully qualified name.
$pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
$desc = $pool->getDescriptorByProtoName($fully_qualifed_name);
if (is_null($desc)) {
throw new \Exception("Class ".$fully_qualifed_name
." hasn't been added to descriptor pool");
}
$klass = $desc->getClass();
$msg = new $klass();
// Merge data into message.
$msg->mergeFromString($this->value);
return $msg;
}
/**
* The type_url will be created according to the given message’s type and
* the value is encoded data from the given message..
* @param message: A proto message.
*/
public function pack($msg)
{
if (!$msg instanceof Message) {
trigger_error("Given parameter is not a message instance.",
E_USER_ERROR);
return;
}
// Set value using serialized message.
$this->value = $msg->serializeToString();
// Set type url.
$pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
$desc = $pool->getDescriptorByClassName(get_class($msg));
$fully_qualifed_name = $desc->getFullName();
$this->type_url = GPBUtil::TYPE_URL_PREFIX . $fully_qualifed_name;
}
/**
* This method returns whether the type_url in any_message is corresponded
* to the given class.
* @param klass: The fully qualified PHP class name of a proto message type.
*/
public function is($klass)
{
$pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
$desc = $pool->getDescriptorByClassName($klass);
$fully_qualifed_name = $desc->getFullName();
$type_url = GPBUtil::TYPE_URL_PREFIX . $fully_qualifed_name;
return $this->type_url === $type_url;
}
}

@ -0,0 +1,32 @@
<?php
namespace Google\Protobuf\Internal;
/**
* Base class for Google\Protobuf\Timestamp, this contains hand-written
* convenience methods.
*/
class TimestampBase extends \Google\Protobuf\Internal\Message
{
/*
* Converts PHP DateTime to Timestamp.
*
* @param \DateTime $datetime
*/
public function fromDateTime(\DateTime $datetime)
{
$this->seconds = $datetime->getTimestamp();
$this->nanos = 1000 * $datetime->format('u');
}
/**
* Converts Timestamp to PHP DateTime.
*
* @return \DateTime $datetime
*/
public function toDateTime()
{
$time = sprintf('%s.%06d', $this->seconds, $this->nanos / 1000);
return \DateTime::createFromFormat('U.u', $time);
}
}

@ -20,31 +20,31 @@ class Method extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>string name = 1;</code>
*/
private $name = '';
protected $name = '';
/**
* A URL of the input message type.
*
* Generated from protobuf field <code>string request_type_url = 2;</code>
*/
private $request_type_url = '';
protected $request_type_url = '';
/**
* If true, the request is streamed.
*
* Generated from protobuf field <code>bool request_streaming = 3;</code>
*/
private $request_streaming = false;
protected $request_streaming = false;
/**
* The URL of the output message type.
*
* Generated from protobuf field <code>string response_type_url = 4;</code>
*/
private $response_type_url = '';
protected $response_type_url = '';
/**
* If true, the response is streamed.
*
* Generated from protobuf field <code>bool response_streaming = 5;</code>
*/
private $response_streaming = false;
protected $response_streaming = false;
/**
* Any metadata attached to the method.
*
@ -56,7 +56,7 @@ class Method extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>.google.protobuf.Syntax syntax = 7;</code>
*/
private $syntax = 0;
protected $syntax = 0;
/**
* Constructor.

@ -81,14 +81,14 @@ class Mixin extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>string name = 1;</code>
*/
private $name = '';
protected $name = '';
/**
* If non-empty specifies a path under which inherited HTTP paths
* are rooted.
*
* Generated from protobuf field <code>string root = 2;</code>
*/
private $root = '';
protected $root = '';
/**
* Constructor.

@ -24,7 +24,7 @@ class Option extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>string name = 1;</code>
*/
private $name = '';
protected $name = '';
/**
* The option's value packed in an Any message. If the value is a primitive,
* the corresponding wrapper type defined in google/protobuf/wrappers.proto
@ -33,7 +33,7 @@ class Option extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>.google.protobuf.Any value = 2;</code>
*/
private $value = null;
protected $value = null;
/**
* Constructor.
@ -101,7 +101,17 @@ class Option extends \Google\Protobuf\Internal\Message
*/
public function getValue()
{
return $this->value;
return isset($this->value) ? $this->value : null;
}
public function hasValue()
{
return isset($this->value);
}
public function clearValue()
{
unset($this->value);
}
/**

@ -22,7 +22,7 @@ class SourceContext extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>string file_name = 1;</code>
*/
private $file_name = '';
protected $file_name = '';
/**
* Constructor.

@ -21,7 +21,7 @@ class StringValue extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>string value = 1;</code>
*/
private $value = '';
protected $value = '';
/**
* Constructor.

@ -40,6 +40,7 @@ class Syntax
return self::$valueToName[$value];
}
public static function value($name)
{
$const = __CLASS__ . '::' . strtoupper($name);

@ -9,17 +9,17 @@ use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* A Timestamp represents a point in time independent of any time zone
* or calendar, represented as seconds and fractions of seconds at
* nanosecond resolution in UTC Epoch time. It is encoded using the
* Proleptic Gregorian Calendar which extends the Gregorian calendar
* backwards to year one. It is encoded assuming all minutes are 60
* seconds long, i.e. leap seconds are "smeared" so that no leap second
* table is needed for interpretation. Range is from
* 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
* By restricting to that range, we ensure that we can convert to
* and from RFC 3339 date strings.
* See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
* A Timestamp represents a point in time independent of any time zone or local
* calendar, encoded as a count of seconds and fractions of seconds at
* nanosecond resolution. The count is relative to an epoch at UTC midnight on
* January 1, 1970, in the proleptic Gregorian calendar which extends the
* Gregorian calendar backwards to year one.
* All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap
* second table is needed for interpretation, using a [24-hour linear
* smear](https://developers.google.com/time/smear).
* The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By
* restricting to that range, we ensure that we can convert to and from [RFC
* 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings.
* # Examples
* Example 1: Compute Timestamp from POSIX `time()`.
* Timestamp timestamp;
@ -44,7 +44,12 @@ use Google\Protobuf\Internal\GPBUtil;
* long millis = System.currentTimeMillis();
* Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
* .setNanos((int) ((millis % 1000) * 1000000)).build();
* Example 5: Compute Timestamp from current time in Python.
* Example 5: Compute Timestamp from Java `Instant.now()`.
* Instant now = Instant.now();
* Timestamp timestamp =
* Timestamp.newBuilder().setSeconds(now.getEpochSecond())
* .setNanos(now.getNano()).build();
* Example 6: Compute Timestamp from current time in Python.
* timestamp = Timestamp()
* timestamp.GetCurrentTime()
* # JSON Mapping
@ -61,17 +66,19 @@ use Google\Protobuf\Internal\GPBUtil;
* For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
* 01:30 UTC on January 15, 2017.
* In JavaScript, one can convert a Date object to this format using the
* standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString]
* standard
* [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
* method. In Python, a standard `datetime.datetime` object can be converted
* to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
* with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
* can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
* http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--
* to this format using
* [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with
* the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use
* the Joda Time's [`ISODateTimeFormat.dateTime()`](
* http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D
* ) to obtain a formatter capable of generating timestamps in this format.
*
* Generated from protobuf message <code>google.protobuf.Timestamp</code>
*/
class Timestamp extends \Google\Protobuf\Internal\Message
class Timestamp extends \Google\Protobuf\Internal\TimestampBase
{
/**
* Represents seconds of UTC time since Unix epoch
@ -80,7 +87,7 @@ class Timestamp extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>int64 seconds = 1;</code>
*/
private $seconds = 0;
protected $seconds = 0;
/**
* Non-negative fractions of a second at nanosecond resolution. Negative
* second values with fractions must still have non-negative nanos values
@ -89,7 +96,7 @@ class Timestamp extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>int32 nanos = 2;</code>
*/
private $nanos = 0;
protected $nanos = 0;
/**
* Constructor.
@ -175,26 +182,5 @@ class Timestamp extends \Google\Protobuf\Internal\Message
return $this;
}
/*
* Converts PHP DateTime to Timestamp.
*
* @param \DateTime $datetime
*/
public function fromDateTime(\DateTime $datetime)
{
$this->seconds = $datetime->getTimestamp();
$this->nanos = 1000 * $datetime->format('u');
}
/**
* Converts Timestamp to PHP DateTime.
*
* @return \DateTime $datetime
*/
public function toDateTime()
{
$time = sprintf('%s.%06d', $this->seconds, $this->nanos / 1000);
return \DateTime::createFromFormat('U.u', $time);
}
}

@ -20,7 +20,7 @@ class Type extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>string name = 1;</code>
*/
private $name = '';
protected $name = '';
/**
* The list of fields.
*
@ -44,13 +44,13 @@ class Type extends \Google\Protobuf\Internal\Message
*
* Generated from protobuf field <code>.google.protobuf.SourceContext source_context = 5;</code>
*/
private $source_context = null;
protected $source_context = null;
/**
* The source syntax.
*
* Generated from protobuf field <code>.google.protobuf.Syntax syntax = 6;</code>
*/
private $syntax = 0;
protected $syntax = 0;
/**
* Constructor.
@ -189,7 +189,17 @@ class Type extends \Google\Protobuf\Internal\Message
*/
public function getSourceContext()
{
return $this->source_context;
return isset($this->source_context) ? $this->source_context : null;
}
public function hasSourceContext()
{
return isset($this->source_context);
}
public function clearSourceContext()
{
unset($this->source_context);
}
/**

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

Loading…
Cancel
Save