예제 #1
0
 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;
 }
예제 #2
0
 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;
 }
예제 #3
0
 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;
 }
예제 #4
0
 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);
 }
예제 #5
0
 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();
 }
예제 #7
0
 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;
 }
예제 #8
0
 /**
  * @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;
 }
예제 #9
0
 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();
 }
예제 #10
0
 /**
  * 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);
 }
예제 #14
0
 function setUp()
 {
     Protobuf::setDefaultCodec(new ProtoBuf\Codec\Json());
 }
예제 #15
0
     * 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();
}
예제 #16
0
// 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);
}
예제 #17
0
 /**
  * @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;
 }