Example #1
0
 protected function _describe(Protobuf\Descriptor $descriptor)
 {
     $name = $descriptor->getName();
     if (isset($this->_resources[$name])) {
         return $this->_resources[$name];
     }
     // Create the message descriptor resource
     $res = \protobuf_desc_message($name);
     // Add the resource immediately in the dictionary to support cyclic references
     $this->_resources[$name] = $res;
     $lazy = $this->getOption('lazy');
     // Iterate over all the fields to setup the message
     foreach ($descriptor->getFields() as $field) {
         $type = $field->getType();
         // Nested messages need to be populated first
         if ($type === Protobuf\Protobuf::TYPE_MESSAGE) {
             // When in lazy decoding mode we handle nested messages as binary fields
             if ($lazy) {
                 $type = Protobuf\Protobuf::TYPE_BYTES;
             } else {
                 // Try to obtain the message descriptor resource for this field
                 $descr = Protobuf\Protobuf::getRegistry()->getDescriptor($field->getReference());
                 if (!$descr) {
                     throw new \RuntimeException('Unable to find a descriptor for message "' . $field->getReference() . '"');
                 }
                 $nested = $this->_describe($descr);
             }
         }
         //printf("N: %d R: %d T: %d Name: %s P: %d\n", $field->getNumber(), $field->getRule(), $type, $field->getName(), $field->isPacked() ? PROTOBUF_FLAG_PACKED : 0);
         // Append the field definition to the message
         \protobuf_desc_field($res, $field->getNumber(), $field->getRule(), $type, $field->getName(), $field->isPacked() ? PROTOBUF_FLAG_PACKED : 0, $type === Protobuf\Protobuf::TYPE_MESSAGE ? $nested : NULL);
     }
     return $res;
 }
 public static function descriptor()
 {
     $descriptor = new Descriptor(__CLASS__, 'payments.PaymentDetails');
     // OPTIONAL STRING network = 1
     $f = new Field();
     $f->number = 1;
     $f->name = "network";
     $f->type = Protobuf::TYPE_STRING;
     $f->rule = Protobuf::RULE_OPTIONAL;
     $f->default = "main";
     $descriptor->addField($f);
     // REPEATED MESSAGE outputs = 2
     $f = new Field();
     $f->number = 2;
     $f->name = "outputs";
     $f->type = Protobuf::TYPE_MESSAGE;
     $f->rule = Protobuf::RULE_REPEATED;
     $f->reference = '\\BitWasp\\Bitcoin\\Payments\\Protobufs\\Output';
     $descriptor->addField($f);
     // REQUIRED UINT64 time = 3
     $f = new Field();
     $f->number = 3;
     $f->name = "time";
     $f->type = Protobuf::TYPE_UINT64;
     $f->rule = Protobuf::RULE_REQUIRED;
     $descriptor->addField($f);
     // OPTIONAL UINT64 expires = 4
     $f = new Field();
     $f->number = 4;
     $f->name = "expires";
     $f->type = Protobuf::TYPE_UINT64;
     $f->rule = Protobuf::RULE_OPTIONAL;
     $descriptor->addField($f);
     // OPTIONAL STRING memo = 5
     $f = new Field();
     $f->number = 5;
     $f->name = "memo";
     $f->type = Protobuf::TYPE_STRING;
     $f->rule = Protobuf::RULE_OPTIONAL;
     $descriptor->addField($f);
     // OPTIONAL STRING payment_url = 6
     $f = new Field();
     $f->number = 6;
     $f->name = "payment_url";
     $f->type = Protobuf::TYPE_STRING;
     $f->rule = Protobuf::RULE_OPTIONAL;
     $descriptor->addField($f);
     // OPTIONAL BYTES merchant_data = 7
     $f = new Field();
     $f->number = 7;
     $f->name = "merchant_data";
     $f->type = Protobuf::TYPE_BYTES;
     $f->rule = Protobuf::RULE_OPTIONAL;
     $descriptor->addField($f);
     foreach (self::$__extensions as $cb) {
         $descriptor->addField($cb(), true);
     }
     return $descriptor;
 }
