/**
  * @param \Protobuf\Compiler\Entity             $entity
  * @param \google\protobuf\FieldDescriptorProto $field
  *
  * @return string[]
  */
 public function generateFieldReadStatement(Entity $entity, FieldDescriptorProto $field)
 {
     $body = [];
     $reference = null;
     $type = $field->getType();
     $name = $field->getName();
     $rule = $field->getLabel();
     $tag = $field->getNumber();
     $options = $field->getOptions();
     $isPack = $options ? $options->getPacked() : false;
     $variable = $this->targetVar ?: '$this->' . $name;
     $breakSttm = $this->getBreakStatement($variable);
     if ($field->hasTypeName()) {
         $typeName = $field->getTypeName();
         $typeEntity = $this->getEntity($typeName);
         $reference = $typeEntity->getNamespacedName();
     }
     if (!$isPack) {
         $body[] = sprintf('\\Protobuf\\WireFormat::assertWireType($wire, %s);', $type->value());
         $body[] = null;
     }
     if ($rule === Label::LABEL_REPEATED() && $isPack) {
         $readSttm = $type === Type::TYPE_ENUM() ? $reference . '::valueOf(' . $this->generateReadScalarStatement($type->value()) . ')' : $this->generateReadScalarStatement($type->value());
         $body[] = '$innerSize  = $reader->readVarint($stream);';
         $body[] = '$innerLimit = $stream->tell() + $innerSize;';
         $body[] = null;
         $body[] = 'if (' . $variable . ' === null) {';
         $body[] = '    ' . $variable . ' = new ' . $this->getCollectionClassName($field) . '();';
         $body[] = '}';
         $body[] = null;
         $body[] = 'while ($stream->tell() < $innerLimit) {';
         $body[] = '    ' . $variable . '->add(' . $readSttm . ');';
         $body[] = '}';
         $body[] = null;
         $body[] = $breakSttm;
         return $body;
     }
     if ($type === Type::TYPE_MESSAGE() && $rule === Label::LABEL_REPEATED()) {
         $body[] = '$innerSize    = $reader->readVarint($stream);';
         $body[] = '$innerMessage = new ' . $reference . '();';
         $body[] = null;
         $body[] = 'if (' . $variable . ' === null) {';
         $body[] = '    ' . $variable . ' = new \\Protobuf\\MessageCollection();';
         $body[] = '}';
         $body[] = null;
         $body[] = $variable . '->add($innerMessage);';
         $body[] = null;
         $body[] = '$context->setLength($innerSize);';
         $body[] = '$innerMessage->readFrom($context);';
         $body[] = '$context->setLength($length);';
         $body[] = null;
         $body[] = $breakSttm;
         return $body;
     }
     if ($type === Type::TYPE_ENUM() && $rule === LABEL::LABEL_REPEATED()) {
         $body[] = 'if (' . $variable . ' === null) {';
         $body[] = '    ' . $variable . ' = new ' . $this->getCollectionClassName($field) . '();';
         $body[] = '}';
         $body[] = null;
         $body[] = $variable . '->add(' . $reference . '::valueOf(' . $this->generateReadScalarStatement($type->value()) . '));';
         $body[] = null;
         $body[] = $breakSttm;
         return $body;
     }
     if ($type === Type::TYPE_MESSAGE()) {
         $body[] = '$innerSize    = $reader->readVarint($stream);';
         $body[] = '$innerMessage = new ' . $reference . '();';
         $body[] = null;
         $body[] = $variable . ' = $innerMessage;';
         $body[] = null;
         $body[] = '$context->setLength($innerSize);';
         $body[] = '$innerMessage->readFrom($context);';
         $body[] = '$context->setLength($length);';
         $body[] = null;
         $body[] = $breakSttm;
         return $body;
     }
     if ($type === Type::TYPE_ENUM()) {
         $body[] = $variable . ' = ' . $reference . '::valueOf(' . $this->generateReadScalarStatement($type->value()) . ');';
         $body[] = null;
         $body[] = $breakSttm;
         return $body;
     }
     if ($rule !== LABEL::LABEL_REPEATED()) {
         $body[] = $variable . ' = ' . $this->generateReadScalarStatement($type->value()) . ';';
         $body[] = null;
         $body[] = $breakSttm;
         return $body;
     }
     $body[] = 'if (' . $variable . ' === null) {';
     $body[] = '    ' . $variable . ' = new ' . $this->getCollectionClassName($field) . '();';
     $body[] = '}';
     $body[] = null;
     $body[] = $variable . '->add(' . $this->generateReadScalarStatement($type->value()) . ');';
     $body[] = null;
     $body[] = $breakSttm;
     return $body;
 }
 protected function compileField(proto\FieldDescriptorProto $field, $ns, $indent)
 {
     // Fetch constants by reflecton
     $refl = new \ReflectionClass('\\DrSlump\\Protobuf');
     $constants = $refl->getConstants();
     // Separate rules and types
     $rules = $types = array();
     foreach ($constants as $k => $v) {
         if (false === strpos($k, '_')) {
             continue;
         }
         list($prefix, $name) = explode('_', $k, 2);
         if ('RULE' === $prefix) {
             $rules[$name] = $v;
         } else {
             if ('TYPE' === $prefix) {
                 $types[$name] = $v;
             }
         }
     }
     // Get the key for the rule and type
     $rule = array_search($field->getLabel(), $rules);
     $type = array_search($field->getType(), $types);
     $s[] = "// {$rule} {$type} " . $field->getName() . " = " . $field->getNumber();
     $s[] = '$f = new \\DrSlump\\Protobuf\\Field();';
     $s[] = '$f->number    = ' . $field->getNumber() . ';';
     $s[] = '$f->name      = "' . $field->getName() . '";';
     $s[] = '$f->type      = \\DrSlump\\Protobuf::TYPE_' . $type . ';';
     $s[] = '$f->rule      = \\DrSlump\\Protobuf::RULE_' . $rule . ';';
     if ($field->hasTypeName()) {
         $ref = $field->getTypeName();
         if (substr($ref, 0, 1) !== '.') {
             throw new \RuntimeException("Only fully qualified names are supported but found '{$ref}' at {$ns}");
         }
         $s[] = '$f->reference = \'\\' . $this->normalizeNS($ref) . "';";
     }
     if ($field->hasDefaultValue()) {
         switch ($field->getType()) {
             case Protobuf::TYPE_BOOL:
                 $bool = filter_var($field->getDefaultValue(), FILTER_VALIDATE_BOOLEAN);
                 $s[] = '$f->default   = ' . ($bool ? 'true' : 'false') . ';';
                 break;
             case Protobuf::TYPE_STRING:
                 $s[] = '$f->default   = "' . addcslashes($field->getDefaultValue(), '"\\') . '";';
                 break;
             case Protobuf::TYPE_ENUM:
                 $value = '\\' . $this->normalizeNS($field->getTypeName()) . '::' . $field->getDefaultValue();
                 $s[] = '$f->default   = ' . $value . ';';
                 break;
             default:
                 // Numbers
                 $s[] = '$f->default   = ' . $field->getDefaultValue() . ';';
         }
     }
     $s[] = '// @@protoc_insertion_point(scope_field)';
     $s[] = '// @@protoc_insertion_point(field_' . $ns . ':' . $field->getName() . ')';
     return $indent . implode(PHP_EOL . $indent, $s);
 }
Esempio n. 3
0
 public function generateField(proto\FieldDescriptorProto $field)
 {
     $reference = 'null';
     if ($field->hasTypeName()) {
         $reference = $field->getTypeName();
         if (substr($reference, 0, 1) !== '.') {
             throw new \RuntimeException('Only fully qualified names are supported: ' . $reference);
         }
         $reference = "'" . $this->normalizeNS($reference) . "'";
     }
     $default = 'null';
     if ($field->hasDefaultValue()) {
         switch ($field->getType()) {
             case Protobuf::TYPE_BOOL:
                 $default = $field->getDefaultValue() ? 'true' : 'false';
                 break;
             case Protobuf::TYPE_STRING:
                 $default = '"' . addcslashes($field->getDefaultValue(), '"\\') . '"';
                 break;
             case Protobuf::TYPE_ENUM:
                 $default = $this->normalizeNS($field->getTypeName()) . '.' . $field->getDefaultValue();
                 break;
             default:
                 // Numbers
                 $default = $field->getDefaultValue();
         }
     }
     $data = array("'" . $field->getName() . "'", $field->getLabel(), $field->getType(), $reference, $default, '{}');
     return '[' . implode(', ', $data) . ']';
 }