pub enum LoadedBlob {
Inline(Vec<u8>),
Chunked(ChunkedBlob),
}Expand description
A blob’s top-level object, read from the store exactly once and held so
a caller needing several views of the same blob — byte length, bounded
prefix, full content — pays a single top-level read_object instead of
one per view. diff --stat is the motivating caller: its text-vs-binary
sniff needs a prefix, then either the length (binary row) or the full
content (text row), and taking each view through a separate store-level
read re-read (and re-hash-verified) the same object two times per
changed file, a per-entry cost that dominates a many-small-files
diffstat (#624).
Chunk objects are still read on demand: Self::len reads none,
Self::prefix reads only leading chunks, Self::into_content
reads them all.
One read stays undeduped by design: Self::prefix on a chunked blob
reads the leading chunk(s) to sniff, and Self::into_content reads
every chunk (including that same leading one) to reassemble — a caller
doing both, as diff --stat does, reads the first chunk twice. Caching
it would need either interior mutability or a consuming-prefix API, to
save an O(1) read on an O(n-chunks) path; not worth it (#624).
Variants§
Inline(Vec<u8>)
An inline Blob: its full content, already
in hand.
Chunked(ChunkedBlob)
A ChunkedBlob manifest: content lives in chunk objects, read
only when a view needs them.
Implementations§
Source§impl LoadedBlob
impl LoadedBlob
Sourcepub fn load<S: ObjectSource + ?Sized>(
store: &S,
hash: &Hash,
) -> WorktreeResult<Self>
pub fn load<S: ObjectSource + ?Sized>( store: &S, hash: &Hash, ) -> WorktreeResult<Self>
Read the top-level object addressed by hash — one store read.
§Errors
WorktreeError::Storeifhashis missing.WorktreeError::Ioifhashresolves to an object that is neither aBlobnor aChunkedBlob.
Sourcepub fn len(&self) -> u64
pub fn len(&self) -> u64
Content byte length from what is already in hand — an inline blob’s
data length, a chunked blob’s manifest total_size — no chunk
reads. total_size is trustworthy without re-verifying against the
chunks: every reassembly path enforces it via
ChunkedBlob::check_reassembled_size, so a manifest with a wrong
total_size cannot have been durably written (#550).
Sourcepub fn prefix<S: ObjectSource + ?Sized>(
&self,
store: &S,
max_len: usize,
) -> WorktreeResult<Cow<'_, [u8]>>
pub fn prefix<S: ObjectSource + ?Sized>( &self, store: &S, max_len: usize, ) -> WorktreeResult<Cow<'_, [u8]>>
Up to max_len leading content bytes. Inline data is borrowed (no
copy, no reads); a chunked blob reads only as many leading chunks
as it takes to cover max_len, then stops — one chunk in practice,
since every chunk but possibly the last is at least
crate::chunker::MIN_SIZE bytes, well above the sniff windows
callers use (e.g. crate::ops::diff::BINARY_SNIFF_LEN).
§Errors
WorktreeError::Storeif a needed chunk is missing.WorktreeError::Ioif a needed chunk is not aBlob.
Sourcepub fn into_content<S: ObjectSource + ?Sized>(
self,
store: &S,
) -> WorktreeResult<Vec<u8>>
pub fn into_content<S: ObjectSource + ?Sized>( self, store: &S, ) -> WorktreeResult<Vec<u8>>
The full content: inline data as-is (no further reads), a chunked
blob reassembled by reading every chunk, with the result length
enforced against the manifest’s total_size (SPEC-OBJECTS §7).
§Errors
WorktreeError::Storeif a chunk is missing.WorktreeError::Ioif a chunk is not aBlob.WorktreeError::Objectif the concatenated chunks do not total the manifest’stotal_size.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for LoadedBlob
impl RefUnwindSafe for LoadedBlob
impl Send for LoadedBlob
impl Sync for LoadedBlob
impl Unpin for LoadedBlob
impl UnsafeUnpin for LoadedBlob
impl UnwindSafe for LoadedBlob
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
Source§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more