Example #3
0
 public static function descriptor()
 {
     $descriptor = new Descriptor(__CLASS__, 'payments.Output');
     // OPTIONAL UINT64 amount = 1
     $f = new Field();
     $f->number = 1;
     $f->name = 'amount';
     $f->type = Protobuf::TYPE_UINT64;
     $f->rule = Protobuf::RULE_OPTIONAL;
     $f->default = 0;
     $descriptor->addField($f);
     // REQUIRED BYTES script = 2
     $f = new Field();
     $f->number = 2;
     $f->name = 'script';
     $f->type = Protobuf::TYPE_BYTES;
     $f->rule = Protobuf::RULE_REQUIRED;
     $descriptor->addField($f);
     foreach (self::$__extensions as $cb) {
         $descriptor->addField($cb(), true);
     }
     return $descriptor;
 }
Example #4
0
 /**
  * Clears/Resets a field by tag number
  *
  * @throws \Exception If trying to modify an unknown field
  * @param int $tag
  * @return \DrSlump\Protobuf\Message - Fluent interface
  */
 public function _clear($tag)
 {
     $f = $this->_descriptor->getField($tag);
     if (!$f) {
         throw new \Exception('Unknown fields not supported');
     }
     $name = $f->getName();
     if (!$f->isExtension()) {
         $this->{$name} = $f->isRepeated() ? array() : NULL;
     } else {
         $this->_extensions[$name] = $f->isRepeated() ? array() : NULL;
     }
     return $this;
 }
 public static function descriptor()
 {
     $descriptor = new Descriptor(__CLASS__, 'payments.PaymentRequest');
     // OPTIONAL UINT32 payment_details_version = 1
     $f = new Field();
     $f->number = 1;
     $f->name = "payment_details_version";
     $f->type = Protobuf::TYPE_UINT32;
     $f->rule = Protobuf::RULE_OPTIONAL;
     $f->default = 1;
     $descriptor->addField($f);
     // OPTIONAL STRING pki_type = 2
     $f = new Field();
     $f->number = 2;
     $f->name = "pki_type";
     $f->type = Protobuf::TYPE_STRING;
     $f->rule = Protobuf::RULE_OPTIONAL;
     $f->default = "none";
     $descriptor->addField($f);
     // OPTIONAL BYTES pki_data = 3
     $f = new Field();
     $f->number = 3;
     $f->name = "pki_data";
     $f->type = Protobuf::TYPE_BYTES;
     $f->rule = Protobuf::RULE_OPTIONAL;
     $descriptor->addField($f);
     // REQUIRED BYTES serialized_payment_details = 4
     $f = new Field();
     $f->number = 4;
     $f->name = "serialized_payment_details";
     $f->type = Protobuf::TYPE_BYTES;
     $f->rule = Protobuf::RULE_REQUIRED;
     $descriptor->addField($f);
     // OPTIONAL BYTES signature = 5
     $f = new Field();
     $f->number = 5;
     $f->name = "signature";
     $f->type = Protobuf::TYPE_BYTES;
     $f->rule = Protobuf::RULE_OPTIONAL;
     $descriptor->addField($f);
     foreach (self::$__extensions as $cb) {
         $descriptor->addField($cb(), true);
     }
     return $descriptor;
 }
