Skip to main content

RangeFrame

Struct RangeFrame 

Source
#[non_exhaustive]
pub struct RangeFrame { pub offset: u64, pub length: u64, pub bytes: Vec<u8>, pub complete: bool, pub total_length: Option<u64>, pub chunk_lens: Option<Vec<u64>>, pub chunk_index: Option<u64>, pub inclusion_proof: Option<String>, pub root: Option<String>, pub chunk_count: Option<u64>, pub chunk_lens_offset: Option<u64>, }
Expand description

One streamed dig.fetchRange frame (L7 spec §8 framing). Frames arrive in ascending offset order and tile the requested range exactly; the caller reassembles by offset and stops on complete.

§The metadata splits into two sets, and which frames carry them differs

Read this before implementing either side — the two halves have different rules, and conforming to the wrong half produces a verification miss on a multi-frame read rather than a clean failure.

  • Identity — fixed-size, on EVERY frame: root, total_length, chunk_count, plus chunk_index where the window is chunk-aligned. These are what let a reader reject a wrong-generation or wrong-layout holder the moment a frame arrives, which is a property the once-per-stream set can never have. They cost a bounded number of bytes, so carrying them everywhere is cheap. Set them with with_identity + with_chunk_index.
  • Prologue — resource-scaling, ONCE per range stream: chunk_lens (paged, located by chunk_lens_offset) and inclusion_proof. Their size is a function of the RESOURCE rather than of the frame, so they ride the first frame or a paged prologue and MUST NOT be repeated on later frames. Set them with with_chunk_lens_page + with_inclusion_proof, or omit them entirely when the request set RangeRequest::skip_layout.

