Remove old PHP extension (#7695)

* Removed references to legacy class names from generated code.

* Removed old PHP extension in favor of new extension. This drops PHP5 compat.

* Updated failure lists for things fixed by the new extension.

* Updated Makefile.am for new file list.

* Fix distcheck.
pull/7699/head
Joshua Haberman 5 years ago committed by GitHub
parent c02ded7a57
commit ffb2b53834
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 43
      Makefile.am
  2. 53
      conformance/failure_list_php_c.txt
  3. 86
      conformance/failure_list_php_c_32.txt
  4. 0
      php/ext/google/protobuf/arena.c
  5. 0
      php/ext/google/protobuf/arena.h
  6. 777
      php/ext/google/protobuf/array.c
  7. 0
      php/ext/google/protobuf/array.h
  8. 635
      php/ext/google/protobuf/builtin_descriptors.inc
  9. 0
      php/ext/google/protobuf/bundled_php.h
  10. 2
      php/ext/google/protobuf/config.m4
  11. 0
      php/ext/google/protobuf/convert.c
  12. 0
      php/ext/google/protobuf/convert.h
  13. 1578
      php/ext/google/protobuf/def.c
  14. 0
      php/ext/google/protobuf/def.h
  15. 2283
      php/ext/google/protobuf/encode_decode.c
  16. 2
      php/ext/google/protobuf/make-preload.php
  17. 918
      php/ext/google/protobuf/map.c
  18. 0
      php/ext/google/protobuf/map.h
  19. 3231
      php/ext/google/protobuf/message.c
  20. 0
      php/ext/google/protobuf/message.h
  21. 0
      php/ext/google/protobuf/names.c
  22. 0
      php/ext/google/protobuf/names.h
  23. 22
      php/ext/google/protobuf/package.xml
  24. 0
      php/ext/google/protobuf/php-upb.c
  25. 0
      php/ext/google/protobuf/php-upb.h
  26. 730
      php/ext/google/protobuf/protobuf.c
  27. 1586
      php/ext/google/protobuf/protobuf.h
  28. 1180
      php/ext/google/protobuf/storage.c
  29. 680
      php/ext/google/protobuf/type_check.c
  30. 13840
      php/ext/google/protobuf/upb.c
  31. 6796
      php/ext/google/protobuf/upb.h
  32. 68
      php/ext/google/protobuf/utf8.c
  33. 36
      php/ext/google/protobuf/utf8.h
  34. 602
      php/ext/google/protobuf2/array.c
  35. 10
      php/ext/google/protobuf2/config.m4
  36. 1085
      php/ext/google/protobuf2/def.c
  37. 590
      php/ext/google/protobuf2/map.c
  38. 841
      php/ext/google/protobuf2/message.c
  39. 349
      php/ext/google/protobuf2/protobuf.c
  40. 89
      php/ext/google/protobuf2/protobuf.h
  41. 11
      php/tests/compile_extension.sh
  42. 2
      php/tests/php_implementation_test.php
  43. 17
      php/tests/test.sh
  44. 6
      src/google/protobuf/compiler/php/php_generator.cc

@ -767,43 +767,28 @@ php_EXTRA_DIST= \
composer.json \ composer.json \
php/README.md \ php/README.md \
php/composer.json \ php/composer.json \
php/ext/google/protobuf/arena.c \
php/ext/google/protobuf/arena.h \
php/ext/google/protobuf/array.c \ php/ext/google/protobuf/array.c \
php/ext/google/protobuf/builtin_descriptors.inc \ php/ext/google/protobuf/array.h \
php/ext/google/protobuf/bundled_php.h \
php/ext/google/protobuf/config.m4 \ php/ext/google/protobuf/config.m4 \
php/ext/google/protobuf/convert.c \
php/ext/google/protobuf/convert.h \
php/ext/google/protobuf/def.c \ php/ext/google/protobuf/def.c \
php/ext/google/protobuf/encode_decode.c \ php/ext/google/protobuf/def.h \
php/ext/google/protobuf/make-preload.php \
php/ext/google/protobuf/map.c \ php/ext/google/protobuf/map.c \
php/ext/google/protobuf/map.h \
php/ext/google/protobuf/message.c \ php/ext/google/protobuf/message.c \
php/ext/google/protobuf/message.h \
php/ext/google/protobuf/names.c \
php/ext/google/protobuf/names.h \
php/ext/google/protobuf/package.xml \ php/ext/google/protobuf/package.xml \
php/ext/google/protobuf/php-upb.c \
php/ext/google/protobuf/php-upb.h \
php/ext/google/protobuf/protobuf.c \ php/ext/google/protobuf/protobuf.c \
php/ext/google/protobuf/protobuf.h \ php/ext/google/protobuf/protobuf.h \
php/ext/google/protobuf/storage.c \
php/ext/google/protobuf/type_check.c \
php/ext/google/protobuf/upb.c \
php/ext/google/protobuf/upb.h \
php/ext/google/protobuf/utf8.c \
php/ext/google/protobuf/utf8.h \
php/ext/google/protobuf2/arena.c \
php/ext/google/protobuf2/arena.h \
php/ext/google/protobuf2/array.c \
php/ext/google/protobuf2/array.h \
php/ext/google/protobuf2/bundled_php.h \
php/ext/google/protobuf2/config.m4 \
php/ext/google/protobuf2/convert.c \
php/ext/google/protobuf2/convert.h \
php/ext/google/protobuf2/def.c \
php/ext/google/protobuf2/def.h \
php/ext/google/protobuf2/make-preload.php \
php/ext/google/protobuf2/map.c \
php/ext/google/protobuf2/map.h \
php/ext/google/protobuf2/message.c \
php/ext/google/protobuf2/message.h \
php/ext/google/protobuf2/names.c \
php/ext/google/protobuf2/names.h \
php/ext/google/protobuf2/php-upb.c \
php/ext/google/protobuf2/php-upb.h \
php/ext/google/protobuf2/protobuf.c \
php/ext/google/protobuf2/protobuf.h \
php/generate_descriptor_protos.sh \ php/generate_descriptor_protos.sh \
php/phpunit.xml \ php/phpunit.xml \
php/release.sh \ php/release.sh \

@ -1,23 +1,4 @@
Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
Recommended.FieldMaskTooManyUnderscore.JsonOutput
Recommended.Proto2.JsonInput.FieldNameExtension.Validator Recommended.Proto2.JsonInput.FieldNameExtension.Validator
Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator
Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator
Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
Recommended.Proto3.JsonInput.MapFieldValueIsNull
Recommended.Proto3.JsonInput.OneofZeroBytes.JsonOutput
Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull
Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull
Recommended.Proto3.JsonInput.StringEndsWithEscapeChar
Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder
Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate
Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
Recommended.Proto3.JsonInput.TimestampHas3FractionalDigits.Validator
Recommended.Proto3.JsonInput.TimestampHas6FractionalDigits.Validator
Recommended.Proto3.ProtobufInput.OneofZeroBytes.JsonOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
@ -28,10 +9,8 @@ Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultO
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
@ -76,36 +55,4 @@ Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOut
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[3].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[4].ProtobufOutput
Required.DurationProtoInputTooLarge.JsonOutput
Required.DurationProtoInputTooSmall.JsonOutput
Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator
Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.JsonOutput
Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
Required.Proto3.JsonInput.DoubleFieldNan.JsonOutput
Required.Proto3.JsonInput.DurationMinValue.JsonOutput
Required.Proto3.JsonInput.DurationRepeatedValue.JsonOutput
Required.Proto3.JsonInput.FloatFieldInfinity.JsonOutput
Required.Proto3.JsonInput.FloatFieldNan.JsonOutput
Required.Proto3.JsonInput.FloatFieldNegativeInfinity.JsonOutput
Required.Proto3.JsonInput.OneofFieldDuplicate
Required.Proto3.JsonInput.RejectTopLevelNull
Required.Proto3.JsonInput.StringFieldSurrogatePair.JsonOutput
Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput
Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.DefaultValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].JsonOutput
Required.TimestampProtoInputTooLarge.JsonOutput
Required.TimestampProtoInputTooSmall.JsonOutput

@ -1,28 +1,4 @@
Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
Recommended.FieldMaskTooManyUnderscore.JsonOutput
Recommended.Proto2.JsonInput.FieldNameExtension.Validator Recommended.Proto2.JsonInput.FieldNameExtension.Validator
Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator
Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator
Recommended.Proto3.JsonInput.DurationHas9FractionalDigits.Validator
Recommended.Proto3.JsonInput.DurationHasZeroFractionalDigit.Validator
Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
Recommended.Proto3.JsonInput.MapFieldValueIsNull
Recommended.Proto3.JsonInput.OneofZeroBytes.JsonOutput
Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull
Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull
Recommended.Proto3.JsonInput.StringEndsWithEscapeChar
Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder
Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate
Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
Recommended.Proto3.JsonInput.TimestampHas3FractionalDigits.Validator
Recommended.Proto3.JsonInput.TimestampHas6FractionalDigits.Validator
Recommended.Proto3.JsonInput.TimestampHas9FractionalDigits.Validator
Recommended.Proto3.JsonInput.TimestampHasZeroFractionalDigit.Validator
Recommended.Proto3.JsonInput.TimestampZeroNormalized.Validator
Recommended.Proto3.ProtobufInput.OneofZeroBytes.JsonOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
@ -33,10 +9,8 @@ Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultO
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
@ -81,64 +55,4 @@ Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOut
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[3].ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[4].ProtobufOutput
Required.DurationProtoInputTooLarge.JsonOutput
Required.DurationProtoInputTooSmall.JsonOutput
Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator
Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.JsonOutput
Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
Required.Proto3.JsonInput.DoubleFieldNan.JsonOutput
Required.Proto3.JsonInput.DurationMaxValue.JsonOutput
Required.Proto3.JsonInput.DurationMaxValue.ProtobufOutput
Required.Proto3.JsonInput.DurationMinValue.JsonOutput
Required.Proto3.JsonInput.DurationMinValue.ProtobufOutput
Required.Proto3.JsonInput.DurationRepeatedValue.JsonOutput
Required.Proto3.JsonInput.DurationRepeatedValue.ProtobufOutput
Required.Proto3.JsonInput.FloatFieldInfinity.JsonOutput
Required.Proto3.JsonInput.FloatFieldNan.JsonOutput
Required.Proto3.JsonInput.FloatFieldNegativeInfinity.JsonOutput
Required.Proto3.JsonInput.Int64FieldMaxValue.JsonOutput
Required.Proto3.JsonInput.Int64FieldMaxValueNotQuoted.JsonOutput
Required.Proto3.JsonInput.Int64FieldMaxValueNotQuoted.ProtobufOutput
Required.Proto3.JsonInput.Int64FieldMaxValue.ProtobufOutput
Required.Proto3.JsonInput.Int64FieldMinValue.JsonOutput
Required.Proto3.JsonInput.Int64FieldMinValueNotQuoted.JsonOutput
Required.Proto3.JsonInput.Int64FieldMinValueNotQuoted.ProtobufOutput
Required.Proto3.JsonInput.Int64FieldMinValue.ProtobufOutput
Required.Proto3.JsonInput.OneofFieldDuplicate
Required.Proto3.JsonInput.RejectTopLevelNull
Required.Proto3.JsonInput.StringFieldSurrogatePair.JsonOutput
Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput
Required.Proto3.JsonInput.TimestampLeap.JsonOutput
Required.Proto3.JsonInput.TimestampLeap.ProtobufOutput
Required.Proto3.JsonInput.TimestampMaxValue.JsonOutput
Required.Proto3.JsonInput.TimestampMaxValue.ProtobufOutput
Required.Proto3.JsonInput.TimestampMinValue.JsonOutput
Required.Proto3.JsonInput.TimestampMinValue.ProtobufOutput
Required.Proto3.JsonInput.TimestampRepeatedValue.JsonOutput
Required.Proto3.JsonInput.TimestampRepeatedValue.ProtobufOutput
Required.Proto3.JsonInput.TimestampWithNegativeOffset.JsonOutput
Required.Proto3.JsonInput.TimestampWithNegativeOffset.ProtobufOutput
Required.Proto3.JsonInput.TimestampWithPositiveOffset.JsonOutput
Required.Proto3.JsonInput.TimestampWithPositiveOffset.ProtobufOutput
Required.Proto3.JsonInput.Uint64FieldMaxValue.JsonOutput
Required.Proto3.JsonInput.Uint64FieldMaxValueNotQuoted.JsonOutput
Required.Proto3.JsonInput.Uint64FieldMaxValueNotQuoted.ProtobufOutput
Required.Proto3.JsonInput.Uint64FieldMaxValue.ProtobufOutput
Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.DefaultValue.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.JsonOutput
Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.ProtobufOutput
Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].JsonOutput
Required.TimestampProtoInputTooLarge.JsonOutput
Required.TimestampProtoInputTooSmall.JsonOutput

