Procházet zdrojové kódy

Add native php support for Duration. (#3583)

Paul Yang před 8 roky
rodič
revize
7f8b91f552

+ 2 - 0
Makefile.am

@@ -603,6 +603,7 @@ php_EXTRA_DIST=                                                       \
   php/src/Google/Protobuf/Any.php                                     \
   php/src/Google/Protobuf/Any.php                                     \
   php/src/Google/Protobuf/Descriptor.php                              \
   php/src/Google/Protobuf/Descriptor.php                              \
   php/src/Google/Protobuf/DescriptorPool.php                          \
   php/src/Google/Protobuf/DescriptorPool.php                          \
+  php/src/Google/Protobuf/Duration.php                                \
   php/src/Google/Protobuf/EnumDescriptor.php                          \
   php/src/Google/Protobuf/EnumDescriptor.php                          \
   php/src/Google/Protobuf/EnumValueDescriptor.php                     \
   php/src/Google/Protobuf/EnumValueDescriptor.php                     \
   php/src/Google/Protobuf/FieldDescriptor.php                         \
   php/src/Google/Protobuf/FieldDescriptor.php                         \
@@ -667,6 +668,7 @@ php_EXTRA_DIST=                                                       \
   php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php   \
   php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php   \
   php/src/Google/Protobuf/Internal/UninterpretedOption.php            \
   php/src/Google/Protobuf/Internal/UninterpretedOption.php            \
   php/src/GPBMetadata/Google/Protobuf/Any.php                         \
   php/src/GPBMetadata/Google/Protobuf/Any.php                         \
+  php/src/GPBMetadata/Google/Protobuf/Duration.php                    \
   php/src/GPBMetadata/Google/Protobuf/Timestamp.php                   \
   php/src/GPBMetadata/Google/Protobuf/Timestamp.php                   \
   php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php         \
   php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php         \
   php/tests/array_test.php                                            \
   php/tests/array_test.php                                            \

+ 53 - 0
php/ext/google/protobuf/message.c

@@ -585,6 +585,59 @@ PHP_METHOD(Any, is) {
   RETURN_BOOL(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
 // Timestamp
 // -----------------------------------------------------------------------------
 // -----------------------------------------------------------------------------

+ 1 - 0
php/ext/google/protobuf/protobuf.c

@@ -257,6 +257,7 @@ 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);
   any_init(TSRMLS_C);
   any_init(TSRMLS_C);
+  duration_init(TSRMLS_C);
   timestamp_init(TSRMLS_C);
   timestamp_init(TSRMLS_C);
 
 
   return 0;
   return 0;

+ 10 - 0
php/ext/google/protobuf/protobuf.h

@@ -519,6 +519,7 @@ static inline int php_proto_zend_lookup_class(
 struct Any;
 struct Any;
 struct DescriptorPool;
 struct DescriptorPool;
 struct Descriptor;
 struct Descriptor;
+struct Duration;
 struct EnumDescriptor;
 struct EnumDescriptor;
 struct EnumValueDescriptor;
 struct EnumValueDescriptor;
 struct FieldDescriptor;
 struct FieldDescriptor;
@@ -536,6 +537,7 @@ struct Timestamp;
 typedef struct Any Any;
 typedef struct Any Any;
 typedef struct DescriptorPool DescriptorPool;
 typedef struct DescriptorPool DescriptorPool;
 typedef struct Descriptor Descriptor;
 typedef struct Descriptor Descriptor;
+typedef struct Duration Duration;
 typedef struct EnumDescriptor EnumDescriptor;
 typedef struct EnumDescriptor EnumDescriptor;
 typedef struct EnumValueDescriptor EnumValueDescriptor;
 typedef struct EnumValueDescriptor EnumValueDescriptor;
 typedef struct FieldDescriptor FieldDescriptor;
 typedef struct FieldDescriptor FieldDescriptor;
@@ -560,6 +562,7 @@ ZEND_END_MODULE_GLOBALS(protobuf)
 // Init module and PHP classes.
 // Init module and PHP classes.
 void any_init(TSRMLS_D);
 void any_init(TSRMLS_D);
 void descriptor_init(TSRMLS_D);
 void descriptor_init(TSRMLS_D);
+void duration_init(TSRMLS_D);
 void enum_descriptor_init(TSRMLS_D);
 void enum_descriptor_init(TSRMLS_D);
 void descriptor_pool_init(TSRMLS_D);
 void descriptor_pool_init(TSRMLS_D);
 void internal_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, pack);
 PHP_METHOD(Any, is);
 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, __construct);
 PHP_METHOD(Timestamp, fromDateTime);
 PHP_METHOD(Timestamp, fromDateTime);
 PHP_METHOD(Timestamp, toDateTime);
 PHP_METHOD(Timestamp, toDateTime);
@@ -1043,6 +1052,7 @@ PHP_METHOD(Timestamp, getNanos);
 PHP_METHOD(Timestamp, setNanos);
 PHP_METHOD(Timestamp, setNanos);
 
 
 extern zend_class_entry* any_type;
 extern zend_class_entry* any_type;
+extern zend_class_entry* duration_type;
 extern zend_class_entry* timestamp_type;
 extern zend_class_entry* timestamp_type;
 
 
 // -----------------------------------------------------------------------------
 // -----------------------------------------------------------------------------

+ 31 - 0
php/src/GPBMetadata/Google/Protobuf/Duration.php

@@ -0,0 +1,31 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: google/protobuf/duration.proto
+
+namespace GPBMetadata\Google\Protobuf;
+
+class Duration
+{
+    public static $is_initialized = false;
+
+    public static function initOnce() {
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+        if (static::$is_initialized == true) {
+          return;
+        }
+        $pool->internalAddGeneratedFile(hex2bin(
+            "0ae3010a1e676f6f676c652f70726f746f6275662f6475726174696f6e2e" .
+            "70726f746f120f676f6f676c652e70726f746f627566222a0a0844757261" .
+            "74696f6e120f0a077365636f6e6473180120012803120d0a056e616e6f73" .
+            "180220012805427c0a13636f6d2e676f6f676c652e70726f746f62756642" .
+            "0d4475726174696f6e50726f746f50015a2a6769746875622e636f6d2f67" .
+            "6f6c616e672f70726f746f6275662f7074797065732f6475726174696f6e" .
+            "f80101a20203475042aa021e476f6f676c652e50726f746f6275662e5765" .
+            "6c6c4b6e6f776e5479706573620670726f746f33"
+        ));
+
+        static::$is_initialized = true;
+    }
+}
+

+ 153 - 0
php/src/Google/Protobuf/Duration.php

@@ -0,0 +1,153 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: google/protobuf/duration.proto
+
+namespace Google\Protobuf;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * A Duration represents a signed, fixed-length span of time represented
+ * as a count of seconds and fractions of seconds at nanosecond
+ * resolution. It is independent of any calendar and concepts like "day"
+ * or "month". It is related to Timestamp in that the difference between
+ * two Timestamp values is a Duration and it can be added or subtracted
+ * from a Timestamp. Range is approximately +-10,000 years.
+ * # Examples
+ * Example 1: Compute Duration from two Timestamps in pseudo code.
+ *     Timestamp start = ...;
+ *     Timestamp end = ...;
+ *     Duration duration = ...;
+ *     duration.seconds = end.seconds - start.seconds;
+ *     duration.nanos = end.nanos - start.nanos;
+ *     if (duration.seconds < 0 && duration.nanos > 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 <code>google.protobuf.Duration</code>
+ */
+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 <code>int64 seconds = 1;</code>
+     */
+    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 <code>int32 nanos = 2;</code>
+     */
+    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 <code>int64 seconds = 1;</code>
+     * @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 <code>int64 seconds = 1;</code>
+     * @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 <code>int32 nanos = 2;</code>
+     * @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 <code>int32 nanos = 2;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setNanos($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->nanos = $var;
+
+        return $this;
+    }
+}
+

+ 11 - 0
php/tests/well_known_test.php

@@ -5,6 +5,7 @@ require_once('test_util.php');
 
 
 use Google\Protobuf\GPBEmpty;
 use Google\Protobuf\GPBEmpty;
 use Google\Protobuf\Any;
 use Google\Protobuf\Any;
+use Google\Protobuf\Duration;
 use Google\Protobuf\Timestamp;
 use Google\Protobuf\Timestamp;
 
 
 use Foo\TestMessage;
 use Foo\TestMessage;
@@ -107,4 +108,14 @@ class WellKnownTest extends TestBase {
         $this->assertSame(\DateTime::class, get_class($to));
         $this->assertSame(\DateTime::class, get_class($to));
         $this->assertSame($from->format('U'), $to->format('U'));
         $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());
+    }
 }
 }