Before 0.13.0 every one of these was “first frame only”, because the whole layout had to fit one frame or the range was unservable (#1640). SPEC.md §5.1.1 is normative.

Fields (Non-exhaustive)§

This struct is marked as non-exhaustive
Non-exhaustive structs could have additional fields added in future. Therefore, non-exhaustive structs cannot be constructed in external crates using the traditional Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.
§offset: u64

This frame’s start offset within the requested range.

§length: u64

This frame’s byte length.

§bytes: Vec<u8>

The raw ciphertext bytes. On the wire they are base64 (base64_bytes) — the canonical dig.fetchRange frame encoding every producer emits.

§complete: bool

Whether this is the final frame of the range.

§total_length: Option<u64>

(identity — every frame) the full resource ciphertext length.

§chunk_lens: Option<Vec<u64>>

(prologue — once per stream) per-chunk ciphertext lengths of the whole resource, in order, or ONE PAGE of them beginning at chunk_lens_offset.

Resource-scaling, so it MUST NOT be repeated on later frames: on a later frame it was only a redundant equality check on an array the client already held. Omitted entirely when the request set RangeRequest::skip_layout.

§chunk_index: Option<u64>

(identity — every frame, where the window is chunk-aligned) index into the resource’s chunk_lens array of the first chunk in THIS frame.

Fixed-size, and about this frame rather than about the resource, so a chunk-aligned continuation frame states it too — see with_chunk_index, which is deliberately separate from the proof setter so stating alignment never costs a repeated proof.

§inclusion_proof: Option<String>

(prologue — once per stream) merkle inclusion proof of the whole resource vs the generation root (base64, relayed verbatim); null/absent for capsule: true (self-verifying on install).

Resource-scaling and capped at MAX_INCLUSION_PROOF_B64. At 4,096 B it would consume the entire remaining frame budget if repeated, which is the concrete reason “once per stream” is a MUST NOT rather than a preference.

§root: Option<String>

(identity — every frame) the generation root (64-hex) this range is served from, and which the inclusion proof is against.

§chunk_count: Option<u64>

(identity — every frame) the resource’s TOTAL chunk count — how many entries the reassembled chunk_lens array has.

Together with root and total_length it is what lets a reader detect a wrong-generation or wrong-layout holder the moment a frame arrives. It is also how a reader sizes the array it is paging in, and how it knows the prologue is complete.

§chunk_lens_offset: Option<u64>

(prologue — once per page) the index into the resource’s chunk_lens array at which THIS frame’s chunk_lens page begins — how a paged prologue is located and reassembled.

A resource whose layout exceeds MAX_CHUNK_LENS_PER_FRAME cannot state it on one frame, so the sender pages it: successive frames each carry up to that many entries, stamped with the offset they start at. A reader places each page at its offset and has the whole array once it holds chunk_count entries. Absent means “this frame’s chunk_lens, if any, begins at 0” — the single-frame layout, which is the pre-0.13.0 shape.

Implementations§

Source§

impl RangeFrame

Source

pub fn data(offset: u64, bytes: Vec<u8>) -> Self

A data frame: bytes at offset, with no metadata — the shape of every continuation frame.

length is derived from bytes, since a frame that misdeclares its own payload length is never what a serve path wants. The metadata a FIRST frame or a prologue page carries is layered on with the with_* setters, so a continuation frame cannot accidentally claim a layout it is not stating — the two shapes are different call chains, not one call with a pile of Nones.

Source

pub fn with_complete(self, complete: bool) -> Self

Mark this as the final frame of the range.

Source

pub fn with_identity( self, root: impl Into<String>, total_length: u64, chunk_count: u64, ) -> Self

The fixed-size identity metadata EVERY frame of a range should carry: the generation root (64-hex) the range is served from, the resource’s ciphertext total_length, and its chunk_count.

These three are what let a reader reject a wrong-generation or wrong-layout holder the moment a frame arrives — which the resource-scaling metadata never could, since it arrives once. They are fixed-size, so carrying them everywhere costs a bounded number of bytes.

Source

pub fn with_chunk_lens_page( self, chunk_lens_offset: u64, chunk_lens: Vec<u64>, ) -> Self

A page of the resource’s chunk_lens array, beginning at entry chunk_lens_offset.

Call it once with offset 0 for a layout that fits one frame (at most MAX_CHUNK_LENS_PER_FRAME entries), or once per page of a paged prologue. chunk_lens is a DECRYPT input — per-chunk AES-GCM-SIV needs the WHOLE array, and a reader rejects an array whose sum differs from total_length — so a page is only ever useful as part of a complete set.

Source

pub fn with_chunk_index(self, chunk_index: u64) -> Self

Where this frame starts in the resource’s chunk sequence — the index into chunk_lens of its first chunk, for a chunk-aligned window.

Fixed-size identity, so a chunk-aligned CONTINUATION frame states it too, not only the first frame. It has its own setter for exactly that reason: it used to be a parameter of with_inclusion_proof, which meant the one field every reader wants on every frame could not be stated without repeating a once-per-stream proof — a SPEC.md §5.1.1 MUST NOT, and 4,096 B per frame against a budget with zero slack.

Source

pub fn with_inclusion_proof(self, inclusion_proof: impl Into<String>) -> Self

The merkle inclusion proof of the whole resource against the generation root (base64, relayed verbatim).

Resource-scaling, so it rides the first frame or the prologue — once per range stream, never repeated. Base64 longer than MAX_INCLUSION_PROOF_B64 is refused by encode: such a resource has no conforming range stream at all, and the holder must say so rather than stream frames a reader cannot verify.

Source

pub fn with_declared_length(self, length: u64) -> Self

Override the declared length, which data otherwise derives from bytes.

For budget fixtures that hold every scalar at its widest legal value. A serve path has no reason to call this: a frame whose length disagrees with its payload is a frame the reader distrusts.

Source

pub fn encode(&self) -> Result<Vec<u8>>

Serialize as a u32 big-endian length prefix + JSON body (one framed frame on the stream).

Fails with io::ErrorKind::InvalidData if bytes exceeds MAX_RANGE_FRAME_PAYLOAD, if inclusion_proof exceeds MAX_INCLUSION_PROOF_B64, or if the serialized body exceeds MAX_FRAMED_BODY for any other reason (an unusually large chunk_lens page). A serving peer therefore cannot emit a frame decode is required to reject: it splits its resource on MAX_RANGE_FRAME_PAYLOAD or it learns about it here, at the send site, with the ceiling named in the error.

The payload is checked separately from the body because the body check alone is too weak: a payload well over the ceiling still fits in MAX_FRAMED_BODY once base64’d when the frame carries no metadata, so it would encode here and then overflow the moment the same span rode a FIRST frame with a chunk table attached — a size-dependent, intermittent failure. One explicit ceiling on bytes makes the limit the same for every frame. The proof is checked for the same reason: it is premise 2 of MAX_FIRST_FRAME_CHUNK_LENS, and a premise only a test believes is not a bound (#1655).

Source

pub async fn decode<R: AsyncRead + Unpin>(r: &mut R) -> Result<Option<Self>>

Read + decode one RangeFrame from r. Returns Ok(None) at clean end-of-stream (the reader hit EOF on a frame boundary), so a consumer loops until None or complete.

Trait Implementations§

Source§

impl Clone for RangeFrame

Source§

fn clone(&self) -> RangeFrame

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for RangeFrame

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for RangeFrame

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Eq for RangeFrame

Source§

impl PartialEq for RangeFrame

Source§

fn eq(&self, other: &RangeFrame) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for RangeFrame

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for RangeFrame

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
Source§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
Source§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more