From 881f4ff6721446c02e11b4cf218e7cd14d374e0d Mon Sep 17 00:00:00 2001
From: Stanley Cheung <stanleycheung@google.com>
Date: Thu, 22 Sep 2016 16:15:58 -0700
Subject: [PATCH] PHP Proto3: new serialization/deserialization for messages

---
 src/php/lib/Grpc/AbstractCall.php        | 26 ++++++++++++++++++++++++
 src/php/lib/Grpc/BidiStreamingCall.php   |  2 +-
 src/php/lib/Grpc/ClientStreamingCall.php |  2 +-
 src/php/lib/Grpc/ServerStreamingCall.php |  2 +-
 src/php/lib/Grpc/UnaryCall.php           |  2 +-
 5 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/src/php/lib/Grpc/AbstractCall.php b/src/php/lib/Grpc/AbstractCall.php
index c58ee56742..e24be3fc76 100644
--- a/src/php/lib/Grpc/AbstractCall.php
+++ b/src/php/lib/Grpc/AbstractCall.php
@@ -120,6 +120,23 @@ abstract class AbstractCall
         $this->call->cancel();
     }
 
+    /**
+     * Serialize a message to the protobuf binary format
+     *
+     * @param mixed $data The Protobuf message
+     *
+     * @return string The protobuf binary format
+     */
+    protected function serializeMessage($data) {
+        // Proto3 implementation
+        if (method_exists($data, 'encode')) {
+            return $data->encode();
+        }
+
+        // Protobuf-PHP implementation
+        return $data->serialize();
+    }
+
     /**
      * Deserialize a response value to an object.
      *
@@ -133,6 +150,15 @@ abstract class AbstractCall
             return;
         }
 
+        // Proto3 implementation
+        if (is_array($this->deserialize)) {
+            list($className, $deserializeFunc) = $this->deserialize;
+            $obj = new $className();
+            $obj->$deserializeFunc($value);
+            return $obj;
+        }
+
+        // Protobuf-PHP implementation
         return call_user_func($this->deserialize, $value);
     }
 
diff --git a/src/php/lib/Grpc/BidiStreamingCall.php b/src/php/lib/Grpc/BidiStreamingCall.php
index 5d6ecfb275..f0e1e811de 100644
--- a/src/php/lib/Grpc/BidiStreamingCall.php
+++ b/src/php/lib/Grpc/BidiStreamingCall.php
@@ -81,7 +81,7 @@ class BidiStreamingCall extends AbstractCall
      */
     public function write($data, $options = [])
     {
-        $message_array = ['message' => $data->serialize()];
+        $message_array = ['message' => $this->serializeMessage($data)];
         if (array_key_exists('flags', $options)) {
             $message_array['flags'] = $options['flags'];
         }
diff --git a/src/php/lib/Grpc/ClientStreamingCall.php b/src/php/lib/Grpc/ClientStreamingCall.php
index c96e26d033..20db809ea3 100644
--- a/src/php/lib/Grpc/ClientStreamingCall.php
+++ b/src/php/lib/Grpc/ClientStreamingCall.php
@@ -62,7 +62,7 @@ class ClientStreamingCall extends AbstractCall
      */
     public function write($data, array $options = [])
     {
-        $message_array = ['message' => $data->serialize()];
+        $message_array = ['message' => $this->serializeMessage($data)];
         if (array_key_exists('flags', $options)) {
             $message_array['flags'] = $options['flags'];
         }
diff --git a/src/php/lib/Grpc/ServerStreamingCall.php b/src/php/lib/Grpc/ServerStreamingCall.php
index 5f0d42c528..5aeeafa94a 100644
--- a/src/php/lib/Grpc/ServerStreamingCall.php
+++ b/src/php/lib/Grpc/ServerStreamingCall.php
@@ -50,7 +50,7 @@ class ServerStreamingCall extends AbstractCall
      */
     public function start($data, $metadata = [], $options = [])
     {
-        $message_array = ['message' => $data->serialize()];
+        $message_array = ['message' => $this->serializeMessage($data)];
         if (array_key_exists('flags', $options)) {
             $message_array['flags'] = $options['flags'];
         }
diff --git a/src/php/lib/Grpc/UnaryCall.php b/src/php/lib/Grpc/UnaryCall.php
index 487b89ebc1..e8eb6487a8 100644
--- a/src/php/lib/Grpc/UnaryCall.php
+++ b/src/php/lib/Grpc/UnaryCall.php
@@ -50,7 +50,7 @@ class UnaryCall extends AbstractCall
      */
     public function start($data, $metadata = [], $options = [])
     {
-        $message_array = ['message' => $data->serialize()];
+        $message_array = ['message' => $this->serializeMessage($data)];
         if (isset($options['flags'])) {
             $message_array['flags'] = $options['flags'];
         }
-- 
GitLab