Example #6
0
 public function offsetUnset($offset)
 {
     if (is_numeric($offset)) {
         $field = $this->_descriptor->getField($offset);
         if (!$field) {
             trigger_error("Protobuf message " . $this->_descriptor->getName() . " doesn't have any field with a tag number of {$offset}", E_USER_NOTICE);
             return;
         }
         if ($field->isExtension()) {
             $data =& $this->_extensions;
         } else {
             $data =& $this->_values;
         }
         if (isset($data[$field->name])) {
             unset($data[$field->name]);
         }
     } else {
         $this->clearExtension($offset);
     }
 }
 public static function descriptor()
 {
     $class = get_called_class();
     // Instantiate a new descriptor
     $descriptor = new Descriptor($class);
     $rflClass = new \ReflectionClass($class);
     $props = $rflClass->getProperties();
     foreach ($props as $prop) {
         $doc = $prop->getDocComment();
         if (empty($doc)) {
             continue;
         }
         // Format: @protobuf(tag=X, type=bool, required=true)
         // Extract annotation from the comment
         if (!preg_match('/@protobuf\\s?\\(([^\\)]+)\\)/', $doc, $m)) {
             continue;
         }
         // Parse params
         $params = explode(',', $m[1]);
         $params = array_filter(array_map('trim', $params));
         $options = array();
         foreach ($params as $param) {
             $parts = explode('=', $param);
             $parts = array_filter(array_map('trim', $parts));
             $options[$parts[0]] = count($parts) < 2 ? true : $parts[1];
         }
         // Check if we have the minimum required options
         if (empty($options['tag'])) {
             throw new \InvalidArgumentException('The tag option is required for property ' . $prop->getName());
         }
         if (empty($options['type'])) {
             throw new \InvalidArgumentException('The type option is required for property ' . $prop->getName());
         }
         // Normalize boolean values
         foreach (array('required', 'optional', 'repeated', 'packed') as $opt) {
             if (isset($options[$opt])) {
                 $options[$opt] = filter_var($options[$opt], FILTER_VALIDATE_BOOLEAN);
             }
         }
         // Build a field descriptor
         $f = new Protobuf\Field();
         $f->number = (int) $options['tag'];
         $f->name = $prop->getName();
         // Convert type name to its numeric constant
         switch (strtolower($options['type'])) {
             case 'double':
                 $f->type = Protobuf\Protobuf::TYPE_DOUBLE;
                 break;
             case 'float':
                 $f->type = Protobuf\Protobuf::TYPE_FLOAT;
                 break;
             case 'int64':
                 $f->type = Protobuf\Protobuf::TYPE_INT64;
                 break;
             case 'uint64':
                 $f->type = Protobuf\Protobuf::TYPE_UINT64;
                 break;
             case 'int32':
                 $f->type = Protobuf\Protobuf::TYPE_INT32;
                 break;
             case 'fixed64':
                 $f->type = Protobuf\Protobuf::TYPE_FIXED64;
                 break;
             case 'fixed32':
                 $f->type = Protobuf\Protobuf::TYPE_FIXED32;
                 break;
             case 'bool':
                 $f->type = Protobuf\Protobuf::TYPE_BOOL;
                 break;
             case 'string':
                 $f->type = Protobuf\Protobuf::TYPE_STRING;
                 break;
             case 'message':
                 $f->type = Protobuf\Protobuf::TYPE_MESSAGE;
                 break;
             case 'bytes':
                 $f->type = Protobuf\Protobuf::TYPE_BYTES;
                 break;
             case 'uint32':
                 $f->type = Protobuf\Protobuf::TYPE_UINT32;
                 break;
             case 'enum':
                 $f->type = Protobuf\Protobuf::TYPE_ENUM;
                 break;
             case 'sfixed32':
                 $f->type = Protobuf\Protobuf::TYPE_SFIXED32;
                 break;
             case 'sfixed64':
                 $f->type = Protobuf\Protobuf::TYPE_SFIXED64;
                 break;
             case 'sint32':
                 $f->type = Protobuf\Protobuf::TYPE_SINT32;
                 break;
             case 'sint64':
                 $f->type = Protobuf\Protobuf::TYPE_SINT64;
                 break;
             default:
                 throw new \InvalidArgumentException('Type ' . $options['type'] . ' is not recognized as valid for property ' . $prop->getName());
         }
         // Define the rule type
         $f->rule = Protobuf\Protobuf::RULE_OPTIONAL;
         if (!empty($options['required'])) {
             $f->rule = Protobuf\Protobuf::RULE_REQUIRED;
         }
         if (!empty($options['repeated'])) {
             $f->rule = Protobuf\Protobuf::RULE_REPEATED;
         }
         // Check if it's flagged as packed
         if (isset($options['packed'])) {
             $f->packed = $options['packed'];
         }
         // Get the reference
         if (isset($options['reference'])) {
             $f->reference = $options['reference'];
         } else {
             if ($f->type === Protobuf\Protobuf::TYPE_MESSAGE || $f->type === Protobuf\Protobuf::TYPE_ENUM) {
                 throw new \InvalidArgumentException('Property ' . $prop->getName() . ' requires the "reference" option');
             }
         }
         if (isset($options['default'])) {
             $f->default = $options['default'];
         }
         // Add the field to the message descriptor
         $descriptor->addField($f);
     }
     return $descriptor;
 }