Pro edição
Writer — Referência Profunda
Visão geral
Seção intitulada “Visão geral”O módulo Writer grava revisões de atualização incremental de PDF e empacota objetos pequenos em Object Streams. O writer incremental impõe uma regra somente-acréscimo (append-only) com falha fechada: cada byte que o buffer continha antes de uma revisão deve permanecer inalterado depois dela. O construtor de Object Stream agrupa objetos elegíveis em um único objeto /Type /ObjStm compactado com FlateDecode, dentro de um tamanho delimitado.
Disponibilidade & licenciamento
Seção intitulada “Disponibilidade & licenciamento”Este recurso é distribuído no NextPDF Pro (nextpdf/pro) e é ativado com um envelope de licença de nível Pro. Uma implantação sem esse direito não carrega as classes do recurso. Compare edições e obtenha uma licença. Não há sinalizador de licença por recurso; o código é distribuído com a edição Pro.
Superfície da API pública
Seção intitulada “Superfície da API pública”O módulo reside no namespace NextPDF\Pro\Writer. Todos os símbolos públicos estão listados abaixo. Os value objects são classes imutáveis final readonly.
| Símbolo | Parâmetros | Comportamento padrão | Retorna | Lança ou falha com | Notas |
|---|---|---|---|---|---|
IncrementalUpdateWriter::writeRevision | BinaryBuffer $buffer, ObjectRegistry $registry, int $prevXrefOffset, int $catalogObject, array $catalogEntries, array $catalogUpdates, array $newObjectNumbers, string $fileId | Estático. Reescreve o catálogo com entradas mescladas, anexa uma tabela de referência cruzada tradicional para objetos novos e modificados, e grava um trailer com /Size, /Root, /Prev e /ID. Verifica depois que o prefixo anterior à revisão é byte a byte igual. | int — offset em bytes da nova tabela de referência cruzada | \NextPDF\Exception\WriterException quando a verificação de prefixo somente-acréscimo falha; getWriterState() retorna dss-append-only-invariant | Ponto de entrada estático. Nenhuma saída utilizável em caso de violação. |
ObjectStreamWriter::addObject | int $objectNumber, string $content | Anexa um objeto ao stream pendente após uma verificação de tamanho. | void | OverflowException quando o índice combinado mais o corpo excederiam 65.536 bytes | $content exclui os invólucros N 0 obj / endobj. |
ObjectStreamWriter::canAccept | string $content | Estima a sobrecarga do índice e testa o total corrente contra o máximo. | bool | Não lança | Predicado puro; sem alteração de estado. |
ObjectStreamWriter::build | nenhum | Constrói o índice, concatena os corpos, compacta com FlateDecode e encapsula o dicionário /Type /ObjStm. | string — conteúdo bruto do Object Stream | ObjectStreamWriteException quando nenhum objeto foi adicionado, ou em uma falha de compactação zlib | O chamador atribui o número do objeto e encapsula os marcadores. |
ObjectStreamWriter::getEntries | nenhum | Recalcula os offsets relativos ao corpo para os objetos acumulados. | list<ObjectStreamEntry> | Não lança | Os offsets são relativos à seção de corpo. |
ObjectStreamWriter::count | nenhum | Informa o número de objetos acumulados. | int | Não lança | — |
ObjStmCompressor::__construct | int $maxStreamSize = 65536, int $maxObjectsPerStream = 200 | Armazena os limites de tamanho e de contagem de objetos usados no agrupamento. | — | Não lança | Os padrões correspondem ao ajuste de Object Stream do módulo. |
ObjStmCompressor::groupObjects | list<array{number: int, generation?: int, content: string}> $objects | Filtra objetos inelegíveis e depois empacota o restante em writers dentro dos limites de tamanho e contagem. | list<ObjectStreamWriter> | Não lança; objetos inelegíveis são ignorados | Objetos com generation diferente de zero passam à serialização normal. |
ObjStmCompressor::isEligible | string $content, int $generation = 0 | Rejeita objetos de stream, /Encrypt, /XRef, /Catalog e qualquer generation diferente de zero. | bool | Não lança | A correspondência de /Type é tolerante a espaços em branco e a escapes #xx. |
ObjStmCompressor::writeToBuffer | list<ObjectStreamWriter> $streams, BinaryBuffer $buffer, ObjectRegistry $registry | Aloca um objeto portador por stream, registra entradas compactadas de tipo 2 e grava cada bloco ObjStm. | list<int> — números dos objetos portadores | Propaga ObjectStreamWriteException de build() em uma rara falha de compactação | Execute após os objetos não elegíveis serem gravados e antes de a referência cruzada ser emitida. |
ObjStmCompressor::estimateSavings | list<ObjectStreamWriter> $streams, int $originalSize | Constrói cada stream para medir o tamanho compactado em relação ao original. | ObjStmCompressionResult | Propaga ObjectStreamWriteException de build() em uma rara falha de compactação | Auxiliar de medição somente leitura. |
ObjectStreamEntry::__construct | int $objectNumber, string $content, int $offset | Registro imutável de um objeto empacotado e seu offset no corpo. | — | Não lança | final readonly; propriedades públicas. |
ObjStmCompressionResult::__construct | int $originalObjectCount, int $streamCount, int $estimatedOriginalSize, int $estimatedCompressedSize | Contêiner imutável de métricas. | — | Não lança | final readonly; propriedades públicas. |
ObjStmCompressionResult::savedBytes | nenhum | Retorna o tamanho original menos o compactado. | int | Não lança | Pode ser negativo quando o empacotamento expandiu os dados. |
ObjStmCompressionResult::savedPercent | nenhum | Retorna a redução percentual. | float | Não lança | Retorna 0.0 quando o tamanho original é zero. |
ObjStmCompressionResult::compressionRatio | nenhum | Retorna o tamanho compactado sobre o original. | float | Não lança | Retorna 1.0 quando o tamanho original é zero. |
ObjectStreamWriteException | — | Sinaliza uma falha na construção do Object Stream. | — | Estende RuntimeException | Lançada por build(); capturável via RuntimeException para compatibilidade retroativa. |
Assinaturas dos pontos de entrada
Seção intitulada “Assinaturas dos pontos de entrada”final class IncrementalUpdateWriter{ public static function writeRevision( BinaryBuffer $buffer, ObjectRegistry $registry, int $prevXrefOffset, int $catalogObject, array $catalogEntries, array $catalogUpdates, array $newObjectNumbers, string $fileId, ): int;}final class ObjectStreamWriter{ public function addObject(int $objectNumber, string $content): void; public function canAccept(string $content): bool; public function build(): string; /** @return list<ObjectStreamEntry> */ public function getEntries(): array; public function count(): int;}final class ObjStmCompressor{ public function __construct( int $maxStreamSize = 65536, int $maxObjectsPerStream = 200, );
/** * @param list<array{number: int, generation?: int, content: string}> $objects * @return list<ObjectStreamWriter> */ public function groupObjects(array $objects): array;
public function isEligible(string $content, int $generation = 0): bool;
/** * @param list<ObjectStreamWriter> $streams * @return list<int> */ public function writeToBuffer(array $streams, BinaryBuffer $buffer, ObjectRegistry $registry): array;
/** @param list<ObjectStreamWriter> $streams */ public function estimateSavings(array $streams, int $originalSize): ObjStmCompressionResult;}Contrato de comportamento
Seção intitulada “Contrato de comportamento”writeRevision grava uma revisão de atualização incremental. Ele captura um snapshot do prefixo do buffer existente antes de gravar. Ele reescreve o catálogo com entradas mescladas, registra os offsets dos novos objetos, grava uma tabela de referência cruzada tradicional agrupada em subseções contíguas e grava um trailer com /Size, /Root, /Prev e /ID. Após gravar, ele compara o prefixo novamente. Se qualquer byte anterior mudou, ele gera WriterException carregando o estado de violação de somente-acréscimo e não retorna saída utilizável. Em caso de sucesso, ele retorna o offset em bytes da nova tabela de referência cruzada para encadear revisões adicionais. É permitido misturar tabelas e streams de referência cruzada entre revisões.
ObjectStreamWriter acumula objetos. addObject gera um erro de estouro quando o índice combinado e o corpo excederiam o máximo de 65.536 bytes descompactados. build gera um erro em um stream vazio; caso contrário, ele compacta o índice mais o corpo e retorna o conteúdo do Object Stream com as entradas /Type /ObjStm, /N, /First, /Length e /Filter /FlateDecode. O chamador atribui o número do objeto e encapsula os marcadores N 0 obj / endobj.
ObjStmCompressor decide quais objetos empacotar. Ele exclui objetos de stream, dicionários de criptografia, streams de referência cruzada, o catálogo do documento e qualquer objeto com número de generation diferente de zero. writeToBuffer aloca um objeto portador por stream, registra cada objeto empacotado como uma entrada de referência cruzada compactada de tipo 2 e grava o bloco ObjStm no offset atual do buffer. estimateSavings constrói cada stream para calcular as métricas de tamanho sem alterar o buffer.
Casos extremos & modos de falha
Seção intitulada “Casos extremos & modos de falha”- A verificação de somente-acréscimo copia o prefixo existente. Seu custo cresce com o tamanho do documento já gravado. Esse custo é intencional e protege os bytes assinados.
- O limite do Object Stream aplica-se ao índice descompactado mais o corpo. Coloque o dicionário de criptografia e outros tipos de objeto excluídos como objetos indiretos diretos.
- A exclusão de
/Typeé tolerante a espaços em branco arbitrários entre tokens e a escapes hexadecimais#xx. Formas como/Type /Encrypt,/Type\n/Encrypte/Type /#45ncryptsão todas rejeitadas, não apenas a grafia literal canônica. - Qualquer objeto que carregue um número de generation diferente de zero é tratado como inelegível e passa à serialização normal
N G obj … endobj, porque a generation de um objeto compactado é implicitamente zero. writeToBufferdeve ser executado após todos os objetos não elegíveis terem sido gravados e antes de a referência cruzada ser emitida. Objetos empacotados não devem também ser serializados separadamente.
Comportamento em modo FIPS
Seção intitulada “Comportamento em modo FIPS”O módulo Writer não realiza operações criptográficas. Ele protege os bytes assinados recusando-se a emitir quando um byte anterior mudaria, o que é um teste de igualdade de bytes, e não um teste criptográfico. A seleção de algoritmos FIPS para assinatura e hashing é regida pelo módulo de assinatura, não por este writer. Ativar ou desativar o modo FIPS não altera o comportamento de nenhum método do Writer.
Conformidade
Seção intitulada “Conformidade”O NextPDF implementa o módulo em conformidade com a ISO 32000-2:2020. O writer incremental segue a gramática de atualização incremental da §7.5.6: cada revisão anexa uma seção de referência cruzada cobrindo apenas objetos novos, alterados ou excluídos, e um trailer cuja entrada /Prev fornece o offset da referência cruzada anterior. O construtor de Object Stream segue o modelo de object-stream da §7.5.7: um índice de pares de número de objeto e offset, com offsets medidos a partir da entrada /First em ordem crescente, precede os corpos dos objetos empacotados. Ambas as referências de cláusula foram verificadas contra o corpus da ISO 32000-2:2020. O encadeamento de revisões para os fluxos de trabalho PAdES B-LT e B-LTA segue a ETSI EN 319 142-1 §5.4, conforme anotado no código-fonte. O suporte a uma cláusula é uma declaração de capacidade de engenharia, não uma certificação; o NextPDF não possui nenhuma certificação formal de conformidade.
Notas de desenvolvimento
Seção intitulada “Notas de desenvolvimento”- Instale o pacote com
composer require nextpdf/pro:^3. As classes resolvem sobNextPDF\Pro\Writer. IncrementalUpdateWriter::writeRevisioné um ponto de entrada estático; ele não mantém estado de instância entre revisões.ObjectStreamEntry,ObjStmCompressionResult,IncrementalUpdateWritere o compressor juntos formam a superfície pública do módulo; o repositório não distribui nenhum exemplo executável para ele.- Uma
WriterExceptiondewriteRevisionindica uma violação de somente-acréscimo. Trate-a como uma falha grave e descarte o buffer. - Os portadores de Object Stream são objetos indiretos; o chamador atribui seus números de objeto por meio do registry.
Limite de publicação
Seção intitulada “Limite de publicação”Esta página documenta apenas o comportamento observável externamente e a superfície de API pública suportada. Caminhos de namespace internos, classes auxiliares, tabelas de mecanismos, nomes de arquivos de runbook e prefixos de ticket estão fora do escopo.