pub struct FetchObjectWriter {
group_order: GroupOrder,
prior_location: Option<(u64, u64)>,
prior_subgroup_id: Option<u64>,
prior_publisher_priority: Option<u8>,
}Expand description
Re-encodes resolved fetch frames onto one FETCH stream.
The exact inverse of FetchObjectReader, and it exists for one caller:
something that has read a stream and is writing a different stream from the
same frames. Removing a frame changes what the frames after it are encoded
against, and draft-20 Section 11.4.4.1 defines nearly every field against
“the prior Object”, so the survivor that follows a removed run cannot keep
its original bytes. What has to change is not one field: an Object that
carried no Group ID Delta because it shared its predecessor’s group needs
one once that predecessor is gone, so a field appears and a flag bit with
it.
§Why this is not a general encoder
Every frame it writes came off a stream, so the caller already holds the
frame’s own FetchObjectHeader alongside the resolved values. That header
is used as the preference: wherever the original shape still encodes the
same meaning against the new predecessor, it is kept, so a stream with
nothing removed from it is reproduced byte for byte. Only where the original
shape would now decode to something else is a different one chosen. An
encoder built from the resolved values alone could not do that — it would
have to invent a canonical form and would rewrite every frame on a stream
that needed no rewriting at all.
§What it refuses
CodecError::InvalidField where no encoding exists rather than picking
one: a Group ID that moves against the FETCH’s Group Order, an Object ID
that does not advance, an Object with neither a Subgroup ID nor the Datagram
bit, and the arithmetic overflows. Each of these is a frame this writer was
handed that no draft-20 stream could carry, and inventing a value for it
would put a different Object on the wire than the one it was given.
Fields§
§group_order: GroupOrder§prior_location: Option<(u64, u64)>Group ID and Object ID of the last frame written, marker or Object.
prior_subgroup_id: Option<u64>Subgroup ID of the last actual Object written that had one.
prior_publisher_priority: Option<u8>Publisher Priority of the last actual Object written.
Implementations§
Source§impl FetchObjectWriter
impl FetchObjectWriter
Sourcepub fn new(group_order: GroupOrder) -> Self
pub fn new(group_order: GroupOrder) -> Self
A writer for a stream whose Groups are being written in group_order.
The order has to match the one the FETCH was opened with, for the same
reason FetchObjectReader::new takes it: it decides whether a Group
ID Delta adds or subtracts, and it is not on the data stream.
Sourcepub fn header_for(
&self,
frame: &FetchObject,
) -> Result<FetchObjectHeader, CodecError>
pub fn header_for( &self, frame: &FetchObject, ) -> Result<FetchObjectHeader, CodecError>
The header that encodes frame against everything written so far.
Does not advance the writer — Self::write_object_header is the call
that does both. Separated so that a caller can measure the bytes a
re-encode would take before committing to it.
§Errors
CodecError::InvalidField for a frame that cannot be encoded against
the current predecessor; see the type’s own documentation for the list.
Sourcefn identity_fields(
&self,
frame: &FetchObject,
original: &FetchObjectHeader,
) -> Result<(Option<VarInt>, Option<VarInt>), CodecError>
fn identity_fields( &self, frame: &FetchObject, original: &FetchObjectHeader, ) -> Result<(Option<VarInt>, Option<VarInt>), CodecError>
The Group ID Delta and Object ID Delta fields, as this predecessor needs them.
Presence is forced by the frame rather than chosen: a group that differs from the predecessor’s has to be stated, and one that matches has to be left off, since a delta of zero means the next group along and not this one. Only the Object ID Delta has a choice to make, and it is made in favour of the shape the frame arrived in.
Sourcefn subgroup_field(
&self,
frame: &FetchObject,
original: &FetchObjectHeader,
) -> Result<(u64, Option<VarInt>), CodecError>
fn subgroup_field( &self, frame: &FetchObject, original: &FetchObjectHeader, ) -> Result<(u64, Option<VarInt>), CodecError>
The Subgroup ID mode bits and the explicit field, if one is needed.
The frame’s own mode is tried first, so a run of Objects that inherited their Subgroup ID keeps inheriting it and its bytes do not move. Only when the predecessor changed under it does a different mode get chosen, and then the cheapest one that says the right number.
Sourcefn priority_field(
&self,
frame: &FetchObject,
original: &FetchObjectHeader,
) -> Result<Option<u8>, CodecError>
fn priority_field( &self, frame: &FetchObject, original: &FetchObjectHeader, ) -> Result<Option<u8>, CodecError>
The Publisher Priority field, or None when the predecessor already
carries it.
Written whenever the frame wrote one, so a publisher that stated a priority on every Object keeps its bytes, and written anyway when the predecessor’s differs or when there is no predecessor to inherit from.
Sourcepub fn write_object_header(
&mut self,
frame: &FetchObject,
out: &mut impl BufMut,
) -> Result<FetchObjectHeader, CodecError>
pub fn write_object_header( &mut self, frame: &FetchObject, out: &mut impl BufMut, ) -> Result<FetchObjectHeader, CodecError>
Encode frame against everything written so far and advance.
Writes the header only. The payload is frame.header.payload_length
bytes and is the caller’s to copy, unchanged — nothing about it depends
on what preceded the Object.
§Errors
CodecError::InvalidField for a frame with no encoding against the
current predecessor. The writer is left untouched when this happens, so
a caller that gives up on one frame and carries on with the next is
writing against the same predecessor it thought it was.
Sourcepub fn advance(&mut self, frame: &FetchObject)
pub fn advance(&mut self, frame: &FetchObject)
Record frame as the predecessor of whatever is written next.
Split from the write so that a caller re-emitting bytes it already holds can advance without producing a header twice — which is what happens whenever the framing a frame arrived in still encodes the same meaning against the frame before it, and is why this is public.
Trait Implementations§
Source§impl Clone for FetchObjectWriter
impl Clone for FetchObjectWriter
Source§fn clone(&self) -> FetchObjectWriter
fn clone(&self) -> FetchObjectWriter
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more