@ -28,389 +28,268 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <ext/spl/spl_iterators.h> #include "array.h"
#include <Zend/zend_API.h> #include <Zend/zend_API.h>
#include <Zend/zend_interfaces.h> #include <Zend/zend_interfaces.h>
#include "protobuf.h" #include <ext/spl/spl_iterators.h>
ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1) // This is not self-contained: it must be after other Zend includes.
ZEND_ARG_INFO(0, index) #include <Zend/zend_exceptions.h>
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2) #include "arena.h"
ZEND_ARG_INFO(0, index) #include "convert.h"
ZEND_ARG_INFO(0, newval) #include "def.h"
ZEND_END_ARG_INFO() #include "php-upb.h"
#include "protobuf.h"
ZEND_BEGIN_ARG_INFO(arginfo_void, 0) static void RepeatedFieldIter_make(zval *val, zval *repeated_field);
ZEND_END_ARG_INFO()
static zend_function_entry repeated_field_methods[] = { // -----------------------------------------------------------------------------
PHP_ME(RepeatedField, __construct, NULL, ZEND_ACC_PUBLIC) // RepeatedField
PHP_ME(RepeatedField, append, NULL, ZEND_ACC_PUBLIC) // -----------------------------------------------------------------------------
PHP_ME(RepeatedField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedField, offsetUnset, arginfo_offsetGet, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedField, count, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedField, getIterator, arginfo_void, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
static zend_function_entry repeated_field_iter_methods[] = { typedef struct {
PHP_ME(RepeatedFieldIter, rewind, arginfo_void, ZEND_ACC_PUBLIC) zend_object std;
PHP_ME(RepeatedFieldIter, current, arginfo_void, ZEND_ACC_PUBLIC) zval arena;
PHP_ME(RepeatedFieldIter, key, arginfo_void, ZEND_ACC_PUBLIC) upb_array *array;
PHP_ME(RepeatedFieldIter, next, arginfo_void, ZEND_ACC_PUBLIC) upb_fieldtype_t type;
PHP_ME(RepeatedFieldIter, valid, arginfo_void, ZEND_ACC_PUBLIC) const Descriptor* desc; // When values are messages.
ZEND_FE_END } RepeatedField;
};
// Forward declare static functions. zend_class_entry *RepeatedField_class_entry;
static zend_object_handlers RepeatedField_object_handlers;
static int repeated_field_array_init(zval *array, upb_fieldtype_t type,
uint size ZEND_FILE_LINE_DC);
static void repeated_field_write_dimension(zval *object, zval *offset,
zval *value TSRMLS_DC);
static HashTable *repeated_field_get_gc(zval *object, CACHED_VALUE **table,
int *n TSRMLS_DC);
#if PHP_MAJOR_VERSION < 7
static zend_object_value repeated_field_create(zend_class_entry *ce TSRMLS_DC);
static zend_object_value repeated_field_iter_create(zend_class_entry *ce TSRMLS_DC);
#else
static zend_object *repeated_field_create(zend_class_entry *ce TSRMLS_DC);
static zend_object *repeated_field_iter_create(zend_class_entry *ce TSRMLS_DC);
#endif
// ----------------------------------------------------------------------------- // PHP Object Handlers /////////////////////////////////////////////////////////
// RepeatedField creation/destruction
// -----------------------------------------------------------------------------
zend_class_entry* repeated_field_type; /**
zend_class_entry* repeated_field_iter_type; * RepeatedField_create()
zend_object_handlers* repeated_field_handlers; *
zend_object_handlers* repeated_field_iter_handlers; * PHP class entry function to allocate and initialize a new RepeatedField
* object.
// Define object free method. */
PHP_PROTO_OBJECT_FREE_START(RepeatedField, repeated_field) static zend_object* RepeatedField_create(zend_class_entry *class_type) {
#if PHP_MAJOR_VERSION < 7 RepeatedField *intern = emalloc(sizeof(RepeatedField));
php_proto_zval_ptr_dtor(intern->array); zend_object_std_init(&intern->std, class_type);
#else intern->std.handlers = &RepeatedField_object_handlers;
php_proto_zval_ptr_dtor(&intern->array); Arena_Init(&intern->arena);
#endif intern->array = NULL;
PHP_PROTO_OBJECT_FREE_END intern->desc = NULL;
// Skip object_properties_init(), we don't allow derived classes.
PHP_PROTO_OBJECT_EMPTY_DTOR_START(RepeatedField, repeated_field) return &intern->std;
PHP_PROTO_OBJECT_DTOR_END
// Define object create method.
PHP_PROTO_OBJECT_CREATE_START(RepeatedField, repeated_field)
#if PHP_MAJOR_VERSION < 7
intern->array = NULL;
#endif
intern->type = 0;
intern->msg_ce = NULL;
PHP_PROTO_OBJECT_CREATE_END(RepeatedField, repeated_field)
// Init class entry.
PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\RepeatedField",
RepeatedField, repeated_field)
zend_class_implements(repeated_field_type TSRMLS_CC, 3, spl_ce_ArrayAccess,
zend_ce_aggregate, spl_ce_Countable);
repeated_field_handlers->write_dimension = repeated_field_write_dimension;
repeated_field_handlers->get_gc = repeated_field_get_gc;
PHP_PROTO_INIT_CLASS_END
// Define array element free function.
#if PHP_MAJOR_VERSION < 7
static inline void php_proto_array_string_release(void *value) {
zval_ptr_dtor(value);
} }
static inline void php_proto_array_object_release(void *value) { /**
zval_ptr_dtor(value); * RepeatedField_dtor()
} *
static inline void php_proto_array_default_release(void *value) { * Object handler to destroy a RepeatedField. This releases all resources
} * associated with the message. Note that it is possible to access a destroyed
#else * object from PHP in rare cases.
static inline void php_proto_array_string_release(zval *value) { */
void* ptr = Z_PTR_P(value); static void RepeatedField_destructor(zend_object* obj) {
zend_string* object = *(zend_string**)ptr; RepeatedField* intern = (RepeatedField*)obj;
zend_string_release(object); ObjCache_Delete(intern->array);
efree(ptr); zval_ptr_dtor(&intern->arena);
} zend_object_std_dtor(&intern->std);
static inline void php_proto_array_object_release(zval *value) {
zval_ptr_dtor(value);
}
static void php_proto_array_default_release(zval* value) {
void* ptr = Z_PTR_P(value);
efree(ptr);
}
#endif
static int repeated_field_array_init(zval *array, upb_fieldtype_t type,
uint size ZEND_FILE_LINE_DC) {
PHP_PROTO_ALLOC_ARRAY(array);
switch (type) {
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES:
zend_hash_init(Z_ARRVAL_P(array), size, NULL,
php_proto_array_string_release, 0);
break;
case UPB_TYPE_MESSAGE:
zend_hash_init(Z_ARRVAL_P(array), size, NULL,
php_proto_array_object_release, 0);
break;
default:
zend_hash_init(Z_ARRVAL_P(array), size, NULL,
php_proto_array_default_release, 0);
}
return SUCCESS;
} }
// ----------------------------------------------------------------------------- static HashTable *RepeatedField_GetProperties(zval *object TSRMLS_DC) {
// RepeatedField Handlers return NULL; // We do not have a properties table.
// ----------------------------------------------------------------------------- }
static void repeated_field_write_dimension(zval *object, zval *offset, static zval *RepeatedField_GetPropertyPtrPtr(zval *object, zval *member,
zval *value TSRMLS_DC) { int type, void **cache_slot) {
uint64_t index; return NULL; // We don't offer direct references to our properties.
}
RepeatedField *intern = UNBOX(RepeatedField, object); // C Functions from array.h ////////////////////////////////////////////////////
HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
int size = native_slot_size(intern->type);
unsigned char memory[NATIVE_SLOT_MAX_SIZE]; // These are documented in the header file.
memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
if (!native_slot_set_by_array(intern->type, intern->msg_ce, memory, void RepeatedField_GetPhpWrapper(zval *val, upb_array *arr,
value TSRMLS_CC)) { const upb_fielddef *f, zval *arena) {
if (!arr) {
ZVAL_NULL(val);
return; return;
} }
if (!offset || Z_TYPE_P(offset) == IS_NULL) { if (!ObjCache_Get(arr, val)) {
index = zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array)); RepeatedField *intern = emalloc(sizeof(RepeatedField));
} else { zend_object_std_init(&intern->std, RepeatedField_class_entry);
if (protobuf_convert_to_uint64(offset, &index)) { intern->std.handlers = &RepeatedField_object_handlers;
if (!zend_hash_index_exists(ht, index)) { ZVAL_COPY(&intern->arena, arena);
zend_error(E_USER_ERROR, "Element at %llu doesn't exist.\n", intern->array = arr;
(long long unsigned int)index); intern->type = upb_fielddef_type(f);
return; intern->desc = Descriptor_GetFromFieldDef(f);
} // Skip object_properties_init(), we don't allow derived classes.
} else { ObjCache_Add(intern->array, &intern->std);
return; ZVAL_OBJ(val, &intern->std);
}
} }
}
if (intern->type == UPB_TYPE_MESSAGE) { upb_array *RepeatedField_GetUpbArray(zval *val, const upb_fielddef *f,
php_proto_zend_hash_index_update_zval(ht, index, *(zval**)memory); upb_arena *arena) {
} else { if (Z_ISREF_P(val)) {
php_proto_zend_hash_index_update_mem(ht, index, memory, size, NULL); ZVAL_DEREF(val);
} }
}
#if PHP_MAJOR_VERSION < 7 if (Z_TYPE_P(val) == IS_ARRAY) {
static HashTable *repeated_field_get_gc(zval *object, zval ***table, // Auto-construct, eg. [1, 2, 3] -> upb_array([1, 2, 3]).
int *n TSRMLS_DC) { upb_array *arr = upb_array_new(arena, upb_fielddef_type(f));
#else HashTable *table = HASH_OF(val);
static HashTable *repeated_field_get_gc(zval *object, zval **table, int *n) { HashPosition pos;
#endif upb_fieldtype_t type = upb_fielddef_type(f);
*table = NULL; const Descriptor *desc = Descriptor_GetFromFieldDef(f);
*n = 0;
RepeatedField *intern = UNBOX(RepeatedField, object);
return PHP_PROTO_HASH_OF(intern->array);
}
// ----------------------------------------------------------------------------- zend_hash_internal_pointer_reset_ex(table, &pos);
// C RepeatedField Utilities
// ----------------------------------------------------------------------------- while (true) {
zval *zv = zend_hash_get_current_data_ex(table, &pos);
upb_msgval val;
void *repeated_field_index_native(RepeatedField *intern, int index TSRMLS_DC) { if (!zv) return arr;
HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
void *value;
if (intern->type == UPB_TYPE_MESSAGE) { if (!Convert_PhpToUpbAutoWrap(zv, &val, type, desc, arena)) {
if (php_proto_zend_hash_index_find_zval(ht, index, (void **)&value) == return NULL;
FAILURE) { }
zend_error(E_USER_ERROR, "Element at %d doesn't exist.\n", index);
return NULL; upb_array_append(arr, val, arena);
zend_hash_move_forward_ex(table, &pos);
} }
} else { } else if (Z_TYPE_P(val) == IS_OBJECT &&
if (php_proto_zend_hash_index_find_mem(ht, index, (void **)&value) == Z_OBJCE_P(val) == RepeatedField_class_entry) {
FAILURE) { // Unwrap existing RepeatedField object to get the upb_array* inside.
zend_error(E_USER_ERROR, "Element at %d doesn't exist.\n", index); RepeatedField *intern = (RepeatedField*)Z_OBJ_P(val);
return NULL; const Descriptor *desc = Descriptor_GetFromFieldDef(f);
if (intern->type != upb_fielddef_type(f) || intern->desc != desc) {
php_error_docref(NULL, E_USER_ERROR,
"Wrong type for this repeated field.");
} }
}
return value;
}
void repeated_field_push_native(RepeatedField *intern, void *value) { upb_arena_fuse(arena, Arena_Get(&intern->arena));
HashTable *ht = PHP_PROTO_HASH_OF(intern->array); return intern->array;
int size = native_slot_size(intern->type);
if (intern->type == UPB_TYPE_MESSAGE) {
php_proto_zend_hash_next_index_insert_zval(ht, value);
} else { } else {
php_proto_zend_hash_next_index_insert_mem(ht, (void **)value, size, NULL); php_error_docref(NULL, E_USER_ERROR, "Must be a repeated field");
return NULL;
} }
} }
void repeated_field_ensure_created( // RepeatedField PHP methods ///////////////////////////////////////////////////
const upb_fielddef *field,
CACHED_VALUE *repeated_field PHP_PROTO_TSRMLS_DC) {
if (ZVAL_IS_NULL(CACHED_PTR_TO_ZVAL_PTR(repeated_field))) {
zval_ptr_dtor(repeated_field);
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL(CACHED_PTR_TO_ZVAL_PTR(repeated_field));
#endif
repeated_field_create_with_field(repeated_field_type, field,
repeated_field PHP_PROTO_TSRMLS_CC);
}
}
void repeated_field_create_with_field(
zend_class_entry *ce, const upb_fielddef *field,
CACHED_VALUE *repeated_field PHP_PROTO_TSRMLS_DC) {
upb_fieldtype_t type = upb_fielddef_type(field);
const zend_class_entry *msg_ce = field_type_class(field PHP_PROTO_TSRMLS_CC);
repeated_field_create_with_type(ce, type, msg_ce,
repeated_field PHP_PROTO_TSRMLS_CC);
}
void repeated_field_create_with_type(
zend_class_entry *ce, upb_fieldtype_t type, const zend_class_entry *msg_ce,
CACHED_VALUE *repeated_field PHP_PROTO_TSRMLS_DC) {
CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(CACHED_PTR_TO_ZVAL_PTR(repeated_field),
repeated_field_type);
RepeatedField *intern =
UNBOX(RepeatedField, CACHED_TO_ZVAL_PTR(*repeated_field));
intern->type = type;
intern->msg_ce = msg_ce;
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL(intern->array);
repeated_field_array_init(intern->array, intern->type, 0 ZEND_FILE_LINE_CC);
#else
repeated_field_array_init(&intern->array, intern->type, 0 ZEND_FILE_LINE_CC);
#endif
// TODO(teboring): Link class entry for message and enum
}
// -----------------------------------------------------------------------------
// PHP RepeatedField Methods
// -----------------------------------------------------------------------------
/** /**
* RepeatedField::__construct()
*
* Constructs an instance of RepeatedField. * Constructs an instance of RepeatedField.
* @param long Type of the stored element. * @param long Type of the stored element.
* @param string Message/Enum class name (message/enum fields only). * @param string Message/Enum class.
*/ */
PHP_METHOD(RepeatedField, __construct) { PHP_METHOD(RepeatedField, __construct) {
long type; RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
upb_arena *arena = Arena_Get(&intern->arena);
zend_long type;
zend_class_entry* klass = NULL; zend_class_entry* klass = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|C", &type, &klass) == if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|C", &type, &klass) != SUCCESS) {
FAILURE) {
return; return;
} }
RepeatedField *intern = UNBOX(RepeatedField, getThis()); intern->type = pbphp_dtype_to_type(type);
intern->type = to_fieldtype(type); intern->desc = Descriptor_GetFromClassEntry(klass);
intern->msg_ce = klass;
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL(intern->array);
repeated_field_array_init(intern->array, intern->type, 0 ZEND_FILE_LINE_CC);
#else
repeated_field_array_init(&intern->array, intern->type, 0 ZEND_FILE_LINE_CC);
#endif
if (intern->type == UPB_TYPE_MESSAGE && klass == NULL) { if (intern->type == UPB_TYPE_MESSAGE && klass == NULL) {
zend_error(E_USER_ERROR, "Message type must have concrete class."); php_error_docref(NULL, E_USER_ERROR,
"Message/enum type must have concrete class.");
return; return;
} }
// TODO(teboring): Consider enum. intern->array = upb_array_new(arena, intern->type);
ObjCache_Add(intern->array, &intern->std);
} }
/** /**
* RepeatedField::append()
*
* Append element to the end of the repeated field. * Append element to the end of the repeated field.
* @param object The element to be added. * @param object The element to be added.
*/ */
PHP_METHOD(RepeatedField, append) { PHP_METHOD(RepeatedField, append) {
zval *value; RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
upb_arena *arena = Arena_Get(&intern->arena);
zval *php_val;
upb_msgval msgval;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &php_val) != SUCCESS ||
FAILURE) { !Convert_PhpToUpb(php_val, &msgval, intern->type, intern->desc, arena)) {
return; return;
} }
repeated_field_write_dimension(getThis(), NULL, value TSRMLS_CC);
upb_array_append(intern->array, msgval, arena);
} }
/** /**
* Check whether the element at given index exists. * RepeatedField::offsetExists()
*
* Implements the ArrayAccess interface. Invoked when PHP code calls:
*
* isset($arr[$idx]);
* empty($arr[$idx]);
*
* @param long The index to be checked. * @param long The index to be checked.
* @return bool True if the element at the given index exists. * @return bool True if the element at the given index exists.
*/ */
PHP_METHOD(RepeatedField, offsetExists) { PHP_METHOD(RepeatedField, offsetExists) {
long index; RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
zend_long index;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
FAILURE) {
return; return;
} }
RepeatedField *intern = UNBOX(RepeatedField, getThis()); RETURN_BOOL(index >= 0 && index < upb_array_size(intern->array));
RETURN_BOOL(index >= 0 &&
index < zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array)));
} }
/** /**
* Return the element at the given index. * RepeatedField::offsetGet()
* This will also be called for: $ele = $arr[0] *
* Implements the ArrayAccess interface. Invoked when PHP code calls:
*
* $x = $arr[$idx];
*
* @param long The index of the element to be fetched. * @param long The index of the element to be fetched.
* @return object The stored element at given index. * @return object The stored element at given index.
* @exception Invalid type for index. * @exception Invalid type for index.
* @exception Non-existing index. * @exception Non-existing index.
*/ */
PHP_METHOD(RepeatedField, offsetGet) { PHP_METHOD(RepeatedField, offsetGet) {
long index; RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
void *memory; zend_long index;
upb_msgval msgval;
zval ret;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
FAILURE) {
return; return;
} }
RepeatedField *intern = UNBOX(RepeatedField, getThis()); if (index < 0 || index >= upb_array_size(intern->array)) {
HashTable *table = PHP_PROTO_HASH_OF(intern->array); zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
return;
if (intern->type == UPB_TYPE_MESSAGE) {
if (php_proto_zend_hash_index_find_zval(table, index, (void **)&memory) ==
FAILURE) {
zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
return;
}
} else {
if (php_proto_zend_hash_index_find_mem(table, index, (void **)&memory) ==
FAILURE) {
zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
return;
}
} }
native_slot_get_by_array(intern->type, memory,
ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC); msgval = upb_array_get(intern->array, index);
Convert_UpbToPhp(msgval, &ret, intern->type, intern->desc, &intern->arena);
RETURN_ZVAL(&ret, 0, 1);
} }
/** /**
* Assign the element at the given index. * RepeatedField::offsetSet()
* This will also be called for: $arr []= $ele and $arr[0] = ele *
* Implements the ArrayAccess interface. Invoked when PHP code calls:
*
* $arr[$idx] = $x;
* $arr []= $x; // Append
*
* @param long The index of the element to be assigned. * @param long The index of the element to be assigned.
* @param object The element to be assigned. * @param object The element to be assigned.
* @exception Invalid type for index. * @exception Invalid type for index.
@ -418,140 +297,306 @@ PHP_METHOD(RepeatedField, offsetGet) {
* @exception Incorrect type of the element. * @exception Incorrect type of the element.
*/ */
PHP_METHOD(RepeatedField, offsetSet) { PHP_METHOD(RepeatedField, offsetSet) {
zval *index, *value; RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &index, &value) == upb_arena *arena = Arena_Get(&intern->arena);
FAILURE) { size_t size = upb_array_size(intern->array);
zval *offset, *val;
int64_t index;
upb_msgval msgval;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &offset, &val) != SUCCESS) {
return;
}
if (Z_TYPE_P(offset) == IS_NULL) {
index = size;
} else if (!Convert_PhpToInt64(offset, &index)) {
return; return;
} }
repeated_field_write_dimension(getThis(), index, value TSRMLS_CC);
if (!Convert_PhpToUpb(val, &msgval, intern->type, intern->desc, arena)) {
return;
}
if (index > size) {
zend_error(E_USER_ERROR, "Element at index %ld doesn't exist.\n", index);
} else if (index == size) {
upb_array_append(intern->array, msgval, Arena_Get(&intern->arena));
} else {
upb_array_set(intern->array, index, msgval);
}
} }
/** /**
* Remove the element at the given index. * RepeatedField::offsetUnset()
* This will also be called for: unset($arr) *
* Implements the ArrayAccess interface. Invoked when PHP code calls:
*
* unset($arr[$idx]);
*
* @param long The index of the element to be removed. * @param long The index of the element to be removed.
* @exception Invalid type for index. * @exception Invalid type for index.
* @exception The element to be removed is not at the end of the RepeatedField. * @exception The element to be removed is not at the end of the RepeatedField.
*/ */
PHP_METHOD(RepeatedField, offsetUnset) { PHP_METHOD(RepeatedField, offsetUnset) {
long index; RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == zend_long index;
FAILURE) { zend_long size = upb_array_size(intern->array);
// Only the element at the end of the array can be removed.
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) != SUCCESS) {
return; return;
} }
RepeatedField *intern = UNBOX(RepeatedField, getThis()); if (size == 0 || index != size - 1) {
php_error_docref(NULL, E_USER_ERROR, "Cannot remove element at %ld.\n",
// Only the element at the end of the array can be removed. index);
if (index == -1 ||
index != (zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array)) - 1)) {
zend_error(E_USER_ERROR, "Cannot remove element at %ld.\n", index);
return; return;
} }
zend_hash_index_del(PHP_PROTO_HASH_OF(intern->array), index); upb_array_resize(intern->array, size - 1, Arena_Get(&intern->arena));
} }
/** /**
* RepeatedField::count()
*
* Implements the Countable interface. Invoked when PHP code calls:
*
* $len = count($arr);
* Return the number of stored elements. * Return the number of stored elements.
* This will also be called for: count($arr) * This will also be called for: count($arr)
* @return long The number of stored elements. * @return long The number of stored elements.
*/ */
PHP_METHOD(RepeatedField, count) { PHP_METHOD(RepeatedField, count) {
RepeatedField *intern = UNBOX(RepeatedField, getThis()); RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
if (zend_parse_parameters_none() == FAILURE) { if (zend_parse_parameters_none() == FAILURE) {
return; return;
} }
RETURN_LONG(zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array))); RETURN_LONG(upb_array_size(intern->array));
} }
/** /**
* Return the beginning iterator. * RepeatedField::getIterator()
* This will also be called for: foreach($arr) *
* Implements the IteratorAggregate interface. Invoked when PHP code calls:
*
* foreach ($arr) {}
*
* @return object Beginning iterator. * @return object Beginning iterator.
*/ */
PHP_METHOD(RepeatedField, getIterator) { PHP_METHOD(RepeatedField, getIterator) {
CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(return_value, zval ret;
repeated_field_iter_type); RepeatedFieldIter_make(&ret, getThis());
RETURN_ZVAL(&ret, 0, 1);
RepeatedField *intern = UNBOX(RepeatedField, getThis());
RepeatedFieldIter *iter = UNBOX(RepeatedFieldIter, return_value);
iter->repeated_field = intern;
iter->position = 0;
} }
ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1)
ZEND_ARG_INFO(0, index)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2)
ZEND_ARG_INFO(0, index)
ZEND_ARG_INFO(0, newval)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_void, 0)
ZEND_END_ARG_INFO()
static zend_function_entry repeated_field_methods[] = {
PHP_ME(RepeatedField, __construct, NULL, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedField, append, NULL, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedField, offsetUnset, arginfo_offsetGet, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedField, count, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedField, getIterator, arginfo_void, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// RepeatedFieldIter creation/destruction // PHP RepeatedFieldIter
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Define object free method. typedef struct {
PHP_PROTO_OBJECT_EMPTY_FREE_START(RepeatedFieldIter, repeated_field_iter) zend_object std;
PHP_PROTO_OBJECT_FREE_END zval repeated_field;
zend_long position;
} RepeatedFieldIter;
PHP_PROTO_OBJECT_EMPTY_DTOR_START(RepeatedFieldIter, repeated_field_iter) zend_class_entry *RepeatedFieldIter_class_entry;
PHP_PROTO_OBJECT_DTOR_END static zend_object_handlers repeated_field_iter_object_handlers;
// Define object create method. /**
PHP_PROTO_OBJECT_CREATE_START(RepeatedFieldIter, repeated_field_iter) * RepeatedFieldIter_create()
intern->repeated_field = NULL; *
intern->position = 0; * PHP class entry function to allocate and initialize a new RepeatedFieldIter
PHP_PROTO_OBJECT_CREATE_END(RepeatedFieldIter, repeated_field_iter) * object.
*/
zend_object* RepeatedFieldIter_create(zend_class_entry *class_type) {
RepeatedFieldIter *intern = emalloc(sizeof(RepeatedFieldIter));
zend_object_std_init(&intern->std, class_type);
intern->std.handlers = &repeated_field_iter_object_handlers;
ZVAL_NULL(&intern->repeated_field);
intern->position = 0;
// Skip object_properties_init(), we don't allow derived classes.
return &intern->std;
}
// Init class entry. /**
PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\RepeatedFieldIter", * RepeatedFieldIter_dtor()
RepeatedFieldIter, repeated_field_iter) *
zend_class_implements(repeated_field_iter_type TSRMLS_CC, 1, zend_ce_iterator); * Object handler to destroy a RepeatedFieldIter. This releases all resources
PHP_PROTO_INIT_CLASS_END * associated with the message. Note that it is possible to access a destroyed
* object from PHP in rare cases.
*/
static void RepeatedFieldIter_dtor(zend_object* obj) {
RepeatedFieldIter* intern = (RepeatedFieldIter*)obj;
zval_ptr_dtor(&intern->repeated_field);
zend_object_std_dtor(&intern->std);
}
// ----------------------------------------------------------------------------- /**
// PHP RepeatedFieldIter Methods * RepeatedFieldIter_make()
// ----------------------------------------------------------------------------- *
* C function to create a RepeatedFieldIter.
*/
static void RepeatedFieldIter_make(zval *val, zval *repeated_field) {
RepeatedFieldIter *iter;
ZVAL_OBJ(val, RepeatedFieldIter_class_entry->create_object(
RepeatedFieldIter_class_entry));
iter = (RepeatedFieldIter*)Z_OBJ_P(val);
ZVAL_COPY(&iter->repeated_field, repeated_field);
}
/*
* When a user writes:
*
* foreach($arr as $key => $val) {}
*
* PHP's iterator protocol is:
*
* $iter = $arr->getIterator();
* for ($iter->rewind(); $iter->valid(); $iter->next()) {
* $key = $iter->key();
* $val = $iter->current();
* }
*/
/**
* RepeatedFieldIter::rewind()
*
* Implements the Iterator interface. Sets the iterator to the first element.
*/
PHP_METHOD(RepeatedFieldIter, rewind) { PHP_METHOD(RepeatedFieldIter, rewind) {
RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis()); RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
intern->position = 0; intern->position = 0;
} }
/**
* RepeatedFieldIter::current()
*
* Implements the Iterator interface. Returns the current value.
*/
PHP_METHOD(RepeatedFieldIter, current) { PHP_METHOD(RepeatedFieldIter, current) {
RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis()); RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
RepeatedField *repeated_field = intern->repeated_field; RepeatedField *field = (RepeatedField*)Z_OBJ_P(&intern->repeated_field);
upb_array *array = field->array;
long index = 0; zend_long index = intern->position;
void *memory; upb_msgval msgval;
zval ret;
if (index < 0 || index >= upb_array_size(array)) {
zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
}
HashTable *table = PHP_PROTO_HASH_OF(repeated_field->array); msgval = upb_array_get(array, index);
if (repeated_field->type == UPB_TYPE_MESSAGE) { Convert_UpbToPhp(msgval, &ret, field->type, field->desc, &field->arena);
if (php_proto_zend_hash_index_find_zval(table, intern->position, RETURN_ZVAL(&ret, 0, 1);
(void **)&memory) == FAILURE) {
zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
return;
}
} else {
if (php_proto_zend_hash_index_find_mem(table, intern->position,
(void **)&memory) == FAILURE) {
zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
return;
}
}
native_slot_get_by_array(repeated_field->type, memory,
ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
} }
/**
* RepeatedFieldIter::key()
*
* Implements the Iterator interface. Returns the current key.
*/
PHP_METHOD(RepeatedFieldIter, key) { PHP_METHOD(RepeatedFieldIter, key) {
RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis()); RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
RETURN_LONG(intern->position); RETURN_LONG(intern->position);
} }
/**
* RepeatedFieldIter::next()
*
* Implements the Iterator interface. Advances to the next element.
*/
PHP_METHOD(RepeatedFieldIter, next) { PHP_METHOD(RepeatedFieldIter, next) {
RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis()); RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
++intern->position; ++intern->position;
} }
/**
* RepeatedFieldIter::valid()
*
* Implements the Iterator interface. Returns true if this is a valid element.
*/
PHP_METHOD(RepeatedFieldIter, valid) { PHP_METHOD(RepeatedFieldIter, valid) {
RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis()); RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
RETURN_BOOL(zend_hash_num_elements(PHP_PROTO_HASH_OF( RepeatedField *field = (RepeatedField*)Z_OBJ_P(&intern->repeated_field);
intern->repeated_field->array)) > intern->position); RETURN_BOOL(intern->position < upb_array_size(field->array));
}
static zend_function_entry repeated_field_iter_methods[] = {
PHP_ME(RepeatedFieldIter, rewind, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedFieldIter, current, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedFieldIter, key, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedFieldIter, next, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedFieldIter, valid, arginfo_void, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
// -----------------------------------------------------------------------------
// Module init.
// -----------------------------------------------------------------------------
/**
* Array_ModuleInit()
*
* Called when the C extension is loaded to register all types.
*/
void Array_ModuleInit() {
zend_class_entry tmp_ce;
zend_object_handlers *h;
// RepeatedField.
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\RepeatedField",
repeated_field_methods);
RepeatedField_class_entry = zend_register_internal_class(&tmp_ce);
zend_class_implements(RepeatedField_class_entry, 3, spl_ce_ArrayAccess,
zend_ce_aggregate, spl_ce_Countable);
RepeatedField_class_entry->ce_flags |= ZEND_ACC_FINAL;
RepeatedField_class_entry->create_object = RepeatedField_create;
h = &RepeatedField_object_handlers;
memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
h->dtor_obj = RepeatedField_destructor;
h->get_properties = RepeatedField_GetProperties;
h->get_property_ptr_ptr = RepeatedField_GetPropertyPtrPtr;
// RepeatedFieldIter
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\RepeatedFieldIter",
repeated_field_iter_methods);
RepeatedFieldIter_class_entry = zend_register_internal_class(&tmp_ce);
zend_class_implements(RepeatedFieldIter_class_entry, 1, zend_ce_iterator);
RepeatedFieldIter_class_entry->ce_flags |= ZEND_ACC_FINAL;
RepeatedFieldIter_class_entry->create_object = RepeatedFieldIter_create;
h = &repeated_field_iter_object_handlers;
memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
h->dtor_obj = RepeatedFieldIter_dtor;
} }

