pub struct ModuleReassembler { /* private fields */ }Expand description
Collects DDB blocks into complete modules.
Usage: call note_dii for every DII (repeats are
idempotent; a changed moduleVersion restarts that module), then feed
every DDB through feed_ddb. DDBs for modules not yet
announced by a DII are ignored — carousels repeat, so the block comes
round again after the DII has been seen.
Memory bounds: each announced module is capped at max_module_size, the
aggregate of all in-progress module buffers at max_total_bytes, and the
number of in-progress slots at max_slots (the byte budget alone does not
model per-slot map/bitset overhead, so many distinct small modules are
bounded separately) — announcements that would exceed any cap are skipped
until completed modules free space, and moduleSize == 0 announcements
are rejected outright. Block tracking is a bitset
(~moduleSize/blockSize/8 bytes), so the worst-case overhead for a
blockSize = 1 announcement is ~12.5% on top of the data buffer.
Liveness on lossy streams: the skip-until-space policy means that when the budget is held by large modules that never complete (sustained loss), later small announcements are starved until the large slots complete or are version-bumped. This is by design — drop and recreate the reassembler to recover from a wedged stream.
Implementations§
Source§impl ModuleReassembler
impl ModuleReassembler
Sourcepub fn new() -> Self
pub fn new() -> Self
New reassembler with DEFAULT_MAX_MODULE_SIZE and
DEFAULT_MAX_TOTAL_BYTES.
Sourcepub fn with_max_module_size(max_module_size: u32) -> Self
pub fn with_max_module_size(max_module_size: u32) -> Self
New reassembler with a custom per-module size cap (aggregate budget
stays at DEFAULT_MAX_TOTAL_BYTES).
Sourcepub fn with_limits(max_module_size: u32, max_total_bytes: usize) -> Self
pub fn with_limits(max_module_size: u32, max_total_bytes: usize) -> Self
New reassembler with explicit per-module and aggregate byte caps
(slot-count cap stays at DEFAULT_MAX_SLOTS).
Sourcepub fn with_max_slots(self, max_slots: usize) -> Self
pub fn with_max_slots(self, max_slots: usize) -> Self
Replace the in-progress slot-count cap (default
DEFAULT_MAX_SLOTS). Announcements past the cap are skipped until
completed modules free slots — the same skip-until-space policy as the
byte budget.
Sourcepub fn note_dii(&mut self, dii: &Dii<'_>)
pub fn note_dii(&mut self, dii: &Dii<'_>)
Register the modules announced by a DII. Skipped: moduleSize == 0
(nothing to reassemble), modules over the per-module cap,
blockSize == 0, and modules that would push the aggregate budget
over max_total_bytes or the slot count to max_slots.
Re-announcement of an in-progress (same-version) module is a no-op; a
new version replaces the old slot (freeing its budget first).
Sourcepub fn feed_ddb(&mut self, ddb: &DownloadDataBlock<'_>) -> Option<Module>
pub fn feed_ddb(&mut self, ddb: &DownloadDataBlock<'_>) -> Option<Module>
Feed one DDB. Returns the completed Module when this block was the
last missing piece. Blocks for unknown (downloadId, moduleId, version)
triples, out-of-range block numbers, repeats, and blocks whose length
disagrees with the DII geometry are ignored.
Sourcepub fn pending_bytes(&self) -> usize
pub fn pending_bytes(&self) -> usize
Total announced moduleSize bytes currently held by in-progress
module buffers — the quantity charged against max_total_bytes.
This counts data-buffer bytes only, not the per-slot map entry and
block-bitset overhead, so it understates true retained memory (the
slot-count cap bounds that overhead instead). Do not use it as a
memory-pressure signal; use pending × expected
module size for a rough upper bound.