DEFAULT_SIZE
DEFAULT_SIZE = 16384
Default frame size in bytes.
Splits a byte stream into fixed-size frames.
Frames are a fixed size rather than content-defined. A pure-PHP FastCDC runs at 4.29 MB/s
per-byte and 5.63 MB/s over unpacked 64 KiB windows, against 683 MB/s for this splitter plus a
BLAKE2b per frame; unpack('C*') on an 8 MB buffer also exhausts a 128 MB memory limit, since
an int array costs roughly 16x the string. Content-defined chunking exists to survive
insertions, which shift every following boundary, and an append-only op log has none.
DeltaCodec covers the case content-defined chunking would have: it compresses a rewritten value against its previous version, measured at 63.7x on that class of change. Files, where an insertion can happen, are handled by BlockSplitter, which detects the shift.
Frame size trades compression against granularity: with a trained zstd dictionary the measured ratio is 6.20x at 8 KiB, 6.39x at 16 KiB, 6.54x at 32 KiB and 6.72x at 64 KiB, while the dictionary's own contribution falls from 40.3% to 15.7% across that range. 16 KiB is the shipped default; calibration against a real site decides whether to move it.
__construct(int $size = \self::DEFAULT_SIZE) : mixed
Constructs a splitter.
| int | $size | Frame size in bytes, between Framer::MIN_SIZE and Framer::MAX_SIZE. Powers of two are not required but are what the defaults use. |
When $size is outside the supported range.
count(int $length) : int
How many frames a payload of a given length produces.
The last frame is short rather than padded, so that appending to a payload never rewrites a frame that was already stored under its own digest.
| int | $length | Payload length in bytes. |
When $length is negative.
Frame count; zero for an empty payload.
split(string $payload) : \Generator<int,string>
Splits a string into frames.
An empty payload yields nothing, which is what lets a caller distinguish "no content" from "one empty frame" without a sentinel.
| string | $payload | The bytes to split. |
Frame index keyed to frame bytes, in order.
splitStream(resource $stream) : \Generator<int,string>
Splits a stream into frames without holding it in memory.
Reads from the current position to EOF. A short read that is not EOF is retried rather than silently producing an under-length frame in the middle of a payload, because a short frame anywhere but the end changes every following boundary and would fork the whole frame chain.
| resource | $stream | An open, readable stream. |
When $stream is not a stream resource.
When a read fails.
Frame index keyed to frame bytes, in order.
frames(string $payload) : \Generator<int,array{hash: string, bytes: string, offset: int}>
Splits a payload and digests each frame.
The common case: a caller wants the frames and their content addresses together, and computing the digest separately would walk the payload twice.
| string | $payload | The bytes to split. |
Frame index keyed to the frame's digest, bytes and byte offset in the payload.
reassemble(list$map, callable $fetch) : string
Rebuilds a payload from frames supplied in order.
Verifies each frame against the digest it was stored under, so a corrupted or substituted frame raises here rather than reaching Drupal as plausible-looking content. The map is the authority on order and length; a missing frame is named rather than skipped.
| list |
$map | Frame digests in order, as returned by Framer::map(). |
| callable | $fetch | Given a frame digest, returns its bytes, or NULL when the frame cannot be found. |
When a frame is missing, or its bytes do not digest to the hash it was stored under.
The reassembled payload.