@ -1,635 +0,0 @@
unsigned char descriptor_proto[] = {
0x0a, 0x9b, 0x3b, 0x0a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73,
0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x12, 0x0f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x4d, 0x0a, 0x11, 0x46, 0x69,
0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
0x53, 0x65, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18,
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x04, 0x66, 0x69, 0x6c,
0x65, 0x22, 0xe4, 0x04, 0x0a, 0x13, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a,
0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12,
0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63,
0x79, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x70,
0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x70,
0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64,
0x65, 0x6e, 0x63, 0x79, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x05, 0x52, 0x10,
0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64,
0x65, 0x6e, 0x63, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x65, 0x61, 0x6b,
0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x18,
0x0b, 0x20, 0x03, 0x28, 0x05, 0x52, 0x0e, 0x77, 0x65, 0x61, 0x6b, 0x44,
0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x43, 0x0a,
0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70,
0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e,
0x75, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d,
0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72,
0x6f, 0x74, 0x6f, 0x52, 0x08, 0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70,
0x65, 0x12, 0x41, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63,
0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52,
0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, 0x09,
0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69,
0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65,
0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x07, 0x6f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x12, 0x49, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
0x63, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x09, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f,
0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f,
0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65,
0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x6e, 0x74,
0x61, 0x78, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x79,
0x6e, 0x74, 0x61, 0x78, 0x22, 0xb9, 0x06, 0x0a, 0x0f, 0x44, 0x65, 0x73,
0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f,
0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x05,
0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44,
0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f,
0x74, 0x6f, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x43, 0x0a,
0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46,
0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x65, 0x78, 0x74,
0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0b, 0x6e, 0x65,
0x73, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
0x6f, 0x52, 0x0a, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x54, 0x79, 0x70,
0x65, 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x74, 0x79,
0x70, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72,
0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x08,
0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x58, 0x0a, 0x0f,
0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x61,
0x6e, 0x67, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x78, 0x74, 0x65,
0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0e,
0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e,
0x67, 0x65, 0x12, 0x44, 0x0a, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f,
0x64, 0x65, 0x63, 0x6c, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
0x6f, 0x52, 0x09, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65, 0x63, 0x6c,
0x12, 0x39, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f,
0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12,
0x55, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f,
0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x2e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65,
0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52,
0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e,
0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76,
0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x03, 0x28,
0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e,
0x61, 0x6d, 0x65, 0x1a, 0x7a, 0x0a, 0x0e, 0x45, 0x78, 0x74, 0x65, 0x6e,
0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a,
0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65,
0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e,
0x64, 0x12, 0x40, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61,
0x6e, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07,
0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x37, 0x0a, 0x0d, 0x52,
0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65,
0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20,
0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10,
0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
0x03, 0x65, 0x6e, 0x64, 0x22, 0x7c, 0x0a, 0x15, 0x45, 0x78, 0x74, 0x65,
0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x70,
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74,
0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69,
0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70,
0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a,
0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x98,
0x06, 0x0a, 0x14, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63,
0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e,
0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x05, 0x6c,
0x61, 0x62, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
0x6f, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x61, 0x62,
0x65, 0x6c, 0x12, 0x3e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05,
0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46,
0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x79, 0x70, 0x65,
0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79,
0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28,
0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12,
0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e,
0x64, 0x65, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75,
0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56,
0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x6e, 0x65, 0x6f,
0x66, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x09, 0x20, 0x01, 0x28,
0x05, 0x52, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x49, 0x6e, 0x64, 0x65,
0x78, 0x12, 0x1b, 0x0a, 0x09, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x6e, 0x61,
0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6a, 0x73,
0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x6f, 0x70,
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69,
0x6f, 0x6e, 0x73, 0x22, 0xb6, 0x02, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65,
0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x55,
0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50,
0x45, 0x5f, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x10, 0x02, 0x12, 0x0e, 0x0a,
0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10,
0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49,
0x4e, 0x54, 0x36, 0x34, 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59,
0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x05, 0x12, 0x10,
0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x58, 0x45, 0x44,
0x36, 0x34, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45,
0x5f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x07, 0x12, 0x0d,
0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x4f, 0x4f, 0x4c, 0x10,
0x08, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54,
0x52, 0x49, 0x4e, 0x47, 0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59,
0x50, 0x45, 0x5f, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x10, 0x0a, 0x12, 0x10,
0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41,
0x47, 0x45, 0x10, 0x0b, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45,
0x5f, 0x42, 0x59, 0x54, 0x45, 0x53, 0x10, 0x0c, 0x12, 0x0f, 0x0a, 0x0b,
0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10,
0x0d, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e,
0x55, 0x4d, 0x10, 0x0e, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45,
0x5f, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x0f, 0x12,
0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58,
0x45, 0x44, 0x36, 0x34, 0x10, 0x10, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59,
0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x11, 0x12,
0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54,
0x36, 0x34, 0x10, 0x12, 0x22, 0x43, 0x0a, 0x05, 0x4c, 0x61, 0x62, 0x65,
0x6c, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x4f,
0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x12, 0x0a,
0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49,
0x52, 0x45, 0x44, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42,
0x45, 0x4c, 0x5f, 0x52, 0x45, 0x50, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10,
0x03, 0x22, 0x63, 0x0a, 0x14, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a,
0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65,
0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe3, 0x02, 0x0a, 0x13, 0x45,
0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73,
0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f,
0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x6f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x4f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69,
0x6f, 0x6e, 0x73, 0x12, 0x5d, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72,
0x76, 0x65, 0x64, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e,
0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65,
0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52,
0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e,
0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76,
0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28,
0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e,
0x61, 0x6d, 0x65, 0x1a, 0x3b, 0x0a, 0x11, 0x45, 0x6e, 0x75, 0x6d, 0x52,
0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65,
0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20,
0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10,
0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
0x03, 0x65, 0x6e, 0x64, 0x22, 0x83, 0x01, 0x0a, 0x18, 0x45, 0x6e, 0x75,
0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a,
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d,
0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e,
0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x07, 0x6f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c,
0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xa7, 0x01, 0x0a, 0x16, 0x53,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a,
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x06, 0x6d, 0x65, 0x74,
0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
0x6f, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x39, 0x0a,
0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52,
0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x89, 0x02, 0x0a,
0x15, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72,
0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12,
0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e,
0x70, 0x75, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70,
0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f,
0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x38,
0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65,
0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52,
0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, 0x0a, 0x10,
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61,
0x6d, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e,
0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x30,
0x0a, 0x10, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x72,
0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08,
0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x73, 0x65, 0x72,
0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67,
0x22, 0x92, 0x09, 0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6a, 0x61, 0x76, 0x61,
0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0b, 0x6a, 0x61, 0x76, 0x61, 0x50, 0x61, 0x63, 0x6b,
0x61, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x6a, 0x61, 0x76, 0x61, 0x5f,
0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x6e,
0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6a,
0x61, 0x76, 0x61, 0x4f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x73,
0x73, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x6a, 0x61, 0x76,
0x61, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x66,
0x69, 0x6c, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x6a, 0x61, 0x76, 0x61, 0x4d,
0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73,
0x12, 0x44, 0x0a, 0x1d, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65, 0x6e,
0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x73,
0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x14, 0x20,
0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x19, 0x6a, 0x61, 0x76,
0x61, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x45, 0x71, 0x75,
0x61, 0x6c, 0x73, 0x41, 0x6e, 0x64, 0x48, 0x61, 0x73, 0x68, 0x12, 0x3a,
0x0a, 0x16, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e,
0x67, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x75, 0x74, 0x66, 0x38,
0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73,
0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x53, 0x74, 0x72, 0x69, 0x6e,
0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x74, 0x66, 0x38, 0x12, 0x53,
0x0a, 0x0c, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x5f, 0x66,
0x6f, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f,
0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x4d,
0x6f, 0x64, 0x65, 0x3a, 0x05, 0x53, 0x50, 0x45, 0x45, 0x44, 0x52, 0x0b,
0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x46, 0x6f, 0x72, 0x12,
0x1d, 0x0a, 0x0a, 0x67, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67,
0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x6f, 0x50,
0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x63, 0x63,
0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x3a,
0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x63, 0x63, 0x47, 0x65,
0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x73, 0x12, 0x39, 0x0a, 0x15, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65,
0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61,
0x6c, 0x73, 0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x47, 0x65, 0x6e,
0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
0x12, 0x35, 0x0a, 0x13, 0x70, 0x79, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72,
0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18,
0x12, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65,
0x52, 0x11, 0x70, 0x79, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x14, 0x70,
0x68, 0x70, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x2a, 0x20, 0x01, 0x28,
0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x12, 0x70, 0x68,
0x70, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72,
0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08,
0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70,
0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2f, 0x0a, 0x10, 0x63,
0x63, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x72, 0x65,
0x6e, 0x61, 0x73, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66,
0x61, 0x6c, 0x73, 0x65, 0x52, 0x0e, 0x63, 0x63, 0x45, 0x6e, 0x61, 0x62,
0x6c, 0x65, 0x41, 0x72, 0x65, 0x6e, 0x61, 0x73, 0x12, 0x2a, 0x0a, 0x11,
0x6f, 0x62, 0x6a, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x70,
0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x24, 0x20, 0x01, 0x28, 0x09, 0x52,
0x0f, 0x6f, 0x62, 0x6a, 0x63, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x50, 0x72,
0x65, 0x66, 0x69, 0x78, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x73, 0x68, 0x61,
0x72, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
0x18, 0x25, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x73, 0x68, 0x61,
0x72, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12,
0x21, 0x0a, 0x0c, 0x73, 0x77, 0x69, 0x66, 0x74, 0x5f, 0x70, 0x72, 0x65,
0x66, 0x69, 0x78, 0x18, 0x27, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73,
0x77, 0x69, 0x66, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x28,
0x0a, 0x10, 0x70, 0x68, 0x70, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f,
0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x28, 0x20, 0x01, 0x28, 0x09,
0x52, 0x0e, 0x70, 0x68, 0x70, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x50, 0x72,
0x65, 0x66, 0x69, 0x78, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x68, 0x70, 0x5f,
0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x29, 0x20,
0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x68, 0x70, 0x4e, 0x61, 0x6d, 0x65,
0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x70, 0x68, 0x70,
0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6e, 0x61,
0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x2c, 0x20, 0x01, 0x28,
0x09, 0x52, 0x14, 0x70, 0x68, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
0x74, 0x61, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12,
0x21, 0x0a, 0x0c, 0x72, 0x75, 0x62, 0x79, 0x5f, 0x70, 0x61, 0x63, 0x6b,
0x61, 0x67, 0x65, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72,
0x75, 0x62, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x58,
0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7,
0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70,
0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x0a, 0x0c, 0x4f, 0x70, 0x74, 0x69,
0x6d, 0x69, 0x7a, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x09, 0x0a, 0x05,
0x53, 0x50, 0x45, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43,
0x4f, 0x44, 0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x10, 0x02, 0x12, 0x10,
0x0a, 0x0c, 0x4c, 0x49, 0x54, 0x45, 0x5f, 0x52, 0x55, 0x4e, 0x54, 0x49,
0x4d, 0x45, 0x10, 0x03, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80,
0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x26, 0x10, 0x27, 0x22, 0xd1, 0x02,
0x0a, 0x0e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x17, 0x6d, 0x65, 0x73, 0x73,
0x61, 0x67, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x77, 0x69, 0x72, 0x65,
0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x14, 0x6d, 0x65,
0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x57, 0x69, 0x72, 0x65,
0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x4c, 0x0a, 0x1f, 0x6e, 0x6f,
0x5f, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x5f, 0x64, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x63, 0x63,
0x65, 0x73, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x3a,
0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x1c, 0x6e, 0x6f, 0x53, 0x74,
0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
0x70, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72,
0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74,
0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61,
0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61,
0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x70, 0x5f, 0x65,
0x6e, 0x74, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08,
0x6d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x58, 0x0a, 0x14,
0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74,
0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69,
0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80,
0x02, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x4a, 0x04, 0x08, 0x09, 0x10,
0x0a, 0x22, 0xe2, 0x03, 0x0a, 0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x0a, 0x05, 0x63, 0x74,
0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x43, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x06,
0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x52, 0x05, 0x63, 0x74, 0x79, 0x70,
0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x18,
0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65,
0x64, 0x12, 0x47, 0x0a, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70, 0x65, 0x18,
0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x2e, 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x09, 0x4a, 0x53, 0x5f,
0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x52, 0x06, 0x6a, 0x73, 0x74, 0x79,
0x70, 0x65, 0x12, 0x19, 0x0a, 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x18, 0x05,
0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52,
0x04, 0x6c, 0x61, 0x7a, 0x79, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70,
0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65,
0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x04,
0x77, 0x65, 0x61, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x12,
0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72,
0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18,
0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74,
0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x2f, 0x0a, 0x05, 0x43, 0x54, 0x79,
0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47,
0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x4f, 0x52, 0x44, 0x10, 0x01,
0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x50,
0x49, 0x45, 0x43, 0x45, 0x10, 0x02, 0x22, 0x35, 0x0a, 0x06, 0x4a, 0x53,
0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e,
0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4a,
0x53, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0d,
0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x10,
0x02, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02,
0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0x73, 0x0a, 0x0c, 0x4f, 0x6e,
0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58,
0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7,
0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70,
0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80,
0x80, 0x80, 0x02, 0x22, 0xc0, 0x01, 0x0a, 0x0b, 0x45, 0x6e, 0x75, 0x6d,
0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x61,
0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x02,
0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x41,
0x6c, 0x69, 0x61, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72,
0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70,
0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75,
0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64,
0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70,
0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65,
0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f,
0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02,
0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0x9e, 0x01, 0x0a, 0x10, 0x45,
0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69,
0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65,
0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x3a,
0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72,
0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f,
0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72,
0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22,
0x9c, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65,
0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x21, 0x20, 0x01,
0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64,
0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a,
0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74,
0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55,
0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64,
0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80,
0x80, 0x02, 0x22, 0xe0, 0x02, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x68, 0x6f,
0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a,
0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x21,
0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52,
0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12,
0x71, 0x0a, 0x11, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e,
0x63, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x22, 0x20, 0x01,
0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74,
0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49,
0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65,
0x76, 0x65, 0x6c, 0x3a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54,
0x45, 0x4e, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e,
0x52, 0x10, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63,
0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f,
0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72,
0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
0x22, 0x50, 0x0a, 0x10, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65,
0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x17, 0x0a, 0x13,
0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f,
0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a,
0x0f, 0x4e, 0x4f, 0x5f, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x45, 0x46, 0x46,
0x45, 0x43, 0x54, 0x53, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x44,
0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x2a, 0x09,
0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x9a, 0x03,
0x0a, 0x13, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a,
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65,
0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f,
0x6e, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x52, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x64, 0x65, 0x6e,
0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x64, 0x65, 0x6e,
0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12,
0x2c, 0x0a, 0x12, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f,
0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20,
0x01, 0x28, 0x04, 0x52, 0x10, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76,
0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a,
0x12, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e,
0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
0x03, 0x52, 0x10, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x49,
0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64,
0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c,
0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74,
0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07,
0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x67, 0x67,
0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x67, 0x67, 0x72,
0x65, 0x67, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x4a,
0x0a, 0x08, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x12, 0x1b,
0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x18,
0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x61, 0x6d, 0x65, 0x50,
0x61, 0x72, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x65, 0x78,
0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x02, 0x28,
0x08, 0x52, 0x0b, 0x69, 0x73, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
0x6f, 0x6e, 0x22, 0xa7, 0x02, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44, 0x0a,
0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f,
0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f,
0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c,
0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xce, 0x01, 0x0a, 0x08,
0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04,
0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02,
0x10, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x04,
0x73, 0x70, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02,
0x10, 0x01, 0x52, 0x04, 0x73, 0x70, 0x61, 0x6e, 0x12, 0x29, 0x0a, 0x10,
0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d,
0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f,
0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65,
0x6e, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x69, 0x6c,
0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73,
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, 0x72, 0x61, 0x69,
0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73,
0x12, 0x3a, 0x0a, 0x19, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f,
0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6d,
0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52,
0x17, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x74, 0x61,
0x63, 0x68, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73,
0x22, 0xd1, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4d,
0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f,
0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x6d, 0x0a, 0x0a, 0x41, 0x6e, 0x6e,
0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70,
0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10,
0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x73,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x46, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x65, 0x67, 0x69,
0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x62, 0x65, 0x67,
0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20,
0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x42, 0x8f, 0x01, 0x0a,
0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x42, 0x10, 0x44, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
0x6f, 0x73, 0x48, 0x01, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x64,
0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x3b, 0x64, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0xf8, 0x01, 0x01, 0xa2,
0x02, 0x03, 0x47, 0x50, 0x42, 0xaa, 0x02, 0x1a, 0x47, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e
};
unsigned int descriptor_proto_len = 7582;

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -8,7 +8,7 @@ $handle = popen($cmd, 'r');
$filenames = explode("\n", stream_get_contents($handle)); $filenames = explode("\n", stream_get_contents($handle));
array_pop($filenames); // empty string after last '\n' array_pop($filenames); // empty string after last '\n'
$filenames[] = "Google/Protobuf/DescriptorPool.php"; $filenames[] = "Google/Protobuf/DescriptorPool.php";
$output = "../ext/google/protobuf2/bundled_php.c"; $output = "../ext/google/protobuf/bundled_php.c";
function stripSuffix($str, $suffix) { function stripSuffix($str, $suffix) {
return substr($str, 0, strlen($str) - strlen($suffix)); return substr($str, 0, strlen($str) - strlen($suffix));

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -25,20 +25,26 @@
<contents> <contents>
<dir baseinstalldir="/" name="/"> <dir baseinstalldir="/" name="/">
<file baseinstalldir="/" name="config.m4" role="src"/> <file baseinstalldir="/" name="config.m4" role="src"/>
<file baseinstalldir="/" name="arena.c" role="src"/>
<file baseinstalldir="/" name="arena.h" role="src"/>
<file baseinstalldir="/" name="array.c" role="src"/> <file baseinstalldir="/" name="array.c" role="src"/>
<file baseinstalldir="/" name="builtin_descriptors.inc" 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"/> <file baseinstalldir="/" name="def.c" role="src"/>
<file baseinstalldir="/" name="encode_decode.c" role="src"/> <file baseinstalldir="/" name="def.h" role="src"/>
<file baseinstalldir="/" name="map.c" role="src"/> <file baseinstalldir="/" name="map.c" role="src"/>
<file baseinstalldir="/" name="map.h" role="src"/>
<file baseinstalldir="/" name="message.c" role="src"/> <file baseinstalldir="/" name="message.c" role="src"/>
<file baseinstalldir="/" name="message.h" role="src"/>
<file baseinstalldir="/" name="names.c" role="src"/>
<file baseinstalldir="/" name="names.h" role="src"/>
<file baseinstalldir="/" name="php-upb.c" role="src"/>
<file baseinstalldir="/" name="php-upb.h" role="src"/>
<file baseinstalldir="/" name="protobuf.c" role="src"/> <file baseinstalldir="/" name="protobuf.c" role="src"/>
<file baseinstalldir="/" name="protobuf.h" role="src"/> <file baseinstalldir="/" name="protobuf.h" role="src"/>
<file baseinstalldir="/" name="storage.c" role="src"/>
<file baseinstalldir="/" name="type_check.c" role="src"/>
<file baseinstalldir="/" name="upb.c" role="src"/>
<file baseinstalldir="/" name="upb.h" role="src"/>
<file baseinstalldir="/" name="utf8.c" role="src"/>
<file baseinstalldir="/" name="utf8.h" role="src"/>
<file baseinstalldir="/" name="LICENSE" role="doc"/> <file baseinstalldir="/" name="LICENSE" role="doc"/>
</dir> </dir>
</contents> </contents>

@ -30,481 +30,281 @@
#include "protobuf.h" #include "protobuf.h"
#include <zend_hash.h> #include <php.h>
#include <Zend/zend_interfaces.h>
static PHP_GINIT_FUNCTION(protobuf);
static PHP_GSHUTDOWN_FUNCTION(protobuf); #include "arena.h"
static PHP_RINIT_FUNCTION(protobuf); #include "array.h"
static PHP_RSHUTDOWN_FUNCTION(protobuf); #include "bundled_php.h"
static PHP_MINIT_FUNCTION(protobuf); #include "convert.h"
static PHP_MSHUTDOWN_FUNCTION(protobuf); #include "def.h"
#include "map.h"
ZEND_DECLARE_MODULE_GLOBALS(protobuf) #include "message.h"
#include "names.h"
// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
// instances.
static HashTable* upb_def_to_php_obj_map;
static upb_inttable upb_def_to_desc_map_persistent;
static upb_inttable upb_def_to_enumdesc_map_persistent;
// Global map from message/enum's php class entry to corresponding wrapper
// Descriptor/EnumDescriptor instances.
static HashTable* ce_to_php_obj_map;
static upb_strtable ce_to_desc_map_persistent;
static upb_strtable ce_to_enumdesc_map_persistent;
// Global map from message/enum's proto fully-qualified name to corresponding
// wrapper Descriptor/EnumDescriptor instances.
static upb_strtable proto_to_desc_map_persistent;
static upb_strtable class_to_desc_map_persistent;
upb_strtable reserved_names;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Global maps. // Module "globals"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
static void add_to_table(HashTable* t, const void* def, void* value) { // Despite the name, module "globals" are really thread-locals:
zval* pDest = NULL; // * PROTOBUF_G(var) accesses the thread-local variable for 'var'. Either:
php_proto_zend_hash_index_update_mem(t, (zend_ulong)def, &value, // * PROTOBUF_G(var) -> protobuf_globals.var (Non-ZTS / non-thread-safe)
sizeof(zval*), (void**)&pDest); // * PROTOBUF_G(var) -> <Zend magic> (ZTS / thread-safe builds)
}
static void* get_from_table(const HashTable* t, const void* def) { #define PROTOBUF_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(protobuf, v)
void** value;
if (php_proto_zend_hash_index_find_mem(t, (zend_ulong)def, (void**)&value) ==
FAILURE) {
return NULL;
}
return *value;
}
void add_def_obj(const void* def, PHP_PROTO_HASHTABLE_VALUE value) { ZEND_BEGIN_MODULE_GLOBALS(protobuf)
#if PHP_MAJOR_VERSION < 7 // Set by the user to make the descriptor pool persist between requests.
Z_ADDREF_P(value); zend_bool keep_descriptor_pool_after_request;
#else
GC_ADDREF(value);
#endif
add_to_table(upb_def_to_php_obj_map, def, value);
}
PHP_PROTO_HASHTABLE_VALUE get_def_obj(const void* def) { // Currently we make the generated pool a "global", which means that if a user
return (PHP_PROTO_HASHTABLE_VALUE)get_from_table(upb_def_to_php_obj_map, def); // does explicitly create threads within their request, the other threads will
} // get different results from DescriptorPool::getGeneratedPool(). We require
// that all descriptors are loaded from the main thread.
zval generated_pool;
void add_msgdef_desc(const upb_msgdef* m, DescriptorInternal* desc) { // A upb_symtab that we are saving for the next request so that we don't have
upb_inttable_insertptr(&upb_def_to_desc_map_persistent, // to rebuild it from scratch. When keep_descriptor_pool_after_request==true,
m, upb_value_ptr(desc)); // we steal the upb_symtab from the global DescriptorPool object just before
} // destroying it.
upb_symtab *saved_symtab;
DescriptorInternal* get_msgdef_desc(const upb_msgdef* m) { // Object cache (see interface in protobuf.h).
upb_value v; HashTable object_cache;
#ifndef NDEBUG
v.ctype = UPB_CTYPE_PTR;
#endif
if (!upb_inttable_lookupptr(&upb_def_to_desc_map_persistent, m, &v)) {
return NULL;
} else {
return upb_value_getptr(v);
}
}
void add_enumdef_enumdesc(const upb_enumdef* e, EnumDescriptorInternal* desc) {
upb_inttable_insertptr(&upb_def_to_enumdesc_map_persistent,
e, upb_value_ptr(desc));
}
EnumDescriptorInternal* get_enumdef_enumdesc(const upb_enumdef* e) {
upb_value v;
#ifndef NDEBUG
v.ctype = UPB_CTYPE_PTR;
#endif
if (!upb_inttable_lookupptr(&upb_def_to_enumdesc_map_persistent, e, &v)) {
return NULL;
} else {
return upb_value_getptr(v);
}
}
void add_ce_obj(const void* ce, PHP_PROTO_HASHTABLE_VALUE value) { // Name cache (see interface in protobuf.h).
#if PHP_MAJOR_VERSION < 7 HashTable name_msg_cache;
Z_ADDREF_P(value); HashTable name_enum_cache;
#else ZEND_END_MODULE_GLOBALS(protobuf)
GC_ADDREF(value);
#endif
add_to_table(ce_to_php_obj_map, ce, value);
}
PHP_PROTO_HASHTABLE_VALUE get_ce_obj(const void* ce) { ZEND_DECLARE_MODULE_GLOBALS(protobuf)
return (PHP_PROTO_HASHTABLE_VALUE)get_from_table(ce_to_php_obj_map, ce);
}
void add_ce_desc(const zend_class_entry* ce, DescriptorInternal* desc) { const zval *get_generated_pool() {
#if PHP_MAJOR_VERSION < 7 return &PROTOBUF_G(generated_pool);
const char* klass = ce->name;
#else
const char* klass = ZSTR_VAL(ce->name);
#endif
upb_strtable_insert(&ce_to_desc_map_persistent, klass,
upb_value_ptr(desc));
} }
DescriptorInternal* get_ce_desc(const zend_class_entry* ce) { // This is a PHP extension (not a Zend extension). What follows is a summary of
#if PHP_MAJOR_VERSION < 7 // a PHP extension's lifetime and when various handlers are called.
const char* klass = ce->name; //
#else // * PHP_GINIT_FUNCTION(protobuf) / PHP_GSHUTDOWN_FUNCTION(protobuf)
const char* klass = ZSTR_VAL(ce->name); // are the constructor/destructor for the globals. The sequence over the
#endif // course of a process lifetime is:
//
upb_value v; // # Process startup
#ifndef NDEBUG // GINIT(<Main Thread Globals>)
v.ctype = UPB_CTYPE_PTR; // MINIT
#endif //
// foreach request:
// RINIT
// # Request is processed here.
// RSHUTDOWN
//
// foreach thread:
// GINIT(<This Thread Globals>)
// # Code for the thread runs here.
// GSHUTDOWN(<This Thread Globals>)
//
// # Process Shutdown
// #
// # These should be running per the docs, but I have not been able to
// # actually get the process-wide shutdown functions to run.
// #
// # MSHUTDOWN
// # GSHUTDOWN(<Main Thread Globals>)
//
// * Threads can be created either explicitly by the user, inside a request,
// or implicitly by the runtime, to process multiple requests concurrently.
// If the latter is being used, then the "foreach thread" block above
// actually looks like this:
//
// foreach thread:
// GINIT(<This Thread Globals>)
// # A non-main thread will only receive requests when using a threaded
// # MPM with Apache
// foreach request:
// RINIT
// # Request is processed here.
// RSHUTDOWN
// GSHUTDOWN(<This Thread Globals>)
//
// That said, it appears that few people use threads with PHP:
// * The pthread package documented at
// https://www.php.net/manual/en/class.thread.php nas not been released
// since 2016, and the current release fails to compile against any PHP
// newer than 7.0.33.
// * The GitHub master branch supports 7.2+, but this has not been released
// to PECL.
// * Its owner has disavowed it as "broken by design" and "in an untenable
// position for the future": https://github.com/krakjoe/pthreads/issues/929
// * The only way to use PHP with requests in different threads is to use the
// Apache 2 mod_php with the "worker" MPM. But this is explicitly
// discouraged by the documentation: https://serverfault.com/a/231660
if (!upb_strtable_lookup(&ce_to_desc_map_persistent, klass, &v)) { static PHP_GSHUTDOWN_FUNCTION(protobuf) {
return NULL; if (protobuf_globals->saved_symtab) {
} else { upb_symtab_free(protobuf_globals->saved_symtab);
return upb_value_getptr(v);
} }
} }
void add_ce_enumdesc(const zend_class_entry* ce, EnumDescriptorInternal* desc) { static PHP_GINIT_FUNCTION(protobuf) {
#if PHP_MAJOR_VERSION < 7 ZVAL_NULL(&protobuf_globals->generated_pool);
const char* klass = ce->name; protobuf_globals->saved_symtab = NULL;
#else
const char* klass = ZSTR_VAL(ce->name);
#endif
upb_strtable_insert(&ce_to_enumdesc_map_persistent, klass,
upb_value_ptr(desc));
}
EnumDescriptorInternal* get_ce_enumdesc(const zend_class_entry* ce) {
#if PHP_MAJOR_VERSION < 7
const char* klass = ce->name;
#else
const char* klass = ZSTR_VAL(ce->name);
#endif
upb_value v;
#ifndef NDEBUG
v.ctype = UPB_CTYPE_PTR;
#endif
if (!upb_strtable_lookup(&ce_to_enumdesc_map_persistent, klass, &v)) {
return NULL;
} else {
return upb_value_getptr(v);
}
} }
bool class_added(const void* ce) { /**
return get_ce_desc(ce) != NULL; * PHP_RINIT_FUNCTION(protobuf)
} *
* This function is run at the beginning of processing each request.
*/
static PHP_RINIT_FUNCTION(protobuf) {
// Create the global generated pool.
// Reuse the symtab (if any) left to us by the last request.
upb_symtab *symtab = PROTOBUF_G(saved_symtab);
DescriptorPool_CreateWithSymbolTable(&PROTOBUF_G(generated_pool), symtab);
void add_proto_desc(const char* proto, DescriptorInternal* desc) { // Set up autoloader for bundled sources.
upb_strtable_insert(&proto_to_desc_map_persistent, proto, zend_eval_string("spl_autoload_register('protobuf_internal_loadbundled');",
upb_value_ptr(desc)); NULL, "autoload_register.php");
}
DescriptorInternal* get_proto_desc(const char* proto) { zend_hash_init(&PROTOBUF_G(object_cache), 64, NULL, NULL, 0);
upb_value v; zend_hash_init(&PROTOBUF_G(name_msg_cache), 64, NULL, NULL, 0);
#ifndef NDEBUG zend_hash_init(&PROTOBUF_G(name_enum_cache), 64, NULL, NULL, 0);
v.ctype = UPB_CTYPE_PTR;
#endif
if (!upb_strtable_lookup(&proto_to_desc_map_persistent, proto, &v)) {
return NULL;
} else {
return upb_value_getptr(v);
}
}
void add_class_desc(const char* klass, DescriptorInternal* desc) { return SUCCESS;
upb_strtable_insert(&class_to_desc_map_persistent, klass,
upb_value_ptr(desc));
} }
DescriptorInternal* get_class_desc(const char* klass) { /**
upb_value v; * PHP_RSHUTDOWN_FUNCTION(protobuf)
#ifndef NDEBUG *
v.ctype = UPB_CTYPE_PTR; * This function is run at the end of processing each request.
#endif */
if (!upb_strtable_lookup(&class_to_desc_map_persistent, klass, &v)) { static PHP_RSHUTDOWN_FUNCTION(protobuf) {
return NULL; // Preserve the symtab if requested.
} else { if (PROTOBUF_G(keep_descriptor_pool_after_request)) {
return upb_value_getptr(v); zval *zv = &PROTOBUF_G(generated_pool);
PROTOBUF_G(saved_symtab) = DescriptorPool_Steal(zv);
} }
}
void add_class_enumdesc(const char* klass, EnumDescriptorInternal* desc) { zval_dtor(&PROTOBUF_G(generated_pool));
upb_strtable_insert(&class_to_desc_map_persistent, klass, zend_hash_destroy(&PROTOBUF_G(object_cache));
upb_value_ptr(desc)); zend_hash_destroy(&PROTOBUF_G(name_msg_cache));
} zend_hash_destroy(&PROTOBUF_G(name_enum_cache));
EnumDescriptorInternal* get_class_enumdesc(const char* klass) { return SUCCESS;
upb_value v;
#ifndef NDEBUG
v.ctype = UPB_CTYPE_PTR;
#endif
if (!upb_strtable_lookup(&class_to_desc_map_persistent, klass, &v)) {
return NULL;
} else {
return upb_value_getptr(v);
}
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Well Known Types. // Bundled PHP sources
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
bool is_inited_file_any; // We bundle PHP sources for well-known types into the C extension. There is no
bool is_inited_file_api; // need to implement these in C.
bool is_inited_file_duration;
bool is_inited_file_field_mask;
bool is_inited_file_empty;
bool is_inited_file_source_context;
bool is_inited_file_struct;
bool is_inited_file_timestamp;
bool is_inited_file_type;
bool is_inited_file_wrappers;
// ----------------------------------------------------------------------------- static PHP_FUNCTION(protobuf_internal_loadbundled) {
// Reserved Name. char *name = NULL;
// ----------------------------------------------------------------------------- zend_long size;
BundledPhp_File *file;
// Although we already have kReservedNames, we still add them to hash table to if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &size) != SUCCESS) {
// speed up look up. return;
const char *const kReservedNames[] = { }
"abstract", "and", "array", "as", "break",
"callable", "case", "catch", "class", "clone", for (file = bundled_files; file->filename; file++) {
"const", "continue", "declare", "default", "die", if (strcmp(file->filename, name) == 0) {
"do", "echo", "else", "elseif", "empty", zend_eval_string((char*)file->contents, NULL, (char*)file->filename);
"enddeclare", "endfor", "endforeach", "endif", "endswitch", return;
"endwhile", "eval", "exit", "extends", "final", }
"for", "foreach", "function", "global", "goto", }
"if", "implements", "include", "include_once", "instanceof",
"insteadof", "interface", "isset", "list", "namespace",
"new", "or", "print", "private", "protected",
"public", "require", "require_once", "return", "static",
"switch", "throw", "trait", "try", "unset",
"use", "var", "while", "xor", "int",
"float", "bool", "string", "true", "false",
"null", "void", "iterable"};
const int kReservedNamesSize = 73;
bool is_reserved_name(const char* name) {
upb_value v;
#ifndef NDEBUG
v.ctype = UPB_CTYPE_UINT64;
#endif
return upb_strtable_lookup2(&reserved_names, name, strlen(name), &v);
} }
ZEND_BEGIN_ARG_INFO_EX(arginfo_load_bundled_source, 0, 0, 1)
ZEND_ARG_INFO(0, class_name)
ZEND_END_ARG_INFO()
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Utilities. // Object Cache.
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
zend_function_entry protobuf_functions[] = { void ObjCache_Add(const void *upb_obj, zend_object *php_obj) {
ZEND_FE_END zend_ulong k = (zend_ulong)upb_obj;
}; zend_hash_index_add_ptr(&PROTOBUF_G(object_cache), k, php_obj);
static const zend_module_dep protobuf_deps[] = {
ZEND_MOD_OPTIONAL("date")
ZEND_MOD_END
};
zend_module_entry protobuf_module_entry = {
STANDARD_MODULE_HEADER_EX,
NULL,
protobuf_deps,
PHP_PROTOBUF_EXTNAME, // extension name
protobuf_functions, // function list
PHP_MINIT(protobuf), // process startup
PHP_MSHUTDOWN(protobuf), // process shutdown
PHP_RINIT(protobuf), // request shutdown
PHP_RSHUTDOWN(protobuf), // request shutdown
NULL, // extension info
PHP_PROTOBUF_VERSION, // extension version
PHP_MODULE_GLOBALS(protobuf), // globals descriptor
PHP_GINIT(protobuf), // globals ctor
PHP_GSHUTDOWN(protobuf), // globals dtor
NULL, // post deactivate
STANDARD_MODULE_PROPERTIES_EX
};
// install module
ZEND_GET_MODULE(protobuf)
// global variables
static PHP_GINIT_FUNCTION(protobuf) {
} }
static PHP_GSHUTDOWN_FUNCTION(protobuf) { void ObjCache_Delete(const void *upb_obj) {
} if (upb_obj) {
zend_ulong k = (zend_ulong)upb_obj;
#if PHP_MAJOR_VERSION >= 7 int ret = zend_hash_index_del(&PROTOBUF_G(object_cache), k);
static void php_proto_hashtable_descriptor_release(zval* value) { PBPHP_ASSERT(ret == SUCCESS);
void* ptr = Z_PTR_P(value);
zend_object* object = *(zend_object**)ptr;
GC_DELREF(object);
if(GC_REFCOUNT(object) == 0) {
zend_objects_store_del(object);
} }
efree(ptr);
}
#endif
static void initialize_persistent_descriptor_pool(TSRMLS_D) {
upb_inttable_init(&upb_def_to_desc_map_persistent, UPB_CTYPE_PTR);
upb_inttable_init(&upb_def_to_enumdesc_map_persistent, UPB_CTYPE_PTR);
upb_strtable_init(&ce_to_desc_map_persistent, UPB_CTYPE_PTR);
upb_strtable_init(&ce_to_enumdesc_map_persistent, UPB_CTYPE_PTR);
upb_strtable_init(&proto_to_desc_map_persistent, UPB_CTYPE_PTR);
upb_strtable_init(&class_to_desc_map_persistent, UPB_CTYPE_PTR);
internal_descriptor_pool_impl_init(&generated_pool_impl TSRMLS_CC);
is_inited_file_any = false;
is_inited_file_api = false;
is_inited_file_duration = false;
is_inited_file_field_mask = false;
is_inited_file_empty = false;
is_inited_file_source_context = false;
is_inited_file_struct = false;
is_inited_file_timestamp = false;
is_inited_file_type = false;
is_inited_file_wrappers = false;
} }
static PHP_RINIT_FUNCTION(protobuf) { bool ObjCache_Get(const void *upb_obj, zval *val) {
ALLOC_HASHTABLE(upb_def_to_php_obj_map); zend_ulong k = (zend_ulong)upb_obj;
zend_hash_init(upb_def_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0); zend_object *obj = zend_hash_index_find_ptr(&PROTOBUF_G(object_cache), k);
ALLOC_HASHTABLE(ce_to_php_obj_map);
zend_hash_init(ce_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0);
generated_pool = NULL;
generated_pool_php = NULL;
internal_generated_pool_php = NULL;
if (PROTOBUF_G(keep_descriptor_pool_after_request)) {
// Needs to clean up obsolete class entry
upb_strtable_iter i;
upb_value v;
DescriptorInternal* desc;
for(upb_strtable_begin(&i, &ce_to_desc_map_persistent);
!upb_strtable_done(&i);
upb_strtable_next(&i)) {
v = upb_strtable_iter_value(&i);
desc = upb_value_getptr(v);
desc->klass = NULL;
}
EnumDescriptorInternal* enumdesc; if (obj) {
for(upb_strtable_begin(&i, &ce_to_enumdesc_map_persistent); GC_ADDREF(obj);
!upb_strtable_done(&i); ZVAL_OBJ(val, obj);
upb_strtable_next(&i)) { return true;
v = upb_strtable_iter_value(&i);
enumdesc = upb_value_getptr(v);
enumdesc->klass = NULL;
}
} else { } else {
initialize_persistent_descriptor_pool(TSRMLS_C); ZVAL_NULL(val);
return false;
} }
return 0;
} }
static void cleanup_desc_table(upb_inttable* t) { // -----------------------------------------------------------------------------
upb_inttable_iter i; // Name Cache.
upb_value v; // -----------------------------------------------------------------------------
DescriptorInternal* desc;
for(upb_inttable_begin(&i, t);
!upb_inttable_done(&i);
upb_inttable_next(&i)) {
v = upb_inttable_iter_value(&i);
desc = upb_value_getptr(v);
if (desc->layout) {
free_layout(desc->layout);
desc->layout = NULL;
}
free(desc->classname);
SYS_FREE(desc);
}
}
static void cleanup_enumdesc_table(upb_inttable* t) { void NameMap_AddMessage(const upb_msgdef *m) {
upb_inttable_iter i; char *k = GetPhpClassname(upb_msgdef_file(m), upb_msgdef_fullname(m));
upb_value v; zend_hash_str_add_ptr(&PROTOBUF_G(name_msg_cache), k, strlen(k), (void*)m);
EnumDescriptorInternal* desc; free(k);
for(upb_inttable_begin(&i, t);
!upb_inttable_done(&i);
upb_inttable_next(&i)) {
v = upb_inttable_iter_value(&i);
desc = upb_value_getptr(v);
free(desc->classname);
SYS_FREE(desc);
}
} }
static void cleanup_persistent_descriptor_pool(TSRMLS_D) { void NameMap_AddEnum(const upb_enumdef *e) {
// Clean up char *k = GetPhpClassname(upb_enumdef_file(e), upb_enumdef_fullname(e));
zend_hash_str_add_ptr(&PROTOBUF_G(name_enum_cache), k, strlen(k), (void*)e);
// Only needs to clean one map out of three (def=>desc, ce=>desc, proto=>desc) free(k);
cleanup_desc_table(&upb_def_to_desc_map_persistent);
cleanup_enumdesc_table(&upb_def_to_enumdesc_map_persistent);
internal_descriptor_pool_impl_destroy(&generated_pool_impl TSRMLS_CC);
upb_inttable_uninit(&upb_def_to_desc_map_persistent);
upb_inttable_uninit(&upb_def_to_enumdesc_map_persistent);
upb_strtable_uninit(&ce_to_desc_map_persistent);
upb_strtable_uninit(&ce_to_enumdesc_map_persistent);
upb_strtable_uninit(&proto_to_desc_map_persistent);
upb_strtable_uninit(&class_to_desc_map_persistent);
} }
static PHP_RSHUTDOWN_FUNCTION(protobuf) { const upb_msgdef *NameMap_GetMessage(zend_class_entry *ce) {
zend_hash_destroy(upb_def_to_php_obj_map); const upb_msgdef *ret =
FREE_HASHTABLE(upb_def_to_php_obj_map); zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name);
zend_hash_destroy(ce_to_php_obj_map);
FREE_HASHTABLE(ce_to_php_obj_map);
#if PHP_MAJOR_VERSION < 7 if (!ret && ce->create_object) {
if (generated_pool_php != NULL) {
zval_dtor(generated_pool_php);
FREE_ZVAL(generated_pool_php);
}
if (internal_generated_pool_php != NULL) {
zval_dtor(internal_generated_pool_php);
FREE_ZVAL(internal_generated_pool_php);
}
#else
if (generated_pool_php != NULL) {
zval tmp; zval tmp;
ZVAL_OBJ(&tmp, generated_pool_php); zval zv;
zval_dtor(&tmp); ZVAL_OBJ(&tmp, ce->create_object(ce));
} zend_call_method_with_0_params(&tmp, ce, NULL, "__construct", &zv);
if (internal_generated_pool_php != NULL) { zval_ptr_dtor(&tmp);
zval tmp; zval_ptr_dtor(&zv);
ZVAL_OBJ(&tmp, internal_generated_pool_php); ret = zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name);
zval_dtor(&tmp);
}
#endif
if (!PROTOBUF_G(keep_descriptor_pool_after_request)) {
cleanup_persistent_descriptor_pool(TSRMLS_C);
} }
return 0; return ret;
} }
static void reserved_names_init() { const upb_enumdef *NameMap_GetEnum(zend_class_entry *ce) {
size_t i; const upb_enumdef *ret =
upb_value v = upb_value_bool(false); zend_hash_find_ptr(&PROTOBUF_G(name_enum_cache), ce->name);
for (i = 0; i < kReservedNamesSize; i++) { return ret;
upb_strtable_insert2(&reserved_names, kReservedNames[i],
strlen(kReservedNames[i]), v);
}
} }
// -----------------------------------------------------------------------------
// Module init.
// -----------------------------------------------------------------------------
zend_function_entry protobuf_functions[] = {
PHP_FE(protobuf_internal_loadbundled, arginfo_load_bundled_source)
ZEND_FE_END
};
static const zend_module_dep protobuf_deps[] = {
ZEND_MOD_OPTIONAL("date")
ZEND_MOD_END
};
PHP_INI_BEGIN() PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("protobuf.keep_descriptor_pool_after_request", "0", STD_PHP_INI_ENTRY("protobuf.keep_descriptor_pool_after_request", "0",
PHP_INI_SYSTEM, OnUpdateBool, PHP_INI_SYSTEM, OnUpdateBool,
@ -514,86 +314,36 @@ PHP_INI_END()
static PHP_MINIT_FUNCTION(protobuf) { static PHP_MINIT_FUNCTION(protobuf) {
REGISTER_INI_ENTRIES(); REGISTER_INI_ENTRIES();
Arena_ModuleInit();
upb_strtable_init(&reserved_names, UPB_CTYPE_UINT64); Array_ModuleInit();
reserved_names_init(); Convert_ModuleInit();
Def_ModuleInit();
if (PROTOBUF_G(keep_descriptor_pool_after_request)) { Map_ModuleInit();
initialize_persistent_descriptor_pool(TSRMLS_C); Message_ModuleInit();
} return SUCCESS;
descriptor_pool_init(TSRMLS_C);
descriptor_init(TSRMLS_C);
enum_descriptor_init(TSRMLS_C);
enum_value_descriptor_init(TSRMLS_C);
field_descriptor_init(TSRMLS_C);
gpb_type_init(TSRMLS_C);
internal_descriptor_pool_init(TSRMLS_C);
map_field_init(TSRMLS_C);
map_field_iter_init(TSRMLS_C);
message_init(TSRMLS_C);
oneof_descriptor_init(TSRMLS_C);
repeated_field_init(TSRMLS_C);
repeated_field_iter_init(TSRMLS_C);
util_init(TSRMLS_C);
gpb_metadata_any_init(TSRMLS_C);
gpb_metadata_api_init(TSRMLS_C);
gpb_metadata_duration_init(TSRMLS_C);
gpb_metadata_field_mask_init(TSRMLS_C);
gpb_metadata_empty_init(TSRMLS_C);
gpb_metadata_source_context_init(TSRMLS_C);
gpb_metadata_struct_init(TSRMLS_C);
gpb_metadata_timestamp_init(TSRMLS_C);
gpb_metadata_type_init(TSRMLS_C);
gpb_metadata_wrappers_init(TSRMLS_C);
any_init(TSRMLS_C);
api_init(TSRMLS_C);
bool_value_init(TSRMLS_C);
bytes_value_init(TSRMLS_C);
double_value_init(TSRMLS_C);
duration_init(TSRMLS_C);
enum_init(TSRMLS_C);
enum_value_init(TSRMLS_C);
field_cardinality_init(TSRMLS_C);
field_init(TSRMLS_C);
field_kind_init(TSRMLS_C);
field_mask_init(TSRMLS_C);
float_value_init(TSRMLS_C);
empty_init(TSRMLS_C);
int32_value_init(TSRMLS_C);
int64_value_init(TSRMLS_C);
list_value_init(TSRMLS_C);
method_init(TSRMLS_C);
mixin_init(TSRMLS_C);
null_value_init(TSRMLS_C);
option_init(TSRMLS_C);
source_context_init(TSRMLS_C);
string_value_init(TSRMLS_C);
struct_init(TSRMLS_C);
syntax_init(TSRMLS_C);
timestamp_init(TSRMLS_C);
type_init(TSRMLS_C);
u_int32_value_init(TSRMLS_C);
u_int64_value_init(TSRMLS_C);
value_init(TSRMLS_C);
return 0;
} }
static PHP_MSHUTDOWN_FUNCTION(protobuf) { static PHP_MSHUTDOWN_FUNCTION(protobuf) {
if (PROTOBUF_G(keep_descriptor_pool_after_request)) { return SUCCESS;
cleanup_persistent_descriptor_pool(TSRMLS_C); }
}
upb_strtable_uninit(&reserved_names);
PEFREE(message_handlers); zend_module_entry protobuf_module_entry = {
PEFREE(repeated_field_handlers); STANDARD_MODULE_HEADER_EX,
PEFREE(repeated_field_iter_handlers); NULL,
PEFREE(map_field_handlers); protobuf_deps,
PEFREE(map_field_iter_handlers); "protobuf", // extension name
protobuf_functions, // function list
PHP_MINIT(protobuf), // process startup
PHP_MSHUTDOWN(protobuf), // process shutdown
PHP_RINIT(protobuf), // request shutdown
PHP_RSHUTDOWN(protobuf), // request shutdown
NULL, // extension info
"3.13.0", // extension version
PHP_MODULE_GLOBALS(protobuf), // globals descriptor
PHP_GINIT(protobuf), // globals ctor
PHP_GSHUTDOWN(protobuf), // globals dtor
NULL, // post deactivate
STANDARD_MODULE_PROPERTIES_EX
};
return 0; ZEND_GET_MODULE(protobuf)
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,680 +0,0 @@
// 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.
// The Zend Engine License, version 2.00
// Copyright (c) 1999-2002 Zend Technologies Ltd. All rights reserved.
// --------------------------------------------------------------------
//
// Redistribution and use in source and binary forms, with or without
// modification, is permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. 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.
//
// 3. The names "Zend" and "Zend Engine" must not be used to endorse
// or promote products derived from this software without prior
// permission from Zend Technologies Ltd. For written permission,
// please contact license@zend.com.
//
// 4. Zend Technologies Ltd. may publish revised and/or new versions
// of the license from time to time. Each version will be given a
// distinguishing version number.
// Once covered code has been published under a particular version
// of the license, you may always continue to use it under the
// terms of that version. You may also choose to use such covered
// code under the terms of any subsequent version of the license
// published by Zend Technologies Ltd. No one other than Zend
// Technologies Ltd. has the right to modify the terms applicable
// to covered code created under this License.
//
// 5. Redistributions of any form whatsoever must retain the following
// acknowledgment:
// "This product includes the Zend Engine, freely available at
// http://www.zend.com"
//
// 6. All advertising materials mentioning features or use of this
// software must display the following acknowledgment:
// "The Zend Engine is freely available at http://www.zend.com"
//
// THIS SOFTWARE IS PROVIDED BY ZEND TECHNOLOGIES LTD. ``AS IS'' AND
// ANY EXPRESSED 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 ZEND
// TECHNOLOGIES LTD. 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.
#include <Zend/zend_operators.h>
#include <Zend/zend_exceptions.h>
#include "protobuf.h"
#include "utf8.h"
static zend_class_entry* util_type;
static const char int64_min_digits[] = "9223372036854775808";
ZEND_BEGIN_ARG_INFO_EX(arg_check_optional, 0, 0, 1)
ZEND_ARG_INFO(1, val)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arg_check_message, 0, 0, 2)
ZEND_ARG_INFO(1, val)
ZEND_ARG_INFO(0, klass)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arg_check_repeated, 0, 0, 2)
ZEND_ARG_INFO(1, val)
ZEND_ARG_INFO(0, type)
ZEND_ARG_INFO(0, klass)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arg_check_map, 0, 0, 3)
ZEND_ARG_INFO(1, val)
ZEND_ARG_INFO(0, key_type)
ZEND_ARG_INFO(0, value_type)
ZEND_ARG_INFO(0, klass)
ZEND_END_ARG_INFO()
static zend_function_entry util_methods[] = {
PHP_ME(Util, checkInt32, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME(Util, checkUint32, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME(Util, checkInt64, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME(Util, checkUint64, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME(Util, checkEnum, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME(Util, checkFloat, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME(Util, checkDouble, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME(Util, checkBool, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME(Util, checkString, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME(Util, checkBytes, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME(Util, checkMessage, arg_check_message, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME(Util, checkMapField, arg_check_map, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME(Util, checkRepeatedField, arg_check_repeated,
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
ZEND_FE_END
};
void util_init(TSRMLS_D) {
zend_class_entry class_type;
INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBUtil",
util_methods);
util_type = zend_register_internal_class(&class_type TSRMLS_CC);
}
// -----------------------------------------------------------------------------
// Type checking/conversion.
// -----------------------------------------------------------------------------
// This is modified from is_numeric_string in zend_operators.h. The behavior of
// this function is the same as is_numeric_string, except that this takes
// int64_t as input instead of long.
static zend_uchar convert_numeric_string(
const char *str, int length, int64_t *lval, double *dval) {
const char *ptr;
int base = 10, digits = 0, dp_or_e = 0;
double local_dval = 0.0;
zend_uchar type;
if (length == 0) {
return IS_NULL;
}
while (*str == ' ' || *str == '\t' || *str == '\n' ||
*str == '\r' || *str == '\v' || *str == '\f') {
str++;
length--;
}
ptr = str;
if (*ptr == '-' || *ptr == '+') {
ptr++;
}
if (ZEND_IS_DIGIT(*ptr)) {
// Handle hex numbers
// str is used instead of ptr to disallow signs and keep old behavior.
if (length > 2 && *str == '0' && (str[1] == 'x' || str[1] == 'X')) {
base = 16;
ptr += 2;
}
// Skip any leading 0s.
while (*ptr == '0') {
ptr++;
}
// Count the number of digits. If a decimal point/exponent is found,
// it's a double. Otherwise, if there's a dval or no need to check for
// a full match, stop when there are too many digits for a int64 */
for (type = IS_LONG;
!(digits >= MAX_LENGTH_OF_INT64 && dval);
digits++, ptr++) {
check_digits:
if (ZEND_IS_DIGIT(*ptr) || (base == 16 && ZEND_IS_XDIGIT(*ptr))) {
continue;
} else if (base == 10) {
if (*ptr == '.' && dp_or_e < 1) {
goto process_double;
} else if ((*ptr == 'e' || *ptr == 'E') && dp_or_e < 2) {
const char *e = ptr + 1;
if (*e == '-' || *e == '+') {
ptr = e++;
}
if (ZEND_IS_DIGIT(*e)) {
goto process_double;
}
}
}
break;
}
if (base == 10) {
if (digits >= MAX_LENGTH_OF_INT64) {
dp_or_e = -1;
goto process_double;
}
} else if (!(digits < SIZEOF_INT64 * 2 ||
(digits == SIZEOF_INT64 * 2 && ptr[-digits] <= '7'))) {
if (dval) {
local_dval = zend_hex_strtod(str, &ptr);
}
type = IS_DOUBLE;
}
} else if (*ptr == '.' && ZEND_IS_DIGIT(ptr[1])) {
process_double:
type = IS_DOUBLE;
// If there's a dval, do the conversion; else continue checking
// the digits if we need to check for a full match.
if (dval) {
local_dval = zend_strtod(str, &ptr);
} else if (dp_or_e != -1) {
dp_or_e = (*ptr++ == '.') ? 1 : 2;
goto check_digits;
}
} else {
return IS_NULL;
}
if (ptr != str + length) {
zend_error(E_NOTICE, "A non well formed numeric value encountered");
return 0;
}
if (type == IS_LONG) {
if (digits == MAX_LENGTH_OF_INT64 - 1) {
int cmp = strcmp(&ptr[-digits], int64_min_digits);
if (!(cmp < 0 || (cmp == 0 && *str == '-'))) {
if (dval) {
*dval = zend_strtod(str, NULL);
}
return IS_DOUBLE;
}
}
if (lval) {
*lval = strtoll(str, NULL, base);
}
return IS_LONG;
} else {
if (dval) {
*dval = local_dval;
}
return IS_DOUBLE;
}
}
#define CONVERT_TO_INTEGER(type) \
static bool convert_int64_to_##type(int64_t val, type##_t* type##_value) { \
*type##_value = (type##_t)val; \
return true; \
} \
\
static bool convert_double_to_##type(double val, type##_t* type##_value) { \
*type##_value = (type##_t)zend_dval_to_lval(val); \
return true; \
} \
\
static bool convert_string_to_##type(const char* val, int len, \
type##_t* type##_value) { \
int64_t lval; \
double dval; \
TSRMLS_FETCH(); \
switch (convert_numeric_string(val, len, &lval, &dval)) { \
case IS_DOUBLE: { \
return convert_double_to_##type(dval, type##_value); \
} \
case IS_LONG: { \
return convert_int64_to_##type(lval, type##_value); \
} \
default: \
zend_throw_exception(NULL, \
"Given string value cannot be converted to integer.", \
0 TSRMLS_CC); \
return false; \
} \
} \
\
bool protobuf_convert_to_##type(zval* from, type##_t* to) { \
TSRMLS_FETCH(); \
switch (Z_TYPE_P(from)) { \
case IS_LONG: { \
return convert_int64_to_##type(Z_LVAL_P(from), to); \
} \
case IS_DOUBLE: { \
return convert_double_to_##type(Z_DVAL_P(from), to); \
} \
case IS_STRING: { \
return convert_string_to_##type(Z_STRVAL_P(from), Z_STRLEN_P(from), \
to); \
} \
default: { \
zend_throw_exception(NULL, \
"Given value cannot be converted to integer.", \
0 TSRMLS_CC); \
return false; \
} \
} \
return false; \
}
CONVERT_TO_INTEGER(int32);
CONVERT_TO_INTEGER(uint32);
CONVERT_TO_INTEGER(int64);
CONVERT_TO_INTEGER(uint64);
#undef CONVERT_TO_INTEGER
#define CONVERT_TO_FLOAT(type) \
static bool convert_int64_to_##type(int64_t val, type* type##_value) { \
*type##_value = (type)val; \
return true; \
} \
\
static bool convert_double_to_##type(double val, type* type##_value) { \
*type##_value = (type)val; \
return true; \
} \
\
static bool convert_string_to_##type(const char* val, int len, \
type* type##_value) { \
int64_t lval; \
double dval; \
\
TSRMLS_FETCH(); \
switch (convert_numeric_string(val, len, &lval, &dval)) { \
case IS_DOUBLE: { \
*type##_value = (type)dval; \
return true; \
} \
case IS_LONG: { \
*type##_value = (type)lval; \
return true; \
} \
default: \
zend_throw_exception(NULL, \
"Given string value cannot be converted to integer.", \
0 TSRMLS_CC); \
return false; \
} \
} \
\
bool protobuf_convert_to_##type(zval* from, type* to) { \
TSRMLS_FETCH(); \
switch (Z_TYPE_P(from)) { \
case IS_LONG: { \
return convert_int64_to_##type(Z_LVAL_P(from), to); \
} \
case IS_DOUBLE: { \
return convert_double_to_##type(Z_DVAL_P(from), to); \
} \
case IS_STRING: { \
return convert_string_to_##type(Z_STRVAL_P(from), Z_STRLEN_P(from), \
to); \
} \
default: { \
zend_throw_exception(NULL, \
"Given value cannot be converted to integer.", \
0 TSRMLS_CC); \
return false; \
} \
} \
return false; \
}
CONVERT_TO_FLOAT(float);
CONVERT_TO_FLOAT(double);
#undef CONVERT_TO_FLOAT
bool protobuf_convert_to_bool(zval* from, int8_t* to) {
TSRMLS_FETCH();
switch (Z_TYPE_P(from)) {
#if PHP_MAJOR_VERSION < 7
case IS_BOOL:
*to = (int8_t)Z_BVAL_P(from);
break;
#else
case IS_TRUE:
*to = 1;
break;
case IS_FALSE:
*to = 0;
break;
#endif
case IS_LONG:
*to = (int8_t)(Z_LVAL_P(from) != 0);
break;
case IS_DOUBLE:
*to = (int8_t)(Z_LVAL_P(from) != 0);
break;
case IS_STRING: {
if (Z_STRLEN_P(from) == 0 ||
(Z_STRLEN_P(from) == 1 && Z_STRVAL_P(from)[0] == '0')) {
*to = 0;
} else {
*to = 1;
}
} break;
default: {
zend_throw_exception(
NULL, "Given value cannot be converted to bool.",
0 TSRMLS_CC);
return false;
}
}
return true;
}
bool protobuf_convert_to_string(zval* from) {
#if PHP_MAJOR_VERSION >= 7
if (Z_ISREF_P(from)) {
ZVAL_DEREF(from);
}
#endif
TSRMLS_FETCH();
switch (Z_TYPE_P(from)) {
case IS_STRING: {
return true;
}
#if PHP_MAJOR_VERSION < 7
case IS_BOOL:
#else
case IS_TRUE:
case IS_FALSE:
#endif
case IS_LONG:
case IS_DOUBLE: {
zval tmp;
php_proto_zend_make_printable_zval(from, &tmp);
ZVAL_COPY_VALUE(from, &tmp);
return true;
}
default:
zend_throw_exception(
NULL, "Given value cannot be converted to string.",
0 TSRMLS_CC);
return false;
}
}
// -----------------------------------------------------------------------------
// PHP Functions.
// -----------------------------------------------------------------------------
// The implementation of type checking for primitive fields is empty. This is
// because type checking is done when direct assigning message fields (e.g.,
// foo->a = 1). Functions defined here are place holders in generated code for
// pure PHP implementation (c extension and pure PHP share the same generated
// code).
#define PHP_TYPE_CHECK(type) \
PHP_METHOD(Util, check##type) {}
PHP_TYPE_CHECK(Int32)
PHP_TYPE_CHECK(Uint32)
PHP_TYPE_CHECK(Int64)
PHP_TYPE_CHECK(Uint64)
PHP_TYPE_CHECK(Enum)
PHP_TYPE_CHECK(Float)
PHP_TYPE_CHECK(Double)
PHP_TYPE_CHECK(Bool)
PHP_TYPE_CHECK(String)
PHP_TYPE_CHECK(Bytes)
#undef PHP_TYPE_CHECK
PHP_METHOD(Util, checkMessage) {
zval* val;
zend_class_entry* klass = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o!C", &val, &klass) ==
FAILURE) {
return;
}
if (val == NULL) {
RETURN_NULL();
}
if (!instanceof_function(Z_OBJCE_P(val), klass TSRMLS_CC)) {
zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
"Given value is not an instance of %s.",
#if PHP_MAJOR_VERSION < 7
klass->name);
#else
ZSTR_VAL(klass->name));
#endif
return;
}
RETURN_ZVAL(val, 1, 0);
}
void check_repeated_field(const zend_class_entry* klass, PHP_PROTO_LONG type,
zval* val, zval* return_value) {
#if PHP_MAJOR_VERSION >= 7
if (Z_ISREF_P(val)) {
ZVAL_DEREF(val);
}
#endif
TSRMLS_FETCH();
if (Z_TYPE_P(val) == IS_ARRAY) {
HashTable* table = HASH_OF(val);
HashPosition pointer;
void* memory;
#if PHP_MAJOR_VERSION < 7
zval* repeated_field;
MAKE_STD_ZVAL(repeated_field);
#else
zval repeated_field;
#endif
repeated_field_create_with_type(repeated_field_type, to_fieldtype(type),
klass, &repeated_field TSRMLS_CC);
for (zend_hash_internal_pointer_reset_ex(table, &pointer);
php_proto_zend_hash_get_current_data_ex(table, (void**)&memory,
&pointer) == SUCCESS;
zend_hash_move_forward_ex(table, &pointer)) {
repeated_field_handlers->write_dimension(
CACHED_TO_ZVAL_PTR(repeated_field), NULL,
CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory) TSRMLS_CC);
}
RETURN_ZVAL(CACHED_TO_ZVAL_PTR(repeated_field), 1, 1);
} else if (Z_TYPE_P(val) == IS_OBJECT) {
if (!instanceof_function(Z_OBJCE_P(val), repeated_field_type TSRMLS_CC)) {
zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
"Given value is not an instance of %s.",
#if PHP_MAJOR_VERSION < 7
repeated_field_type->name);
#else
ZSTR_VAL(repeated_field_type->name));
#endif
return;
}
RepeatedField* intern = UNBOX(RepeatedField, val);
if (to_fieldtype(type) != intern->type) {
zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
"Incorrect repeated field type.");
return;
}
if (klass != NULL && intern->msg_ce != klass) {
zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
"Expect a repeated field of %s, but %s is given.",
#if PHP_MAJOR_VERSION < 7
klass->name, intern->msg_ce->name);
#else
ZSTR_VAL(klass->name),
ZSTR_VAL(intern->msg_ce->name));
#endif
return;
}
RETURN_ZVAL(val, 1, 0);
} else {
zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
"Incorrect repeated field type.");
return;
}
}
PHP_METHOD(Util, checkRepeatedField) {
zval* val;
PHP_PROTO_LONG type;
const zend_class_entry* klass = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl|C", &val, &type,
&klass) == FAILURE) {
return;
}
RETURN_ZVAL(val, 1, 0);
}
void check_map_field(const zend_class_entry* klass, PHP_PROTO_LONG key_type,
PHP_PROTO_LONG value_type, zval* val, zval* return_value) {
#if PHP_MAJOR_VERSION >= 7
if (Z_ISREF_P(val)) {
ZVAL_DEREF(val);
}
#endif
TSRMLS_FETCH();
if (Z_TYPE_P(val) == IS_ARRAY) {
HashTable* table = Z_ARRVAL_P(val);
HashPosition pointer;
zval key;
void* value;
#if PHP_MAJOR_VERSION < 7
zval* map_field;
MAKE_STD_ZVAL(map_field);
#else
zval map_field;
#endif
map_field_create_with_type(map_field_type, to_fieldtype(key_type),
to_fieldtype(value_type), klass,
&map_field TSRMLS_CC);
for (zend_hash_internal_pointer_reset_ex(table, &pointer);
php_proto_zend_hash_get_current_data_ex(table, (void**)&value,
&pointer) == SUCCESS;
zend_hash_move_forward_ex(table, &pointer)) {
zend_hash_get_current_key_zval_ex(table, &key, &pointer);
map_field_handlers->write_dimension(
CACHED_TO_ZVAL_PTR(map_field), &key,
CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)value) TSRMLS_CC);
zval_dtor(&key);
}
RETURN_ZVAL(CACHED_TO_ZVAL_PTR(map_field), 1, 1);
} else if (Z_TYPE_P(val) == IS_OBJECT) {
if (!instanceof_function(Z_OBJCE_P(val), map_field_type TSRMLS_CC)) {
zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
"Given value is not an instance of %s.",
#if PHP_MAJOR_VERSION < 7
map_field_type->name);
#else
ZSTR_VAL(map_field_type->name));
#endif
return;
}
Map* intern = UNBOX(Map, val);
if (to_fieldtype(key_type) != intern->key_type) {
zend_throw_exception(
NULL, "Incorrect map field key type.",
0 TSRMLS_CC);
return;
}
if (to_fieldtype(value_type) != intern->value_type) {
zend_throw_exception(
NULL, "Incorrect map field value type.",
0 TSRMLS_CC);
return;
}
if (klass != NULL && intern->msg_ce != klass) {
zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
"Expect a map field of %s, but %s is given.",
#if PHP_MAJOR_VERSION < 7
klass->name, intern->msg_ce->name);
#else
ZSTR_VAL(klass->name),
ZSTR_VAL(intern->msg_ce->name));
#endif
return;
}
RETURN_ZVAL(val, 1, 0);
} else {
zend_throw_exception(
NULL, "Incorrect map field type.",
0 TSRMLS_CC);
return;
}
}
PHP_METHOD(Util, checkMapField) {
zval* val;
PHP_PROTO_LONG key_type, value_type;
const zend_class_entry* klass = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zll|C", &val, &key_type,
&value_type, &klass) == FAILURE) {
return;
}
RETURN_ZVAL(val, 1, 0);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,68 +0,0 @@
// 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.
#include <stdbool.h>
#include <stdint.h>
#include "utf8.h"
static const uint8_t utf8_offset[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0,
};
bool is_structurally_valid_utf8(const char* buf, int len) {
int i, j;
uint8_t offset;
i = 0;
while (i < len) {
offset = utf8_offset[(uint8_t)buf[i]];
if (offset == 0 || i + offset > len) {
return false;
}
for (j = i + 1; j < i + offset; j++) {
if ((buf[j] & 0xc0) != 0x80) {
return false;
}
}
i += offset;
}
return i == len;
}

