pub fn reemit_subgroup_object(
draft: DraftVersion,
prev_forwarded: Option<u64>,
object_id: u64,
raw: &[u8],
out: &mut impl BufMut,
) -> Result<Reemit, CodecError>Expand description
Re-emit a subgroup object whose wire bytes are already known, adjusting only this draft’s encoding of its identity.
This is the whole of what removing an object from a subgroup stream
costs. Drafts 07-13 encode absolute Object IDs, so every survivor’s
bytes are already correct and this copies raw unchanged after checking
that IDs still increase. Drafts 14-19 encode id - prev - 1, so the
leading varint is recomputed against prev_forwarded; when its minimal
encoding is byte-identical to the one in raw the bytes are still
copied unchanged. Everything after the ID field — extension block,
length, status, payload — is always copied verbatim.
After one object is re-emitted following an elided run, the writer’s cursor re-converges with the reader’s, so every later object’s original bytes remain correct. An elide therefore costs at most one fix-up, not a re-encode of the stream’s tail.
prev_forwarded is the absolute Object ID of the last object actually
forwarded on this stream, or None when none has been.
§raw need not be a complete object
Any prefix is legal provided the whole leading Object ID field is
present. Everything after that field is copied byte-for-byte, however
many bytes there are, and no length validation is performed — this
function never reads the extension block, never reads the payload
length field and never compares it to raw.len(). It cannot: on drafts
07-13 it does not decode past the ID at all, and on 14-19 it decodes
exactly one varint.
This is what lets a caller fix up the first chunk of an oversized
object — an object too large to buffer is forwarded in chunks, and only
the first one carries the ID field. A caller that cannot guarantee the ID
field is whole in the chunk it passes gets
CodecError::InvalidField rather than a silent truncation.
Do not add a completeness check. A raw.len() >= wire_len assertion
would look defensive, would pass every test that feeds it whole objects,
and would refuse the prefix this function exists to accept.
§Errors
CodecError::InvalidField when object_id is not strictly greater
than prev_forwarded, when the recomputed delta exceeds the varint
range, or when raw does not begin with a decodable varint — which
includes a raw too short to hold the whole leading varint.
§Examples
use moqtap_codec::dispatch::{reemit_subgroup_object, Reemit};
use moqtap_codec::version::DraftVersion;
// A draft-19 object that was encoded as the successor of ID 4 —
// leading delta 0 — re-emitted after ID 3 was the last one forwarded.
let raw = [0x00, 0x02, 0xca, 0xfe];
let mut out = Vec::new();
let what = reemit_subgroup_object(DraftVersion::Draft19, Some(3), 5, &raw, &mut out).unwrap();
assert_eq!(what, Reemit::Reencoded { id_bytes_before: 1, id_bytes_after: 1 });
assert_eq!(out, [0x01, 0x02, 0xca, 0xfe]);