From 7f8b91f552e80964d995712c26306410854d8ad1 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Tue, 5 Sep 2017 14:10:32 -0700 Subject: Add native php support for Duration. (#3583) --- php/ext/google/protobuf/message.c | 53 ++++++++ php/ext/google/protobuf/protobuf.c | 1 + php/ext/google/protobuf/protobuf.h | 10 ++ php/src/GPBMetadata/Google/Protobuf/Duration.php | 31 +++++ php/src/Google/Protobuf/Duration.php | 153 +++++++++++++++++++++++ php/tests/well_known_test.php | 11 ++ 6 files changed, 259 insertions(+) create mode 100644 php/src/GPBMetadata/Google/Protobuf/Duration.php create mode 100644 php/src/Google/Protobuf/Duration.php (limited to 'php') diff --git a/php/ext/google/protobuf/message.c b/php/ext/google/protobuf/message.c index 1faf486e..50a0430c 100644 --- a/php/ext/google/protobuf/message.c +++ b/php/ext/google/protobuf/message.c @@ -585,6 +585,59 @@ PHP_METHOD(Any, is) { RETURN_BOOL(is); } +// ----------------------------------------------------------------------------- +// Duration +// ----------------------------------------------------------------------------- + +static zend_function_entry duration_methods[] = { + PHP_ME(Duration, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Duration, getSeconds, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Duration, setSeconds, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Duration, getNanos, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Duration, setNanos, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* duration_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Duration", + Duration, duration) + zend_class_implements(duration_type TSRMLS_CC, 1, message_type); + zend_declare_property_long(duration_type, "seconds", strlen("seconds"), + 0 ,ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_long(duration_type, "nanos", strlen("nanos"), + 0 ,ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(Duration, __construct) { + PHP_PROTO_HASHTABLE_VALUE desc_php = get_ce_obj(duration_type); + if (desc_php == NULL) { + init_generated_pool_once(TSRMLS_C); + const char* generated_file = + "0ae3010a1e676f6f676c652f70726f746f6275662f6475726174696f6e2e" + "70726f746f120f676f6f676c652e70726f746f627566222a0a0844757261" + "74696f6e120f0a077365636f6e6473180120012803120d0a056e616e6f73" + "180220012805427c0a13636f6d2e676f6f676c652e70726f746f62756642" + "0d4475726174696f6e50726f746f50015a2a6769746875622e636f6d2f67" + "6f6c616e672f70726f746f6275662f7074797065732f6475726174696f6e" + "f80101a20203475042aa021e476f6f676c652e50726f746f6275662e5765" + "6c6c4b6e6f776e5479706573620670726f746f33"; + char* binary; + int binary_len; + hex_to_binary(generated_file, &binary, &binary_len); + + internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC); + FREE(binary); + } + + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(duration_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(Duration, duration, Seconds, "seconds") +PHP_PROTO_FIELD_ACCESSORS(Duration, duration, Nanos, "nanos") + // ----------------------------------------------------------------------------- // Timestamp // ----------------------------------------------------------------------------- diff --git a/php/ext/google/protobuf/protobuf.c b/php/ext/google/protobuf/protobuf.c index ec4e6523..42bc31cf 100644 --- a/php/ext/google/protobuf/protobuf.c +++ b/php/ext/google/protobuf/protobuf.c @@ -257,6 +257,7 @@ static PHP_MINIT_FUNCTION(protobuf) { repeated_field_iter_init(TSRMLS_C); util_init(TSRMLS_C); any_init(TSRMLS_C); + duration_init(TSRMLS_C); timestamp_init(TSRMLS_C); return 0; diff --git a/php/ext/google/protobuf/protobuf.h b/php/ext/google/protobuf/protobuf.h index 8ad7f6ca..d4ab2ce8 100644 --- a/php/ext/google/protobuf/protobuf.h +++ b/php/ext/google/protobuf/protobuf.h @@ -519,6 +519,7 @@ static inline int php_proto_zend_lookup_class( struct Any; struct DescriptorPool; struct Descriptor; +struct Duration; struct EnumDescriptor; struct EnumValueDescriptor; struct FieldDescriptor; @@ -536,6 +537,7 @@ struct Timestamp; typedef struct Any Any; typedef struct DescriptorPool DescriptorPool; typedef struct Descriptor Descriptor; +typedef struct Duration Duration; typedef struct EnumDescriptor EnumDescriptor; typedef struct EnumValueDescriptor EnumValueDescriptor; typedef struct FieldDescriptor FieldDescriptor; @@ -560,6 +562,7 @@ ZEND_END_MODULE_GLOBALS(protobuf) // Init module and PHP classes. void any_init(TSRMLS_D); void descriptor_init(TSRMLS_D); +void duration_init(TSRMLS_D); void enum_descriptor_init(TSRMLS_D); void descriptor_pool_init(TSRMLS_D); void internal_descriptor_pool_init(TSRMLS_D); @@ -1034,6 +1037,12 @@ PHP_METHOD(Any, unpack); PHP_METHOD(Any, pack); PHP_METHOD(Any, is); +PHP_METHOD(Duration, __construct); +PHP_METHOD(Duration, getSeconds); +PHP_METHOD(Duration, setSeconds); +PHP_METHOD(Duration, getNanos); +PHP_METHOD(Duration, setNanos); + PHP_METHOD(Timestamp, __construct); PHP_METHOD(Timestamp, fromDateTime); PHP_METHOD(Timestamp, toDateTime); @@ -1043,6 +1052,7 @@ PHP_METHOD(Timestamp, getNanos); PHP_METHOD(Timestamp, setNanos); extern zend_class_entry* any_type; +extern zend_class_entry* duration_type; extern zend_class_entry* timestamp_type; // ----------------------------------------------------------------------------- diff --git a/php/src/GPBMetadata/Google/Protobuf/Duration.php b/php/src/GPBMetadata/Google/Protobuf/Duration.php new file mode 100644 index 00000000..b1c85ad8 --- /dev/null +++ b/php/src/GPBMetadata/Google/Protobuf/Duration.php @@ -0,0 +1,31 @@ +internalAddGeneratedFile(hex2bin( + "0ae3010a1e676f6f676c652f70726f746f6275662f6475726174696f6e2e" . + "70726f746f120f676f6f676c652e70726f746f627566222a0a0844757261" . + "74696f6e120f0a077365636f6e6473180120012803120d0a056e616e6f73" . + "180220012805427c0a13636f6d2e676f6f676c652e70726f746f62756642" . + "0d4475726174696f6e50726f746f50015a2a6769746875622e636f6d2f67" . + "6f6c616e672f70726f746f6275662f7074797065732f6475726174696f6e" . + "f80101a20203475042aa021e476f6f676c652e50726f746f6275662e5765" . + "6c6c4b6e6f776e5479706573620670726f746f33" + )); + + static::$is_initialized = true; + } +} + diff --git a/php/src/Google/Protobuf/Duration.php b/php/src/Google/Protobuf/Duration.php new file mode 100644 index 00000000..ca1c4c07 --- /dev/null +++ b/php/src/Google/Protobuf/Duration.php @@ -0,0 +1,153 @@ + 0) { + * duration.seconds += 1; + * duration.nanos -= 1000000000; + * } else if (durations.seconds > 0 && duration.nanos < 0) { + * duration.seconds -= 1; + * duration.nanos += 1000000000; + * } + * Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. + * Timestamp start = ...; + * Duration duration = ...; + * Timestamp end = ...; + * end.seconds = start.seconds + duration.seconds; + * end.nanos = start.nanos + duration.nanos; + * if (end.nanos < 0) { + * end.seconds -= 1; + * end.nanos += 1000000000; + * } else if (end.nanos >= 1000000000) { + * end.seconds += 1; + * end.nanos -= 1000000000; + * } + * Example 3: Compute Duration from datetime.timedelta in Python. + * td = datetime.timedelta(days=3, minutes=10) + * duration = Duration() + * duration.FromTimedelta(td) + * # JSON Mapping + * In JSON format, the Duration type is encoded as a string rather than an + * object, where the string ends in the suffix "s" (indicating seconds) and + * is preceded by the number of seconds, with nanoseconds expressed as + * fractional seconds. For example, 3 seconds with 0 nanoseconds should be + * encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should + * be expressed in JSON format as "3.000000001s", and 3 seconds and 1 + * microsecond should be expressed in JSON format as "3.000001s". + * + * Generated from protobuf message google.protobuf.Duration + */ +class Duration extends \Google\Protobuf\Internal\Message +{ + /** + * Signed seconds of the span of time. Must be from -315,576,000,000 + * to +315,576,000,000 inclusive. Note: these bounds are computed from: + * 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + * + * Generated from protobuf field int64 seconds = 1; + */ + private $seconds = 0; + /** + * Signed fractions of a second at nanosecond resolution of the span + * of time. Durations less than one second are represented with a 0 + * `seconds` field and a positive or negative `nanos` field. For durations + * of one second or more, a non-zero value for the `nanos` field must be + * of the same sign as the `seconds` field. Must be from -999,999,999 + * to +999,999,999 inclusive. + * + * Generated from protobuf field int32 nanos = 2; + */ + private $nanos = 0; + + public function __construct() { + \GPBMetadata\Google\Protobuf\Duration::initOnce(); + parent::__construct(); + } + + /** + * Signed seconds of the span of time. Must be from -315,576,000,000 + * to +315,576,000,000 inclusive. Note: these bounds are computed from: + * 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + * + * Generated from protobuf field int64 seconds = 1; + * @return int|string + */ + public function getSeconds() + { + return $this->seconds; + } + + /** + * Signed seconds of the span of time. Must be from -315,576,000,000 + * to +315,576,000,000 inclusive. Note: these bounds are computed from: + * 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + * + * Generated from protobuf field int64 seconds = 1; + * @param int|string $var + * @return $this + */ + public function setSeconds($var) + { + GPBUtil::checkInt64($var); + $this->seconds = $var; + + return $this; + } + + /** + * Signed fractions of a second at nanosecond resolution of the span + * of time. Durations less than one second are represented with a 0 + * `seconds` field and a positive or negative `nanos` field. For durations + * of one second or more, a non-zero value for the `nanos` field must be + * of the same sign as the `seconds` field. Must be from -999,999,999 + * to +999,999,999 inclusive. + * + * Generated from protobuf field int32 nanos = 2; + * @return int + */ + public function getNanos() + { + return $this->nanos; + } + + /** + * Signed fractions of a second at nanosecond resolution of the span + * of time. Durations less than one second are represented with a 0 + * `seconds` field and a positive or negative `nanos` field. For durations + * of one second or more, a non-zero value for the `nanos` field must be + * of the same sign as the `seconds` field. Must be from -999,999,999 + * to +999,999,999 inclusive. + * + * Generated from protobuf field int32 nanos = 2; + * @param int $var + * @return $this + */ + public function setNanos($var) + { + GPBUtil::checkInt32($var); + $this->nanos = $var; + + return $this; + } +} + diff --git a/php/tests/well_known_test.php b/php/tests/well_known_test.php index 4441b13b..690ce5f5 100644 --- a/php/tests/well_known_test.php +++ b/php/tests/well_known_test.php @@ -5,6 +5,7 @@ require_once('test_util.php'); use Google\Protobuf\GPBEmpty; use Google\Protobuf\Any; +use Google\Protobuf\Duration; use Google\Protobuf\Timestamp; use Foo\TestMessage; @@ -107,4 +108,14 @@ class WellKnownTest extends TestBase { $this->assertSame(\DateTime::class, get_class($to)); $this->assertSame($from->format('U'), $to->format('U')); } + + public function testDuration() + { + $duration = new Duration(); + + $duration->setSeconds(1); + $duration->setNanos(2); + $this->assertEquals(1, $duration->getSeconds()); + $this->assertSame(2, $duration->getNanos()); + } } -- cgit v1.2.3