@ -1,36 +0,0 @@
// 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.
#ifndef GOOGLE_PROTOBUF_UTF8_H_
#define GOOGLE_PROTOBUF_UTF8_H_
bool is_structurally_valid_utf8(const char* buf, int len);
#endif // GOOGLE_PROTOBUF_UTF8_H_

@ -1,602 +0,0 @@
// 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.
#include "array.h"
#include <Zend/zend_API.h>
#include <Zend/zend_interfaces.h>
#include <ext/spl/spl_iterators.h>
// This is not self-contained: it must be after other Zend includes.
#include <Zend/zend_exceptions.h>
#include "arena.h"
#include "convert.h"
#include "def.h"
#include "php-upb.h"
#include "protobuf.h"
static void RepeatedFieldIter_make(zval *val, zval *repeated_field);
// -----------------------------------------------------------------------------
// RepeatedField
// -----------------------------------------------------------------------------
typedef struct {
zend_object std;
zval arena;
upb_array *array;
upb_fieldtype_t type;
const Descriptor* desc; // When values are messages.
} RepeatedField;
zend_class_entry *RepeatedField_class_entry;
static zend_object_handlers RepeatedField_object_handlers;
// PHP Object Handlers /////////////////////////////////////////////////////////
/**
* RepeatedField_create()
*
* PHP class entry function to allocate and initialize a new RepeatedField
* object.
*/
static zend_object* RepeatedField_create(zend_class_entry *class_type) {
RepeatedField *intern = emalloc(sizeof(RepeatedField));
zend_object_std_init(&intern->std, class_type);
intern->std.handlers = &RepeatedField_object_handlers;
Arena_Init(&intern->arena);
intern->array = NULL;
intern->desc = NULL;
// Skip object_properties_init(), we don't allow derived classes.
return &intern->std;
}
/**
* RepeatedField_dtor()
*
* Object handler to destroy a RepeatedField. This releases all resources
* associated with the message. Note that it is possible to access a destroyed
* object from PHP in rare cases.
*/
static void RepeatedField_destructor(zend_object* obj) {
RepeatedField* intern = (RepeatedField*)obj;
ObjCache_Delete(intern->array);
zval_ptr_dtor(&intern->arena);
zend_object_std_dtor(&intern->std);
}
static HashTable *RepeatedField_GetProperties(zval *object TSRMLS_DC) {
return NULL; // We do not have a properties table.
}
static zval *RepeatedField_GetPropertyPtrPtr(zval *object, zval *member,
int type, void **cache_slot) {
return NULL; // We don't offer direct references to our properties.
}
// C Functions from array.h ////////////////////////////////////////////////////
// These are documented in the header file.
void RepeatedField_GetPhpWrapper(zval *val, upb_array *arr,
const upb_fielddef *f, zval *arena) {
if (!arr) {
ZVAL_NULL(val);
return;
}
if (!ObjCache_Get(arr, val)) {
RepeatedField *intern = emalloc(sizeof(RepeatedField));
zend_object_std_init(&intern->std, RepeatedField_class_entry);
intern->std.handlers = &RepeatedField_object_handlers;
ZVAL_COPY(&intern->arena, arena);
intern->array = arr;
intern->type = upb_fielddef_type(f);
intern->desc = Descriptor_GetFromFieldDef(f);
// Skip object_properties_init(), we don't allow derived classes.
ObjCache_Add(intern->array, &intern->std);
ZVAL_OBJ(val, &intern->std);
}
}
upb_array *RepeatedField_GetUpbArray(zval *val, const upb_fielddef *f,
upb_arena *arena) {
if (Z_ISREF_P(val)) {
ZVAL_DEREF(val);
}
if (Z_TYPE_P(val) == IS_ARRAY) {
// Auto-construct, eg. [1, 2, 3] -> upb_array([1, 2, 3]).
upb_array *arr = upb_array_new(arena, upb_fielddef_type(f));
HashTable *table = HASH_OF(val);
HashPosition pos;
upb_fieldtype_t type = upb_fielddef_type(f);
const Descriptor *desc = Descriptor_GetFromFieldDef(f);
zend_hash_internal_pointer_reset_ex(table, &pos);
while (true) {
zval *zv = zend_hash_get_current_data_ex(table, &pos);
upb_msgval val;
if (!zv) return arr;
if (!Convert_PhpToUpbAutoWrap(zv, &val, type, desc, arena)) {
return NULL;
}
upb_array_append(arr, val, arena);
zend_hash_move_forward_ex(table, &pos);
}
} else if (Z_TYPE_P(val) == IS_OBJECT &&
Z_OBJCE_P(val) == RepeatedField_class_entry) {
// Unwrap existing RepeatedField object to get the upb_array* inside.
RepeatedField *intern = (RepeatedField*)Z_OBJ_P(val);
const Descriptor *desc = Descriptor_GetFromFieldDef(f);
if (intern->type != upb_fielddef_type(f) || intern->desc != desc) {
php_error_docref(NULL, E_USER_ERROR,
"Wrong type for this repeated field.");
}
upb_arena_fuse(arena, Arena_Get(&intern->arena));
return intern->array;
} else {
php_error_docref(NULL, E_USER_ERROR, "Must be a repeated field");
return NULL;
}
}
// RepeatedField PHP methods ///////////////////////////////////////////////////
/**
* RepeatedField::__construct()
*
* Constructs an instance of RepeatedField.
* @param long Type of the stored element.
* @param string Message/Enum class.
*/
PHP_METHOD(RepeatedField, __construct) {
RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
upb_arena *arena = Arena_Get(&intern->arena);
zend_long type;
zend_class_entry* klass = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|C", &type, &klass) != SUCCESS) {
return;
}
intern->type = pbphp_dtype_to_type(type);
intern->desc = Descriptor_GetFromClassEntry(klass);
if (intern->type == UPB_TYPE_MESSAGE && klass == NULL) {
php_error_docref(NULL, E_USER_ERROR,
"Message/enum type must have concrete class.");
return;
}
intern->array = upb_array_new(arena, intern->type);
ObjCache_Add(intern->array, &intern->std);
}
/**
* RepeatedField::append()
*
* Append element to the end of the repeated field.
* @param object The element to be added.
*/
PHP_METHOD(RepeatedField, append) {
RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
upb_arena *arena = Arena_Get(&intern->arena);
zval *php_val;
upb_msgval msgval;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &php_val) != SUCCESS ||
!Convert_PhpToUpb(php_val, &msgval, intern->type, intern->desc, arena)) {
return;
}
upb_array_append(intern->array, msgval, arena);
}
/**
* RepeatedField::offsetExists()
*
* Implements the ArrayAccess interface. Invoked when PHP code calls:
*
* isset($arr[$idx]);
* empty($arr[$idx]);
*
* @param long The index to be checked.
* @return bool True if the element at the given index exists.
*/
PHP_METHOD(RepeatedField, offsetExists) {
RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
zend_long index;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
return;
}
RETURN_BOOL(index >= 0 && index < upb_array_size(intern->array));
}
/**
* RepeatedField::offsetGet()
*
* Implements the ArrayAccess interface. Invoked when PHP code calls:
*
* $x = $arr[$idx];
*
* @param long The index of the element to be fetched.
* @return object The stored element at given index.
* @exception Invalid type for index.
* @exception Non-existing index.
*/
PHP_METHOD(RepeatedField, offsetGet) {
RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
zend_long index;
upb_msgval msgval;
zval ret;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
return;
}
if (index < 0 || index >= upb_array_size(intern->array)) {
zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
return;
}
msgval = upb_array_get(intern->array, index);
Convert_UpbToPhp(msgval, &ret, intern->type, intern->desc, &intern->arena);
RETURN_ZVAL(&ret, 0, 1);
}
/**
* RepeatedField::offsetSet()
*
* Implements the ArrayAccess interface. Invoked when PHP code calls:
*
* $arr[$idx] = $x;
* $arr []= $x; // Append
*
* @param long The index of the element to be assigned.
* @param object The element to be assigned.
* @exception Invalid type for index.
* @exception Non-existing index.
* @exception Incorrect type of the element.
*/
PHP_METHOD(RepeatedField, offsetSet) {
RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
upb_arena *arena = Arena_Get(&intern->arena);
size_t size = upb_array_size(intern->array);
zval *offset, *val;
int64_t index;
upb_msgval msgval;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &offset, &val) != SUCCESS) {
return;
}
if (Z_TYPE_P(offset) == IS_NULL) {
index = size;
} else if (!Convert_PhpToInt64(offset, &index)) {
return;
}
if (!Convert_PhpToUpb(val, &msgval, intern->type, intern->desc, arena)) {
return;
}
if (index > size) {
zend_error(E_USER_ERROR, "Element at index %ld doesn't exist.\n", index);
} else if (index == size) {
upb_array_append(intern->array, msgval, Arena_Get(&intern->arena));
} else {
upb_array_set(intern->array, index, msgval);
}
}
/**
* RepeatedField::offsetUnset()
*
* Implements the ArrayAccess interface. Invoked when PHP code calls:
*
* unset($arr[$idx]);
*
* @param long The index of the element to be removed.
* @exception Invalid type for index.
* @exception The element to be removed is not at the end of the RepeatedField.
*/
PHP_METHOD(RepeatedField, offsetUnset) {
RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
zend_long index;
zend_long size = upb_array_size(intern->array);
// Only the element at the end of the array can be removed.
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) != SUCCESS) {
return;
}
if (size == 0 || index != size - 1) {
php_error_docref(NULL, E_USER_ERROR, "Cannot remove element at %ld.\n",
index);
return;
}
upb_array_resize(intern->array, size - 1, Arena_Get(&intern->arena));
}
/**
* RepeatedField::count()
*
* Implements the Countable interface. Invoked when PHP code calls:
*
* $len = count($arr);
* Return the number of stored elements.
* This will also be called for: count($arr)
* @return long The number of stored elements.
*/
PHP_METHOD(RepeatedField, count) {
RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
if (zend_parse_parameters_none() == FAILURE) {
return;
}
RETURN_LONG(upb_array_size(intern->array));
}
/**
* RepeatedField::getIterator()
*
* Implements the IteratorAggregate interface. Invoked when PHP code calls:
*
* foreach ($arr) {}
*
* @return object Beginning iterator.
*/
PHP_METHOD(RepeatedField, getIterator) {
zval ret;
RepeatedFieldIter_make(&ret, getThis());
RETURN_ZVAL(&ret, 0, 1);
}
ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1)
ZEND_ARG_INFO(0, index)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2)
ZEND_ARG_INFO(0, index)
ZEND_ARG_INFO(0, newval)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_void, 0)
ZEND_END_ARG_INFO()
static zend_function_entry repeated_field_methods[] = {
PHP_ME(RepeatedField, __construct, NULL, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedField, append, NULL, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedField, offsetUnset, arginfo_offsetGet, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedField, count, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedField, getIterator, arginfo_void, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
// -----------------------------------------------------------------------------
// PHP RepeatedFieldIter
// -----------------------------------------------------------------------------
typedef struct {
zend_object std;
zval repeated_field;
zend_long position;
} RepeatedFieldIter;
zend_class_entry *RepeatedFieldIter_class_entry;
static zend_object_handlers repeated_field_iter_object_handlers;
/**
* RepeatedFieldIter_create()
*
* PHP class entry function to allocate and initialize a new RepeatedFieldIter
* object.
*/
zend_object* RepeatedFieldIter_create(zend_class_entry *class_type) {
RepeatedFieldIter *intern = emalloc(sizeof(RepeatedFieldIter));
zend_object_std_init(&intern->std, class_type);
intern->std.handlers = &repeated_field_iter_object_handlers;
ZVAL_NULL(&intern->repeated_field);
intern->position = 0;
// Skip object_properties_init(), we don't allow derived classes.
return &intern->std;
}
/**
* RepeatedFieldIter_dtor()
*
* Object handler to destroy a RepeatedFieldIter. This releases all resources
* associated with the message. Note that it is possible to access a destroyed
* object from PHP in rare cases.
*/
static void RepeatedFieldIter_dtor(zend_object* obj) {
RepeatedFieldIter* intern = (RepeatedFieldIter*)obj;
zval_ptr_dtor(&intern->repeated_field);
zend_object_std_dtor(&intern->std);
}
/**
* RepeatedFieldIter_make()
*
* C function to create a RepeatedFieldIter.
*/
static void RepeatedFieldIter_make(zval *val, zval *repeated_field) {
RepeatedFieldIter *iter;
ZVAL_OBJ(val, RepeatedFieldIter_class_entry->create_object(
RepeatedFieldIter_class_entry));
iter = (RepeatedFieldIter*)Z_OBJ_P(val);
ZVAL_COPY(&iter->repeated_field, repeated_field);
}
/*
* When a user writes:
*
* foreach($arr as $key => $val) {}
*
* PHP's iterator protocol is:
*
* $iter = $arr->getIterator();
* for ($iter->rewind(); $iter->valid(); $iter->next()) {
* $key = $iter->key();
* $val = $iter->current();
* }
*/
/**
* RepeatedFieldIter::rewind()
*
* Implements the Iterator interface. Sets the iterator to the first element.
*/
PHP_METHOD(RepeatedFieldIter, rewind) {
RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
intern->position = 0;
}
/**
* RepeatedFieldIter::current()
*
* Implements the Iterator interface. Returns the current value.
*/
PHP_METHOD(RepeatedFieldIter, current) {
RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
RepeatedField *field = (RepeatedField*)Z_OBJ_P(&intern->repeated_field);
upb_array *array = field->array;
zend_long index = intern->position;
upb_msgval msgval;
zval ret;
if (index < 0 || index >= upb_array_size(array)) {
zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
}
msgval = upb_array_get(array, index);
Convert_UpbToPhp(msgval, &ret, field->type, field->desc, &field->arena);
RETURN_ZVAL(&ret, 0, 1);
}
/**
* RepeatedFieldIter::key()
*
* Implements the Iterator interface. Returns the current key.
*/
PHP_METHOD(RepeatedFieldIter, key) {
RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
RETURN_LONG(intern->position);
}
/**
* RepeatedFieldIter::next()
*
* Implements the Iterator interface. Advances to the next element.
*/
PHP_METHOD(RepeatedFieldIter, next) {
RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
++intern->position;
}
/**
* RepeatedFieldIter::valid()
*
* Implements the Iterator interface. Returns true if this is a valid element.
*/
PHP_METHOD(RepeatedFieldIter, valid) {
RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
RepeatedField *field = (RepeatedField*)Z_OBJ_P(&intern->repeated_field);
RETURN_BOOL(intern->position < upb_array_size(field->array));
}
static zend_function_entry repeated_field_iter_methods[] = {
PHP_ME(RepeatedFieldIter, rewind, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedFieldIter, current, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedFieldIter, key, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedFieldIter, next, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(RepeatedFieldIter, valid, arginfo_void, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
// -----------------------------------------------------------------------------
// Module init.
// -----------------------------------------------------------------------------
/**
* Array_ModuleInit()
*
* Called when the C extension is loaded to register all types.
*/
void Array_ModuleInit() {
zend_class_entry tmp_ce;
zend_object_handlers *h;
// RepeatedField.
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\RepeatedField",
repeated_field_methods);
RepeatedField_class_entry = zend_register_internal_class(&tmp_ce);
zend_class_implements(RepeatedField_class_entry, 3, spl_ce_ArrayAccess,
zend_ce_aggregate, spl_ce_Countable);
RepeatedField_class_entry->ce_flags |= ZEND_ACC_FINAL;
RepeatedField_class_entry->create_object = RepeatedField_create;
h = &RepeatedField_object_handlers;
memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
h->dtor_obj = RepeatedField_destructor;
h->get_properties = RepeatedField_GetProperties;
h->get_property_ptr_ptr = RepeatedField_GetPropertyPtrPtr;
// RepeatedFieldIter
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\RepeatedFieldIter",
repeated_field_iter_methods);
RepeatedFieldIter_class_entry = zend_register_internal_class(&tmp_ce);
zend_class_implements(RepeatedFieldIter_class_entry, 1, zend_ce_iterator);
RepeatedFieldIter_class_entry->ce_flags |= ZEND_ACC_FINAL;
RepeatedFieldIter_class_entry->create_object = RepeatedFieldIter_create;
h = &repeated_field_iter_object_handlers;
memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
h->dtor_obj = RepeatedFieldIter_dtor;
}

@ -1,10 +0,0 @@
PHP_ARG_ENABLE(protobuf, whether to enable Protobuf extension, [ --enable-protobuf Enable Protobuf extension])
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)
fi

File diff suppressed because it is too large Load Diff

@ -1,590 +0,0 @@
// 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.
#include "map.h"
#include <Zend/zend_API.h>
#include <Zend/zend_interfaces.h>
#include <ext/spl/spl_iterators.h>
#include "arena.h"
#include "convert.h"
#include "php-upb.h"
#include "protobuf.h"
static void MapFieldIter_make(zval *val, zval *map_field);
// -----------------------------------------------------------------------------
// MapField
// -----------------------------------------------------------------------------
typedef struct {
zend_object std;
zval arena;
upb_map *map;
upb_fieldtype_t key_type;
upb_fieldtype_t val_type;
const Descriptor* desc; // When values are messages.
} MapField;
zend_class_entry *MapField_class_entry;
static zend_object_handlers MapField_object_handlers;
// PHP Object Handlers /////////////////////////////////////////////////////////
/**
* MapField_create()
*
* PHP class entry function to allocate and initialize a new MapField
* object.
*/
static zend_object* MapField_create(zend_class_entry *class_type) {
MapField *intern = emalloc(sizeof(MapField));
zend_object_std_init(&intern->std, class_type);
intern->std.handlers = &MapField_object_handlers;
Arena_Init(&intern->arena);
intern->map = NULL;
// Skip object_properties_init(), we don't allow derived classes.
return &intern->std;
}
/**
* MapField_dtor()
*
* Object handler to destroy a MapField. This releases all resources
* associated with the message. Note that it is possible to access a destroyed
* object from PHP in rare cases.
*/
static void MapField_destructor(zend_object* obj) {
MapField* intern = (MapField*)obj;
ObjCache_Delete(intern->map);
zval_ptr_dtor(&intern->arena);
zend_object_std_dtor(&intern->std);
}
static zval *Map_GetPropertyPtrPtr(zval *object, zval *member, int type,
void **cache_slot) {
return NULL; // We don't offer direct references to our properties.
}
static HashTable *map_get_properties(zval *object TSRMLS_DC) {
return NULL; // We do not have a properties table.
}
// C Functions from map.h //////////////////////////////////////////////////////
// These are documented in the header file.
void MapField_GetPhpWrapper(zval *val, upb_map *map, const upb_fielddef *f,
zval *arena) {
if (!map) {
ZVAL_NULL(val);
return;
}
if (!ObjCache_Get(map, val)) {
const upb_msgdef *ent = upb_fielddef_msgsubdef(f);
const upb_fielddef *key_f = upb_msgdef_itof(ent, 1);
const upb_fielddef *val_f = upb_msgdef_itof(ent, 2);
MapField *intern = emalloc(sizeof(MapField));
zend_object_std_init(&intern->std, MapField_class_entry);
intern->std.handlers = &MapField_object_handlers;
ZVAL_COPY(&intern->arena, arena);
intern->map = map;
intern->key_type = upb_fielddef_type(key_f);
intern->val_type = upb_fielddef_type(val_f);
intern->desc = Descriptor_GetFromFieldDef(val_f);
// Skip object_properties_init(), we don't allow derived classes.
ObjCache_Add(intern->map, &intern->std);
ZVAL_OBJ(val, &intern->std);
}
}
upb_map *MapField_GetUpbMap(zval *val, const upb_fielddef *f, upb_arena *arena) {
const upb_msgdef *ent = upb_fielddef_msgsubdef(f);
const upb_fielddef *key_f = upb_msgdef_itof(ent, 1);
const upb_fielddef *val_f = upb_msgdef_itof(ent, 2);
upb_fieldtype_t key_type = upb_fielddef_type(key_f);
upb_fieldtype_t val_type = upb_fielddef_type(val_f);
const Descriptor *desc = Descriptor_GetFromFieldDef(val_f);
if (Z_ISREF_P(val)) {
ZVAL_DEREF(val);
}
if (Z_TYPE_P(val) == IS_ARRAY) {
upb_map *map = upb_map_new(arena, key_type, val_type);
HashTable *table = HASH_OF(val);
HashPosition pos;
zend_hash_internal_pointer_reset_ex(table, &pos);
while (true) {
zval php_key;
zval *php_val;
upb_msgval upb_key;
upb_msgval upb_val;
zend_hash_get_current_key_zval_ex(table, &php_key, &pos);
php_val = zend_hash_get_current_data_ex(table, &pos);
if (!php_val) return map;
if (!Convert_PhpToUpb(&php_key, &upb_key, key_type, NULL, arena) ||
!Convert_PhpToUpbAutoWrap(php_val, &upb_val, val_type, desc, arena)) {
return NULL;
}
upb_map_set(map, upb_key, upb_val, arena);
zend_hash_move_forward_ex(table, &pos);
zval_dtor(&php_key);
}
} else if (Z_TYPE_P(val) == IS_OBJECT &&
Z_OBJCE_P(val) == MapField_class_entry) {
MapField *intern = (MapField*)Z_OBJ_P(val);
if (intern->key_type != key_type || intern->val_type != val_type ||
intern->desc != desc) {
php_error_docref(NULL, E_USER_ERROR, "Wrong type for this map field.");
return NULL;
}
upb_arena_fuse(arena, Arena_Get(&intern->arena));
return intern->map;
} else {
php_error_docref(NULL, E_USER_ERROR, "Must be a map");
return NULL;
}
}
// MapField PHP methods ////////////////////////////////////////////////////////
/**
* MapField::__construct()
*
* Constructs an instance of MapField.
* @param long Key type.
* @param long Value type.
* @param string Message/Enum class (message/enum value types only).
*/
PHP_METHOD(MapField, __construct) {
MapField *intern = (MapField*)Z_OBJ_P(getThis());
upb_arena *arena = Arena_Get(&intern->arena);
zend_long key_type, val_type;
zend_class_entry* klass = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll|C", &key_type, &val_type,
&klass) != SUCCESS) {
return;
}
intern->key_type = pbphp_dtype_to_type(key_type);
intern->val_type = pbphp_dtype_to_type(val_type);
intern->desc = Descriptor_GetFromClassEntry(klass);
// Check that the key type is an allowed type.
switch (intern->key_type) {
case UPB_TYPE_INT32:
case UPB_TYPE_INT64:
case UPB_TYPE_UINT32:
case UPB_TYPE_UINT64:
case UPB_TYPE_BOOL:
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES:
// These are OK.
break;
default:
zend_error(E_USER_ERROR, "Invalid key type for map.");
}
if (intern->val_type == UPB_TYPE_MESSAGE && klass == NULL) {
php_error_docref(NULL, E_USER_ERROR,
"Message/enum type must have concrete class.");
return;
}
intern->map = upb_map_new(arena, intern->key_type, intern->val_type);
ObjCache_Add(intern->map, &intern->std);
}
/**
* MapField::offsetExists()
*
* Implements the ArrayAccess interface. Invoked when PHP code calls:
*
* isset($map[$idx]);
* empty($map[$idx]);
*
* @param long The index to be checked.
* @return bool True if the element at the given index exists.
*/
PHP_METHOD(MapField, offsetExists) {
MapField *intern = (MapField*)Z_OBJ_P(getThis());
zval *key;
upb_msgval upb_key;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS ||
!Convert_PhpToUpb(key, &upb_key, intern->key_type, intern->desc, NULL)) {
return;
}
RETURN_BOOL(upb_map_get(intern->map, upb_key, NULL));
}
/**
* MapField::offsetGet()
*
* Implements the ArrayAccess interface. Invoked when PHP code calls:
*
* $x = $map[$idx];
*
* @param long The index of the element to be fetched.
* @return object The stored element at given index.
* @exception Invalid type for index.
* @exception Non-existing index.
*/
PHP_METHOD(MapField, offsetGet) {
MapField *intern = (MapField*)Z_OBJ_P(getThis());
zval *key;
zval ret;
upb_msgval upb_key, upb_val;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS ||
!Convert_PhpToUpb(key, &upb_key, intern->key_type, intern->desc, NULL)) {
return;
}
if (!upb_map_get(intern->map, upb_key, &upb_val)) {
zend_error(E_USER_ERROR, "Given key doesn't exist.");
return;
}
Convert_UpbToPhp(upb_val, &ret, intern->val_type, intern->desc, &intern->arena);
RETURN_ZVAL(&ret, 0, 1);
}
/**
* MapField::offsetSet()
*
* Implements the ArrayAccess interface. Invoked when PHP code calls:
*
* $map[$idx] = $x;
*
* @param long The index of the element to be assigned.
* @param object The element to be assigned.
* @exception Invalid type for index.
* @exception Non-existing index.
* @exception Incorrect type of the element.
*/
PHP_METHOD(MapField, offsetSet) {
MapField *intern = (MapField*)Z_OBJ_P(getThis());
upb_arena *arena = Arena_Get(&intern->arena);
zval *key, *val;
upb_msgval upb_key, upb_val;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &key, &val) != SUCCESS ||
!Convert_PhpToUpb(key, &upb_key, intern->key_type, NULL, NULL) ||
!Convert_PhpToUpb(val, &upb_val, intern->val_type, intern->desc, arena)) {
return;
}
upb_map_set(intern->map, upb_key, upb_val, arena);
}
/**
* MapField::offsetUnset()
*
* Implements the ArrayAccess interface. Invoked when PHP code calls:
*
* unset($map[$idx]);
*
* @param long The index of the element to be removed.
* @exception Invalid type for index.
* @exception The element to be removed is not at the end of the MapField.
*/
PHP_METHOD(MapField, offsetUnset) {
MapField *intern = (MapField*)Z_OBJ_P(getThis());
zval *key;
upb_msgval upb_key;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS ||
!Convert_PhpToUpb(key, &upb_key, intern->key_type, NULL, NULL)) {
return;
}
upb_map_delete(intern->map, upb_key);
}
/**
* MapField::count()
*
* Implements the Countable interface. Invoked when PHP code calls:
*
* $len = count($map);
* Return the number of stored elements.
* This will also be called for: count($map)
* @return long The number of stored elements.
*/
PHP_METHOD(MapField, count) {
MapField *intern = (MapField*)Z_OBJ_P(getThis());
if (zend_parse_parameters_none() == FAILURE) {
return;
}
RETURN_LONG(upb_map_size(intern->map));
}
/**
* MapField::getIterator()
*
* Implements the IteratorAggregate interface. Invoked when PHP code calls:
*
* foreach ($arr) {}
*
* @return object Beginning iterator.
*/
PHP_METHOD(MapField, getIterator) {
zval ret;
MapFieldIter_make(&ret, getThis());
RETURN_ZVAL(&ret, 0, 1);
}
ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1)
ZEND_ARG_INFO(0, index)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2)
ZEND_ARG_INFO(0, index)
ZEND_ARG_INFO(0, newval)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_void, 0)
ZEND_END_ARG_INFO()
static zend_function_entry MapField_methods[] = {
PHP_ME(MapField, __construct, NULL, ZEND_ACC_PUBLIC)
PHP_ME(MapField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC)
PHP_ME(MapField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC)
PHP_ME(MapField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC)
PHP_ME(MapField, offsetUnset, arginfo_offsetGet, ZEND_ACC_PUBLIC)
PHP_ME(MapField, count, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(MapField, getIterator, arginfo_void, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
// -----------------------------------------------------------------------------
// MapFieldIter
// -----------------------------------------------------------------------------
typedef struct {
zend_object std;
zval map_field;
size_t position;
} MapFieldIter;
zend_class_entry *MapFieldIter_class_entry;
static zend_object_handlers MapFieldIter_object_handlers;
/**
* MapFieldIter_create()
*
* PHP class entry function to allocate and initialize a new MapFieldIter
* object.
*/
zend_object* MapFieldIter_create(zend_class_entry *class_type) {
MapFieldIter *intern = emalloc(sizeof(MapFieldIter));
zend_object_std_init(&intern->std, class_type);
intern->std.handlers = &MapFieldIter_object_handlers;
ZVAL_NULL(&intern->map_field);
intern->position = 0;
// Skip object_properties_init(), we don't allow derived classes.
return &intern->std;
}
/**
* MapFieldIter_dtor()
*
* Object handler to destroy a MapFieldIter. This releases all resources
* associated with the message. Note that it is possible to access a destroyed
* object from PHP in rare cases.
*/
static void map_field_iter_dtor(zend_object* obj) {
MapFieldIter* intern = (MapFieldIter*)obj;
zval_ptr_dtor(&intern->map_field);
zend_object_std_dtor(&intern->std);
}
/**
* MapFieldIter_make()
*
* Function to create a MapFieldIter directly from C.
*/
static void MapFieldIter_make(zval *val, zval *map_field) {
MapFieldIter *iter;
ZVAL_OBJ(val,
MapFieldIter_class_entry->create_object(MapFieldIter_class_entry));
iter = (MapFieldIter*)Z_OBJ_P(val);
ZVAL_COPY(&iter->map_field, map_field);
}
// -----------------------------------------------------------------------------
// PHP MapFieldIter Methods
// -----------------------------------------------------------------------------
/*
* When a user writes:
*
* foreach($arr as $key => $val) {}
*
* PHP translates this into:
*
* $iter = $arr->getIterator();
* for ($iter->rewind(); $iter->valid(); $iter->next()) {
* $key = $iter->key();
* $val = $iter->current();
* }
*/
/**
* MapFieldIter::rewind()
*
* Implements the Iterator interface. Sets the iterator to the first element.
*/
PHP_METHOD(MapFieldIter, rewind) {
MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis());
MapField *map_field = (MapField*)Z_OBJ_P(&intern->map_field);
intern->position = UPB_MAP_BEGIN;
upb_mapiter_next(map_field->map, &intern->position);
}
/**
* MapFieldIter::current()
*
* Implements the Iterator interface. Returns the current value.
*/
PHP_METHOD(MapFieldIter, current) {
MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis());
MapField *field = (MapField*)Z_OBJ_P(&intern->map_field);
upb_msgval upb_val = upb_mapiter_value(field->map, intern->position);
zval ret;
Convert_UpbToPhp(upb_val, &ret, field->val_type, field->desc, &field->arena);
RETURN_ZVAL(&ret, 0, 1);
}
/**
* MapFieldIter::key()
*
* Implements the Iterator interface. Returns the current key.
*/
PHP_METHOD(MapFieldIter, key) {
MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis());
MapField *field = (MapField*)Z_OBJ_P(&intern->map_field);
upb_msgval upb_key = upb_mapiter_key(field->map, intern->position);
zval ret;
Convert_UpbToPhp(upb_key, &ret, field->key_type, NULL, NULL);
RETURN_ZVAL(&ret, 0, 1);
}
/**
* MapFieldIter::next()
*
* Implements the Iterator interface. Advances to the next element.
*/
PHP_METHOD(MapFieldIter, next) {
MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis());
MapField *field = (MapField*)Z_OBJ_P(&intern->map_field);
upb_mapiter_next(field->map, &intern->position);
}
/**
* MapFieldIter::valid()
*
* Implements the Iterator interface. Returns true if this is a valid element.
*/
PHP_METHOD(MapFieldIter, valid) {
MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis());
MapField *field = (MapField*)Z_OBJ_P(&intern->map_field);
bool done = upb_mapiter_done(field->map, intern->position);
RETURN_BOOL(!done);
}
static zend_function_entry map_field_iter_methods[] = {
PHP_ME(MapFieldIter, rewind, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(MapFieldIter, current, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(MapFieldIter, key, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(MapFieldIter, next, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(MapFieldIter, valid, arginfo_void, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
// -----------------------------------------------------------------------------
// Module init.
// -----------------------------------------------------------------------------
/**
* Map_ModuleInit()
*
* Called when the C extension is loaded to register all types.
*/
void Map_ModuleInit() {
zend_class_entry tmp_ce;
zend_object_handlers *h;
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\MapField",
MapField_methods);
MapField_class_entry = zend_register_internal_class(&tmp_ce);
zend_class_implements(MapField_class_entry, 3, spl_ce_ArrayAccess,
zend_ce_aggregate, spl_ce_Countable);
MapField_class_entry->ce_flags |= ZEND_ACC_FINAL;
MapField_class_entry->create_object = MapField_create;
h = &MapField_object_handlers;
memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
h->dtor_obj = MapField_destructor;
h->get_properties = map_get_properties;
h->get_property_ptr_ptr = Map_GetPropertyPtrPtr;
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\MapFieldIter",
map_field_iter_methods);
MapFieldIter_class_entry = zend_register_internal_class(&tmp_ce);
zend_class_implements(MapFieldIter_class_entry, 1, zend_ce_iterator);
MapFieldIter_class_entry->ce_flags |= ZEND_ACC_FINAL;
MapFieldIter_class_entry->ce_flags |= ZEND_ACC_FINAL;
MapFieldIter_class_entry->create_object = MapFieldIter_create;
h = &MapFieldIter_object_handlers;
memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
h->dtor_obj = map_field_iter_dtor;
}

@ -1,841 +0,0 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2014 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.
#include "message.h"
#include <inttypes.h>
#include <php.h>
#include <stdlib.h>
// This is not self-contained: it must be after other Zend includes.
#include <Zend/zend_exceptions.h>
#include "arena.h"
#include "array.h"
#include "convert.h"
#include "def.h"
#include "map.h"
#include "php-upb.h"
#include "protobuf.h"
// -----------------------------------------------------------------------------
// Message
// -----------------------------------------------------------------------------
typedef struct {
zend_object std;
zval arena;
const Descriptor* desc;
upb_msg *msg;
} Message;
zend_class_entry *message_ce;
static zend_object_handlers message_object_handlers;
// PHP Object Handlers /////////////////////////////////////////////////////////
/**
* Message_create()
*
* PHP class entry function to allocate and initialize a new Message object.
*/
static zend_object* Message_create(zend_class_entry *class_type) {
Message *intern = emalloc(sizeof(Message));
// XXX(haberman): verify whether we actually want to take this route.
class_type->default_properties_count = 0;
zend_object_std_init(&intern->std, class_type);
intern->std.handlers = &message_object_handlers;
Arena_Init(&intern->arena);
return &intern->std;
}
/**
* Message_dtor()
*
* Object handler to destroy a Message. This releases all resources associated
* with the message. Note that it is possible to access a destroyed object from
* PHP in rare cases.
*/
static void Message_dtor(zend_object* obj) {
Message* intern = (Message*)obj;
ObjCache_Delete(intern->msg);
zval_dtor(&intern->arena);
zend_object_std_dtor(&intern->std);
}
/**
* get_field()
*
* Helper function to look up a field given a member name (as a string).
*/
static const upb_fielddef *get_field(Message *msg, zval *member) {
const upb_msgdef *m = msg->desc->msgdef;
const upb_fielddef *f =
upb_msgdef_ntof(m, Z_STRVAL_P(member), Z_STRLEN_P(member));
if (!f) {
zend_throw_exception_ex(NULL, 0, "No such property %s.",
ZSTR_VAL(msg->desc->class_entry->name));
}
return f;
}
/**
* Message_read_property()
*
* Object handler for reading a property in PHP. Called when PHP code does:
*
* $x = $message->foobar;
*
* Note that all properties of generated messages are private, so this should
* only be possible to invoke from generated code, which has accessors like:
*
* public function getOptionalInt32()
* {
* return $this->optional_int32;
* }
*
* We lookup the field and return the scalar, RepeatedField, or MapField for
* this field.
*/
static zval *Message_read_property(zval *obj, zval *member, int type,
void **cache_slot, zval *rv) {
Message* intern = (Message*)Z_OBJ_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);
}
return rv;
}
/**
* Message_write_property()
*
* Object handler for writing a property in PHP. Called when PHP code does:
*
* $message->foobar = $x;
*
* Note that all properties of generated messages are private, so this should
* only be possible to invoke from generated code, which has accessors like:
*
* public function setOptionalInt32($var)
* {
* GPBUtil::checkInt32($var);
* $this->optional_int32 = $var;
*
* return $this;
* }
*
* The C extension version of checkInt32() doesn't actually check anything, so
* we perform all checking and conversion in this function.
*/
static void Message_write_property(zval *obj, zval *member, zval *val,
void **cache_slot) {
Message* intern = (Message*)Z_OBJ_P(obj);
const upb_fielddef *f = get_field(intern, member);
upb_arena *arena = Arena_Get(&intern->arena);
upb_msgval msgval;
if (!f) return;
if (upb_fielddef_ismap(f)) {
msgval.map_val = MapField_GetUpbMap(val, f, arena);
if (!msgval.map_val) return;
} else if (upb_fielddef_isseq(f)) {
msgval.array_val = RepeatedField_GetUpbArray(val, f, arena);
if (!msgval.array_val) return;
} 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;
}
upb_msg_set(intern->msg, f, msgval, arena);
}
/**
* Message_get_property_ptr_ptr()
*
* Object handler for the get_property_ptr_ptr event in PHP. This returns a
* reference to our internal properties. We don't support this, so we return
* NULL.
*/
static zval *Message_get_property_ptr_ptr(zval *object, zval *member, int type,
void **cache_slot) {
return NULL; // We do not have a properties table.
}
/**
* Message_get_properties()
*
* Object handler for the get_properties event in PHP. This returns a HashTable
* of our internal properties. We don't support this, so we return NULL.
*/
static HashTable* Message_get_properties(zval* object TSRMLS_DC) {
return NULL; // We don't offer direct references to our properties.
}
// C Functions from message.h. /////////////////////////////////////////////////
// These are documented in the header file.
void Message_GetPhpWrapper(zval *val, const Descriptor *desc, upb_msg *msg,
zval *arena) {
if (!msg) {
ZVAL_NULL(val);
return;
}
if (!ObjCache_Get(msg, val)) {
Message *intern = emalloc(sizeof(Message));
// XXX(haberman): verify whether we actually want to take this route.
desc->class_entry->default_properties_count = 0;
zend_object_std_init(&intern->std, desc->class_entry);
intern->std.handlers = &message_object_handlers;
ZVAL_COPY(&intern->arena, arena);
intern->desc = desc;
intern->msg = msg;
ZVAL_OBJ(val, &intern->std);
ObjCache_Add(intern->msg, &intern->std);
}
}
bool Message_GetUpbMessage(zval *val, const Descriptor *desc, upb_arena *arena,
upb_msg **msg) {
PBPHP_ASSERT(desc);
if (Z_ISREF_P(val)) {
ZVAL_DEREF(val);
}
if (Z_TYPE_P(val) == IS_NULL) {
*msg = NULL;
return true;
}
if (Z_TYPE_P(val) == IS_OBJECT &&
instanceof_function(Z_OBJCE_P(val), desc->class_entry)) {
Message *intern = (Message*)Z_OBJ_P(val);
upb_arena_fuse(arena, Arena_Get(&intern->arena));
*msg = intern->msg;
return true;
} else {
zend_throw_exception_ex(NULL, 0, "Given value is not an instance of %s.",
ZSTR_VAL(desc->class_entry->name));
return false;
}
}
// Message PHP methods /////////////////////////////////////////////////////////
/**
* Message_InitFromPhp()
*
* Helper method to handle the initialization of a message from a PHP value, eg.
*
* $m = new TestMessage([
* 'optional_int32' => -42,
* 'optional_bool' => true,
* 'optional_string' => 'a',
* 'optional_enum' => TestEnum::ONE,
* 'optional_message' => new Sub([
* 'a' => 33
* ]),
* 'repeated_int32' => [-42, -52],
* 'repeated_enum' => [TestEnum::ZERO, TestEnum::ONE],
* 'repeated_message' => [new Sub(['a' => 34]),
* new Sub(['a' => 35])],
* 'map_int32_int32' => [-62 => -62],
* 'map_int32_enum' => [1 => TestEnum::ONE],
* 'map_int32_message' => [1 => new Sub(['a' => 36])],
* ]);
*
* The initializer must be an array.
*/
bool Message_InitFromPhp(upb_msg *msg, const upb_msgdef *m, zval *init,
upb_arena *arena) {
HashTable* table = HASH_OF(init);
HashPosition pos;
if (Z_ISREF_P(init)) {
ZVAL_DEREF(init);
}
if (Z_TYPE_P(init) != IS_ARRAY) {
zend_throw_exception_ex(NULL, 0,
"Initializer for a message %s must be an array.",
upb_msgdef_fullname(m));
return false;
}
zend_hash_internal_pointer_reset_ex(table, &pos);
while (true) { // Iterate over key/value pairs.
zval key;
zval *val;
const upb_fielddef *f;
upb_msgval msgval;
zend_hash_get_current_key_zval_ex(table, &key, &pos);
val = zend_hash_get_current_data_ex(table, &pos);
if (!val) return true; // Finished iteration.
if (Z_ISREF_P(val)) {
ZVAL_DEREF(val);
}
f = upb_msgdef_ntof(m, Z_STRVAL_P(&key), Z_STRLEN_P(&key));
if (!f) {
zend_throw_exception_ex(NULL, 0,
"No such field %s", Z_STRVAL_P(&key));
return false;
}
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 {
const Descriptor *desc = Descriptor_GetFromFieldDef(f);
upb_fieldtype_t type = upb_fielddef_type(f);
if (!Convert_PhpToUpbAutoWrap(val, &msgval, type, desc, arena)) {
return false;
}
}
upb_msg_set(msg, f, msgval, arena);
zend_hash_move_forward_ex(table, &pos);
zval_dtor(&key);
}
}
/**
* Message::__construct()
*
* Constructor for Message.
* @param array Map of initial values ['k' = val]
*/
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);
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a!", &init_arr) == FAILURE) {
return;
}
if (init_arr) {
Message_InitFromPhp(intern->msg, desc->msgdef, init_arr, arena);
}
}
/**
* Message::discardUnknownFields()
*
* Discards any unknown fields for this message or any submessages.
*/
PHP_METHOD(Message, discardUnknownFields) {
Message* intern = (Message*)Z_OBJ_P(getThis());
upb_msg_discardunknown(intern->msg, intern->desc->msgdef, 64);
}
/**
* Message::clear()
*
* Clears all fields of this message.
*/
PHP_METHOD(Message, clear) {
Message* intern = (Message*)Z_OBJ_P(getThis());
upb_msg_clear(intern->msg, intern->desc->msgdef);
}
/**
* Message::mergeFrom()
*
* Merges from the given message, which must be of the same class as us.
* @param object Message to merge from.
*/
PHP_METHOD(Message, mergeFrom) {
Message* intern = (Message*)Z_OBJ_P(getThis());
Message* from;
upb_arena *arena = Arena_Get(&intern->arena);
const upb_msglayout *l = upb_msgdef_layout(intern->desc->msgdef);
zval* value;
char *pb;
size_t size;
bool ok;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &value,
intern->desc->class_entry) == FAILURE) {
return;
}
from = (Message*)Z_OBJ_P(value);
// Should be guaranteed since we passed the class type to
// zend_parse_parameters().
PBPHP_ASSERT(from->desc == intern->desc);
// TODO(haberman): use a temp arena for this once we can make upb_decode()
// copy strings.
pb = upb_encode(from->msg, l, arena, &size);
if (!pb) {
zend_throw_exception_ex(NULL, 0, "Max nesting exceeded");
return;
}
ok = upb_decode(pb, size, intern->msg, l, arena);
PBPHP_ASSERT(ok);
}
/**
* Message::mergeFromString()
*
* Merges from the given string.
* @param string Binary protobuf data to merge.
*/
PHP_METHOD(Message, mergeFromString) {
Message* intern = (Message*)Z_OBJ_P(getThis());
char *data = NULL;
char *data_copy = NULL;
zend_long data_len;
const upb_msglayout *l = upb_msgdef_layout(intern->desc->msgdef);
upb_arena *arena = Arena_Get(&intern->arena);
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &data, &data_len) ==
FAILURE) {
return;
}
// TODO(haberman): avoid this copy when we can make the decoder copy.
data_copy = upb_arena_malloc(arena, data_len);
memcpy(data_copy, data, data_len);
if (!upb_decode(data_copy, data_len, intern->msg, l, arena)) {
zend_throw_exception_ex(NULL, 0, "Error occurred during parsing");
return;
}
}
/**
* Message::serializeToString()
*
* Serializes this message instance to protobuf data.
* @return string Serialized protobuf data.
*/
PHP_METHOD(Message, serializeToString) {
Message* intern = (Message*)Z_OBJ_P(getThis());
const upb_msglayout *l = upb_msgdef_layout(intern->desc->msgdef);
upb_arena *tmp_arena = upb_arena_new();
char *data;
size_t size;
data = upb_encode(intern->msg, l, tmp_arena, &size);
if (!data) {
zend_throw_exception_ex(NULL, 0, "Error occurred during serialization");
upb_arena_free(tmp_arena);
return;
}
RETVAL_STRINGL(data, size);
upb_arena_free(tmp_arena);
}
/**
* Message::mergeFromJsonString()
*
* Merges the JSON data parsed from the given string.
* @param string Serialized JSON data.
*/
PHP_METHOD(Message, mergeFromJsonString) {
Message* intern = (Message*)Z_OBJ_P(getThis());
char *data = NULL;
char *data_copy = NULL;
zend_long data_len;
upb_arena *arena = Arena_Get(&intern->arena);
upb_status status;
zend_bool ignore_json_unknown = false;
int options = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &data, &data_len,
&ignore_json_unknown) == FAILURE) {
return;
}
// TODO(haberman): avoid this copy when we can make the decoder copy.
data_copy = upb_arena_malloc(arena, data_len + 1);
memcpy(data_copy, data, data_len);
data_copy[data_len] = '\0';
if (ignore_json_unknown) {
options |= UPB_JSONDEC_IGNOREUNKNOWN;
}
upb_status_clear(&status);
if (!upb_json_decode(data_copy, data_len, intern->msg, intern->desc->msgdef,
DescriptorPool_GetSymbolTable(), options, arena,
&status)) {
zend_throw_exception_ex(NULL, 0, "Error occurred during parsing: %s",
upb_status_errmsg(&status));
return;
}
}
/**
* Message::serializeToJsonString()
*
* Serializes this object to JSON.
* @return string Serialized JSON data.
*/
PHP_METHOD(Message, serializeToJsonString) {
Message* intern = (Message*)Z_OBJ_P(getThis());
size_t size;
int options = 0;
char buf[1024];
zend_bool preserve_proto_fieldnames = false;
upb_status status;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b",
&preserve_proto_fieldnames) == FAILURE) {
return;
}
if (preserve_proto_fieldnames) {
options |= UPB_JSONENC_PROTONAMES;
}
upb_status_clear(&status);
size = upb_json_encode(intern->msg, intern->desc->msgdef,
DescriptorPool_GetSymbolTable(), options, buf,
sizeof(buf), &status);
if (!upb_ok(&status)) {
zend_throw_exception_ex(NULL, 0,
"Error occurred during JSON serialization: %s",
upb_status_errmsg(&status));
return;
}
if (size >= sizeof(buf)) {
char *buf2 = malloc(size + 1);
upb_json_encode(intern->msg, intern->desc->msgdef,
DescriptorPool_GetSymbolTable(), options, buf2, size + 1,
&status);
RETVAL_STRINGL(buf2, size);
free(buf2);
} else {
RETVAL_STRINGL(buf, size);
}
}
/**
* Message::readWrapperValue()
*
* Returns an unboxed value for the given field. This is called from generated
* methods for wrapper fields, eg.
*
* public function getDoubleValueUnwrapped()
* {
* return $this->readWrapperValue("double_value");
* }
*
* @return Unwrapped field value or null.
*/
PHP_METHOD(Message, readWrapperValue) {
Message* intern = (Message*)Z_OBJ_P(getThis());
char* member;
const upb_fielddef *f;
zend_long size;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &member, &size) == FAILURE) {
return;
}
f = upb_msgdef_ntof(intern->desc->msgdef, member, size);
if (!f || !upb_msgdef_iswrapper(upb_fielddef_msgsubdef(f))) {
zend_throw_exception_ex(NULL, 0, "Message %s has no field %s",
upb_msgdef_fullname(intern->desc->msgdef), member);
return;
}
if (upb_msg_has(intern->msg, f)) {
const upb_msg *wrapper = upb_msg_get(intern->msg, f).msg_val;
const upb_msgdef *m = upb_fielddef_msgsubdef(f);
const upb_fielddef *val_f = upb_msgdef_itof(m, 1);
const upb_fieldtype_t val_type = upb_fielddef_type(val_f);
upb_msgval msgval = upb_msg_get(wrapper, val_f);
zval ret;
Convert_UpbToPhp(msgval, &ret, val_type, NULL, &intern->arena);
RETURN_ZVAL(&ret, 1, 0);
} else {
RETURN_NULL();
}
}
/**
* Message::writeWrapperValue()
*
* Sets the given wrapper field to the given unboxed value. This is called from
* generated methods for wrapper fields, eg.
*
*
* public function setDoubleValueUnwrapped($var)
* {
* $this->writeWrapperValue("double_value", $var);
* return $this;
* }
*
* @param Unwrapped field value or null.
*/
PHP_METHOD(Message, writeWrapperValue) {
Message* intern = (Message*)Z_OBJ_P(getThis());
upb_arena *arena = Arena_Get(&intern->arena);
char* member;
const upb_fielddef *f;
upb_msgval msgval;
zend_long size;
zval* val;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz", &member, &size, &val) ==
FAILURE) {
return;
}
f = upb_msgdef_ntof(intern->desc->msgdef, member, size);
if (!f || !upb_msgdef_iswrapper(upb_fielddef_msgsubdef(f))) {
zend_throw_exception_ex(NULL, 0, "Message %s has no field %s",
upb_msgdef_fullname(intern->desc->msgdef), member);
return;
}
if (Z_ISREF_P(val)) {
ZVAL_DEREF(val);
}
if (Z_TYPE_P(val) == IS_NULL) {
upb_msg_clearfield(intern->msg, f);
} else {
const upb_msgdef *m = upb_fielddef_msgsubdef(f);
const upb_fielddef *val_f = upb_msgdef_itof(m, 1);
upb_fieldtype_t val_type = upb_fielddef_type(val_f);
upb_msg *wrapper;
if (!Convert_PhpToUpb(val, &msgval, val_type, NULL, arena)) {
return; // Error is already set.
}
wrapper = upb_msg_mutable(intern->msg, f, arena).msg;
upb_msg_set(wrapper, val_f, msgval, arena);
}
}
/**
* Message::whichOneof()
*
* Given a oneof name, returns the name of the field that is set for this oneof,
* or otherwise the empty string.
*
* @return string The field name in this oneof that is currently set.
*/
PHP_METHOD(Message, whichOneof) {
Message* intern = (Message*)Z_OBJ_P(getThis());
const upb_oneofdef* oneof;
const upb_fielddef* field;
char* name;
zend_long len;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &len) == FAILURE) {
return;
}
oneof = upb_msgdef_ntoo(intern->desc->msgdef, name, len);
if (!oneof) {
zend_throw_exception_ex(NULL, 0, "Message %s has no oneof %s",
upb_msgdef_fullname(intern->desc->msgdef), name);
return;
}
field = upb_msg_whichoneof(intern->msg, oneof);
RETURN_STRING(field ? upb_fielddef_name(field) : "");
}
/**
* Message::readOneof()
*
* Returns the contents of the given oneof field, given a field number. Called
* from generated code methods such as:
*
* public function getDoubleValueOneof()
* {
* return $this->readOneof(10);
* }
*
* @return object The oneof's field value.
*/
PHP_METHOD(Message, readOneof) {
Message* intern = (Message*)Z_OBJ_P(getThis());
zend_long field_num;
const upb_fielddef* f;
zval ret;
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);
}
{
upb_msgval msgval = upb_msg_get(intern->msg, f);
const Descriptor *subdesc = Descriptor_GetFromFieldDef(f);
Convert_UpbToPhp(msgval, &ret, upb_fielddef_type(f), subdesc,
&intern->arena);
}
RETURN_ZVAL(&ret, 1, 0);
}
/**
* Message::writeOneof()
*
* Sets the contents of the given oneof field, given a field number. Called
* from generated code methods such as:
*
* public function setDoubleValueOneof($var)
* {
* GPBUtil::checkMessage($var, \Google\Protobuf\DoubleValue::class);
* $this->writeOneof(10, $var);
*
* return $this;
* }
*
* The C extension version of GPBUtil::check*() does nothing, so we perform
* all type checking and conversion here.
*
* @param integer The field number we are setting.
* @param object The field value we want to set.
*/
PHP_METHOD(Message, writeOneof) {
Message* intern = (Message*)Z_OBJ_P(getThis());
zend_long field_num;
const upb_fielddef* f;
upb_arena *arena = Arena_Get(&intern->arena);
upb_msgval msgval;
zval* val;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz", &field_num, &val) ==
FAILURE) {
return;
}
f = upb_msgdef_itof(intern->desc->msgdef, field_num);
if (!Convert_PhpToUpb(val, &msgval, upb_fielddef_type(f),
Descriptor_GetFromFieldDef(f), arena)) {
return;
}
upb_msg_set(intern->msg, f, msgval, arena);
}
static zend_function_entry Message_methods[] = {
PHP_ME(Message, clear, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Message, discardUnknownFields, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Message, serializeToString, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Message, mergeFromString, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Message, serializeToJsonString, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Message, mergeFromJsonString, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Message, mergeFrom, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Message, readWrapperValue, NULL, ZEND_ACC_PROTECTED)
PHP_ME(Message, writeWrapperValue, NULL, ZEND_ACC_PROTECTED)
PHP_ME(Message, readOneof, NULL, ZEND_ACC_PROTECTED)
PHP_ME(Message, writeOneof, NULL, ZEND_ACC_PROTECTED)
PHP_ME(Message, whichOneof, NULL, ZEND_ACC_PROTECTED)
PHP_ME(Message, __construct, NULL, ZEND_ACC_PROTECTED)
ZEND_FE_END
};
/**
* Message_ModuleInit()
*
* Called when the C extension is loaded to register all types.
*/
void Message_ModuleInit() {
zend_class_entry tmp_ce;
zend_object_handlers *h = &message_object_handlers;
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\Message",
Message_methods);
message_ce = zend_register_internal_class(&tmp_ce);
message_ce->create_object = Message_create;
memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
h->dtor_obj = Message_dtor;
h->read_property = Message_read_property;
h->write_property = Message_write_property;
h->get_properties = Message_get_properties;
h->get_property_ptr_ptr = Message_get_property_ptr_ptr;
}

