Index: third_party/protobuf/php/src/Google/Protobuf/Internal/Message.php |
diff --git a/third_party/protobuf/php/src/Google/Protobuf/Internal/Message.php b/third_party/protobuf/php/src/Google/Protobuf/Internal/Message.php |
new file mode 100644 |
index 0000000000000000000000000000000000000000..3d1f1598cae6134d2b4923b030ce32174c231b70 |
--- /dev/null |
+++ b/third_party/protobuf/php/src/Google/Protobuf/Internal/Message.php |
@@ -0,0 +1,679 @@ |
+<?php |
+ |
+// Protocol Buffers - Google's data interchange format |
+// Copyright 2008 Google Inc. All rights reserved. |
+// https://developers.google.com/protocol-buffers/ |
+// |
+// Redistribution and use in source and binary forms, with or without |
+// modification, are permitted provided that the following conditions are |
+// met: |
+// |
+// * Redistributions of source code must retain the above copyright |
+// notice, this list of conditions and the following disclaimer. |
+// * Redistributions in binary form must reproduce the above |
+// copyright notice, this list of conditions and the following disclaimer |
+// in the documentation and/or other materials provided with the |
+// distribution. |
+// * Neither the name of Google Inc. nor the names of its |
+// contributors may be used to endorse or promote products derived from |
+// this software without specific prior written permission. |
+// |
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ |
+/** |
+ * Defines Message, the parent class extended by all protocol message classes. |
+ */ |
+ |
+namespace Google\Protobuf\Internal; |
+ |
+use Google\Protobuf\Internal\InputStream; |
+use Google\Protobuf\Internal\OutputStream; |
+use Google\Protobuf\Internal\DescriptorPool; |
+use Google\Protobuf\Internal\GPBLabel; |
+use Google\Protobuf\Internal\GPBType; |
+use Google\Protobuf\Internal\GPBWire; |
+use Google\Protobuf\Internal\MapEntry; |
+use Google\Protobuf\Internal\RepeatedField; |
+ |
+/** |
+ * Parent class of all proto messages. Users should not instantiate this class |
+ * or extend this class or its child classes by their own. See the comment of |
+ * specific functions for more details. |
+ */ |
+class Message |
+{ |
+ |
+ /** |
+ * @ignore |
+ */ |
+ private $desc; |
+ |
+ /** |
+ * @ignore |
+ */ |
+ public function __construct($desc = NULL) |
+ { |
+ // MapEntry message is shared by all types of map fields, whose |
+ // descriptors are different from each other. Thus, we cannot find a |
+ // specific descriptor from the descriptor pool. |
+ if (get_class($this) === 'Google\Protobuf\Internal\MapEntry') { |
+ $this->desc = $desc; |
+ return; |
+ } |
+ $pool = DescriptorPool::getGeneratedPool(); |
+ $this->desc = $pool->getDescriptorByClassName(get_class($this)); |
+ foreach ($this->desc->getField() as $field) { |
+ $setter = $field->getSetter(); |
+ if ($field->isMap()) { |
+ $message_type = $field->getMessageType(); |
+ $key_field = $message_type->getFieldByNumber(1); |
+ $value_field = $message_type->getFieldByNumber(2); |
+ switch ($value_field->getType()) { |
+ case GPBType::MESSAGE: |
+ case GPBType::GROUP: |
+ $map_field = new MapField( |
+ $key_field->getType(), |
+ $value_field->getType(), |
+ $value_field->getMessageType()->getClass()); |
+ $this->$setter($map_field); |
+ break; |
+ case GPBType::ENUM: |
+ $map_field = new MapField( |
+ $key_field->getType(), |
+ $value_field->getType(), |
+ $value_field->getEnumType()->getClass()); |
+ $this->$setter($map_field); |
+ break; |
+ default: |
+ $map_field = new MapField( |
+ $key_field->getType(), |
+ $value_field->getType()); |
+ $this->$setter($map_field); |
+ break; |
+ } |
+ } else if ($field->getLabel() === GPBLabel::REPEATED) { |
+ switch ($field->getType()) { |
+ case GPBType::MESSAGE: |
+ case GPBType::GROUP: |
+ $repeated_field = new RepeatedField( |
+ $field->getType(), |
+ $field->getMessageType()->getClass()); |
+ $this->$setter($repeated_field); |
+ break; |
+ case GPBType::ENUM: |
+ $repeated_field = new RepeatedField( |
+ $field->getType(), |
+ $field->getEnumType()->getClass()); |
+ $this->$setter($repeated_field); |
+ break; |
+ default: |
+ $repeated_field = new RepeatedField($field->getType()); |
+ $this->$setter($repeated_field); |
+ break; |
+ } |
+ } else if ($field->getOneofIndex() !== -1) { |
+ $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()]; |
+ $oneof_name = $oneof->getName(); |
+ $this->$oneof_name = new OneofField($oneof); |
+ } else if ($field->getLabel() === GPBLabel::OPTIONAL && |
+ PHP_INT_SIZE == 4) { |
+ switch ($field->getType()) { |
+ case GPBType::INT64: |
+ case GPBType::UINT64: |
+ case GPBType::FIXED64: |
+ case GPBType::SFIXED64: |
+ case GPBType::SINT64: |
+ $this->$setter("0"); |
+ } |
+ } |
+ } |
+ } |
+ |
+ protected function readOneof($number) |
+ { |
+ $field = $this->desc->getFieldByNumber($number); |
+ $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()]; |
+ $oneof_name = $oneof->getName(); |
+ $oneof_field = $this->$oneof_name; |
+ if ($number === $oneof_field->getNumber()) { |
+ return $oneof_field->getValue(); |
+ } else { |
+ return $this->defaultValue($field); |
+ } |
+ } |
+ |
+ protected function writeOneof($number, $value) |
+ { |
+ $field = $this->desc->getFieldByNumber($number); |
+ $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()]; |
+ $oneof_name = $oneof->getName(); |
+ $oneof_field = $this->$oneof_name; |
+ $oneof_field->setValue($value); |
+ $oneof_field->setFieldName($field->getName()); |
+ $oneof_field->setNumber($number); |
+ } |
+ |
+ /** |
+ * @ignore |
+ */ |
+ private function defaultValue($field) |
+ { |
+ $value = null; |
+ |
+ switch ($field->getType()) { |
+ case GPBType::DOUBLE: |
+ case GPBType::FLOAT: |
+ return 0.0; |
+ case GPBType::UINT32: |
+ case GPBType::UINT64: |
+ case GPBType::INT32: |
+ case GPBType::INT64: |
+ case GPBType::FIXED32: |
+ case GPBType::FIXED64: |
+ case GPBType::SFIXED32: |
+ case GPBType::SFIXED64: |
+ case GPBType::SINT32: |
+ case GPBType::SINT64: |
+ case GPBType::ENUM: |
+ return 0; |
+ case GPBType::BOOL: |
+ return false; |
+ case GPBType::STRING: |
+ case GPBType::BYTES: |
+ return ""; |
+ case GPBType::GROUP: |
+ case GPBType::MESSAGE: |
+ return null; |
+ default: |
+ user_error("Unsupported type."); |
+ return false; |
+ } |
+ } |
+ |
+ /** |
+ * @ignore |
+ */ |
+ private static function parseFieldFromStreamNoTag($input, $field, &$value) |
+ { |
+ switch ($field->getType()) { |
+ case GPBType::DOUBLE: |
+ if (!GPBWire::readDouble($input, $value)) { |
+ return false; |
+ } |
+ break; |
+ case GPBType::FLOAT: |
+ if (!GPBWire::readFloat($input, $value)) { |
+ return false; |
+ } |
+ break; |
+ case GPBType::INT64: |
+ if (!GPBWire::readInt64($input, $value)) { |
+ return false; |
+ } |
+ break; |
+ case GPBType::UINT64: |
+ if (!GPBWire::readUint64($input, $value)) { |
+ return false; |
+ } |
+ break; |
+ case GPBType::INT32: |
+ if (!GPBWire::readInt32($input, $value)) { |
+ return false; |
+ } |
+ break; |
+ case GPBType::FIXED64: |
+ if (!GPBWire::readFixed64($input, $value)) { |
+ return false; |
+ } |
+ break; |
+ case GPBType::FIXED32: |
+ if (!GPBWire::readFixed32($input, $value)) { |
+ return false; |
+ } |
+ break; |
+ case GPBType::BOOL: |
+ if (!GPBWire::readBool($input, $value)) { |
+ return false; |
+ } |
+ break; |
+ case GPBType::STRING: |
+ // TODO(teboring): Add utf-8 check. |
+ if (!GPBWire::readString($input, $value)) { |
+ return false; |
+ } |
+ break; |
+ case GPBType::GROUP: |
+ echo "GROUP\xA"; |
+ trigger_error("Not implemented.", E_ERROR); |
+ break; |
+ case GPBType::MESSAGE: |
+ if ($field->isMap()) { |
+ $value = new MapEntry($field->getMessageType()); |
+ } else { |
+ $klass = $field->getMessageType()->getClass(); |
+ $value = new $klass; |
+ } |
+ if (!GPBWire::readMessage($input, $value)) { |
+ return false; |
+ } |
+ break; |
+ case GPBType::BYTES: |
+ if (!GPBWire::readString($input, $value)) { |
+ return false; |
+ } |
+ break; |
+ case GPBType::UINT32: |
+ if (!GPBWire::readUint32($input, $value)) { |
+ return false; |
+ } |
+ break; |
+ case GPBType::ENUM: |
+ // TODO(teboring): Check unknown enum value. |
+ if (!GPBWire::readInt32($input, $value)) { |
+ return false; |
+ } |
+ break; |
+ case GPBType::SFIXED32: |
+ if (!GPBWire::readSfixed32($input, $value)) { |
+ return false; |
+ } |
+ break; |
+ case GPBType::SFIXED64: |
+ if (!GPBWire::readSfixed64($input, $value)) { |
+ return false; |
+ } |
+ break; |
+ case GPBType::SINT32: |
+ if (!GPBWire::readSint32($input, $value)) { |
+ return false; |
+ } |
+ break; |
+ case GPBType::SINT64: |
+ if (!GPBWire::readSint64($input, $value)) { |
+ return false; |
+ } |
+ break; |
+ default: |
+ user_error("Unsupported type."); |
+ return false; |
+ } |
+ return true; |
+ } |
+ |
+ /** |
+ * @ignore |
+ */ |
+ private function parseFieldFromStream($tag, $input, $field) |
+ { |
+ $value = null; |
+ $field_type = $field->getType(); |
+ |
+ $value_format = GPBWire::UNKNOWN; |
+ if (GPBWire::getTagWireType($tag) === |
+ GPBWire::getWireType($field_type)) { |
+ $value_format = GPBWire::NORMAL_FORMAT; |
+ } elseif ($field->isPackable() && |
+ GPBWire::getTagWireType($tag) === |
+ GPBWire::WIRETYPE_LENGTH_DELIMITED) { |
+ $value_format = GPBWire::PACKED_FORMAT; |
+ } |
+ |
+ if ($value_format === GPBWire::NORMAL_FORMAT) { |
+ if (!self::parseFieldFromStreamNoTag($input, $field, $value)) { |
+ return false; |
+ } |
+ } elseif ($value_format === GPBWire::PACKED_FORMAT) { |
+ $length = 0; |
+ if (!GPBWire::readInt32($input, $length)) { |
+ return false; |
+ } |
+ $limit = $input->pushLimit($length); |
+ $getter = $field->getGetter(); |
+ while ($input->bytesUntilLimit() > 0) { |
+ if (!self::parseFieldFromStreamNoTag($input, $field, $value)) { |
+ return false; |
+ } |
+ $this->$getter()[] = $value; |
+ } |
+ $input->popLimit($limit); |
+ return true; |
+ } else { |
+ return false; |
+ } |
+ |
+ if ($field->isMap()) { |
+ $getter = $field->getGetter(); |
+ $this->$getter()[$value->getKey()] = $value->getValue(); |
+ } else if ($field->isRepeated()) { |
+ $getter = $field->getGetter(); |
+ $this->$getter()[] = $value; |
+ } else { |
+ $setter = $field->getSetter(); |
+ $this->$setter($value); |
+ } |
+ |
+ return true; |
+ } |
+ |
+ /** |
+ * Parses a protocol buffer contained in a string. |
+ * |
+ * This function takes a string in the (non-human-readable) binary wire |
+ * format, matching the encoding output by encode(). |
+ * |
+ * @param string $data Binary protobuf data. |
+ * @return bool Return true on success. |
+ */ |
+ public function decode($data) |
+ { |
+ $input = new InputStream($data); |
+ $this->parseFromStream($input); |
+ } |
+ |
+ /** |
+ * @ignore |
+ */ |
+ public function parseFromStream($input) |
+ { |
+ while (true) { |
+ $tag = $input->readTag(); |
+ // End of input. This is a valid place to end, so return true. |
+ if ($tag === 0) { |
+ return true; |
+ } |
+ |
+ $number = GPBWire::getTagFieldNumber($tag); |
+ $field = $this->desc->getFieldByNumber($number); |
+ |
+ if (!$this->parseFieldFromStream($tag, $input, $field)) { |
+ return false; |
+ } |
+ } |
+ } |
+ |
+ /** |
+ * @ignore |
+ */ |
+ private function serializeSingularFieldToStream($field, &$output) |
+ { |
+ if (!$this->existField($field)) { |
+ return true; |
+ } |
+ $getter = $field->getGetter(); |
+ $value = $this->$getter(); |
+ if (!GPBWire::serializeFieldToStream($value, $field, true, $output)) { |
+ return false; |
+ } |
+ return true; |
+ } |
+ |
+ /** |
+ * @ignore |
+ */ |
+ private function serializeRepeatedFieldToStream($field, &$output) |
+ { |
+ $getter = $field->getGetter(); |
+ $values = $this->$getter(); |
+ $count = count($values); |
+ if ($count === 0) { |
+ return true; |
+ } |
+ |
+ $packed = $field->getPacked(); |
+ if ($packed) { |
+ if (!GPBWire::writeTag( |
+ $output, |
+ GPBWire::makeTag($field->getNumber(), GPBType::STRING))) { |
+ return false; |
+ } |
+ $size = 0; |
+ foreach ($values as $value) { |
+ $size += $this->fieldDataOnlyByteSize($field, $value); |
+ } |
+ if (!$output->writeVarint32($size)) { |
+ return false; |
+ } |
+ } |
+ |
+ foreach ($values as $value) { |
+ if (!GPBWire::serializeFieldToStream( |
+ $value, |
+ $field, |
+ !$packed, |
+ $output)) { |
+ return false; |
+ } |
+ } |
+ return true; |
+ } |
+ |
+ /** |
+ * @ignore |
+ */ |
+ private function serializeMapFieldToStream($field, $output) |
+ { |
+ $getter = $field->getGetter(); |
+ $values = $this->$getter(); |
+ $count = count($values); |
+ if ($count === 0) { |
+ return true; |
+ } |
+ |
+ foreach ($values as $key => $value) { |
+ $map_entry = new MapEntry($field->getMessageType()); |
+ $map_entry->setKey($key); |
+ $map_entry->setValue($value); |
+ if (!GPBWire::serializeFieldToStream( |
+ $map_entry, |
+ $field, |
+ true, |
+ $output)) { |
+ return false; |
+ } |
+ } |
+ return true; |
+ } |
+ |
+ /** |
+ * @ignore |
+ */ |
+ private function serializeFieldToStream(&$output, $field) |
+ { |
+ if ($field->isMap()) { |
+ return $this->serializeMapFieldToStream($field, $output); |
+ } elseif ($field->isRepeated()) { |
+ return $this->serializeRepeatedFieldToStream($field, $output); |
+ } else { |
+ return $this->serializeSingularFieldToStream($field, $output); |
+ } |
+ } |
+ |
+ /** |
+ * @ignore |
+ */ |
+ public function serializeToStream(&$output) |
+ { |
+ $fields = $this->desc->getField(); |
+ foreach ($fields as $field) { |
+ if (!$this->serializeFieldToStream($output, $field)) { |
+ return false; |
+ } |
+ } |
+ return true; |
+ } |
+ |
+ /** |
+ * Serialize the message to string. |
+ * @return string Serialized binary protobuf data. |
+ */ |
+ public function encode() |
+ { |
+ $output = new OutputStream($this->byteSize()); |
+ $this->serializeToStream($output); |
+ return $output->getData(); |
+ } |
+ |
+ /** |
+ * @ignore |
+ */ |
+ private function existField($field) |
+ { |
+ $getter = $field->getGetter(); |
+ $value = $this->$getter(); |
+ return $value !== $this->defaultValue($field); |
+ } |
+ |
+ /** |
+ * @ignore |
+ */ |
+ private function repeatedFieldDataOnlyByteSize($field) |
+ { |
+ $size = 0; |
+ |
+ $getter = $field->getGetter(); |
+ $values = $this->$getter(); |
+ $count = count($values); |
+ if ($count !== 0) { |
+ $size += $count * GPBWire::tagSize($field); |
+ foreach ($values as $value) { |
+ $size += $this->singularFieldDataOnlyByteSize($field); |
+ } |
+ } |
+ } |
+ |
+ /** |
+ * @ignore |
+ */ |
+ private function fieldDataOnlyByteSize($field, $value) |
+ { |
+ $size = 0; |
+ |
+ switch ($field->getType()) { |
+ case GPBType::BOOL: |
+ $size += 1; |
+ break; |
+ case GPBType::FLOAT: |
+ case GPBType::FIXED32: |
+ case GPBType::SFIXED32: |
+ $size += 4; |
+ break; |
+ case GPBType::DOUBLE: |
+ case GPBType::FIXED64: |
+ case GPBType::SFIXED64: |
+ $size += 8; |
+ break; |
+ case GPBType::UINT32: |
+ case GPBType::INT32: |
+ case GPBType::ENUM: |
+ $size += GPBWire::varint32Size($value); |
+ break; |
+ case GPBType::UINT64: |
+ case GPBType::INT64: |
+ $size += GPBWire::varint64Size($value); |
+ break; |
+ case GPBType::SINT32: |
+ $size += GPBWire::sint32Size($value); |
+ break; |
+ case GPBType::SINT64: |
+ $size += GPBWire::sint64Size($value); |
+ break; |
+ case GPBType::STRING: |
+ case GPBType::BYTES: |
+ $size += strlen($value); |
+ $size += GPBWire::varint32Size($size); |
+ break; |
+ case GPBType::MESSAGE: |
+ $size += $value->byteSize(); |
+ $size += GPBWire::varint32Size($size); |
+ break; |
+ case GPBType::GROUP: |
+ // TODO(teboring): Add support. |
+ user_error("Unsupported type."); |
+ break; |
+ default: |
+ user_error("Unsupported type."); |
+ return 0; |
+ } |
+ |
+ return $size; |
+ } |
+ |
+ /** |
+ * @ignore |
+ */ |
+ private function fieldByteSize($field) |
+ { |
+ $size = 0; |
+ if ($field->isMap()) { |
+ $getter = $field->getGetter(); |
+ $values = $this->$getter(); |
+ $count = count($values); |
+ if ($count !== 0) { |
+ $size += $count * GPBWire::tagSize($field); |
+ $message_type = $field->getMessageType(); |
+ $key_field = $message_type->getFieldByNumber(1); |
+ $value_field = $message_type->getFieldByNumber(2); |
+ foreach ($values as $key => $value) { |
+ $data_size = 0; |
+ $data_size += $this->fieldDataOnlyByteSize($key_field, $key); |
+ $data_size += $this->fieldDataOnlyByteSize( |
+ $value_field, |
+ $value); |
+ $data_size += GPBWire::tagSize($key_field); |
+ $data_size += GPBWire::tagSize($value_field); |
+ $size += GPBWire::varint32Size($data_size) + $data_size; |
+ } |
+ } |
+ } elseif ($field->isRepeated()) { |
+ $getter = $field->getGetter(); |
+ $values = $this->$getter(); |
+ $count = count($values); |
+ if ($count !== 0) { |
+ if ($field->getPacked()) { |
+ $data_size = 0; |
+ foreach ($values as $value) { |
+ $data_size += $this->fieldDataOnlyByteSize($field, $value); |
+ } |
+ $size += GPBWire::tagSize($field); |
+ $size += GPBWire::varint32Size($data_size); |
+ $size += $data_size; |
+ } else { |
+ $size += $count * GPBWire::tagSize($field); |
+ foreach ($values as $value) { |
+ $size += $this->fieldDataOnlyByteSize($field, $value); |
+ } |
+ } |
+ } |
+ } elseif ($this->existField($field)) { |
+ $size += GPBWire::tagSize($field); |
+ $getter = $field->getGetter(); |
+ $value = $this->$getter(); |
+ $size += $this->fieldDataOnlyByteSize($field, $value); |
+ } |
+ return $size; |
+ } |
+ |
+ /** |
+ * @ignore |
+ */ |
+ public function byteSize() |
+ { |
+ $size = 0; |
+ |
+ $fields = $this->desc->getField(); |
+ foreach ($fields as $field) { |
+ $size += $this->fieldByteSize($field); |
+ } |
+ return $size; |
+ } |
+} |