/** * @param \Protobuf\Compiler\Entity $entity * @param \google\protobuf\FieldDescriptorProto $field * * @return array */ protected function generateFieldMerge(Entity $entity, FieldDescriptorProto $field) { $lines = []; $fieldName = $field->getName(); $format = '$this->%s = ($message->%s !== null) ? $message->%s : $this->%s;'; $lines[] = sprintf($format, $fieldName, $fieldName, $fieldName, $fieldName); return $lines; }
/** * @param \Protobuf\Compiler\Entity $entity * @param \google\protobuf\FieldDescriptorProto $field * * @return string[] */ public function generateFieldWriteStatement(Entity $entity, FieldDescriptorProto $field) { $body = []; $name = $field->getName(); $type = $field->getType(); $rule = $field->getLabel(); $tag = $field->getNumber(); $options = $field->getOptions(); $variable = $this->targetVar ?: '$this->' . $name; $isPack = $options ? $options->getPacked() : false; $wire = $isPack ? WireFormat::WIRE_LENGTH : WireFormat::getWireType($type->value(), null); $key = WireFormat::getFieldKey($tag, $wire); if ($rule === Label::LABEL_REPEATED() && $isPack) { $itemValSttm = $type === Type::TYPE_ENUM() ? '$val->value()' : '$val'; $body[] = '$innerSize = 0;'; $body[] = '$calculator = $sizeContext->getSizeCalculator();'; $body[] = null; $body[] = 'foreach (' . $variable . ' as $val) {'; $body[] = ' $innerSize += ' . $this->generateValueSizeStatement($type->value(), $itemValSttm) . ';'; $body[] = '}'; $body[] = null; $body[] = '$writer->writeVarint($stream, ' . $key . ');'; $body[] = '$writer->writeVarint($stream, $innerSize);'; $body[] = null; $body[] = 'foreach (' . $variable . ' as $val) {'; $body[] = ' ' . $this->generateWriteScalarStatement($type->value(), $itemValSttm) . ';'; $body[] = '}'; return $body; } if ($type === Type::TYPE_MESSAGE() && $rule === Label::LABEL_REPEATED()) { $body[] = 'foreach (' . $variable . ' as $val) {'; $body[] = ' $writer->writeVarint($stream, ' . $key . ');'; $body[] = ' $writer->writeVarint($stream, $val->serializedSize($sizeContext));'; $body[] = ' $val->writeTo($context);'; $body[] = '}'; return $body; } if ($type === Type::TYPE_ENUM() && $rule === LABEL::LABEL_REPEATED()) { $body[] = 'foreach (' . $variable . ' as $val) {'; $body[] = ' $writer->writeVarint($stream, ' . $key . ');'; $body[] = ' ' . $this->generateWriteScalarStatement($type->value(), '$val->value()') . ';'; $body[] = '}'; return $body; } if ($rule === Label::LABEL_REPEATED()) { $body[] = 'foreach (' . $variable . ' as $val) {'; $body[] = ' $writer->writeVarint($stream, ' . $key . ');'; $body[] = ' ' . $this->generateWriteScalarStatement($type->value(), '$val') . ';'; $body[] = '}'; return $body; } if ($type === Type::TYPE_ENUM()) { $body[] = sprintf('$writer->writeVarint($stream, %s);', $key); $body[] = $this->generateWriteScalarStatement($type->value(), $variable . '->value()') . ';'; return $body; } if ($type !== Type::TYPE_MESSAGE()) { $body[] = sprintf('$writer->writeVarint($stream, %s);', $key); $body[] = $this->generateWriteScalarStatement($type->value(), $variable) . ';'; return $body; } $body[] = '$writer->writeVarint($stream, ' . $key . ');'; $body[] = '$writer->writeVarint($stream, ' . $variable . '->serializedSize($sizeContext));'; $body[] = $variable . '->writeTo($context);'; return $body; }
/** * @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 generateAccessors(proto\FieldDescriptorProto $field, $ns, $indent) { $tag = $field->getNumber(); $name = $field->getName(); $camel = $this->compiler->camelize(ucfirst($name)); $typehint = ''; $typedoc = $this->getJavaDocType($field); if (0 === strpos($typedoc, '\\')) { $typehint = $typedoc; } // hasXXX $s[] = "/**"; $s[] = " * Check if <{$name}> has a value"; $s[] = " *"; $s[] = " * @return boolean"; $s[] = " */"; $s[] = "public function has{$camel}(){"; $s[] = " return \$this->_has({$tag});"; $s[] = "}"; $s[] = ""; // clearXXX $s[] = "/**"; $s[] = " * Clear <{$name}> value"; $s[] = " *"; $s[] = " * @return \\" . $this->normalizeNS($ns); $s[] = " */"; $s[] = "public function clear{$camel}(){"; $s[] = " return \$this->_clear({$tag});"; $s[] = "}"; $s[] = ""; if ($field->getLabel() === Protobuf::RULE_REPEATED) { // getXXX $s[] = "/**"; $s[] = " * Get <{$name}> value"; $s[] = " *"; $s[] = " * @param int \$idx"; $s[] = " * @return {$typedoc}"; $s[] = " */"; $s[] = "public function get{$camel}(\$idx = NULL){"; $s[] = " return \$this->_get({$tag}, \$idx);"; $s[] = "}"; $s[] = ""; // setXXX $s[] = "/**"; $s[] = " * Set <{$name}> value"; $s[] = " *"; $s[] = " * @param {$typedoc} \$value"; $s[] = " * @return \\" . $this->normalizeNS($ns); $s[] = " */"; $s[] = "public function set{$camel}({$typehint} \$value, \$idx = NULL){"; $s[] = " return \$this->_set({$tag}, \$value, \$idx);"; $s[] = "}"; $s[] = ""; $s[] = "/**"; $s[] = " * Get all elements of <{$name}>"; $s[] = " *"; $s[] = " * @return {$typedoc}[]"; $s[] = " */"; $s[] = "public function get{$camel}List(){"; $s[] = " return \$this->_get({$tag});"; $s[] = "}"; $s[] = ""; $s[] = "/**"; $s[] = " * Add a new element to <{$name}>"; $s[] = " *"; $s[] = " * @param {$typedoc} \$value"; $s[] = " * @return \\" . $this->normalizeNS($ns); $s[] = " */"; $s[] = "public function add{$camel}({$typehint} \$value){"; $s[] = " return \$this->_add({$tag}, \$value);"; $s[] = "}"; $s[] = ""; } else { // getXXX $s[] = "/**"; $s[] = " * Get <{$name}> value"; $s[] = " *"; $s[] = " * @return {$typedoc}"; $s[] = " */"; $s[] = "public function get{$camel}(){"; $s[] = " return \$this->_get({$tag});"; $s[] = "}"; $s[] = ""; // setXXX $s[] = "/**"; $s[] = " * Set <{$name}> value"; $s[] = " *"; $s[] = " * @param {$typedoc} \$value"; $s[] = " * @return \\" . $this->normalizeNS($ns); $s[] = " */"; $s[] = "public function set{$camel}({$typehint} \$value){"; $s[] = " return \$this->_set({$tag}, \$value);"; $s[] = "}"; $s[] = ""; } return $indent . implode(PHP_EOL . $indent, $s); }
/** * @param \Protobuf\Compiler\Entity $entity * @param \google\protobuf\FieldDescriptorProto $field * * @return string */ protected function generateExtensionMethod(Entity $entity, FieldDescriptorProto $field) { $fieldName = $field->getName(); $descriptor = $entity->getDescriptor(); $methodName = $this->getCamelizedName($field); $bodyGen = new ExtensionsGenerator($this->context); $body = implode(PHP_EOL, $bodyGen->generateBody($entity, $field)); $method = MethodGenerator::fromArray(['static' => true, 'body' => $body, 'name' => $methodName, 'docblock' => ['shortDescription' => "Extension field : {$fieldName}", 'tags' => [['name' => 'return', 'description' => '\\Protobuf\\Extension']]]]); $method->getDocblock()->setWordWrap(false); return $method; }
/** * @param \Protobuf\Compiler\Entity $entity * @param \google\protobuf\FieldDescriptorProto $field * * @return array */ protected function generateAddValue(Entity $entity, FieldDescriptorProto $field) { $lines = []; $fieldName = $field->getName(); $methodName = 'add' . $this->getClassifiedName($field); $lines[] = 'foreach ($values[\'' . $fieldName . '\'] as $item) {'; $lines[] = ' $message->' . $methodName . '($item);'; $lines[] = '}'; return $lines; }
/** * @param \google\protobuf\FieldDescriptorProto $field * * @return string */ protected function getCamelizedName(FieldDescriptorProto $field) { $name = $field->getName(); $value = $this->getCamelizedValue($name); return $value; }
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) . ']'; }
/** * @param \google\protobuf\FieldDescriptorProto $field * * @return string[] */ protected function generateFieldBody(FieldDescriptorProto $field) { $lines = []; $name = $field->getName(); $number = $field->getNumber(); $typeName = $field->getTypeName(); $extendee = $field->getExtendee(); $type = $field->getType()->name(); $label = $field->getLabel()->name(); $default = $this->getDefaultFieldValue($field); $values = ['number' => var_export($number, true), 'name' => var_export($name, true), 'type' => '\\google\\protobuf\\FieldDescriptorProto\\Type::' . $type . '()', 'label' => '\\google\\protobuf\\FieldDescriptorProto\\Label::' . $label . '()']; if ($extendee) { $values['extendee'] = var_export($extendee, true); } if ($typeName) { $values['type_name'] = var_export($typeName, true); } if ($field->hasDefaultValue()) { $values['default_value'] = $default; } $lines[] = '\\google\\protobuf\\FieldDescriptorProto::fromArray(['; $lines = array_merge($lines, $this->generateArrayLines($values)); $lines[] = ']),'; return $lines; }
/** * @param \Protobuf\Compiler\Entity $entity * @param \google\protobuf\FieldDescriptorProto $field * * @return string */ protected function generateExtensionField(Entity $entity, FieldDescriptorProto $field) { $name = $field->getName(); $number = $field->getNumber(); $docBlock = $this->getDocBlockType($field); $type = $this->getFieldTypeName($field); $label = $this->getFieldLabelName($field); $property = PropertyGenerator::fromArray(['static' => true, 'name' => $name, 'visibility' => PropertyGenerator::VISIBILITY_PROTECTED, 'docblock' => ['shortDescription' => "Extension field : {$name} {$label} {$type} = {$number}", 'tags' => [['name' => 'var', 'description' => '\\Protobuf\\Extension']]]]); $property->getDocblock()->setWordWrap(false); return $property; }
/** * @param \Protobuf\Compiler\Entity $entity * @param \google\protobuf\FieldDescriptorProto $field * * @return string[] */ protected function generateFieldCondition(Entity $entity, FieldDescriptorProto $field) { $body = []; $fieldName = $field->getName(); $format = 'if ($this->%s !== null) {'; $sttm = $this->generateFieldWriteStatement($entity, $field); $lines = $this->addIndentation($sttm, 1); $body[] = sprintf($format, $fieldName); $body = array_merge($body, $lines); $body[] = '}'; return $body; }