@ -1,349 +0,0 @@
// 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.
#include "protobuf.h"
#include <php.h>
#include <Zend/zend_interfaces.h>
#include "arena.h"
#include "array.h"
#include "bundled_php.h"
#include "convert.h"
#include "def.h"
#include "map.h"
#include "message.h"
#include "names.h"
// -----------------------------------------------------------------------------
// Module "globals"
// -----------------------------------------------------------------------------
// Despite the name, module "globals" are really thread-locals:
// * PROTOBUF_G(var) accesses the thread-local variable for 'var'. Either:
// * PROTOBUF_G(var) -> protobuf_globals.var (Non-ZTS / non-thread-safe)
// * PROTOBUF_G(var) -> <Zend magic> (ZTS / thread-safe builds)
#define PROTOBUF_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(protobuf, v)
ZEND_BEGIN_MODULE_GLOBALS(protobuf)
// Set by the user to make the descriptor pool persist between requests.
zend_bool keep_descriptor_pool_after_request;
// Currently we make the generated pool a "global", which means that if a user
// does explicitly create threads within their request, the other threads will
// get different results from DescriptorPool::getGeneratedPool(). We require
// that all descriptors are loaded from the main thread.
zval generated_pool;
// A upb_symtab that we are saving for the next request so that we don't have
// to rebuild it from scratch. When keep_descriptor_pool_after_request==true,
// we steal the upb_symtab from the global DescriptorPool object just before
// destroying it.
upb_symtab *saved_symtab;
// Object cache (see interface in protobuf.h).
HashTable object_cache;
// Name cache (see interface in protobuf.h).
HashTable name_msg_cache;
HashTable name_enum_cache;
ZEND_END_MODULE_GLOBALS(protobuf)
ZEND_DECLARE_MODULE_GLOBALS(protobuf)
const zval *get_generated_pool() {
return &PROTOBUF_G(generated_pool);
}
// This is a PHP extension (not a Zend extension). What follows is a summary of
// a PHP extension's lifetime and when various handlers are called.
//
// * PHP_GINIT_FUNCTION(protobuf) / PHP_GSHUTDOWN_FUNCTION(protobuf)
// are the constructor/destructor for the globals. The sequence over the
// course of a process lifetime is:
//
// # Process startup
// GINIT(<Main Thread Globals>)
// MINIT
//
// foreach request:
// RINIT
// # Request is processed here.
// RSHUTDOWN
//
// foreach thread:
// GINIT(<This Thread Globals>)
// # Code for the thread runs here.
// GSHUTDOWN(<This Thread Globals>)
//
// # Process Shutdown
// #
// # These should be running per the docs, but I have not been able to
// # actually get the process-wide shutdown functions to run.
// #
// # MSHUTDOWN
// # GSHUTDOWN(<Main Thread Globals>)
//
// * Threads can be created either explicitly by the user, inside a request,
// or implicitly by the runtime, to process multiple requests concurrently.
// If the latter is being used, then the "foreach thread" block above
// actually looks like this:
//
// foreach thread:
// GINIT(<This Thread Globals>)
// # A non-main thread will only receive requests when using a threaded
// # MPM with Apache
// foreach request:
// RINIT
// # Request is processed here.
// RSHUTDOWN
// GSHUTDOWN(<This Thread Globals>)
//
// That said, it appears that few people use threads with PHP:
// * The pthread package documented at
// https://www.php.net/manual/en/class.thread.php nas not been released
// since 2016, and the current release fails to compile against any PHP
// newer than 7.0.33.
// * The GitHub master branch supports 7.2+, but this has not been released
// to PECL.
// * Its owner has disavowed it as "broken by design" and "in an untenable
// position for the future": https://github.com/krakjoe/pthreads/issues/929
// * The only way to use PHP with requests in different threads is to use the
// Apache 2 mod_php with the "worker" MPM. But this is explicitly
// discouraged by the documentation: https://serverfault.com/a/231660
static PHP_GSHUTDOWN_FUNCTION(protobuf) {
if (protobuf_globals->saved_symtab) {
upb_symtab_free(protobuf_globals->saved_symtab);
}
}
static PHP_GINIT_FUNCTION(protobuf) {
ZVAL_NULL(&protobuf_globals->generated_pool);
protobuf_globals->saved_symtab = NULL;
}
/**
* PHP_RINIT_FUNCTION(protobuf)
*
* This function is run at the beginning of processing each request.
*/
static PHP_RINIT_FUNCTION(protobuf) {
// Create the global generated pool.
// Reuse the symtab (if any) left to us by the last request.
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);
return SUCCESS;
}
/**
* PHP_RSHUTDOWN_FUNCTION(protobuf)
*
* This function is run at the end of processing each request.
*/
static PHP_RSHUTDOWN_FUNCTION(protobuf) {
// Preserve the symtab if requested.
if (PROTOBUF_G(keep_descriptor_pool_after_request)) {
zval *zv = &PROTOBUF_G(generated_pool);
PROTOBUF_G(saved_symtab) = DescriptorPool_Steal(zv);
}
zval_dtor(&PROTOBUF_G(generated_pool));
zend_hash_destroy(&PROTOBUF_G(object_cache));
zend_hash_destroy(&PROTOBUF_G(name_msg_cache));
zend_hash_destroy(&PROTOBUF_G(name_enum_cache));
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.
// -----------------------------------------------------------------------------
void ObjCache_Add(const void *upb_obj, zend_object *php_obj) {
zend_ulong k = (zend_ulong)upb_obj;
zend_hash_index_add_ptr(&PROTOBUF_G(object_cache), k, php_obj);
}
void ObjCache_Delete(const void *upb_obj) {
if (upb_obj) {
zend_ulong k = (zend_ulong)upb_obj;
int ret = zend_hash_index_del(&PROTOBUF_G(object_cache), k);
PBPHP_ASSERT(ret == SUCCESS);
}
}
bool ObjCache_Get(const void *upb_obj, zval *val) {
zend_ulong k = (zend_ulong)upb_obj;
zend_object *obj = zend_hash_index_find_ptr(&PROTOBUF_G(object_cache), k);
if (obj) {
GC_ADDREF(obj);
ZVAL_OBJ(val, obj);
return true;
} else {
ZVAL_NULL(val);
return false;
}
}
// -----------------------------------------------------------------------------
// Name Cache.
// -----------------------------------------------------------------------------
void NameMap_AddMessage(const upb_msgdef *m) {
char *k = GetPhpClassname(upb_msgdef_file(m), upb_msgdef_fullname(m));
zend_hash_str_add_ptr(&PROTOBUF_G(name_msg_cache), k, strlen(k), (void*)m);
free(k);
}
void NameMap_AddEnum(const upb_enumdef *e) {
char *k = GetPhpClassname(upb_enumdef_file(e), upb_enumdef_fullname(e));
zend_hash_str_add_ptr(&PROTOBUF_G(name_enum_cache), k, strlen(k), (void*)e);
free(k);
}
const upb_msgdef *NameMap_GetMessage(zend_class_entry *ce) {
const upb_msgdef *ret =
zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name);
if (!ret && ce->create_object) {
zval tmp;
zval zv;
ZVAL_OBJ(&tmp, ce->create_object(ce));
zend_call_method_with_0_params(&tmp, ce, NULL, "__construct", &zv);
zval_ptr_dtor(&tmp);
zval_ptr_dtor(&zv);
ret = zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name);
}
return ret;
}
const upb_enumdef *NameMap_GetEnum(zend_class_entry *ce) {
const upb_enumdef *ret =
zend_hash_find_ptr(&PROTOBUF_G(name_enum_cache), ce->name);
return ret;
}
// -----------------------------------------------------------------------------
// Module init.
// -----------------------------------------------------------------------------
zend_function_entry protobuf_functions[] = {
PHP_FE(protobuf_internal_loadbundled, arginfo_load_bundled_source)
ZEND_FE_END
};
static const zend_module_dep protobuf_deps[] = {
ZEND_MOD_OPTIONAL("date")
ZEND_MOD_END
};
PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("protobuf.keep_descriptor_pool_after_request", "0",
PHP_INI_SYSTEM, OnUpdateBool,
keep_descriptor_pool_after_request, zend_protobuf_globals,
protobuf_globals)
PHP_INI_END()
static PHP_MINIT_FUNCTION(protobuf) {
REGISTER_INI_ENTRIES();
Arena_ModuleInit();
Array_ModuleInit();
Convert_ModuleInit();
Def_ModuleInit();
Map_ModuleInit();
Message_ModuleInit();
return SUCCESS;
}
static PHP_MSHUTDOWN_FUNCTION(protobuf) {
return SUCCESS;
}
zend_module_entry protobuf_module_entry = {
STANDARD_MODULE_HEADER_EX,
NULL,
protobuf_deps,
"protobuf", // extension name
protobuf_functions, // function list
PHP_MINIT(protobuf), // process startup
PHP_MSHUTDOWN(protobuf), // process shutdown
PHP_RINIT(protobuf), // request shutdown
PHP_RSHUTDOWN(protobuf), // request shutdown
NULL, // extension info
"3.13.0", // extension version
PHP_MODULE_GLOBALS(protobuf), // globals descriptor
PHP_GINIT(protobuf), // globals ctor
PHP_GSHUTDOWN(protobuf), // globals dtor
NULL, // post deactivate
STANDARD_MODULE_PROPERTIES_EX
};
ZEND_GET_MODULE(protobuf)

