Browse Source

Fix issues for php map when parsing missing key/value (#6588)

* For missing message value, map should create a default message
instance in order to keep its invariable.
* On 32-bit platform, int64 map key should be string
Paul Yang 6 years ago
parent
commit
342ae0ebc3

+ 14 - 0
php/src/Google/Protobuf/Internal/MapEntry.php

@@ -32,6 +32,7 @@
 
 namespace Google\Protobuf\Internal;
 
+use Google\Protobuf\Internal\GPBType;
 use Google\Protobuf\Internal\Message;
 
 class MapEntry extends Message
@@ -39,6 +40,19 @@ class MapEntry extends Message
     public $key;
     public $value;
 
+    public function __construct($desc) {
+        parent::__construct($desc);
+        // For MapEntry, getValue should always return a valid value. Thus, we
+        // need to create a default instance value if the value type is
+        // message, in case no value is provided in data.
+        $value_field = $desc->getFieldByNumber(2);
+        if ($value_field->getType() == GPBType::MESSAGE) {
+            $klass = $value_field->getMessageType()->getClass();
+            $value = new $klass;
+            $this->setValue($value);
+        }
+    }
+
     public function setKey($key) {
       $this->key = $key;
     }

+ 18 - 8
php/src/Google/Protobuf/Internal/MapFieldIter.php

@@ -91,14 +91,24 @@ class MapFieldIter implements \Iterator
     public function key()
     {
         $key = key($this->container);
-        if ($this->key_type === GPBType::BOOL) {
-            // PHP associative array stores bool as integer for key.
-            return boolval($key);
-        } elseif ($this->key_type === GPBType::STRING) {
-            // PHP associative array stores int string as int for key.
-            return strval($key);
-        } else {
-            return $key;
+        switch ($this->key_type) {
+            case GPBType::INT64:
+            case GPBType::UINT64:
+            case GPBType::FIXED64:
+            case GPBType::SFIXED64:
+            case GPBType::SINT64:
+                if (PHP_INT_SIZE === 8) {
+                    return $key;
+                }
+                // Intentionally fall through
+            case GPBType::STRING:
+                // PHP associative array stores int string as int for key.
+                return strval($key);
+            case GPBType::BOOL:
+                // PHP associative array stores bool as integer for key.
+                return boolval($key);
+            default:
+                return $key;
         }
     }