protected function decodeMessage(Protobuf\MessageInterface $message, $data) { // Get message descriptor $descriptor = Protobuf::getRegistry()->getDescriptor($message); $isLazy = $this->getOption('lazy'); $useTagNumber = $this->getOption('tags'); foreach ($data as $key => $v) { // Get the field by tag number or name $field = $useTagNumber ? $descriptor->getField($key) : $descriptor->getFieldByName($key); // Unknown field found if (!$field) { $unknown = new PhpArray\Unknown($key, gettype($v), $v); $message->addUnknown($unknown); continue; } if ($field->isRepeated()) { // Make sure the value is an array of values $v = is_array($v) && (empty($v) || is_int(key($v))) ? $v : array($v); // If we are packing lazy values use a LazyRepeat as container if ($isLazy && $field->getType() === Protobuf::TYPE_MESSAGE) { $v = new Protobuf\LazyRepeat($v); $v->codec = $this; $v->descriptor = $field; } else { foreach ($v as $k => $vv) { $v[$k] = $this->filterValue($vv, $field); } } } else { $v = $this->filterValue($v, $field); } $message->initValue($field->getName(), $v); } return $message; }
protected function decodeMessage(Protobuf\Message $message, $data) { // Get message descriptor $descriptor = Protobuf::getRegistry()->getDescriptor($message); // Split the index in UTF8 characters preg_match_all('/./u', $data[0], $chars); $chars = $chars[0]; for ($i = 1; $i < count($data); $i++) { $k = $this->c2i($chars[$i - 1]) - 48; $v = $data[$i]; $field = $descriptor->getField($k); if (NULL === $field) { // Unknown $unknown = new PhpArray\Unknown($k, gettype($v), $v); $message->addUnknown($unknown); continue; } $name = $field->getName(); if ($field->getType() === Protobuf::TYPE_MESSAGE) { $nested = $field->getReference(); if ($field->isRepeated()) { foreach ($v as $kk => $vv) { $v[$kk] = $this->decodeMessage(new $nested(), $vv); } $message->initValue($name, $v); } else { $obj = $this->decodeMessage(new $nested(), $v); $message->initValue($name, $obj); } } else { $message->initValue($name, $v); } } return $message; }
protected function decodeMessage(Protobuf\Message $message, $data) { // Get message descriptor $descriptor = Protobuf::getRegistry()->getDescriptor($message); foreach ($data as $key => $v) { // Get the field by tag number or name $field = $this->useTagNumber ? $descriptor->getField($key) : $descriptor->getFieldByName($key); // Unknown field found if (!$field) { $unknown = new PhpArray\Unknown($key, gettype($v), $v); $message->addUnknown($unknown); continue; } if ($field->isRepeated()) { // Make sure the value is an array of values $v = is_array($v) && is_int(key($v)) ? $v : array($v); foreach ($v as $k => $vv) { $v[$k] = $this->filterValue($vv, $field); } } else { $v = $this->filterValue($v, $field); } $message->_set($field->getNumber(), $v); } return $message; }
function testUnregisterDefaultCodec() { $result = Protobuf::unregisterCodec('default'); $this->assertTrue($result); // Ensure a new default is given $getted = Protobuf::getCodec(); $this->assertInstanceOf('DrSlump\\Protobuf\\Codec\\Binary', $getted); }
public function flush() { $message = new Msg(); $message->ok = true; $message->events = $this->events; $this->socketClient->open(); $this->socketClient->write(Protobuf::encode($message)); $this->socketClient->close(); }
/** * @test */ public function itShouldSendEvents() { $anEvent = new Event(); $anotherEvent = new Event(); $message = $this->aMessage(array($anEvent, $anotherEvent)); $socketClient = $this->socketClientMock(); $socketClient->expects($this->once())->method('write')->with(Protobuf::encode($message)); $client = new Client($socketClient, $this->eventBuilderFactoryMock()); $client->sendEvent($anEvent); $client->sendEvent($anotherEvent); $client->flush(); }
protected function encodeMessage(Protobuf\MessageInterface $message, $level = 0) { $descriptor = Protobuf::getRegistry()->getDescriptor($message); $strict = $this->getOption('strict'); $indent = str_repeat(' ', $level); $data = ''; foreach ($descriptor->getFields() as $tag => $field) { $empty = !isset($message[$tag]); if ($strict && $empty && $field->isRequired() && !$field->hasDefault()) { throw new \UnexpectedValueException('Message ' . $descriptor->getName() . '\'s field tag ' . $tag . '(' . $field->getName() . ') is required but has no value'); } if ($empty && !$field->hasDefault()) { continue; } $name = $field->getName(); $value = $message[$tag]; if ($value === NULL) { continue; } if ($field->isRepeated()) { foreach ($value as $val) { // Skip nullified repeated values if (NULL === $val) { continue; } else { if ($field->getType() !== Protobuf::TYPE_MESSAGE) { $data .= $indent . $name . ': ' . json_encode($val) . "\n"; } else { $data .= $indent . $name . " {\n"; $data .= $this->encodeMessage($val, $level + 1); $data .= $indent . "}\n"; } } } } else { if ($field->getType() === Protobuf::TYPE_MESSAGE) { $data .= $indent . $name . " {\n"; $data .= $this->encodeMessage($value, $level + 1); $data .= $indent . "}\n"; } else { $data .= $indent . $name . ': ' . json_encode($value) . "\n"; } } } return $data; }
/** * @param \DrSlump\Protobuf\MessageInterface $message * @param string $data * @return \DrSlump\Protobuf\MessageInterface */ protected function _decodeMessage(\DrSlump\Protobuf\MessageInterface $message, $data) { $descriptor = Protobuf::getRegistry()->getDescriptor($message); $name = $descriptor->getName(); $res = $this->_describe($descriptor); $ret = \protobuf_decode($res, $data); // In non lazy mode we just pass the returned array thru the PhpArray codec if (!$this->getOption('lazy')) { if (!$this->_codec) { $this->_codec = new PhpArray(); $this->_codec->setOption('lazy', false); } return $this->_codec->decode($message, $ret); } // In lazy mode we need to walk thru the fields to convert message strings // to LazyValue / LazyRepeat foreach ($descriptor->getFields() as $field) { $name = $field->getName(); if (!isset($ret[$name])) { continue; } $value = $ret[$name]; if ($field->getType() === Protobuf::TYPE_MESSAGE) { if ($field->getRule() === Protobuf::RULE_REPEATED) { $value = new Protobuf\LazyRepeat($value); $value->codec = $this; $value->descriptor = $field; } else { $lazy = new Protobuf\LazyValue(); $lazy->codec = $this; $lazy->descriptor = $field; $lazy->value = $value; $value = $lazy; } } $message->initValue($name, $value); } return $message; }
protected function encodeMessage(Protobuf\Message $message) { $writer = new NativeWriter(); // Get message descriptor $descriptor = Protobuf::getRegistry()->getDescriptor($message); $strict = $this->getOption('strict'); foreach ($descriptor->getFields() as $tag => $field) { $empty = !isset($message[$tag]); if ($strict && $empty && $field->isRequired() && !$field->hasDefault()) { throw new \UnexpectedValueException('Message ' . get_class($message) . '\'s field tag ' . $tag . '(' . $field->getName() . ') is required but has no value'); } // Skip unknown fields if ($empty && !$field->hasDefault()) { continue; } $type = $field->getType(); $wire = $field->isPacked() ? self::WIRE_LENGTH : $this->getWireType($type, null); // Compute key with tag number and wire type $key = $tag << 3 | $wire; $value = $message[$tag]; if (NULL === $value) { continue; } if ($field->isRepeated()) { // Packed fields are encoded as a length-delimited stream containing // the concatenated encoding of each value. if ($field->isPacked() && !empty($value)) { $subwriter = new NativeWriter(); foreach ($value as $val) { $this->encodeSimpleType($subwriter, $type, $val); } $data = $subwriter->getBytes(); $writer->varint($key); $writer->varint(strlen($data)); $writer->write($data); } else { foreach ($value as $val) { // Skip nullified repeated values if (NULL === $val) { continue; } else { if ($type !== Protobuf::TYPE_MESSAGE) { $writer->varint($key); $this->encodeSimpleType($writer, $type, $val); } else { $writer->varint($key); $data = $this->encodeMessage($val); $writer->varint(strlen($data)); $writer->write($data); } } } } } else { if ($type !== Protobuf::TYPE_MESSAGE) { $writer->varint($key); $this->encodeSimpleType($writer, $type, $value); } else { $writer->varint($key); $data = $this->encodeMessage($value); $writer->varint(strlen($data)); $writer->write($data); } } } return $writer->getBytes(); }
/** * Serialize the current object data * * @param CodecInterface|null $codec * @return string */ public function serialize(Protobuf\CodecInterface $codec = null) { $codec = Protobuf::getCodec($codec); return $codec->encode($this); }
function testUnserializeComplexMessage() { $json = '{ "1":[ { "1":"John Doe", "2":2051, "3":"*****@*****.**", "4":[ {"1":"1231231212","2":1}, {"1":"55512321312","2":0} ] }, { "1":"Iv\\u00e1n Montes", "2":23, "3":"*****@*****.**", "4":[{"1":"3493123123","2":2}] } ] }'; $json = preg_replace('/\\n\\s*/', '', $json); $complex = Protobuf::decode('Tests\\AddressBook', $json); $this->assertEquals(count($complex->person), 2); $this->assertEquals($complex->getPerson(0)->name, 'John Doe'); $this->assertEquals($complex->getPerson(1)->name, 'Iván Montes'); $this->assertEquals($complex->getPerson(0)->getPhone(1)->number, '55512321312'); }
function testUnserializeComplexMessage() { $xml = new SimpleXMLElement('<root></root>'); $p = $xml->addChild('person'); $p->addChild('name', 'John Doe'); $p->addChild('id', 2051); $p->addChild('email', '*****@*****.**'); $p = $p->addChild('phone'); $p->addChild('number', '1231231212'); $p->addChild('type', 1); $p = $xml->addChild('person'); $p->addChild('name', 'Iván Montes'); $p->addChild('id', 23); $p->addChild('email', '*****@*****.**'); $p = $p->addChild('phone'); $p->addChild('number', '3493123123'); $p->addChild('type', 2); $complex = Protobuf::decode('Tests\\AddressBook', $xml->asXML()); $this->assertEquals(count($complex->person), 2); $this->assertEquals($complex->getPerson(0)->name, 'John Doe'); $this->assertEquals($complex->getPerson(1)->name, 'Iván Montes'); $this->assertEquals($complex->getPerson(1)->getPhone(0)->number, '3493123123'); }
/** * @expectedException BadMethodCallException */ function testUnserializeNotImplemented() { $txt = "foo: \"FOO\"\nbar: \"BAR\"\n"; $simple = Protobuf::decode('Tests\\Simple', $txt); }
function setUp() { Protobuf::setDefaultCodec(new ProtoBuf\Codec\Json()); }
* Encodes a message using the default codec * * @static * @param \DrSlump\Protobuf\Message $message * @return string */ public static function encode(Protobuf\Message $message) { $codec = self::getCodec(); return $codec->encode($message); } /** * @static * @param String|Message $message * @param String $data * @return \DrSlump\Protobuf\Message */ public static function decode($message, $data) { if (is_string($message)) { $message = '\\' . ltrim($message, '\\'); $message = new $message(); } $codec = self::getCodec(); return $codec->decode($message, $data); } } // Register the autoloader automatically if not disabled via a constant if (!defined('DRSLUMP_PROTOBUF_AUTOLOAD') || DRSLUMP_PROTOBUF_AUTOLOAD) { Protobuf::autoload(); }
// furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // Set up default timezone date_default_timezone_set('GMT'); // For non pear packaged versions use relative include path if (strpos('@php_bin@', '@php_bin') === 0) { set_include_path(__DIR__ . DIRECTORY_SEPARATOR . 'library' . PATH_SEPARATOR . get_include_path()); } // Disable strict errors for the compiler error_reporting(error_reporting() & ~E_STRICT); require_once 'DrSlump/Protobuf.php'; // Setup autoloader \DrSlump\Protobuf::autoload(); try { // Run the cli interface \DrSlump\Protobuf\Compiler\Cli::run(__FILE__); exit(0); } catch (Exception $e) { fputs(STDERR, (string) $e . PHP_EOL); exit(1); }
/** * @param \DrSlump\Protobuf\Codec\Binary\Reader $reader * @param \DrSlump\Protobuf\Message $message * @param int $length * @return \DrSlump\Protobuf\Message */ protected function decodeMessage($reader, \DrSlump\Protobuf\Message $message, $length = NULL) { /** @var $message \DrSlump\Protobuf\Message */ /** @var $descriptor \DrSlump\Protobuf\Descriptor */ // Get message descriptor $descriptor = Protobuf::getRegistry()->getDescriptor($message); // Cache locally the message fields $fields = $descriptor->getFields(); // Calculate the maximum offset if we have defined a length $limit = !is_null($length) ? $reader->pos() + $length : NULL; $pos = $reader->pos(); // Keep reading until we reach the end or the limit while ($limit === NULL && !$reader->eof() || $limit !== NULL && $reader->pos() < $limit) { // Get initial varint with tag number and wire type $key = $reader->varint(); if ($reader->eof()) { break; } $wire = $key & 0x7; $tag = $key >> 3; // Find the matching field for the tag number if (!isset($fields[$tag])) { $data = $this->decodeUnknown($reader, $wire); $unknown = new Binary\Unknown($tag, $wire, $data); $message->addUnknown($unknown); continue; } $field = $fields[$tag]; $type = $field->getType(); // Check if we are dealing with a packed stream, we cannot rely on the packed // flag of the message since we cannot be certain if the creator of the message // was using it. if ($wire === self::WIRE_LENGTH && $field->isRepeated() && self::$PACKABLE[$type]) { $len = $reader->varint(); $until = $reader->pos() + $len; $wire = $this->getWireType($type); while ($reader->pos() < $until) { $item = $this->decodeSimpleType($reader, $type, $wire); $message->_add($tag, $item); } } else { // Assert wire and type match $this->assertWireType($wire, $type); // Check if it's a sub-message if ($type === Protobuf::TYPE_MESSAGE) { $submessage = $field->getReference(); $submessage = new $submessage(); $len = $reader->varint(); $value = $this->decodeMessage($reader, $submessage, $len); } else { $value = $this->decodeSimpleType($reader, $type, $wire); } // Support non-packed repeated fields if ($field->isRepeated()) { $message->_add($tag, $value); } else { $message->_set($tag, $value); } } } return $message; }