/** * @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; }
public static function isPacked(\google\protobuf\FieldDescriptorProto $field) { return self::LABEL_REPEATED == $field->getLabel() && $field->getOptions()->getPacked(); }
/** * @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; }