Pro エディション
Writer — 詳細リファレンス
Writer モジュールは、PDF の差分更新リビジョンを書き込み、小さなオブジェクトを Object Stream にパックします。差分ライターは、フェイルクローズドな追記専用ルールを強制します。リビジョン前にバッファが保持していたすべてのバイトは、リビジョン後も変更されないまま残らなければなりません。Object Stream ビルダーは、対象となるオブジェクトを制限サイズの範囲内で 1 つの FlateDecode 圧縮 /Type /ObjStm オブジェクトにまとめます。
提供状況とライセンス
「提供状況とライセンス」という見出しのセクションこの機能は NextPDF Pro(nextpdf/pro)で提供され、Pro ティアのライセンスエンベロープで有効化されます。そのエンタイトルメントを持たないデプロイでは、この機能のクラスはロードされません。エディションを比較してライセンスを取得。機能ごとのライセンスフラグはなく、このコードは Pro エディションに同梱されます。
公開 API サーフェス
「公開 API サーフェス」という見出しのセクションこのモジュールは NextPDF\Pro\Writer 名前空間に属します。すべての公開シンボルを以下に列挙します。値オブジェクトはイミュータブルな final readonly クラスです。
| シンボル | パラメーター | デフォルト動作 | 戻り値 | 送出または失敗 | 備考 |
|---|---|---|---|---|---|
IncrementalUpdateWriter::writeRevision | BinaryBuffer $buffer, ObjectRegistry $registry, int $prevXrefOffset, int $catalogObject, array $catalogEntries, array $catalogUpdates, array $newObjectNumbers, string $fileId | 静的。マージされたエントリでカタログを書き直し、新規および変更されたオブジェクト向けの従来型相互参照テーブルを追記し、/Size、/Root、/Prev、/ID を持つトレーラーを書き込む。書き込み後にリビジョン前のプレフィックスがバイト単位で等しいことを検証。 | int — 新しい相互参照テーブルのバイトオフセット | 追記専用プレフィックスチェックが失敗した場合に \NextPDF\Exception\WriterException。getWriterState() は dss-append-only-invariant を返す | 静的エントリーポイント。違反時は使用可能な出力なし。 |
ObjectStreamWriter::addObject | int $objectNumber, string $content | サイズチェックの後、保留中ストリームに 1 オブジェクトを追記。 | void | 結合されたインデックスとボディが 65,536 バイトを超える場合に OverflowException | $content は N 0 obj / endobj ラッパーを含まない。 |
ObjectStreamWriter::canAccept | string $content | インデックスのオーバーヘッドを見積もり、累計を最大値と照合。 | bool | 送出しない | 純粋な述語。状態変更なし。 |
ObjectStreamWriter::build | なし | インデックスを構築し、ボディを連結し、FlateDecode で圧縮し、/Type /ObjStm ディクショナリでラップ。 | string — 生の Object Stream コンテンツ | オブジェクトが追加されていない場合、または zlib 圧縮失敗時に ObjectStreamWriteException | 呼び出し元がオブジェクト番号を割り当ててマーカーをラップ。 |
ObjectStreamWriter::getEntries | なし | 蓄積されたオブジェクトのボディ相対オフセットを再計算。 | list<ObjectStreamEntry> | 送出しない | オフセットはボディセクション相対。 |
ObjectStreamWriter::count | なし | 蓄積されたオブジェクト数を報告。 | int | 送出しない | — |
ObjStmCompressor::__construct | int $maxStreamSize = 65536, int $maxObjectsPerStream = 200 | グループ化に用いるサイズおよびオブジェクト数の上限を保持。 | — | 送出しない | デフォルトはモジュールの Object Stream チューニングに一致。 |
ObjStmCompressor::groupObjects | list<array{number: int, generation?: int, content: string}> $objects | 対象外のオブジェクトを除外し、残りをサイズと数の上限内でライターにパック。 | list<ObjectStreamWriter> | 送出しない。対象外オブジェクトはスキップ | 非ゼロ世代のオブジェクトは通常のシリアライズにフォールスルー。 |
ObjStmCompressor::isEligible | string $content, int $generation = 0 | ストリームオブジェクト、/Encrypt、/XRef、/Catalog、および非ゼロ世代を拒否。 | bool | 送出しない | /Type の照合は空白および #xx エスケープに寛容。 |
ObjStmCompressor::writeToBuffer | list<ObjectStreamWriter> $streams, BinaryBuffer $buffer, ObjectRegistry $registry | ストリームごとにキャリアオブジェクトを割り当て、type-2 圧縮エントリを登録し、各 ObjStm ブロックを書き込む。 | list<int> — キャリアオブジェクト番号 | まれな圧縮失敗時に build() からの ObjectStreamWriteException を伝播 | 対象外オブジェクトの書き込み後、相互参照の出力前に実行。 |
ObjStmCompressor::estimateSavings | list<ObjectStreamWriter> $streams, int $originalSize | 各ストリームを構築し、圧縮後サイズを元サイズと比較して測定。 | ObjStmCompressionResult | まれな圧縮失敗時に build() からの ObjectStreamWriteException を伝播 | 読み取り専用の測定ヘルパー。 |
ObjectStreamEntry::__construct | int $objectNumber, string $content, int $offset | パックされた 1 オブジェクトとそのボディオフセットのイミュータブルなレコード。 | — | 送出しない | final readonly。パブリックプロパティ。 |
ObjStmCompressionResult::__construct | int $originalObjectCount, int $streamCount, int $estimatedOriginalSize, int $estimatedCompressedSize | イミュータブルなメトリクスコンテナ。 | — | 送出しない | final readonly。パブリックプロパティ。 |
ObjStmCompressionResult::savedBytes | なし | 元サイズから圧縮後サイズを引いた値を返す。 | int | 送出しない | パックによりデータが膨張した場合は負になり得る。 |
ObjStmCompressionResult::savedPercent | なし | 削減率をパーセントで返す。 | float | 送出しない | 元サイズがゼロの場合は 0.0 を返す。 |
ObjStmCompressionResult::compressionRatio | なし | 圧縮後サイズを元サイズで割った値を返す。 | float | 送出しない | 元サイズがゼロの場合は 1.0 を返す。 |
ObjectStreamWriteException | — | Object Stream の構築失敗を通知。 | — | RuntimeException を継承 | build() から送出。後方互換のため RuntimeException で捕捉可能。 |
エントリーポイントのシグネチャ
「エントリーポイントのシグネチャ」という見出しのセクション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;}挙動コントラクト
「挙動コントラクト」という見出しのセクションwriteRevision は 1 つの差分更新リビジョンを書き込みます。書き込みの前に、既存のバッファプレフィックスをスナップショットします。マージされたエントリでカタログを書き直し、新しいオブジェクトオフセットを登録し、連続したサブセクションにグループ化された従来型の相互参照テーブルを書き込み、/Size、/Root、/Prev、/ID を持つトレーラーを書き込みます。書き込み後、再びプレフィックスを比較します。それ以前のいずれかのバイトが変更されていた場合は、追記専用違反の状態を保持する WriterException を発生させ、使用可能な出力を返しません。成功すると、さらにリビジョンをチェーンするための新しい相互参照テーブルのバイトオフセットを返します。リビジョン間で相互参照テーブルとストリームを混在させることは許可されています。
ObjectStreamWriter はオブジェクトを蓄積します。addObject は、結合されたインデックスとボディが非圧縮で最大値 65,536 バイトを超える場合にオーバーフローエラーを発生させます。build は空のストリームに対してエラーを発生させます。そうでない場合は、インデックスとボディを圧縮し、/Type /ObjStm、/N、/First、/Length、/Filter /FlateDecode の各エントリを持つ Object Stream コンテンツを返します。オブジェクト番号の割り当てと N 0 obj / endobj マーカーのラップは呼び出し元が行います。
ObjStmCompressor はどのオブジェクトをパックするかを決定します。ストリームオブジェクト、暗号化ディクショナリ、相互参照ストリーム、ドキュメントカタログ、および非ゼロ世代番号を持つ任意のオブジェクトを除外します。writeToBuffer はストリームごとにキャリアオブジェクトを割り当て、パックされた各オブジェクトを type-2 圧縮相互参照エントリとして登録し、現在のバッファオフセットに ObjStm ブロックを書き込みます。estimateSavings は各ストリームを構築してサイズメトリクスを算出し、バッファを変更しません。
エッジケースと失敗モード
「エッジケースと失敗モード」という見出しのセクション- 追記専用チェックは既存のプレフィックスをコピーします。そのコストは、すでに書き込まれたドキュメントのサイズとともに増大します。このコストは意図的なものであり、署名されたバイトを保護します。
- Object Stream の制限は、非圧縮のインデックスとボディに適用されます。暗号化ディクショナリやその他の除外対象のオブジェクトタイプは、直接的な間接オブジェクトとして配置してください。
/Typeの除外は、トークン間の任意の空白および#xxの 16 進エスケープに寛容です。/Type /Encrypt、/Type\n/Encrypt、/Type /#45ncryptのような形式はすべて拒否され、正規のリテラル表記だけが対象ではありません。- 非ゼロ世代番号を持つ任意のオブジェクトは対象外として扱われ、通常の
N G obj … endobjシリアライズにフォールスルーします。圧縮オブジェクトの世代は暗黙的にゼロであるためです。 writeToBufferは、すべての対象外オブジェクトが書き込まれた後、かつ相互参照が出力される前に実行しなければなりません。パックされたオブジェクトを別途シリアライズしてはなりません。
FIPS モードの挙動
「FIPS モードの挙動」という見出しのセクションWriter モジュールは暗号操作を一切実行しません。それ以前のバイトが変更される場合に出力を拒否することで署名されたバイトを保護しますが、これは暗号的なテストではなくバイト等価性のテストです。署名およびハッシュ処理の FIPS アルゴリズム選択は、このライターではなく署名モジュールによって管理されます。FIPS モードの有効化・無効化は、いずれの Writer メソッドの動作も変更しません。
NextPDF はこのモジュールを ISO 32000-2:2020 に対して実装しています。差分ライターは §7.5.6 の差分更新文法に従い、各リビジョンは新規・変更・削除されたオブジェクトのみを対象とする相互参照セクションと、/Prev エントリが前の相互参照のオフセットを示すトレーラーを追記します。Object Stream ビルダーは §7.5.7 の Object Stream モデルに従い、オブジェクト番号とオフセットの組のインデックス(オフセットは /First エントリから測定され昇順)がパックされたオブジェクトボディに先行します。いずれの節参照も ISO 32000-2:2020 コーパスに対して検証済みです。PAdES B-LT および B-LTA ワークフローのリビジョンチェーンは、ソースに注釈されているとおり ETSI EN 319 142-1 §5.4 に従います。ある節へのサポートはエンジニアリング上の能力表明であり、認証ではありません。NextPDF は正式な適合認証を保有していません。
開発上の注意
「開発上の注意」という見出しのセクション- パッケージは
composer require nextpdf/pro:^3でインストールします。クラスはNextPDF\Pro\Writer配下に解決されます。 IncrementalUpdateWriter::writeRevisionは静的エントリーポイントであり、リビジョン間でインスタンス状態を保持しません。ObjectStreamEntry、ObjStmCompressionResult、IncrementalUpdateWriter、およびコンプレッサーが合わせてモジュールの公開サーフェスを構成します。リポジトリはこれに対する実行可能なサンプルを同梱していません。writeRevisionからのWriterExceptionは追記専用違反を示します。ハード障害として扱い、バッファを破棄してください。- Object Stream のキャリアは間接オブジェクトです。呼び出し元がレジストリを通じてそのオブジェクト番号を割り当てます。
公開の境界
「公開の境界」という見出しのセクションこのページは、外部から観測可能な動作とサポートされる公開 API サーフェスのみを記載します。内部の名前空間パス、ヘルパークラス、メカニズムの一覧表、ランブックのファイル名、チケットのプレフィックスは対象外です。