Unverified Commit bcda919c authored by Paul Yang's avatar Paul Yang Committed by GitHub

Fix php well known type conformance tests (#3828)

* Fix php well known type conformance tests

* Properly generate code for test.proto

* Provide GPBMetadata files in c extensions for generated files to import.

* Remove unnecessary test

* Clean up code

* Add declaration for initOnce.

* Refactoring
parent 239dba53
...@@ -256,7 +256,7 @@ if USE_EXTERNAL_PROTOC ...@@ -256,7 +256,7 @@ if USE_EXTERNAL_PROTOC
protoc_middleman: $(conformance_protoc_inputs) $(conformance_proto2_protoc_inputs) $(well_known_type_protoc_inputs) google-protobuf protoc_middleman: $(conformance_protoc_inputs) $(conformance_proto2_protoc_inputs) $(well_known_type_protoc_inputs) google-protobuf
$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --objc_out=. --python_out=. --php_out=. --js_out=import_style=commonjs,binary:. $(conformance_protoc_inputs) $(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --objc_out=. --python_out=. --php_out=. --js_out=import_style=commonjs,binary:. $(conformance_protoc_inputs)
$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --objc_out=. --python_out=. --js_out=import_style=commonjs,binary:. $(conformance_proto2_protoc_inputs) $(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --objc_out=. --python_out=. --js_out=import_style=commonjs,binary:. $(conformance_proto2_protoc_inputs)
$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --python_out=. --php_out=. --js_out=import_style=commonjs,binary:google-protobuf $(well_known_type_protoc_inputs) $(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --python_out=. --js_out=import_style=commonjs,binary:google-protobuf $(well_known_type_protoc_inputs)
## $(PROTOC) -I$(srcdir) -I$(top_srcdir) --java_out=lite:lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs) ## $(PROTOC) -I$(srcdir) -I$(top_srcdir) --java_out=lite:lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs)
touch protoc_middleman touch protoc_middleman
...@@ -268,7 +268,7 @@ else ...@@ -268,7 +268,7 @@ else
protoc_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(conformance_protoc_inputs) $(conformance_proto2_protoc_inputs) $(well_known_type_protoc_inputs) google-protobuf protoc_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(conformance_protoc_inputs) $(conformance_proto2_protoc_inputs) $(well_known_type_protoc_inputs) google-protobuf
oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --objc_out=$$oldpwd --python_out=$$oldpwd --php_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd $(conformance_protoc_inputs) ) oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --objc_out=$$oldpwd --python_out=$$oldpwd --php_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd $(conformance_protoc_inputs) )
oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --objc_out=. --python_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd $(conformance_proto2_protoc_inputs) ) oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --objc_out=. --python_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd $(conformance_proto2_protoc_inputs) )
oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --python_out=$$oldpwd --php_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd/google-protobuf $(well_known_type_protoc_inputs) ) oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --python_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd/google-protobuf $(well_known_type_protoc_inputs) )
## @mkdir -p lite ## @mkdir -p lite
## oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --java_out=lite:$$oldpwd/lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs) ) ## oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --java_out=lite:$$oldpwd/lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs) )
touch protoc_middleman touch protoc_middleman
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
define("GOOGLE_INTERNAL_NAMESPACE", "Google\\Protobuf\\Internal\\"); define("GOOGLE_INTERNAL_NAMESPACE", "Google\\Protobuf\\Internal\\");
define("GOOGLE_NAMESPACE", "Google\\Protobuf\\"); define("GOOGLE_NAMESPACE", "Google\\Protobuf\\");
define("GOOGLE_GPBMETADATA_NAMESPACE", "GPBMetadata\\Google\\Protobuf\\Internal\\"); define("GOOGLE_GPBMETADATA_NAMESPACE", "GPBMetadata\\Google\\Protobuf\\");
function protobuf_autoloader_impl($class, $prefix) { function protobuf_autoloader_impl($class, $prefix) {
$length = strlen($prefix); $length = strlen($prefix);
......
...@@ -3,24 +3,6 @@ ...@@ -3,24 +3,6 @@
require_once("Conformance/WireFormat.php"); require_once("Conformance/WireFormat.php");
require_once("Conformance/ConformanceResponse.php"); require_once("Conformance/ConformanceResponse.php");
require_once("Conformance/ConformanceRequest.php"); require_once("Conformance/ConformanceRequest.php");
require_once("Google/Protobuf/Any.php");
require_once("Google/Protobuf/Duration.php");
require_once("Google/Protobuf/FieldMask.php");
require_once("Google/Protobuf/Struct.php");
require_once("Google/Protobuf/Value.php");
require_once("Google/Protobuf/ListValue.php");
require_once("Google/Protobuf/NullValue.php");
require_once("Google/Protobuf/Timestamp.php");
require_once("Google/Protobuf/DoubleValue.php");
require_once("Google/Protobuf/BytesValue.php");
require_once("Google/Protobuf/FloatValue.php");
require_once("Google/Protobuf/Int64Value.php");
require_once("Google/Protobuf/UInt32Value.php");
require_once("Google/Protobuf/BoolValue.php");
require_once("Google/Protobuf/DoubleValue.php");
require_once("Google/Protobuf/Int32Value.php");
require_once("Google/Protobuf/StringValue.php");
require_once("Google/Protobuf/UInt64Value.php");
require_once("Protobuf_test_messages/Proto3/ForeignMessage.php"); require_once("Protobuf_test_messages/Proto3/ForeignMessage.php");
require_once("Protobuf_test_messages/Proto3/ForeignEnum.php"); require_once("Protobuf_test_messages/Proto3/ForeignEnum.php");
require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3.php"); require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3.php");
...@@ -28,12 +10,6 @@ require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3_NestedMessage.php ...@@ -28,12 +10,6 @@ require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3_NestedMessage.php
require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3_NestedEnum.php"); require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3_NestedEnum.php");
require_once("GPBMetadata/Conformance.php"); require_once("GPBMetadata/Conformance.php");
require_once("GPBMetadata/Google/Protobuf/Any.php");
require_once("GPBMetadata/Google/Protobuf/Duration.php");
require_once("GPBMetadata/Google/Protobuf/FieldMask.php");
require_once("GPBMetadata/Google/Protobuf/Struct.php");
require_once("GPBMetadata/Google/Protobuf/Timestamp.php");
require_once("GPBMetadata/Google/Protobuf/Wrappers.php");
require_once("GPBMetadata/Google/Protobuf/TestMessagesProto3.php"); require_once("GPBMetadata/Google/Protobuf/TestMessagesProto3.php");
use \Conformance\WireFormat; use \Conformance\WireFormat;
...@@ -78,7 +54,12 @@ function doTest($request) ...@@ -78,7 +54,12 @@ function doTest($request)
} elseif ($request->getRequestedOutputFormat() == WireFormat::PROTOBUF) { } elseif ($request->getRequestedOutputFormat() == WireFormat::PROTOBUF) {
$response->setProtobufPayload($test_message->serializeToString()); $response->setProtobufPayload($test_message->serializeToString());
} elseif ($request->getRequestedOutputFormat() == WireFormat::JSON) { } elseif ($request->getRequestedOutputFormat() == WireFormat::JSON) {
$response->setJsonPayload($test_message->serializeToJsonString()); try {
$response->setJsonPayload($test_message->serializeToJsonString());
} catch (Exception $e) {
$response->setSerializeError($e->getMessage());
return $response;
}
} }
return $response; return $response;
......
...@@ -7,92 +7,7 @@ Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator ...@@ -7,92 +7,7 @@ Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator
Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator
Recommended.Proto3.JsonInput.DurationHas9FractionalDigits.Validator Recommended.Proto3.JsonInput.DurationHas9FractionalDigits.Validator
Recommended.Proto3.JsonInput.DurationHasZeroFractionalDigit.Validator Recommended.Proto3.JsonInput.DurationHasZeroFractionalDigit.Validator
Required.DurationProtoInputTooLarge.JsonOutput Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
Required.DurationProtoInputTooSmall.JsonOutput
Required.Proto3.JsonInput.Any.JsonOutput
Required.Proto3.JsonInput.Any.ProtobufOutput
Required.Proto3.JsonInput.AnyNested.JsonOutput
Required.Proto3.JsonInput.AnyNested.ProtobufOutput
Required.Proto3.JsonInput.AnyUnorderedTypeTag.JsonOutput
Required.Proto3.JsonInput.AnyUnorderedTypeTag.ProtobufOutput
Required.Proto3.JsonInput.AnyWithDuration.JsonOutput
Required.Proto3.JsonInput.AnyWithDuration.ProtobufOutput
Required.Proto3.JsonInput.AnyWithFieldMask.JsonOutput
Required.Proto3.JsonInput.AnyWithFieldMask.ProtobufOutput
Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.JsonOutput
Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput
Required.Proto3.JsonInput.AnyWithStruct.JsonOutput
Required.Proto3.JsonInput.AnyWithStruct.ProtobufOutput
Required.Proto3.JsonInput.AnyWithTimestamp.JsonOutput
Required.Proto3.JsonInput.AnyWithTimestamp.ProtobufOutput
Required.Proto3.JsonInput.AnyWithValueForInteger.JsonOutput
Required.Proto3.JsonInput.AnyWithValueForInteger.ProtobufOutput
Required.Proto3.JsonInput.AnyWithValueForJsonObject.JsonOutput
Required.Proto3.JsonInput.AnyWithValueForJsonObject.ProtobufOutput
Required.Proto3.JsonInput.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.FieldMask.JsonOutput
Required.Proto3.JsonInput.FieldMask.ProtobufOutput
Required.Proto3.JsonInput.OptionalBoolWrapper.JsonOutput
Required.Proto3.JsonInput.OptionalBoolWrapper.ProtobufOutput
Required.Proto3.JsonInput.OptionalBytesWrapper.JsonOutput
Required.Proto3.JsonInput.OptionalBytesWrapper.ProtobufOutput
Required.Proto3.JsonInput.OptionalDoubleWrapper.JsonOutput
Required.Proto3.JsonInput.OptionalDoubleWrapper.ProtobufOutput
Required.Proto3.JsonInput.OptionalFloatWrapper.JsonOutput
Required.Proto3.JsonInput.OptionalFloatWrapper.ProtobufOutput
Required.Proto3.JsonInput.OptionalInt32Wrapper.JsonOutput
Required.Proto3.JsonInput.OptionalInt32Wrapper.ProtobufOutput
Required.Proto3.JsonInput.OptionalInt64Wrapper.JsonOutput
Required.Proto3.JsonInput.OptionalInt64Wrapper.ProtobufOutput
Required.Proto3.JsonInput.OptionalStringWrapper.JsonOutput
Required.Proto3.JsonInput.OptionalStringWrapper.ProtobufOutput
Required.Proto3.JsonInput.OptionalUint32Wrapper.JsonOutput
Required.Proto3.JsonInput.OptionalUint32Wrapper.ProtobufOutput
Required.Proto3.JsonInput.OptionalUint64Wrapper.JsonOutput
Required.Proto3.JsonInput.OptionalUint64Wrapper.ProtobufOutput
Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
Required.Proto3.JsonInput.RepeatedBoolWrapper.JsonOutput
Required.Proto3.JsonInput.RepeatedBoolWrapper.ProtobufOutput
Required.Proto3.JsonInput.RepeatedBytesWrapper.JsonOutput
Required.Proto3.JsonInput.RepeatedBytesWrapper.ProtobufOutput
Required.Proto3.JsonInput.RepeatedDoubleWrapper.JsonOutput
Required.Proto3.JsonInput.RepeatedDoubleWrapper.ProtobufOutput
Required.Proto3.JsonInput.RepeatedFloatWrapper.JsonOutput
Required.Proto3.JsonInput.RepeatedFloatWrapper.ProtobufOutput
Required.Proto3.JsonInput.RepeatedInt32Wrapper.JsonOutput
Required.Proto3.JsonInput.RepeatedInt32Wrapper.ProtobufOutput
Required.Proto3.JsonInput.RepeatedInt64Wrapper.JsonOutput
Required.Proto3.JsonInput.RepeatedInt64Wrapper.ProtobufOutput
Required.Proto3.JsonInput.RepeatedStringWrapper.JsonOutput
Required.Proto3.JsonInput.RepeatedStringWrapper.ProtobufOutput
Required.Proto3.JsonInput.RepeatedUint32Wrapper.JsonOutput
Required.Proto3.JsonInput.RepeatedUint32Wrapper.ProtobufOutput
Required.Proto3.JsonInput.RepeatedUint64Wrapper.JsonOutput
Required.Proto3.JsonInput.RepeatedUint64Wrapper.ProtobufOutput
Required.Proto3.JsonInput.Struct.JsonOutput
Required.Proto3.JsonInput.Struct.ProtobufOutput
Required.Proto3.JsonInput.ValueAcceptBool.JsonOutput
Required.Proto3.JsonInput.ValueAcceptBool.ProtobufOutput
Required.Proto3.JsonInput.ValueAcceptFloat.JsonOutput
Required.Proto3.JsonInput.ValueAcceptFloat.ProtobufOutput
Required.Proto3.JsonInput.ValueAcceptInteger.JsonOutput
Required.Proto3.JsonInput.ValueAcceptInteger.ProtobufOutput
Required.Proto3.JsonInput.ValueAcceptList.JsonOutput
Required.Proto3.JsonInput.ValueAcceptList.ProtobufOutput
Required.Proto3.JsonInput.ValueAcceptNull.JsonOutput
Required.Proto3.JsonInput.ValueAcceptNull.ProtobufOutput
Required.Proto3.JsonInput.ValueAcceptObject.JsonOutput
Required.Proto3.JsonInput.ValueAcceptObject.ProtobufOutput
Required.Proto3.JsonInput.ValueAcceptString.JsonOutput
Required.Proto3.JsonInput.ValueAcceptString.ProtobufOutput
Required.TimestampProtoInputTooLarge.JsonOutput
Required.TimestampProtoInputTooSmall.JsonOutput
Required.Proto3.JsonInput.FloatFieldTooLarge Required.Proto3.JsonInput.FloatFieldTooLarge
Required.Proto3.JsonInput.FloatFieldTooSmall Required.Proto3.JsonInput.FloatFieldTooSmall
Required.Proto3.JsonInput.DoubleFieldTooSmall Required.Proto3.JsonInput.DoubleFieldTooSmall
......
...@@ -2029,3 +2029,45 @@ PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, BoolValue, "bool_value") ...@@ -2029,3 +2029,45 @@ PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, BoolValue, "bool_value")
PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, StructValue, "struct_value") PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, StructValue, "struct_value")
PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, ListValue, "list_value") PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, ListValue, "list_value")
PHP_PROTO_ONEOF_ACCESSORS(Value, value, Kind, "kind") PHP_PROTO_ONEOF_ACCESSORS(Value, value, Kind, "kind")
// -----------------------------------------------------------------------------
// GPBMetadata files for well known types
// -----------------------------------------------------------------------------
#define DEFINE_GPBMETADATA_FILE(LOWERNAME, CAMELNAME, CLASSNAME) \
zend_class_entry* gpb_metadata_##LOWERNAME##_type; \
static zend_function_entry gpb_metadata_##LOWERNAME##_methods[] = { \
PHP_ME(GPBMetadata_##CAMELNAME, initOnce, NULL, \
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) \
ZEND_FE_END \
}; \
void gpb_metadata_##LOWERNAME##_init(TSRMLS_D) { \
zend_class_entry class_type; \
INIT_CLASS_ENTRY(class_type, CLASSNAME, \
gpb_metadata_##LOWERNAME##_methods); \
gpb_metadata_##LOWERNAME##_type = \
zend_register_internal_class(&class_type TSRMLS_CC); \
} \
PHP_METHOD(GPBMetadata_##CAMELNAME, initOnce) { \
init_file_##LOWERNAME(TSRMLS_C); \
}
DEFINE_GPBMETADATA_FILE(any, Any, "GPBMetadata\\Google\\Protobuf\\Any");
DEFINE_GPBMETADATA_FILE(api, Api, "GPBMetadata\\Google\\Protobuf\\Api");
DEFINE_GPBMETADATA_FILE(duration, Duration,
"GPBMetadata\\Google\\Protobuf\\Duration");
DEFINE_GPBMETADATA_FILE(field_mask, FieldMask,
"GPBMetadata\\Google\\Protobuf\\FieldMask");
DEFINE_GPBMETADATA_FILE(empty, Empty,
"GPBMetadata\\Google\\Protobuf\\GPBEmpty");
DEFINE_GPBMETADATA_FILE(source_context, SourceContext,
"GPBMetadata\\Google\\Protobuf\\SourceContext");
DEFINE_GPBMETADATA_FILE(struct, Struct,
"GPBMetadata\\Google\\Protobuf\\Struct");
DEFINE_GPBMETADATA_FILE(timestamp, Timestamp,
"GPBMetadata\\Google\\Protobuf\\Timestamp");
DEFINE_GPBMETADATA_FILE(type, Type, "GPBMetadata\\Google\\Protobuf\\Type");
DEFINE_GPBMETADATA_FILE(wrappers, Wrappers,
"GPBMetadata\\Google\\Protobuf\\Wrappers");
#undef DEFINE_GPBMETADATA_FILE
...@@ -300,6 +300,17 @@ static PHP_MINIT_FUNCTION(protobuf) { ...@@ -300,6 +300,17 @@ static PHP_MINIT_FUNCTION(protobuf) {
repeated_field_iter_init(TSRMLS_C); repeated_field_iter_init(TSRMLS_C);
util_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); any_init(TSRMLS_C);
api_init(TSRMLS_C); api_init(TSRMLS_C);
bool_value_init(TSRMLS_C); bool_value_init(TSRMLS_C);
......
...@@ -610,7 +610,6 @@ typedef struct BytesValue BytesValue; ...@@ -610,7 +610,6 @@ typedef struct BytesValue BytesValue;
typedef struct Descriptor Descriptor; typedef struct Descriptor Descriptor;
typedef struct Descriptor Descriptor; typedef struct Descriptor Descriptor;
typedef struct DescriptorPool DescriptorPool; typedef struct DescriptorPool DescriptorPool;
typedef struct DescriptorPool DescriptorPool;
typedef struct DoubleValue DoubleValue; typedef struct DoubleValue DoubleValue;
typedef struct Duration Duration; typedef struct Duration Duration;
typedef struct Enum Enum; typedef struct Enum Enum;
...@@ -630,7 +629,6 @@ typedef struct GPBEmpty GPBEmpty; ...@@ -630,7 +629,6 @@ typedef struct GPBEmpty GPBEmpty;
typedef struct Int32Value Int32Value; typedef struct Int32Value Int32Value;
typedef struct Int64Value Int64Value; typedef struct Int64Value Int64Value;
typedef struct InternalDescriptorPool InternalDescriptorPool; typedef struct InternalDescriptorPool InternalDescriptorPool;
typedef struct InternalDescriptorPool InternalDescriptorPool;
typedef struct ListValue ListValue; typedef struct ListValue ListValue;
typedef struct Map Map; typedef struct Map Map;
typedef struct Map Map; typedef struct Map Map;
...@@ -714,6 +712,17 @@ void uint64_value_init(TSRMLS_D); ...@@ -714,6 +712,17 @@ void uint64_value_init(TSRMLS_D);
void util_init(TSRMLS_D); void util_init(TSRMLS_D);
void value_init(TSRMLS_D); void value_init(TSRMLS_D);
void gpb_metadata_any_init(TSRMLS_D);
void gpb_metadata_api_init(TSRMLS_D);
void gpb_metadata_duration_init(TSRMLS_D);
void gpb_metadata_field_mask_init(TSRMLS_D);
void gpb_metadata_empty_init(TSRMLS_D);
void gpb_metadata_source_context_init(TSRMLS_D);
void gpb_metadata_struct_init(TSRMLS_D);
void gpb_metadata_timestamp_init(TSRMLS_D);
void gpb_metadata_type_init(TSRMLS_D);
void gpb_metadata_wrappers_init(TSRMLS_D);
// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor // Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
// instances. // instances.
void add_def_obj(const void* def, PHP_PROTO_HASHTABLE_VALUE value); void add_def_obj(const void* def, PHP_PROTO_HASHTABLE_VALUE value);
...@@ -1170,6 +1179,17 @@ extern zend_class_entry* oneof_descriptor_type; ...@@ -1170,6 +1179,17 @@ extern zend_class_entry* oneof_descriptor_type;
// Well Known Type. // Well Known Type.
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
PHP_METHOD(GPBMetadata_Any, initOnce);
PHP_METHOD(GPBMetadata_Api, initOnce);
PHP_METHOD(GPBMetadata_Duration, initOnce);
PHP_METHOD(GPBMetadata_FieldMask, initOnce);
PHP_METHOD(GPBMetadata_Empty, initOnce);
PHP_METHOD(GPBMetadata_SourceContext, initOnce);
PHP_METHOD(GPBMetadata_Struct, initOnce);
PHP_METHOD(GPBMetadata_Timestamp, initOnce);
PHP_METHOD(GPBMetadata_Type, initOnce);
PHP_METHOD(GPBMetadata_Wrappers, initOnce);
PHP_METHOD(Any, __construct); PHP_METHOD(Any, __construct);
PHP_METHOD(Any, getTypeUrl); PHP_METHOD(Any, getTypeUrl);
PHP_METHOD(Any, setTypeUrl); PHP_METHOD(Any, setTypeUrl);
......
...@@ -207,9 +207,9 @@ class Any extends \Google\Protobuf\Internal\Message ...@@ -207,9 +207,9 @@ class Any extends \Google\Protobuf\Internal\Message
public function unpack() public function unpack()
{ {
// Get fully qualifed name from type url. // Get fully qualifed name from type url.
$url_prifix_len = strlen(Any::TYPE_URL_PREFIX); $url_prifix_len = strlen(GPBUtil::TYPE_URL_PREFIX);
if (substr($this->type_url, 0, $url_prifix_len) != if (substr($this->type_url, 0, $url_prifix_len) !=
Any::TYPE_URL_PREFIX) { GPBUtil::TYPE_URL_PREFIX) {
throw new \Exception( throw new \Exception(
"Type url needs to be type.googleapis.com/fully-qulified"); "Type url needs to be type.googleapis.com/fully-qulified");
} }
...@@ -251,7 +251,7 @@ class Any extends \Google\Protobuf\Internal\Message ...@@ -251,7 +251,7 @@ class Any extends \Google\Protobuf\Internal\Message
$pool = DescriptorPool::getGeneratedPool(); $pool = DescriptorPool::getGeneratedPool();
$desc = $pool->getDescriptorByClassName(get_class($msg)); $desc = $pool->getDescriptorByClassName(get_class($msg));
$fully_qualifed_name = $desc->getFullName(); $fully_qualifed_name = $desc->getFullName();
$this->type_url = Any::TYPE_URL_PREFIX.substr( $this->type_url = GPBUtil::TYPE_URL_PREFIX.substr(
$fully_qualifed_name, 1, strlen($fully_qualifed_name)); $fully_qualifed_name, 1, strlen($fully_qualifed_name));
} }
...@@ -265,7 +265,7 @@ class Any extends \Google\Protobuf\Internal\Message ...@@ -265,7 +265,7 @@ class Any extends \Google\Protobuf\Internal\Message
$pool = DescriptorPool::getGeneratedPool(); $pool = DescriptorPool::getGeneratedPool();
$desc = $pool->getDescriptorByClassName($klass); $desc = $pool->getDescriptorByClassName($klass);
$fully_qualifed_name = $desc->getFullName(); $fully_qualifed_name = $desc->getFullName();
$type_url = Any::TYPE_URL_PREFIX.substr( $type_url = GPBUtil::TYPE_URL_PREFIX.substr(
$fully_qualifed_name, 1, strlen($fully_qualifed_name)); $fully_qualifed_name, 1, strlen($fully_qualifed_name));
return $this->type_url === $type_url; return $this->type_url === $type_url;
} }
......
...@@ -38,19 +38,26 @@ class GPBJsonWire ...@@ -38,19 +38,26 @@ class GPBJsonWire
public static function serializeFieldToStream( public static function serializeFieldToStream(
$value, $value,
$field, $field,
&$output) &$output, $has_field_name = true)
{ {
$output->writeRaw("\"", 1); if ($has_field_name) {
$field_name = GPBJsonWire::formatFieldName($field); $output->writeRaw("\"", 1);
$output->writeRaw($field_name, strlen($field_name)); $field_name = GPBJsonWire::formatFieldName($field);
$output->writeRaw("\":", 2); $output->writeRaw($field_name, strlen($field_name));
return static::serializeFieldValueToStream($value, $field, $output); $output->writeRaw("\":", 2);
}
return static::serializeFieldValueToStream(
$value,
$field,
$output,
!$has_field_name);
} }
private static function serializeFieldValueToStream( public static function serializeFieldValueToStream(
$values, $values,
$field, $field,
&$output) &$output,
$is_well_known = false)
{ {
if ($field->isMap()) { if ($field->isMap()) {
$output->writeRaw("{", 1); $output->writeRaw("{", 1);
...@@ -84,7 +91,8 @@ class GPBJsonWire ...@@ -84,7 +91,8 @@ class GPBJsonWire
if (!static::serializeSingularFieldValueToStream( if (!static::serializeSingularFieldValueToStream(
$key, $key,
$key_field, $key_field,
$output)) { $output,
$is_well_known)) {
return false; return false;
} }
if ($additional_quote) { if ($additional_quote) {
...@@ -94,7 +102,8 @@ class GPBJsonWire ...@@ -94,7 +102,8 @@ class GPBJsonWire
if (!static::serializeSingularFieldValueToStream( if (!static::serializeSingularFieldValueToStream(
$value, $value,
$value_field, $value_field,
$output)) { $output,
$is_well_known)) {
return false; return false;
} }
} }
...@@ -112,7 +121,8 @@ class GPBJsonWire ...@@ -112,7 +121,8 @@ class GPBJsonWire
if (!static::serializeSingularFieldValueToStream( if (!static::serializeSingularFieldValueToStream(
$value, $value,
$field, $field,
$output)) { $output,
$is_well_known)) {
return false; return false;
} }
} }
...@@ -122,14 +132,15 @@ class GPBJsonWire ...@@ -122,14 +132,15 @@ class GPBJsonWire
return static::serializeSingularFieldValueToStream( return static::serializeSingularFieldValueToStream(
$values, $values,
$field, $field,
$output); $output,
$is_well_known);
} }
} }
private static function serializeSingularFieldValueToStream( private static function serializeSingularFieldValueToStream(
$value, $value,
$field, $field,
&$output) &$output, $is_well_known = false)
{ {
switch ($field->getType()) { switch ($field->getType()) {
case GPBType::SFIXED32: case GPBType::SFIXED32:
...@@ -186,6 +197,10 @@ class GPBJsonWire ...@@ -186,6 +197,10 @@ class GPBJsonWire
break; break;
case GPBType::ENUM: case GPBType::ENUM:
$enum_desc = $field->getEnumType(); $enum_desc = $field->getEnumType();
if ($enum_desc->getClass() === "Google\Protobuf\NullValue") {
$output->writeRaw("null", 4);
break;
}
$enum_value_desc = $enum_desc->getValueByNumber($value); $enum_value_desc = $enum_desc->getValueByNumber($value);
if (!is_null($enum_value_desc)) { if (!is_null($enum_value_desc)) {
$str_value = $enum_value_desc->getName(); $str_value = $enum_value_desc->getName();
...@@ -205,7 +220,11 @@ class GPBJsonWire ...@@ -205,7 +220,11 @@ class GPBJsonWire
} }
break; break;
case GPBType::BYTES: case GPBType::BYTES:
$value = base64_encode($value); $bytes_value = base64_encode($value);
$output->writeRaw("\"", 1);
$output->writeRaw($bytes_value, strlen($bytes_value));
$output->writeRaw("\"", 1);
break;
case GPBType::STRING: case GPBType::STRING:
$value = json_encode($value); $value = json_encode($value);
$output->writeRaw($value, strlen($value)); $output->writeRaw($value, strlen($value));
......
...@@ -32,14 +32,29 @@ ...@@ -32,14 +32,29 @@
namespace Google\Protobuf\Internal; namespace Google\Protobuf\Internal;
use Google\Protobuf\Duration;
use Google\Protobuf\FieldMask;
use Google\Protobuf\Internal\GPBType; use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField; use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\MapField; use Google\Protobuf\Internal\MapField;
function camel2underscore($input) {
preg_match_all(
'!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!',
$input,
$matches);
$ret = $matches[0];
foreach ($ret as &$match) {
$match = $match == strtoupper($match) ? strtolower($match) : lcfirst($match);
}
return implode('_', $ret);
}
class GPBUtil class GPBUtil
{ {
const NANOS_PER_MILLISECOND = 1000000; const NANOS_PER_MILLISECOND = 1000000;
const NANOS_PER_MICROSECOND = 1000; const NANOS_PER_MICROSECOND = 1000;
const TYPE_URL_PREFIX = 'type.googleapis.com/';
public static function divideInt64ToInt32($value, &$high, &$low, $trim = false) public static function divideInt64ToInt32($value, &$high, &$low, $trim = false)
{ {
...@@ -358,7 +373,7 @@ class GPBUtil ...@@ -358,7 +373,7 @@ class GPBUtil
} }
return $result; return $result;
} }
public static function parseTimestamp($timestamp) public static function parseTimestamp($timestamp)
{ {
// prevent parsing timestamps containing with the non-existant year "0000" // prevent parsing timestamps containing with the non-existant year "0000"
...@@ -370,7 +385,7 @@ class GPBUtil ...@@ -370,7 +385,7 @@ class GPBUtil
if (substr($timestamp, -1, 1) === "z") { if (substr($timestamp, -1, 1) === "z") {
throw new \Exception("Timezone cannot be a lowercase z."); throw new \Exception("Timezone cannot be a lowercase z.");
} }
$nanoseconds = 0; $nanoseconds = 0;
$periodIndex = strpos($timestamp, "."); $periodIndex = strpos($timestamp, ".");
if ($periodIndex !== false) { if ($periodIndex !== false) {
...@@ -411,9 +426,15 @@ class GPBUtil ...@@ -411,9 +426,15 @@ class GPBUtil
$value->setNanos($nanoseconds); $value->setNanos($nanoseconds);
return $value; return $value;
} }
public static function formatTimestamp($value) public static function formatTimestamp($value)
{ {
if (bccomp($value->getSeconds(), "253402300800") != -1) {
throw new GPBDecodeException("Duration number too large.");
}
if (bccomp($value->getSeconds(), "-62135596801") != 1) {
throw new GPBDecodeException("Duration number too small.");
}
$nanoseconds = static::getNanosecondsForTimestamp($value->getNanos()); $nanoseconds = static::getNanosecondsForTimestamp($value->getNanos());
if (!empty($nanoseconds)) { if (!empty($nanoseconds)) {
$nanoseconds = ".".$nanoseconds; $nanoseconds = ".".$nanoseconds;
...@@ -422,6 +443,93 @@ class GPBUtil ...@@ -422,6 +443,93 @@ class GPBUtil
return $date->format("Y-m-d\TH:i:s".$nanoseconds."\Z"); return $date->format("Y-m-d\TH:i:s".$nanoseconds."\Z");
} }
public static function parseDuration($value)
{
if (strlen($value) < 2 || substr($value, -1) !== "s") {
throw new GPBDecodeException("Missing s after duration string");
}
$number = substr($value, 0, -1);
if (bccomp($number, "315576000001") != -1) {
throw new GPBDecodeException("Duration number too large.");
}
if (bccomp($number, "-315576000001") != 1) {
throw new GPBDecodeException("Duration number too small.");
}
$pos = strrpos($number, ".");
if ($pos !== false) {
$seconds = substr($number, 0, $pos);
if (bccomp($seconds, 0) < 0) {
$nanos = bcmul("0" . substr($number, $pos), -1000000000);
} else {
$nanos = bcmul("0" . substr($number, $pos), 1000000000);
}
} else {
$seconds = $number;
$nanos = 0;
}
$duration = new Duration();
$duration->setSeconds($seconds);
$duration->setNanos($nanos);
return $duration;
}
public static function formatDuration($value)
{
if (bccomp($value->getSeconds(), "315576000001") != -1) {
throw new GPBDecodeException("Duration number too large.");
}
if (bccomp($value->getSeconds(), "-315576000001") != 1) {
throw new GPBDecodeException("Duration number too small.");
}
return strval(bcadd($value->getSeconds(),
$value->getNanos() / 1000000000.0, 9));
}
public static function parseFieldMask($paths_string)
{
$path_strings = explode(",", $paths_string);
$field_mask = new FieldMask();
$paths = $field_mask->getPaths();
foreach($path_strings as &$path_string) {
$field_strings = explode(".", $path_string);
foreach($field_strings as &$field_string) {
$field_string = camel2underscore($field_string);
}
$path_string = implode(".", $field_strings);
$paths[] = $path_string;
}
return $field_mask;
}
public static function formatFieldMask($field_mask)
{
$converted_paths = [];
foreach($field_mask->getPaths() as $path) {
$fields = explode('.', $path);
$converted_path = [];
foreach ($fields as $field) {
$segments = explode('_', $field);
$start = true;
$converted_segments = "";
foreach($segments as $segment) {
if (!$start) {
$converted = ucfirst($segment);
} else {
$converted = $segment;
$start = false;
}
$converted_segments .= $converted;
}
$converted_path []= $converted_segments;
}
$converted_path = implode(".", $converted_path);
$converted_paths []= $converted_path;
}
return implode(",", $converted_paths);
}
public static function getNanosecondsForTimestamp($nanoseconds) public static function getNanosecondsForTimestamp($nanoseconds)
{ {
if ($nanoseconds == 0) { if ($nanoseconds == 0) {
...@@ -435,4 +543,29 @@ class GPBUtil ...@@ -435,4 +543,29 @@ class GPBUtil
} }
return sprintf('%09d', $nanoseconds); return sprintf('%09d', $nanoseconds);
} }
public static function hasSpecialJsonMapping($msg)
{
return is_a($msg, 'Google\Protobuf\Any') ||
is_a($msg, "Google\Protobuf\ListValue") ||
is_a($msg, "Google\Protobuf\Struct") ||
is_a($msg, "Google\Protobuf\Value") ||
is_a($msg, "Google\Protobuf\Duration") ||
is_a($msg, "Google\Protobuf\Timestamp") ||
is_a($msg, "Google\Protobuf\FieldMask") ||
static::hasJsonValue($msg);
}
public static function hasJsonValue($msg)
{
return is_a($msg, "Google\Protobuf\DoubleValue") ||
is_a($msg, "Google\Protobuf\FloatValue") ||
is_a($msg, "Google\Protobuf\Int64Value") ||
is_a($msg, "Google\Protobuf\UInt64Value") ||
is_a($msg, "Google\Protobuf\Int32Value") ||
is_a($msg, "Google\Protobuf\UInt32Value") ||
is_a($msg, "Google\Protobuf\BoolValue") ||
is_a($msg, "Google\Protobuf\StringValue") ||
is_a($msg, "Google\Protobuf\BytesValue");
}
} }
...@@ -44,6 +44,10 @@ use Google\Protobuf\Internal\GPBType; ...@@ -44,6 +44,10 @@ use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\GPBWire; use Google\Protobuf\Internal\GPBWire;
use Google\Protobuf\Internal\MapEntry; use Google\Protobuf\Internal\MapEntry;
use Google\Protobuf\Internal\RepeatedField; use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\ListValue;
use Google\Protobuf\Value;
use Google\Protobuf\Struct;
use Google\Protobuf\NullValue;
/** /**
* Parent class of all proto messages. Users should not instantiate this class * Parent class of all proto messages. Users should not instantiate this class
...@@ -701,16 +705,22 @@ class Message ...@@ -701,16 +705,22 @@ class Message
$field, $field,
$is_map_key = false) $is_map_key = false)
{ {
if (is_null($value)) {
return $this->defaultValue($field);
}
switch ($field->getType()) { switch ($field->getType()) {
case GPBType::MESSAGE: case GPBType::MESSAGE:
$klass = $field->getMessageType()->getClass(); $klass = $field->getMessageType()->getClass();
$submsg = new $klass; $submsg = new $klass;
if ($field->isTimestamp()) { if (is_a($submsg, "Google\Protobuf\Duration")) {
if (!is_string($value)) { if (is_null($value)) {
return $this->defaultValue($field);
} else if (!is_string($value)) {
throw new GPBDecodeException("Expect string.");
}
return GPBUtil::parseDuration($value);
} else if ($field->isTimestamp()) {
if (is_null($value)) {
return $this->defaultValue($field);
} else if (!is_string($value)) {
throw new GPBDecodeException("Expect string."); throw new GPBDecodeException("Expect string.");
} }
try { try {
...@@ -721,16 +731,31 @@ class Message ...@@ -721,16 +731,31 @@ class Message
$submsg->setSeconds($timestamp->getSeconds()); $submsg->setSeconds($timestamp->getSeconds());
$submsg->setNanos($timestamp->getNanos()); $submsg->setNanos($timestamp->getNanos());
} else if ($klass !== "Google\Protobuf\Any") { } else if (is_a($submsg, "Google\Protobuf\FieldMask")) {
if (!is_object($value) && !is_array($value)) { if (is_null($value)) {
return $this->defaultValue($field);
}
try {
return GPBUtil::parseFieldMask($value);
} catch (\Exception $e) {
throw new GPBDecodeException("Invalid FieldMask: ".$e->getMessage());
}
} else {
if (is_null($value) &&
!is_a($submsg, "Google\Protobuf\Value")) {
return $this->defaultValue($field);
}
if (GPBUtil::hasSpecialJsonMapping($submsg)) {
} elseif (!is_object($value) && !is_array($value)) {
throw new GPBDecodeException("Expect message."); throw new GPBDecodeException("Expect message.");
} }
$submsg->mergeFromJsonArray($value); $submsg->mergeFromJsonArray($value);
} }
return $submsg; return $submsg;
case GPBType::ENUM: case GPBType::ENUM:
if (is_integer($value)) { if (is_null($value)) {
return $this->defaultValue($field);
} else if (is_integer($value)) {
return $value; return $value;
} else { } else {
$enum_value = $enum_value =
...@@ -740,11 +765,17 @@ class Message ...@@ -740,11 +765,17 @@ class Message
return $enum_value->getNumber(); return $enum_value->getNumber();
} }
case GPBType::STRING: case GPBType::STRING:
if (is_null($value)) {
return $this->defaultValue($field);
}
if (!is_string($value)) { if (!is_string($value)) {
throw new GPBDecodeException("Expect string"); throw new GPBDecodeException("Expect string");
} }
return $value; return $value;
case GPBType::BYTES: case GPBType::BYTES:
if (is_null($value)) {
return $this->defaultValue($field);
}
if (!is_string($value)) { if (!is_string($value)) {
throw new GPBDecodeException("Expect string"); throw new GPBDecodeException("Expect string");
} }
...@@ -755,6 +786,9 @@ class Message ...@@ -755,6 +786,9 @@ class Message
} }
return $proto_value; return $proto_value;
case GPBType::BOOL: case GPBType::BOOL:
if (is_null($value)) {
return $this->defaultValue($field);
}
if ($is_map_key) { if ($is_map_key) {
if ($value === "true") { if ($value === "true") {
return true; return true;
...@@ -771,6 +805,9 @@ class Message ...@@ -771,6 +805,9 @@ class Message
} }
return $value; return $value;
case GPBType::FLOAT: case GPBType::FLOAT:
if (is_null($value)) {
return $this->defaultValue($field);
}
if ($value === "Infinity") { if ($value === "Infinity") {
return INF; return INF;
} }
...@@ -782,6 +819,9 @@ class Message ...@@ -782,6 +819,9 @@ class Message
} }
return $value; return $value;
case GPBType::DOUBLE: case GPBType::DOUBLE:
if (is_null($value)) {
return $this->defaultValue($field);
}
if ($value === "Infinity") { if ($value === "Infinity") {
return INF; return INF;
} }
...@@ -793,6 +833,9 @@ class Message ...@@ -793,6 +833,9 @@ class Message
} }
return $value; return $value;
case GPBType::INT32: case GPBType::INT32:
if (is_null($value)) {
return $this->defaultValue($field);
}
if (!is_numeric($value)) { if (!is_numeric($value)) {
throw new GPBDecodeException( throw new GPBDecodeException(
"Invalid data type for int32 field"); "Invalid data type for int32 field");
...@@ -807,6 +850,9 @@ class Message ...@@ -807,6 +850,9 @@ class Message
} }
return $value; return $value;
case GPBType::UINT32: case GPBType::UINT32:
if (is_null($value)) {
return $this->defaultValue($field);
}
if (!is_numeric($value)) { if (!is_numeric($value)) {
throw new GPBDecodeException( throw new GPBDecodeException(
"Invalid data type for uint32 field"); "Invalid data type for uint32 field");
...@@ -817,6 +863,9 @@ class Message ...@@ -817,6 +863,9 @@ class Message
} }
return $value; return $value;
case GPBType::INT64: case GPBType::INT64:
if (is_null($value)) {
return $this->defaultValue($field);
}
if (!is_numeric($value)) { if (!is_numeric($value)) {
throw new GPBDecodeException( throw new GPBDecodeException(
"Invalid data type for int64 field"); "Invalid data type for int64 field");
...@@ -831,6 +880,9 @@ class Message ...@@ -831,6 +880,9 @@ class Message
} }
return $value; return $value;
case GPBType::UINT64: case GPBType::UINT64:
if (is_null($value)) {
return $this->defaultValue($field);
}
if (!is_numeric($value)) { if (!is_numeric($value)) {
throw new GPBDecodeException( throw new GPBDecodeException(
"Invalid data type for int64 field"); "Invalid data type for int64 field");
...@@ -844,14 +896,107 @@ class Message ...@@ -844,14 +896,107 @@ class Message
} }
return $value; return $value;
case GPBType::FIXED64: case GPBType::FIXED64:
if (is_null($value)) {
return $this->defaultValue($field);
}
return $value; return $value;
default: default:
return $value; return $value;
} }
} }
private function mergeFromJsonArray($array) protected function mergeFromJsonArray($array)
{ {
if (is_a($this, "Google\Protobuf\Any")) {
$this->clear();
$this->setTypeUrl($array["@type"]);
$msg = $this->unpack();
if (GPBUtil::hasSpecialJsonMapping($msg)) {
$msg->mergeFromJsonArray($array["value"]);
} else {
unset($array["@type"]);
$msg->mergeFromJsonArray($array);
}
$this->setValue($msg->serializeToString());
return;
}
if (is_a($this, "Google\Protobuf\DoubleValue") ||
is_a($this, "Google\Protobuf\FloatValue") ||
is_a($this, "Google\Protobuf\Int64Value") ||
is_a($this, "Google\Protobuf\UInt64Value") ||
is_a($this, "Google\Protobuf\Int32Value") ||
is_a($this, "Google\Protobuf\UInt32Value") ||
is_a($this, "Google\Protobuf\BoolValue") ||
is_a($this, "Google\Protobuf\StringValue")) {
$this->setValue($array);
return;
}
if (is_a($this, "Google\Protobuf\BytesValue")) {
$this->setValue(base64_decode($array));
return;
}
if (is_a($this, "Google\Protobuf\Duration")) {
$this->mergeFrom(GPBUtil::parseDuration($array));
return;
}
if (is_a($this, "Google\Protobuf\FieldMask")) {
$this->mergeFrom(GPBUtil::parseFieldMask($array));
return;
}
if (is_a($this, "Google\Protobuf\Timestamp")) {
$this->mergeFrom(GPBUtil::parseTimestamp($array));
return;
}
if (is_a($this, "Google\Protobuf\Struct")) {
$fields = $this->getFields();
foreach($array as $key => $value) {
$v = new Value();
$v->mergeFromJsonArray($value);
$fields[$key] = $v;
}
}
if (is_a($this, "Google\Protobuf\Value")) {
if (is_bool($array)) {
$this->setBoolValue($array);
} elseif (is_string($array)) {
$this->setStringValue($array);
} elseif (is_null($array)) {
$this->setNullValue(0);
} elseif (is_double($array) || is_integer($array)) {
$this->setNumberValue($array);
} elseif (is_array($array)) {
if (array_values($array) !== $array) {
// Associative array
$struct_value = $this->getStructValue();
if (is_null($struct_value)) {
$struct_value = new Struct();
$this->setStructValue($struct_value);
}
foreach ($array as $key => $v) {
$value = new Value();
$value->mergeFromJsonArray($v);
$values = $struct_value->getFields();
$values[$key]= $value;
}
} else {
// Array
$list_value = $this->getListValue();
if (is_null($list_value)) {
$list_value = new ListValue();
$this->setListValue($list_value);
}
foreach ($array as $v) {
$value = new Value();
$value->mergeFromJsonArray($v);
$values = $list_value->getValues();
$values[]= $value;
}
}
} else {
throw new GPBDecodeException("Invalid type for Value.");
}
return;
}
foreach ($array as $key => $value) { foreach ($array as $key => $value) {
$field = $this->desc->getFieldByJsonName($key); $field = $this->desc->getFieldByJsonName($key);
if (is_null($field)) { if (is_null($field)) {
...@@ -1037,7 +1182,8 @@ class Message ...@@ -1037,7 +1182,8 @@ class Message
{ {
$getter = $field->getGetter(); $getter = $field->getGetter();
$values = $this->$getter(); $values = $this->$getter();
return GPBJsonWire::serializeFieldToStream($values, $field, $output); return GPBJsonWire::serializeFieldToStream(
$values, $field, $output, !GPBUtil::hasSpecialJsonMapping($this));
} }
/** /**
...@@ -1060,16 +1206,57 @@ class Message ...@@ -1060,16 +1206,57 @@ class Message
*/ */
public function serializeToJsonStream(&$output) public function serializeToJsonStream(&$output)
{ {
if (get_class($this) === 'Google\Protobuf\Timestamp') { if (is_a($this, 'Google\Protobuf\Any')) {
$output->writeRaw("{", 1);
$type_field = $this->desc->getFieldByNumber(1);
$value_msg = $this->unpack();
// Serialize type url.
$output->writeRaw("\"@type\":", 8);
$output->writeRaw("\"", 1);
$output->writeRaw($this->getTypeUrl(), strlen($this->getTypeUrl()));
$output->writeRaw("\"", 1);
// Serialize value
if (GPBUtil::hasSpecialJsonMapping($value_msg)) {
$output->writeRaw(",\"value\":", 9);
$value_msg->serializeToJsonStream($output);
} else {
$value_fields = $value_msg->desc->getField();
foreach ($value_fields as $field) {
if ($value_msg->existField($field)) {
$output->writeRaw(",", 1);
if (!$value_msg->serializeFieldToJsonStream($output, $field)) {
return false;
}
}
}
}
$output->writeRaw("}", 1);
} elseif (is_a($this, 'Google\Protobuf\FieldMask')) {
$field_mask = GPBUtil::formatFieldMask($this);
$output->writeRaw("\"", 1);
$output->writeRaw($field_mask, strlen($field_mask));
$output->writeRaw("\"", 1);
} elseif (is_a($this, 'Google\Protobuf\Duration')) {
$duration = GPBUtil::formatDuration($this) . "s";
$output->writeRaw("\"", 1);
$output->writeRaw($duration, strlen($duration));
$output->writeRaw("\"", 1);
} elseif (get_class($this) === 'Google\Protobuf\Timestamp') {
$timestamp = GPBUtil::formatTimestamp($this); $timestamp = GPBUtil::formatTimestamp($this);
$timestamp = json_encode($timestamp); $timestamp = json_encode($timestamp);
$output->writeRaw($timestamp, strlen($timestamp)); $output->writeRaw($timestamp, strlen($timestamp));
} else { } else {
$output->writeRaw("{", 1); if (!GPBUtil::hasSpecialJsonMapping($this)) {
$output->writeRaw("{", 1);
}
$fields = $this->desc->getField(); $fields = $this->desc->getField();
$first = true; $first = true;
foreach ($fields as $field) { foreach ($fields as $field) {
if ($this->existField($field)) { if ($this->existField($field) ||
GPBUtil::hasJsonValue($this)) {
if ($first) { if ($first) {
$first = false; $first = false;
} else { } else {
...@@ -1080,7 +1267,9 @@ class Message ...@@ -1080,7 +1267,9 @@ class Message
} }
} }
} }
$output->writeRaw("}", 1); if (!GPBUtil::hasSpecialJsonMapping($this)) {
$output->writeRaw("}", 1);
}
} }
return true; return true;
} }
...@@ -1263,6 +1452,10 @@ class Message ...@@ -1263,6 +1452,10 @@ class Message
break; break;
case GPBType::ENUM: case GPBType::ENUM:
$enum_desc = $field->getEnumType(); $enum_desc = $field->getEnumType();
if ($enum_desc->getClass() === "Google\Protobuf\NullValue") {
$size += 4;
break;
}
$enum_value_desc = $enum_desc->getValueByNumber($value); $enum_value_desc = $enum_desc->getValueByNumber($value);
if (!is_null($enum_value_desc)) { if (!is_null($enum_value_desc)) {
$size += 2; // size for "" $size += 2; // size for ""
...@@ -1284,6 +1477,12 @@ class Message ...@@ -1284,6 +1477,12 @@ class Message
$size += strlen($value); $size += strlen($value);
break; break;
case GPBType::BYTES: case GPBType::BYTES:
# if (is_a($this, "Google\Protobuf\BytesValue")) {
# $size += strlen(json_encode($value));
# } else {
# $size += strlen(base64_encode($value));
# $size += 2; // size for \"\"
# }
$size += strlen(base64_encode($value)); $size += strlen(base64_encode($value));
$size += 2; // size for \"\" $size += 2; // size for \"\"
break; break;
...@@ -1375,8 +1574,11 @@ class Message ...@@ -1375,8 +1574,11 @@ class Message
$values = $this->$getter(); $values = $this->$getter();
$count = count($values); $count = count($values);
if ($count !== 0) { if ($count !== 0) {
$size += 5; // size for "\"\":{}". if (!GPBUtil::hasSpecialJsonMapping($this)) {
$size += strlen($field->getJsonName()); // size for field name $size += 3; // size for "\"\":".
$size += strlen($field->getJsonName()); // size for field name
}
$size += 2; // size for "{}".
$size += $count - 1; // size for commas $size += $count - 1; // size for commas
$getter = $field->getGetter(); $getter = $field->getGetter();
$map_entry = $field->getMessageType(); $map_entry = $field->getMessageType();
...@@ -1408,17 +1610,22 @@ class Message ...@@ -1408,17 +1610,22 @@ class Message
$values = $this->$getter(); $values = $this->$getter();
$count = count($values); $count = count($values);
if ($count !== 0) { if ($count !== 0) {
$size += 5; // size for "\"\":[]". if (!GPBUtil::hasSpecialJsonMapping($this)) {
$size += strlen($field->getJsonName()); // size for field name $size += 3; // size for "\"\":".
$size += strlen($field->getJsonName()); // size for field name
}
$size += 2; // size for "[]".
$size += $count - 1; // size for commas $size += $count - 1; // size for commas
$getter = $field->getGetter(); $getter = $field->getGetter();
foreach ($values as $value) { foreach ($values as $value) {
$size += $this->fieldDataOnlyJsonByteSize($field, $value); $size += $this->fieldDataOnlyJsonByteSize($field, $value);
} }
} }
} elseif ($this->existField($field)) { } elseif ($this->existField($field) || GPBUtil::hasJsonValue($this)) {
$size += 3; // size for "\"\":". if (!GPBUtil::hasSpecialJsonMapping($this)) {
$size += strlen($field->getJsonName()); // size for field name $size += 3; // size for "\"\":".
$size += strlen($field->getJsonName()); // size for field name
}
$getter = $field->getGetter(); $getter = $field->getGetter();
$value = $this->$getter(); $value = $this->$getter();
$size += $this->fieldDataOnlyJsonByteSize($field, $value); $size += $this->fieldDataOnlyJsonByteSize($field, $value);
...@@ -1473,14 +1680,41 @@ class Message ...@@ -1473,14 +1680,41 @@ class Message
public function jsonByteSize() public function jsonByteSize()
{ {
$size = 0; $size = 0;
if (get_class($this) === 'Google\Protobuf\Timestamp') { if (is_a($this, 'Google\Protobuf\Any')) {
// Size for "{}".
$size += 2;
// Size for "\"@type\":".
$size += 8;
// Size for url. +2 for "" /.
$size += strlen($this->getTypeUrl()) + 2;
$value_msg = $this->unpack();
if (GPBUtil::hasSpecialJsonMapping($value_msg)) {
// Size for "\",value\":".
$size += 9;
$size += $value_msg->jsonByteSize();
} else {
// Size for value. +1 for comma, -2 for "{}".
$size += $value_msg->jsonByteSize() -1;
}
} elseif (get_class($this) === 'Google\Protobuf\FieldMask') {
$field_mask = GPBUtil::formatFieldMask($this);
$size += strlen($field_mask) + 2; // 2 for ""
} elseif (get_class($this) === 'Google\Protobuf\Duration') {
$duration = GPBUtil::formatDuration($this) . "s";
$size += strlen($duration) + 2; // 2 for ""
} elseif (get_class($this) === 'Google\Protobuf\Timestamp') {
$timestamp = GPBUtil::formatTimestamp($this); $timestamp = GPBUtil::formatTimestamp($this);
$timestamp = json_encode($timestamp); $timestamp = json_encode($timestamp);
$size += strlen($timestamp); $size += strlen($timestamp);
} else { } else {
// Size for "{}". if (!GPBUtil::hasSpecialJsonMapping($this)) {
$size += 2; // Size for "{}".
$size += 2;
}
$fields = $this->desc->getField(); $fields = $this->desc->getField();
$count = 0; $count = 0;
foreach ($fields as $field) { foreach ($fields as $field) {
......
...@@ -363,7 +363,8 @@ generate_php_test_proto() { ...@@ -363,7 +363,8 @@ generate_php_test_proto() {
proto/test_service_namespace.proto \ proto/test_service_namespace.proto \
proto/test_descriptors.proto proto/test_descriptors.proto
pushd ../../src pushd ../../src
./protoc --php_out=../php/tests/generated -I../php/tests -I. ../php/tests/proto/test_import_descriptor_proto.proto ./protoc --php_out=../php/tests/generated -I../php/tests -I. \
../php/tests/proto/test_import_descriptor_proto.proto
popd popd
popd popd
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment