| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022 |
- <?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\CodedInputStream;
- use Google\Protobuf\Internal\CodedOutputStream;
- 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;
- use Google\Protobuf\ListValue;
- use Google\Protobuf\Value;
- use Google\Protobuf\Struct;
- use Google\Protobuf\NullValue;
- /**
- * 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;
- private $unknown = "";
- /**
- * @ignore
- */
- public function __construct($data = 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 ($this instanceof MapEntry) {
- $this->initWithDescriptor($data);
- } else {
- $this->initWithGeneratedPool();
- if (is_array($data)) {
- $this->mergeFromArray($data);
- } else if (!empty($data)) {
- throw new \InvalidArgumentException(
- 'Message constructor must be an array or null.'
- );
- }
- }
- }
- /**
- * @ignore
- */
- private function initWithGeneratedPool()
- {
- $pool = DescriptorPool::getGeneratedPool();
- $this->desc = $pool->getDescriptorByClassName(get_class($this));
- if (is_null($this->desc)) {
- user_error(get_class($this) . " is not found in descriptor pool.");
- return;
- }
- 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");
- }
- }
- }
- }
- /**
- * @ignore
- */
- private function initWithDescriptor(Descriptor $desc)
- {
- $this->desc = $desc;
- foreach ($desc->getField() as $field) {
- $setter = $field->getSetter();
- $defaultValue = $this->defaultValue($field);
- $this->$setter($defaultValue);
- }
- }
- protected function readWrapperValue($member)
- {
- $field = $this->desc->getFieldByName($member);
- $oneof_index = $field->getOneofIndex();
- if ($oneof_index === -1) {
- $wrapper = $this->$member;
- } else {
- $wrapper = $this->readOneof($field->getNumber());
- }
- if (is_null($wrapper)) {
- return NULL;
- } else {
- return $wrapper->getValue();
- }
- }
- protected function writeWrapperValue($member, $value)
- {
- $field = $this->desc->getFieldByName($member);
- $wrapped_value = $value;
- if (!is_null($value)) {
- $desc = $field->getMessageType();
- $klass = $desc->getClass();
- $wrapped_value = new $klass;
- $wrapped_value->setValue($value);
- }
- $oneof_index = $field->getOneofIndex();
- if ($oneof_index === -1) {
- $this->$member = $wrapped_value;
- } else {
- $this->writeOneof($field->getNumber(), $wrapped_value);
- }
- }
- 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 hasOneof($number)
- {
- $field = $this->desc->getFieldByNumber($number);
- $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()];
- $oneof_name = $oneof->getName();
- $oneof_field = $this->$oneof_name;
- return $number === $oneof_field->getNumber();
- }
- 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);
- }
- protected function whichOneof($oneof_name)
- {
- $oneof_field = $this->$oneof_name;
- $number = $oneof_field->getNumber();
- if ($number == 0) {
- return "";
- }
- $field = $this->desc->getFieldByNumber($number);
- return $field->getName();
- }
- /**
- * @ignore
- */
- private function defaultValue($field)
- {
- $value = null;
- switch ($field->getType()) {
- case GPBType::DOUBLE:
- case GPBType::FLOAT:
- return 0.0;
- case GPBType::UINT32:
- case GPBType::INT32:
- case GPBType::FIXED32:
- case GPBType::SFIXED32:
- case GPBType::SINT32:
- case GPBType::ENUM:
- return 0;
- case GPBType::INT64:
- case GPBType::UINT64:
- case GPBType::FIXED64:
- case GPBType::SFIXED64:
- case GPBType::SINT64:
- if (PHP_INT_SIZE === 4) {
- return '0';
- } else {
- 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 function skipField($input, $tag)
- {
- $number = GPBWire::getTagFieldNumber($tag);
- if ($number === 0) {
- throw new GPBDecodeException("Illegal field number zero.");
- }
- $start = $input->current();
- switch (GPBWire::getTagWireType($tag)) {
- case GPBWireType::VARINT:
- $uint64 = 0;
- if (!$input->readVarint64($uint64)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside varint.");
- }
- break;
- case GPBWireType::FIXED64:
- $uint64 = 0;
- if (!$input->readLittleEndian64($uint64)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside fixed64.");
- }
- break;
- case GPBWireType::FIXED32:
- $uint32 = 0;
- if (!$input->readLittleEndian32($uint32)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside fixed32.");
- }
- break;
- case GPBWireType::LENGTH_DELIMITED:
- $length = 0;
- if (!$input->readVarint32($length)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside length.");
- }
- $data = NULL;
- if (!$input->readRaw($length, $data)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside length delimited data.");
- }
- break;
- case GPBWireType::START_GROUP:
- case GPBWireType::END_GROUP:
- throw new GPBDecodeException("Unexpected wire type.");
- default:
- throw new GPBDecodeException("Unexpected wire type.");
- }
- $end = $input->current();
- $bytes = str_repeat(chr(0), CodedOutputStream::MAX_VARINT64_BYTES);
- $size = CodedOutputStream::writeVarintToArray($tag, $bytes, true);
- $this->unknown .= substr($bytes, 0, $size) . $input->substr($start, $end);
- }
- /**
- * @ignore
- */
- private static function parseFieldFromStreamNoTag($input, $field, &$value)
- {
- switch ($field->getType()) {
- case GPBType::DOUBLE:
- if (!GPBWire::readDouble($input, $value)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside double field.");
- }
- break;
- case GPBType::FLOAT:
- if (!GPBWire::readFloat($input, $value)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside float field.");
- }
- break;
- case GPBType::INT64:
- if (!GPBWire::readInt64($input, $value)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside int64 field.");
- }
- break;
- case GPBType::UINT64:
- if (!GPBWire::readUint64($input, $value)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside uint64 field.");
- }
- break;
- case GPBType::INT32:
- if (!GPBWire::readInt32($input, $value)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside int32 field.");
- }
- break;
- case GPBType::FIXED64:
- if (!GPBWire::readFixed64($input, $value)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside fixed64 field.");
- }
- break;
- case GPBType::FIXED32:
- if (!GPBWire::readFixed32($input, $value)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside fixed32 field.");
- }
- break;
- case GPBType::BOOL:
- if (!GPBWire::readBool($input, $value)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside bool field.");
- }
- break;
- case GPBType::STRING:
- // TODO(teboring): Add utf-8 check.
- if (!GPBWire::readString($input, $value)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside string field.");
- }
- break;
- case GPBType::GROUP:
- 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)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside message.");
- }
- break;
- case GPBType::BYTES:
- if (!GPBWire::readString($input, $value)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside bytes field.");
- }
- break;
- case GPBType::UINT32:
- if (!GPBWire::readUint32($input, $value)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside uint32 field.");
- }
- break;
- case GPBType::ENUM:
- // TODO(teboring): Check unknown enum value.
- if (!GPBWire::readInt32($input, $value)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside enum field.");
- }
- break;
- case GPBType::SFIXED32:
- if (!GPBWire::readSfixed32($input, $value)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside sfixed32 field.");
- }
- break;
- case GPBType::SFIXED64:
- if (!GPBWire::readSfixed64($input, $value)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside sfixed64 field.");
- }
- break;
- case GPBType::SINT32:
- if (!GPBWire::readSint32($input, $value)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside sint32 field.");
- }
- break;
- case GPBType::SINT64:
- if (!GPBWire::readSint64($input, $value)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside sint64 field.");
- }
- break;
- default:
- user_error("Unsupported type.");
- return false;
- }
- return true;
- }
- /**
- * @ignore
- */
- private function parseFieldFromStream($tag, $input, $field)
- {
- $value = null;
- if (is_null($field)) {
- $value_format = GPBWire::UNKNOWN;
- } elseif (GPBWire::getTagWireType($tag) ===
- GPBWire::getWireType($field->getType())) {
- $value_format = GPBWire::NORMAL_FORMAT;
- } elseif ($field->isPackable() &&
- GPBWire::getTagWireType($tag) ===
- GPBWire::WIRETYPE_LENGTH_DELIMITED) {
- $value_format = GPBWire::PACKED_FORMAT;
- } else {
- // the wire type doesn't match. Put it in our unknown field set.
- $value_format = GPBWire::UNKNOWN;
- }
- if ($value_format === GPBWire::UNKNOWN) {
- $this->skipField($input, $tag);
- return;
- } elseif ($value_format === GPBWire::NORMAL_FORMAT) {
- self::parseFieldFromStreamNoTag($input, $field, $value);
- } elseif ($value_format === GPBWire::PACKED_FORMAT) {
- $length = 0;
- if (!GPBWire::readInt32($input, $length)) {
- throw new GPBDecodeException(
- "Unexpected EOF inside packed length.");
- }
- $limit = $input->pushLimit($length);
- $getter = $field->getGetter();
- while ($input->bytesUntilLimit() > 0) {
- self::parseFieldFromStreamNoTag($input, $field, $value);
- $this->appendHelper($field, $value);
- }
- $input->popLimit($limit);
- return;
- } else {
- return;
- }
- if ($field->isMap()) {
- $this->kvUpdateHelper($field, $value->getKey(), $value->getValue());
- } else if ($field->isRepeated()) {
- $this->appendHelper($field, $value);
- } else {
- $setter = $field->getSetter();
- $this->$setter($value);
- }
- }
- /**
- * Clear all containing fields.
- * @return null.
- */
- public function clear()
- {
- $this->unknown = "";
- 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) {
- switch ($field->getType()) {
- case GPBType::DOUBLE :
- case GPBType::FLOAT :
- $this->$setter(0.0);
- break;
- case GPBType::INT32 :
- case GPBType::FIXED32 :
- case GPBType::UINT32 :
- case GPBType::SFIXED32 :
- case GPBType::SINT32 :
- case GPBType::ENUM :
- $this->$setter(0);
- break;
- case GPBType::BOOL :
- $this->$setter(false);
- break;
- case GPBType::STRING :
- case GPBType::BYTES :
- $this->$setter("");
- break;
- case GPBType::GROUP :
- case GPBType::MESSAGE :
- $null = null;
- $this->$setter($null);
- break;
- }
- if (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");
- }
- } else {
- switch ($field->getType()) {
- case GPBType::INT64:
- case GPBType::UINT64:
- case GPBType::FIXED64:
- case GPBType::SFIXED64:
- case GPBType::SINT64:
- $this->$setter(0);
- }
- }
- }
- }
- }
- /**
- * Clear all unknown fields previously parsed.
- * @return null.
- */
- public function discardUnknownFields()
- {
- $this->unknown = "";
- foreach ($this->desc->getField() as $field) {
- if ($field->getType() != GPBType::MESSAGE) {
- continue;
- }
- if ($field->isMap()) {
- $value_field = $field->getMessageType()->getFieldByNumber(2);
- if ($value_field->getType() != GPBType::MESSAGE) {
- continue;
- }
- $getter = $field->getGetter();
- $map = $this->$getter();
- foreach ($map as $key => $value) {
- $value->discardUnknownFields();
- }
- } else if ($field->getLabel() === GPBLabel::REPEATED) {
- $getter = $field->getGetter();
- $arr = $this->$getter();
- foreach ($arr as $sub) {
- $sub->discardUnknownFields();
- }
- } else if ($field->getLabel() === GPBLabel::OPTIONAL) {
- $getter = $field->getGetter();
- $sub = $this->$getter();
- if (!is_null($sub)) {
- $sub->discardUnknownFields();
- }
- }
- }
- }
- /**
- * Merges the contents of the specified message into current message.
- *
- * This method merges the contents of the specified message into the
- * current message. Singular fields that are set in the specified message
- * overwrite the corresponding fields in the current message. Repeated
- * fields are appended. Map fields key-value pairs are overwritten.
- * Singular/Oneof sub-messages are recursively merged. All overwritten
- * sub-messages are deep-copied.
- *
- * @param object $msg Protobuf message to be merged from.
- * @return null.
- */
- public function mergeFrom($msg)
- {
- if (get_class($this) !== get_class($msg)) {
- user_error("Cannot merge messages with different class.");
- return;
- }
- foreach ($this->desc->getField() as $field) {
- $setter = $field->getSetter();
- $getter = $field->getGetter();
- if ($field->isMap()) {
- if (count($msg->$getter()) != 0) {
- $value_field = $field->getMessageType()->getFieldByNumber(2);
- foreach ($msg->$getter() as $key => $value) {
- if ($value_field->getType() == GPBType::MESSAGE) {
- $klass = $value_field->getMessageType()->getClass();
- $copy = new $klass;
- $copy->mergeFrom($value);
- $this->kvUpdateHelper($field, $key, $copy);
- } else {
- $this->kvUpdateHelper($field, $key, $value);
- }
- }
- }
- } else if ($field->getLabel() === GPBLabel::REPEATED) {
- if (count($msg->$getter()) != 0) {
- foreach ($msg->$getter() as $tmp) {
- if ($field->getType() == GPBType::MESSAGE) {
- $klass = $field->getMessageType()->getClass();
- $copy = new $klass;
- $copy->mergeFrom($tmp);
- $this->appendHelper($field, $copy);
- } else {
- $this->appendHelper($field, $tmp);
- }
- }
- }
- } else if ($field->getLabel() === GPBLabel::OPTIONAL) {
- if($msg->$getter() !== $this->defaultValue($field)) {
- $tmp = $msg->$getter();
- if ($field->getType() == GPBType::MESSAGE) {
- if (is_null($this->$getter())) {
- $klass = $field->getMessageType()->getClass();
- $new_msg = new $klass;
- $this->$setter($new_msg);
- }
- $this->$getter()->mergeFrom($tmp);
- } else {
- $this->$setter($tmp);
- }
- }
- }
- }
- }
- /**
- * 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 serializeToString().
- * See mergeFrom() for merging behavior, if the field is already set in the
- * specified message.
- *
- * @param string $data Binary protobuf data.
- * @return null.
- * @throws \Exception Invalid data.
- */
- public function mergeFromString($data)
- {
- $input = new CodedInputStream($data);
- $this->parseFromStream($input);
- }
- /**
- * Parses a json string to protobuf message.
- *
- * This function takes a string in the json wire format, matching the
- * encoding output by serializeToJsonString().
- * See mergeFrom() for merging behavior, if the field is already set in the
- * specified message.
- *
- * @param string $data Json protobuf data.
- * @return null.
- * @throws \Exception Invalid data.
- */
- public function mergeFromJsonString($data, $ignore_unknown = false)
- {
- $input = new RawInputStream($data);
- $this->parseFromJsonStream($input, $ignore_unknown);
- }
- /**
- * @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);
- $this->parseFieldFromStream($tag, $input, $field);
- }
- }
- private function convertJsonValueToProtoValue(
- $value,
- $field,
- $ignore_unknown,
- $is_map_key = false)
- {
- switch ($field->getType()) {
- case GPBType::MESSAGE:
- $klass = $field->getMessageType()->getClass();
- $submsg = new $klass;
- if (is_a($submsg, "Google\Protobuf\Duration")) {
- if (is_null($value)) {
- return $this->defaultValue($field);
- } else if (!is_string($value)) {
- throw new GPBDecodeException("Expect string.");
- }
- return GPBUtil::parseDuration($value);
- } else if ($field->isTimestamp()) {
- if (is_null($value)) {
- return $this->defaultValue($field);
- } else if (!is_string($value)) {
- throw new GPBDecodeException("Expect string.");
- }
- try {
- $timestamp = GPBUtil::parseTimestamp($value);
- } catch (\Exception $e) {
- throw new GPBDecodeException(
- "Invalid RFC 3339 timestamp: ".$e->getMessage());
- }
- $submsg->setSeconds($timestamp->getSeconds());
- $submsg->setNanos($timestamp->getNanos());
- } else if (is_a($submsg, "Google\Protobuf\FieldMask")) {
- if (is_null($value)) {
- return $this->defaultValue($field);
- }
- try {
- return GPBUtil::parseFieldMask($value);
- } catch (\Exception $e) {
- throw new GPBDecodeException(
- "Invalid FieldMask: ".$e->getMessage());
- }
- } else {
- if (is_null($value) &&
- !is_a($submsg, "Google\Protobuf\Value")) {
- return $this->defaultValue($field);
- }
- if (GPBUtil::hasSpecialJsonMapping($submsg)) {
- } elseif (!is_object($value) && !is_array($value)) {
- throw new GPBDecodeException("Expect message.");
- }
- $submsg->mergeFromJsonArray($value, $ignore_unknown);
- }
- return $submsg;
- case GPBType::ENUM:
- if (is_null($value)) {
- return $this->defaultValue($field);
- }
- if (is_integer($value)) {
- return $value;
- }
- $enum_value = $field->getEnumType()->getValueByName($value);
- if (!is_null($enum_value)) {
- return $enum_value->getNumber();
- } else if ($ignore_unknown) {
- return $this->defaultValue($field);
- } else {
- throw new GPBDecodeException(
- "Enum field only accepts integer or enum value name");
- }
- case GPBType::STRING:
- if (is_null($value)) {
- return $this->defaultValue($field);
- }
- if (is_numeric($value)) {
- return strval($value);
- }
- if (!is_string($value)) {
- throw new GPBDecodeException(
- "String field only accepts string value");
- }
- return $value;
- case GPBType::BYTES:
- if (is_null($value)) {
- return $this->defaultValue($field);
- }
- if (!is_string($value)) {
- throw new GPBDecodeException(
- "Byte field only accepts string value");
- }
- $proto_value = base64_decode($value, true);
- if ($proto_value === false) {
- throw new GPBDecodeException("Invalid base64 characters");
- }
- return $proto_value;
- case GPBType::BOOL:
- if (is_null($value)) {
- return $this->defaultValue($field);
- }
- if ($is_map_key) {
- if ($value === "true") {
- return true;
- }
- if ($value === "false") {
- return false;
- }
- throw new GPBDecodeException(
- "Bool field only accepts bool value");
- }
- if (!is_bool($value)) {
- throw new GPBDecodeException(
- "Bool field only accepts bool value");
- }
- return $value;
- case GPBType::FLOAT:
- case GPBType::DOUBLE:
- if (is_null($value)) {
- return $this->defaultValue($field);
- }
- if ($value === "Infinity") {
- return INF;
- }
- if ($value === "-Infinity") {
- return -INF;
- }
- if ($value === "NaN") {
- return NAN;
- }
- return $value;
- case GPBType::INT32:
- case GPBType::SINT32:
- case GPBType::SFIXED32:
- if (is_null($value)) {
- return $this->defaultValue($field);
- }
- if (!is_numeric($value)) {
- throw new GPBDecodeException(
- "Invalid data type for int32 field");
- }
- if (is_string($value) && trim($value) !== $value) {
- throw new GPBDecodeException(
- "Invalid data type for int32 field");
- }
- if (bccomp($value, "2147483647") > 0) {
- throw new GPBDecodeException(
- "Int32 too large");
- }
- if (bccomp($value, "-2147483648") < 0) {
- throw new GPBDecodeException(
- "Int32 too small");
- }
- return $value;
- case GPBType::UINT32:
- case GPBType::FIXED32:
- if (is_null($value)) {
- return $this->defaultValue($field);
- }
- if (!is_numeric($value)) {
- throw new GPBDecodeException(
- "Invalid data type for uint32 field");
- }
- if (is_string($value) && trim($value) !== $value) {
- throw new GPBDecodeException(
- "Invalid data type for int32 field");
- }
- if (bccomp($value, 4294967295) > 0) {
- throw new GPBDecodeException(
- "Uint32 too large");
- }
- return $value;
- case GPBType::INT64:
- case GPBType::SINT64:
- case GPBType::SFIXED64:
- if (is_null($value)) {
- return $this->defaultValue($field);
- }
- if (!is_numeric($value)) {
- throw new GPBDecodeException(
- "Invalid data type for int64 field");
- }
- if (is_string($value) && trim($value) !== $value) {
- throw new GPBDecodeException(
- "Invalid data type for int64 field");
- }
- if (bccomp($value, "9223372036854775807") > 0) {
- throw new GPBDecodeException(
- "Int64 too large");
- }
- if (bccomp($value, "-9223372036854775808") < 0) {
- throw new GPBDecodeException(
- "Int64 too small");
- }
- return $value;
- case GPBType::UINT64:
- case GPBType::FIXED64:
- if (is_null($value)) {
- return $this->defaultValue($field);
- }
- if (!is_numeric($value)) {
- throw new GPBDecodeException(
- "Invalid data type for int64 field");
- }
- if (is_string($value) && trim($value) !== $value) {
- throw new GPBDecodeException(
- "Invalid data type for int64 field");
- }
- if (bccomp($value, "18446744073709551615") > 0) {
- throw new GPBDecodeException(
- "Uint64 too large");
- }
- if (bccomp($value, "9223372036854775807") > 0) {
- $value = bcsub($value, "18446744073709551616");
- }
- return $value;
- default:
- return $value;
- }
- }
- /**
- * Populates the message from a user-supplied PHP array. Array keys
- * correspond to Message properties and nested message properties.
- *
- * Example:
- * ```
- * $message->mergeFromArray([
- * 'name' => 'This is a message name',
- * 'interval' => [
- * 'startTime' => time() - 60,
- * 'endTime' => time(),
- * ]
- * ]);
- * ```
- *
- * This method will trigger an error if it is passed data that cannot
- * be converted to the correct type. For example, a StringValue field
- * must receive data that is either a string or a StringValue object.
- *
- * @param array $array An array containing message properties and values.
- * @return null.
- */
- protected function mergeFromArray(array $array)
- {
- // Just call the setters for the field names
- foreach ($array as $key => $value) {
- $field = $this->desc->getFieldByName($key);
- if (is_null($field)) {
- throw new \UnexpectedValueException(
- 'Invalid message property: ' . $key);
- }
- $setter = $field->getSetter();
- if ($field->isMap()) {
- $valueField = $field->getMessageType()->getFieldByName('value');
- if (!is_null($valueField) && $valueField->isWrapperType()) {
- self::normalizeArrayElementsToMessageType($value, $valueField->getMessageType()->getClass());
- }
- } elseif ($field->isWrapperType()) {
- $class = $field->getMessageType()->getClass();
- if ($field->isRepeated()) {
- self::normalizeArrayElementsToMessageType($value, $class);
- } else {
- self::normalizeToMessageType($value, $class);
- }
- }
- $this->$setter($value);
- }
- }
- /**
- * Tries to normalize the elements in $value into a provided protobuf
- * wrapper type $class. If $value is any type other than array, we do
- * not do any conversion, and instead rely on the existing protobuf
- * type checking. If $value is an array, we process each element and
- * try to convert it to an instance of $class.
- *
- * @param mixed $value The array of values to normalize.
- * @param string $class The expected wrapper class name
- */
- private static function normalizeArrayElementsToMessageType(&$value, $class)
- {
- if (!is_array($value)) {
- // In the case that $value is not an array, we do not want to
- // attempt any conversion. Note that this includes the cases
- // when $value is a RepeatedField of MapField. In those cases,
- // we do not need to convert the elements, as they should
- // already be the correct types.
- return;
- } else {
- // Normalize each element in the array.
- foreach ($value as $key => &$elementValue) {
- self::normalizeToMessageType($elementValue, $class);
- }
- }
- }
- /**
- * Tries to normalize $value into a provided protobuf wrapper type $class.
- * If $value is any type other than an object, we attempt to construct an
- * instance of $class and assign $value to it using the setValue method
- * shared by all wrapper types.
- *
- * This method will raise an error if it receives a type that cannot be
- * assigned to the wrapper type via setValue.
- *
- * @param mixed $value The value to normalize.
- * @param string $class The expected wrapper class name
- */
- private static function normalizeToMessageType(&$value, $class)
- {
- if (is_null($value) || is_object($value)) {
- // This handles the case that $value is an instance of $class. We
- // choose not to do any more strict checking here, relying on the
- // existing type checking done by GPBUtil.
- return;
- } else {
- // Try to instantiate $class and set the value
- try {
- $msg = new $class;
- $msg->setValue($value);
- $value = $msg;
- return;
- } catch (\Exception $exception) {
- trigger_error(
- "Error normalizing value to type '$class': " . $exception->getMessage(),
- E_USER_ERROR
- );
- }
- }
- }
- protected function mergeFromJsonArray($array, $ignore_unknown)
- {
- if (is_a($this, "Google\Protobuf\Any")) {
- $this->clear();
- $this->setTypeUrl($array["@type"]);
- $msg = $this->unpack();
- if (GPBUtil::hasSpecialJsonMapping($msg)) {
- $msg->mergeFromJsonArray($array["value"], $ignore_unknown);
- } else {
- unset($array["@type"]);
- $msg->mergeFromJsonArray($array, $ignore_unknown);
- }
- $this->setValue($msg->serializeToString());
- return;
- }
- if (is_a($this, "Google\Protobuf\DoubleValue") ||
- is_a($this, "Google\Protobuf\FloatValue") ||
- is_a($this, "Google\Protobuf\Int64Value") ||
- is_a($this, "Google\Protobuf\UInt64Value") ||
- is_a($this, "Google\Protobuf\Int32Value") ||
- is_a($this, "Google\Protobuf\UInt32Value") ||
- is_a($this, "Google\Protobuf\BoolValue") ||
- is_a($this, "Google\Protobuf\StringValue")) {
- $this->setValue($array);
- return;
- }
- if (is_a($this, "Google\Protobuf\BytesValue")) {
- $this->setValue(base64_decode($array));
- return;
- }
- if (is_a($this, "Google\Protobuf\Duration")) {
- $this->mergeFrom(GPBUtil::parseDuration($array));
- return;
- }
- if (is_a($this, "Google\Protobuf\FieldMask")) {
- $this->mergeFrom(GPBUtil::parseFieldMask($array));
- return;
- }
- if (is_a($this, "Google\Protobuf\Timestamp")) {
- $this->mergeFrom(GPBUtil::parseTimestamp($array));
- return;
- }
- if (is_a($this, "Google\Protobuf\Struct")) {
- $fields = $this->getFields();
- foreach($array as $key => $value) {
- $v = new Value();
- $v->mergeFromJsonArray($value, $ignore_unknown);
- $fields[$key] = $v;
- }
- }
- if (is_a($this, "Google\Protobuf\Value")) {
- if (is_bool($array)) {
- $this->setBoolValue($array);
- } elseif (is_string($array)) {
- $this->setStringValue($array);
- } elseif (is_null($array)) {
- $this->setNullValue(0);
- } elseif (is_double($array) || is_integer($array)) {
- $this->setNumberValue($array);
- } elseif (is_array($array)) {
- if (array_values($array) !== $array) {
- // Associative array
- $struct_value = $this->getStructValue();
- if (is_null($struct_value)) {
- $struct_value = new Struct();
- $this->setStructValue($struct_value);
- }
- foreach ($array as $key => $v) {
- $value = new Value();
- $value->mergeFromJsonArray($v, $ignore_unknown);
- $values = $struct_value->getFields();
- $values[$key]= $value;
- }
- } else {
- // Array
- $list_value = $this->getListValue();
- if (is_null($list_value)) {
- $list_value = new ListValue();
- $this->setListValue($list_value);
- }
- foreach ($array as $v) {
- $value = new Value();
- $value->mergeFromJsonArray($v, $ignore_unknown);
- $values = $list_value->getValues();
- $values[]= $value;
- }
- }
- } else {
- throw new GPBDecodeException("Invalid type for Value.");
- }
- return;
- }
- $this->mergeFromArrayJsonImpl($array, $ignore_unknown);
- }
- private function mergeFromArrayJsonImpl($array, $ignore_unknown)
- {
- foreach ($array as $key => $value) {
- $field = $this->desc->getFieldByJsonName($key);
- if (is_null($field)) {
- $field = $this->desc->getFieldByName($key);
- if (is_null($field)) {
- continue;
- }
- }
- if ($field->isMap()) {
- if (is_null($value)) {
- continue;
- }
- $key_field = $field->getMessageType()->getFieldByNumber(1);
- $value_field = $field->getMessageType()->getFieldByNumber(2);
- foreach ($value as $tmp_key => $tmp_value) {
- if (is_null($tmp_value)) {
- throw new \Exception(
- "Map value field element cannot be null.");
- }
- $proto_key = $this->convertJsonValueToProtoValue(
- $tmp_key,
- $key_field,
- $ignore_unknown,
- true);
- $proto_value = $this->convertJsonValueToProtoValue(
- $tmp_value,
- $value_field,
- $ignore_unknown);
- self::kvUpdateHelper($field, $proto_key, $proto_value);
- }
- } else if ($field->isRepeated()) {
- if (is_null($value)) {
- continue;
- }
- foreach ($value as $tmp) {
- if (is_null($tmp)) {
- throw new \Exception(
- "Repeated field elements cannot be null.");
- }
- $proto_value = $this->convertJsonValueToProtoValue(
- $tmp,
- $field,
- $ignore_unknown);
- self::appendHelper($field, $proto_value);
- }
- } else {
- $setter = $field->getSetter();
- $proto_value = $this->convertJsonValueToProtoValue(
- $value,
- $field,
- $ignore_unknown);
- if ($field->getType() === GPBType::MESSAGE) {
- if (is_null($proto_value)) {
- continue;
- }
- $getter = $field->getGetter();
- $submsg = $this->$getter();
- if (!is_null($submsg)) {
- $submsg->mergeFrom($proto_value);
- continue;
- }
- }
- $this->$setter($proto_value);
- }
- }
- }
- /**
- * @ignore
- */
- public function parseFromJsonStream($input, $ignore_unknown)
- {
- $array = json_decode($input->getData(), true, 512, JSON_BIGINT_AS_STRING);
- if ($this instanceof \Google\Protobuf\ListValue) {
- $array = ["values"=>$array];
- }
- if (is_null($array)) {
- if ($this instanceof \Google\Protobuf\Value) {
- $this->setNullValue(\Google\Protobuf\NullValue::NULL_VALUE);
- return;
- } else {
- throw new GPBDecodeException(
- "Cannot decode json string: " . $input->getData());
- }
- }
- try {
- $this->mergeFromJsonArray($array, $ignore_unknown);
- } catch (\Exception $e) {
- throw new GPBDecodeException($e->getMessage());
- }
- }
- /**
- * @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, true)) {
- 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
- */
- private function serializeFieldToJsonStream(&$output, $field)
- {
- $getter = $field->getGetter();
- $values = $this->$getter();
- return GPBJsonWire::serializeFieldToStream(
- $values, $field, $output, !GPBUtil::hasSpecialJsonMapping($this));
- }
- /**
- * @ignore
- */
- public function serializeToStream(&$output)
- {
- $fields = $this->desc->getField();
- foreach ($fields as $field) {
- if (!$this->serializeFieldToStream($output, $field)) {
- return false;
- }
- }
- $output->writeRaw($this->unknown, strlen($this->unknown));
- return true;
- }
- /**
- * @ignore
- */
- public function serializeToJsonStream(&$output)
- {
- if (is_a($this, 'Google\Protobuf\Any')) {
- $output->writeRaw("{", 1);
- $type_field = $this->desc->getFieldByNumber(1);
- $value_msg = $this->unpack();
- // Serialize type url.
- $output->writeRaw("\"@type\":", 8);
- $output->writeRaw("\"", 1);
- $output->writeRaw($this->getTypeUrl(), strlen($this->getTypeUrl()));
- $output->writeRaw("\"", 1);
- // Serialize value
- if (GPBUtil::hasSpecialJsonMapping($value_msg)) {
- $output->writeRaw(",\"value\":", 9);
- $value_msg->serializeToJsonStream($output);
- } else {
- $value_fields = $value_msg->desc->getField();
- foreach ($value_fields as $field) {
- if ($value_msg->existField($field)) {
- $output->writeRaw(",", 1);
- if (!$value_msg->serializeFieldToJsonStream($output, $field)) {
- return false;
- }
- }
- }
- }
- $output->writeRaw("}", 1);
- } elseif (is_a($this, 'Google\Protobuf\FieldMask')) {
- $field_mask = GPBUtil::formatFieldMask($this);
- $output->writeRaw("\"", 1);
- $output->writeRaw($field_mask, strlen($field_mask));
- $output->writeRaw("\"", 1);
- } elseif (is_a($this, 'Google\Protobuf\Duration')) {
- $duration = GPBUtil::formatDuration($this) . "s";
- $output->writeRaw("\"", 1);
- $output->writeRaw($duration, strlen($duration));
- $output->writeRaw("\"", 1);
- } elseif (get_class($this) === 'Google\Protobuf\Timestamp') {
- $timestamp = GPBUtil::formatTimestamp($this);
- $timestamp = json_encode($timestamp);
- $output->writeRaw($timestamp, strlen($timestamp));
- } elseif (get_class($this) === 'Google\Protobuf\ListValue') {
- $field = $this->desc->getField()[1];
- if (!$this->existField($field)) {
- $output->writeRaw("[]", 2);
- } else {
- if (!$this->serializeFieldToJsonStream($output, $field)) {
- return false;
- }
- }
- } elseif (get_class($this) === 'Google\Protobuf\Struct') {
- $field = $this->desc->getField()[1];
- if (!$this->existField($field)) {
- $output->writeRaw("{}", 2);
- } else {
- if (!$this->serializeFieldToJsonStream($output, $field)) {
- return false;
- }
- }
- } else {
- if (!GPBUtil::hasSpecialJsonMapping($this)) {
- $output->writeRaw("{", 1);
- }
- $fields = $this->desc->getField();
- $first = true;
- foreach ($fields as $field) {
- if ($this->existField($field) ||
- GPBUtil::hasJsonValue($this)) {
- if ($first) {
- $first = false;
- } else {
- $output->writeRaw(",", 1);
- }
- if (!$this->serializeFieldToJsonStream($output, $field)) {
- return false;
- }
- }
- }
- if (!GPBUtil::hasSpecialJsonMapping($this)) {
- $output->writeRaw("}", 1);
- }
- }
- return true;
- }
- /**
- * Serialize the message to string.
- * @return string Serialized binary protobuf data.
- */
- public function serializeToString()
- {
- $output = new CodedOutputStream($this->byteSize());
- $this->serializeToStream($output);
- return $output->getData();
- }
- /**
- * Serialize the message to json string.
- * @return string Serialized json protobuf data.
- */
- public function serializeToJsonString()
- {
- $output = new CodedOutputStream($this->jsonByteSize());
- $this->serializeToJsonStream($output);
- return $output->getData();
- }
- /**
- * @ignore
- */
- private function existField($field)
- {
- $getter = $field->getGetter();
- $hazzer = "has" . substr($getter, 3);
- if (method_exists($this, $hazzer)) {
- return $this->$hazzer();
- } else if ($field->getOneofIndex() !== -1) {
- // For old generated code, which does not have hazzers for oneof
- // fields.
- $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()];
- $oneof_name = $oneof->getName();
- return $this->$oneof_name->getNumber() === $field->getNumber();
- }
- $values = $this->$getter();
- if ($field->isMap()) {
- return count($values) !== 0;
- } elseif ($field->isRepeated()) {
- return count($values) !== 0;
- } else {
- return $values !== $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::INT32:
- case GPBType::ENUM:
- $size += GPBWire::varint32Size($value, true);
- break;
- case GPBType::UINT32:
- $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 fieldDataOnlyJsonByteSize($field, $value)
- {
- $size = 0;
- switch ($field->getType()) {
- case GPBType::SFIXED32:
- case GPBType::SINT32:
- case GPBType::INT32:
- $size += strlen(strval($value));
- break;
- case GPBType::FIXED32:
- case GPBType::UINT32:
- if ($value < 0) {
- $value = bcadd($value, "4294967296");
- }
- $size += strlen(strval($value));
- break;
- case GPBType::FIXED64:
- case GPBType::UINT64:
- if ($value < 0) {
- $value = bcadd($value, "18446744073709551616");
- }
- // Intentional fall through.
- case GPBType::SFIXED64:
- case GPBType::INT64:
- case GPBType::SINT64:
- $size += 2; // size for ""
- $size += strlen(strval($value));
- break;
- case GPBType::FLOAT:
- if (is_nan($value)) {
- $size += strlen("NaN") + 2;
- } elseif ($value === INF) {
- $size += strlen("Infinity") + 2;
- } elseif ($value === -INF) {
- $size += strlen("-Infinity") + 2;
- } else {
- $size += strlen(sprintf("%.8g", $value));
- }
- break;
- case GPBType::DOUBLE:
- if (is_nan($value)) {
- $size += strlen("NaN") + 2;
- } elseif ($value === INF) {
- $size += strlen("Infinity") + 2;
- } elseif ($value === -INF) {
- $size += strlen("-Infinity") + 2;
- } else {
- $size += strlen(sprintf("%.17g", $value));
- }
- break;
- case GPBType::ENUM:
- $enum_desc = $field->getEnumType();
- if ($enum_desc->getClass() === "Google\Protobuf\NullValue") {
- $size += 4;
- break;
- }
- $enum_value_desc = $enum_desc->getValueByNumber($value);
- if (!is_null($enum_value_desc)) {
- $size += 2; // size for ""
- $size += strlen($enum_value_desc->getName());
- } else {
- $str_value = strval($value);
- $size += strlen($str_value);
- }
- break;
- case GPBType::BOOL:
- if ($value) {
- $size += 4;
- } else {
- $size += 5;
- }
- break;
- case GPBType::STRING:
- $value = json_encode($value, JSON_UNESCAPED_UNICODE);
- $size += strlen($value);
- break;
- case GPBType::BYTES:
- # if (is_a($this, "Google\Protobuf\BytesValue")) {
- # $size += strlen(json_encode($value));
- # } else {
- # $size += strlen(base64_encode($value));
- # $size += 2; // size for \"\"
- # }
- $size += strlen(base64_encode($value));
- $size += 2; // size for \"\"
- break;
- case GPBType::MESSAGE:
- $size += $value->jsonByteSize();
- break;
- # case GPBType::GROUP:
- # // TODO(teboring): Add support.
- # user_error("Unsupported type.");
- # break;
- default:
- user_error("Unsupported type " . $field->getType());
- 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;
- if ($key != $this->defaultValue($key_field)) {
- $data_size += $this->fieldDataOnlyByteSize(
- $key_field,
- $key);
- $data_size += GPBWire::tagSize($key_field);
- }
- if ($value != $this->defaultValue($value_field)) {
- $data_size += $this->fieldDataOnlyByteSize(
- $value_field,
- $value);
- $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
- */
- private function fieldJsonByteSize($field)
- {
- $size = 0;
- if ($field->isMap()) {
- $getter = $field->getGetter();
- $values = $this->$getter();
- $count = count($values);
- if ($count !== 0) {
- if (!GPBUtil::hasSpecialJsonMapping($this)) {
- $size += 3; // size for "\"\":".
- $size += strlen($field->getJsonName()); // size for field name
- }
- $size += 2; // size for "{}".
- $size += $count - 1; // size for commas
- $getter = $field->getGetter();
- $map_entry = $field->getMessageType();
- $key_field = $map_entry->getFieldByNumber(1);
- $value_field = $map_entry->getFieldByNumber(2);
- switch ($key_field->getType()) {
- case GPBType::STRING:
- case GPBType::SFIXED64:
- case GPBType::INT64:
- case GPBType::SINT64:
- case GPBType::FIXED64:
- case GPBType::UINT64:
- $additional_quote = false;
- break;
- default:
- $additional_quote = true;
- }
- foreach ($values as $key => $value) {
- if ($additional_quote) {
- $size += 2; // size for ""
- }
- $size += $this->fieldDataOnlyJsonByteSize($key_field, $key);
- $size += $this->fieldDataOnlyJsonByteSize($value_field, $value);
- $size += 1; // size for :
- }
- }
- } elseif ($field->isRepeated()) {
- $getter = $field->getGetter();
- $values = $this->$getter();
- $count = count($values);
- if ($count !== 0) {
- if (!GPBUtil::hasSpecialJsonMapping($this)) {
- $size += 3; // size for "\"\":".
- $size += strlen($field->getJsonName()); // size for field name
- }
- $size += 2; // size for "[]".
- $size += $count - 1; // size for commas
- $getter = $field->getGetter();
- foreach ($values as $value) {
- $size += $this->fieldDataOnlyJsonByteSize($field, $value);
- }
- }
- } elseif ($this->existField($field) || GPBUtil::hasJsonValue($this)) {
- if (!GPBUtil::hasSpecialJsonMapping($this)) {
- $size += 3; // size for "\"\":".
- $size += strlen($field->getJsonName()); // size for field name
- }
- $getter = $field->getGetter();
- $value = $this->$getter();
- $size += $this->fieldDataOnlyJsonByteSize($field, $value);
- }
- return $size;
- }
- /**
- * @ignore
- */
- public function byteSize()
- {
- $size = 0;
- $fields = $this->desc->getField();
- foreach ($fields as $field) {
- $size += $this->fieldByteSize($field);
- }
- $size += strlen($this->unknown);
- return $size;
- }
- private function appendHelper($field, $append_value)
- {
- $getter = $field->getGetter();
- $setter = $field->getSetter();
- $field_arr_value = $this->$getter();
- $field_arr_value[] = $append_value;
- if (!is_object($field_arr_value)) {
- $this->$setter($field_arr_value);
- }
- }
- private function kvUpdateHelper($field, $update_key, $update_value)
- {
- $getter = $field->getGetter();
- $setter = $field->getSetter();
- $field_arr_value = $this->$getter();
- $field_arr_value[$update_key] = $update_value;
- if (!is_object($field_arr_value)) {
- $this->$setter($field_arr_value);
- }
- }
- /**
- * @ignore
- */
- public function jsonByteSize()
- {
- $size = 0;
- if (is_a($this, 'Google\Protobuf\Any')) {
- // Size for "{}".
- $size += 2;
- // Size for "\"@type\":".
- $size += 8;
- // Size for url. +2 for "" /.
- $size += strlen($this->getTypeUrl()) + 2;
- $value_msg = $this->unpack();
- if (GPBUtil::hasSpecialJsonMapping($value_msg)) {
- // Size for "\",value\":".
- $size += 9;
- $size += $value_msg->jsonByteSize();
- } else {
- // Size for value. +1 for comma, -2 for "{}".
- $size += $value_msg->jsonByteSize() -1;
- }
- } elseif (get_class($this) === 'Google\Protobuf\FieldMask') {
- $field_mask = GPBUtil::formatFieldMask($this);
- $size += strlen($field_mask) + 2; // 2 for ""
- } elseif (get_class($this) === 'Google\Protobuf\Duration') {
- $duration = GPBUtil::formatDuration($this) . "s";
- $size += strlen($duration) + 2; // 2 for ""
- } elseif (get_class($this) === 'Google\Protobuf\Timestamp') {
- $timestamp = GPBUtil::formatTimestamp($this);
- $timestamp = json_encode($timestamp);
- $size += strlen($timestamp);
- } elseif (get_class($this) === 'Google\Protobuf\ListValue') {
- $field = $this->desc->getField()[1];
- if ($this->existField($field)) {
- $field_size = $this->fieldJsonByteSize($field);
- $size += $field_size;
- } else {
- // Size for "[]".
- $size += 2;
- }
- } elseif (get_class($this) === 'Google\Protobuf\Struct') {
- $field = $this->desc->getField()[1];
- if ($this->existField($field)) {
- $field_size = $this->fieldJsonByteSize($field);
- $size += $field_size;
- } else {
- // Size for "{}".
- $size += 2;
- }
- } else {
- if (!GPBUtil::hasSpecialJsonMapping($this)) {
- // Size for "{}".
- $size += 2;
- }
- $fields = $this->desc->getField();
- $count = 0;
- foreach ($fields as $field) {
- $field_size = $this->fieldJsonByteSize($field);
- $size += $field_size;
- if ($field_size != 0) {
- $count++;
- }
- }
- // size for comma
- $size += $count > 0 ? ($count - 1) : 0;
- }
- return $size;
- }
- }
|