@ -1,89 +0,0 @@
// 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.
#ifndef PHP_PROTOBUF_H_
#define PHP_PROTOBUF_H_
#include <php.h>
#include <stdbool.h>
#include "php-upb.h"
const zval *get_generated_pool();
#if PHP_VERSION_ID < 70300
#define GC_ADDREF(h) ++GC_REFCOUNT(h)
#define GC_DELREF(h) --GC_REFCOUNT(h)
#endif
// ptr -> PHP object cache. This is a weak map that caches lazily-created
// wrapper objects around upb types:
// * upb_msg* -> Message
// * upb_array* -> RepeatedField
// * upb_map*, -> MapField
// * upb_msgdef* -> Descriptor
// * upb_enumdef* -> EnumDescriptor
// * zend_class_entry* -> Descriptor
//
// Each wrapped object should add itself to the map when it is constructed, and
// remove itself from the map when it is destroyed. This is how we ensure that
// the map only contains live objects. The map is weak so it does not actually
// take references to the cached objects.
void ObjCache_Add(const void *key, zend_object *php_obj);
void ObjCache_Delete(const void *key);
bool ObjCache_Get(const void *key, zval *val);
// PHP class name map. This is necessary because the pb_name->php_class_name
// transformation is non-reversible, so when we need to look up a msgdef or
// enumdef by PHP class, we can't turn the class name into a pb_name.
// * php_class_name -> upb_msgdef*
// * php_class_name -> upb_enumdef*
void NameMap_AddMessage(const upb_msgdef *m);
void NameMap_AddEnum(const upb_enumdef *m);
const upb_msgdef *NameMap_GetMessage(zend_class_entry *ce);
const upb_enumdef *NameMap_GetEnum(zend_class_entry *ce);
// We need our own assert() because PHP takes control of NDEBUG in its headers.
#ifdef PBPHP_ENABLE_ASSERTS
#define PBPHP_ASSERT(x) \
do { \
if (!(x)) { \
fprintf(stderr, "Assertion failure at %s:%d %s", __FILE__, __LINE__, \
#x); \
abort(); \
} \
} while (false)
#else
#define PBPHP_ASSERT(x) \
do { \
} while (false && (x))
#endif
#endif // PHP_PROTOBUF_H_

@ -12,18 +12,9 @@ else
CFLAGS="-g -O0 -Wall" CFLAGS="-g -O0 -Wall"
fi fi
pushd ../ext/google/protobuf pushd ../ext/google/protobuf
phpize --clean phpize --clean
rm -f configure.in configure.ac rm -f configure.in configure.ac
php make-preload.php
phpize && ./configure --with-php-config=$(which php-config) CFLAGS="$CFLAGS" && make phpize && ./configure --with-php-config=$(which php-config) CFLAGS="$CFLAGS" && make
popd popd
if [ $(php -r "echo PHP_VERSION;" | cut -c1) != "5" ]; then
pushd ../ext/google/protobuf2
phpize --clean
rm -f configure.in configure.ac
php make-preload.php
phpize && ./configure --with-php-config=$(which php-config) CFLAGS="$CFLAGS" && make
popd
fi

@ -538,7 +538,7 @@ class ImplementationTest extends TestBase
/** /**
* @expectedException Exception * @expectedException Exception
* @expectedExceptionMessage Expect Foo\TestMessage_Sub. * @expectedExceptionMessage Expect Foo\TestMessage\Sub.
*/ */
public function testArraysForMessagesThrowsException() public function testArraysForMessagesThrowsException()
{ {

@ -8,14 +8,9 @@ cd $(dirname $0)
./compile_extension.sh ./compile_extension.sh
PHP_VERSION=$(php -r "echo PHP_VERSION;") PHP_VERSION=$(php -r "echo PHP_VERSION;")
TEST_NEW_EXTENSION=true
# Each version of PHPUnit supports a fairly narrow range of PHP versions. # Each version of PHPUnit supports a fairly narrow range of PHP versions.
case "$PHP_VERSION" in case "$PHP_VERSION" in
5.*.*)
PHPUNIT=phpunit-5.6.8.phar
TEST_NEW_EXTENSION=false
;;
7.0.*|7.1.*|7.2.*) 7.0.*|7.1.*|7.2.*)
# Oddly older than for 5.6. Not sure the reason. # Oddly older than for 5.6. Not sure the reason.
PHPUNIT=phpunit-5.6.0.phar PHPUNIT=phpunit-5.6.0.phar
@ -24,7 +19,7 @@ case "$PHP_VERSION" in
PHPUNIT=phpunit-8.phar PHPUNIT=phpunit-8.phar
;; ;;
*) *)
echo "ERROR: Unknown PHP version $PHP_VERSION" echo "ERROR: Unsupported PHP version $PHP_VERSION"
exit 1 exit 1
;; ;;
esac esac
@ -39,9 +34,6 @@ do
echo "* $t" echo "* $t"
echo "****************************" echo "****************************"
php -dextension=../ext/google/protobuf/modules/protobuf.so $PHPUNIT --bootstrap autoload.php $t php -dextension=../ext/google/protobuf/modules/protobuf.so $PHPUNIT --bootstrap autoload.php $t
if [ "$TEST_NEW_EXTENSION" = "true" ]; then
php -dextension=../ext/google/protobuf2/modules/protobuf.so $PHPUNIT --bootstrap autoload.php $t
fi
echo "" echo ""
done done
@ -51,9 +43,6 @@ do
echo "* $t persistent" echo "* $t persistent"
echo "****************************" echo "****************************"
php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf/modules/protobuf.so $PHPUNIT --bootstrap autoload.php $t php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf/modules/protobuf.so $PHPUNIT --bootstrap autoload.php $t
if [ "$TEST_NEW_EXTENSION" = "true" ]; then
php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf2/modules/protobuf.so $PHPUNIT --bootstrap autoload.php $t
fi
echo "" echo ""
done done
@ -64,10 +53,6 @@ export ZEND_DONT_UNLOAD_MODULES=1
export USE_ZEND_ALLOC=0 export USE_ZEND_ALLOC=0
valgrind --leak-check=yes php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php valgrind --leak-check=yes php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
valgrind --leak-check=yes php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php valgrind --leak-check=yes php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
if [ "$TEST_NEW_EXTENSION" = "true" ]; then
valgrind --leak-check=yes php -dextension=../ext/google/protobuf2/modules/protobuf.so memory_leak_test.php
valgrind --leak-check=yes php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf2/modules/protobuf.so memory_leak_test.php
fi
# TODO(teboring): Only for debug (phpunit has memory leak which blocks this beging used by # TODO(teboring): Only for debug (phpunit has memory leak which blocks this beging used by
# regresssion test.) # regresssion test.)

@ -744,11 +744,11 @@ void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor,
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
printer->Print( printer->Print(
"GPBUtil::checkMessage($var, \\^class_name^::class);\n", "GPBUtil::checkMessage($var, \\^class_name^::class);\n",
"class_name", LegacyFullClassName(field->message_type(), is_descriptor)); "class_name", FullClassName(field->message_type(), is_descriptor));
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
printer->Print( printer->Print(
"GPBUtil::checkEnum($var, \\^class_name^::class);\n", "GPBUtil::checkEnum($var, \\^class_name^::class);\n",
"class_name", LegacyFullClassName(field->enum_type(), is_descriptor)); "class_name", FullClassName(field->enum_type(), is_descriptor));
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
printer->Print( printer->Print(
"GPBUtil::checkString($var, ^utf8^);\n", "GPBUtil::checkString($var, ^utf8^);\n",
@ -1754,7 +1754,7 @@ void GenerateWrapperFieldSetterDocComment(io::Printer* printer, const FieldDescr
printer->Print("/**\n"); printer->Print("/**\n");
printer->Print( printer->Print(
" * Sets the field by wrapping a primitive type in a ^message_name^ object.\n\n", " * Sets the field by wrapping a primitive type in a ^message_name^ object.\n\n",
"message_name", LegacyFullClassName(field->message_type(), false)); "message_name", FullClassName(field->message_type(), false));
GenerateDocCommentBody(printer, field); GenerateDocCommentBody(printer, field);
printer->Print( printer->Print(
" * Generated from protobuf field <code>^def^</code>\n", " * Generated from protobuf field <code>^def^</code>\n",

Loading…
Cancel
Save