Skip to main content

BStackGuardedSlice

Trait BStackGuardedSlice 

Source
pub trait BStackGuardedSlice<'a, A: BStackAllocator + 'a>
where Self: 'a,
{
Show 40 methods // Required methods fn len(&self) -> u64; unsafe fn raw_block(&self) -> BStackSlice<'a>; // Provided methods fn as_slice(&self) -> Result<BStackSlice<'a>, Error> { ... } fn is_empty(&self) -> bool { ... } fn decode<'d>(&self, data: &'d [u8]) -> Result<Cow<'d, [u8]>> { ... } fn encode<'d>(&self, data: &'d [u8]) -> Result<Cow<'d, [u8]>> { ... } fn on_read(&self, offset: u64, len: u64) -> Result<()> { ... } fn on_write(&self, offset: u64, len: u64) -> Result<()> { ... } fn pre_read(&self, _offset: u64, _len: u64) -> Result<()> { ... } fn post_read<'d>(&self, data: &'d [u8]) -> Result<Cow<'d, [u8]>> { ... } fn pre_write<'d>(&self, data: &'d [u8]) -> Result<Cow<'d, [u8]>> { ... } fn post_write(&self, _offset: u64, _len: u64) -> Result<()> { ... } fn start(&self) -> u64 { ... } fn end(&self) -> u64 { ... } fn range(&self) -> Range<u64> { ... } fn as_range(&self) -> BStackRange { ... } fn stack(&self) -> &'a BStack { ... } fn read(&self) -> Result<Vec<u8>> { ... } fn read_into(&self, buf: &mut [u8]) -> Result<()> { ... } fn read_range(&self, start: u64, end: u64) -> Result<Vec<u8>> { ... } fn read_range_into(&self, start: u64, buf: &mut [u8]) -> Result<()> { ... } fn get(&self, index: u64) -> Result<Option<u8>> { ... } fn contains(&self, needle: u8) -> Result<bool> { ... } fn starts_with(&self, prefix: &[u8]) -> Result<bool> { ... } fn ends_with(&self, suffix: &[u8]) -> Result<bool> { ... } fn find(&self, needle: u8) -> Result<Option<u64>> { ... } fn rfind(&self, needle: u8) -> Result<Option<u64>> { ... } fn position(&self, predicate: impl Fn(u8) -> bool) -> Result<Option<u64>> { ... } fn rposition(&self, predicate: impl Fn(u8) -> bool) -> Result<Option<u64>> { ... } fn write(&self, data: impl AsRef<[u8]>) -> Result<()> { ... } fn copy_from_slice(&self, src: &[u8]) -> Result<()> { ... } fn write_range(&self, start: u64, data: impl AsRef<[u8]>) -> Result<()> { ... } fn zero(&self) -> Result<()> { ... } fn zero_range(&self, start: u64, n: u64) -> Result<()> { ... } fn fill(&self, value: u8) -> Result<()> { ... } fn fill_with(&self, f: impl FnMut() -> u8) -> Result<()> { ... } fn process(&self, f: impl FnOnce(&mut [u8])) -> Result<()> { ... } fn copy_within(&self, src: Range<u64>, dest: u64) -> Result<()> { ... } fn to_owned_in<'b, B: BStackOwnedSliceAllocator>( &self, allocator: &'b B, ) -> Result<BStackOwnedSlice<'b, B>> { ... } fn to_owned_uninit_in<'b, B>( &self, allocator: &'b B, ) -> Result<BStackOwnedSlice<'b, B>> where B: BStackUninitAllocator + BStackOwnedSliceAllocator { ... }
}
Expand description

A BStackSlice abstraction with lifecycle hooks for transparent I/O interception.

A is the allocator type, given as a generic parameter so that a single implementing struct can satisfy BStackGuardedSlice<'a, A> for any allocator without being locked to one concrete choice.

§Required methods

Implement len and the unsafe raw_block, which binds the trait to an underlying BStackSlice; every other method has a working default. as_slice defaults to returning Unsupported — override it to expose an apparent view when a meaningful one exists.

§Hooks

Override any combination of four hooks to intercept I/O:

HookRole
decodeTransform raw bytes read from disk into the apparent bytes.
encodeTransform apparent bytes into the raw bytes written to disk.
on_readObserve or deny a read. Return Err to deny.
on_writeObserve a completed write (audit, metadata).

decode/encode default to identity (Cow::Borrowed, no allocation); on_read/on_write default to no-ops. Both offsets are relative to the start of the slice (0 is the first byte of this view).

decode/encode are whole-block transforms: read/write and the derived range methods route the entire apparent block through them, which is why a transforming guard (encryption, compression) can implement just len, raw_block, decode, and encode.

§Deprecated hooks

The former hooks are deprecated since 0.4.4 and removed in 0.5.0: post_readdecode, pre_writeencode, pre_readon_read, post_writeon_write. Note pre_read’s offset was absolute whereas on_read’s is relative. The new hooks bridge to the old ones by default, so an implementor overriding only the old hooks keeps working unchanged until 0.5.0.

§Borrow semantics

A guard sits at the same semantic position as BStackSlice: a borrowed I/O view that owns no region and frees nothing on Drop. Because it binds only to a BStackSlice it cannot hold a still-freeable region, and so inherits the crate’s on-disk borrow soundness unchanged. See the module-level documentation for the full argument.

§Lifetime

'a is the allocator lifetime, matching BStackSlice<'a>. All implementors must satisfy Self: 'a and A: 'a. as_slice and raw_block hand back BStackSlice<'a> at that full lifetime — the borrowed-view convention shared with BStackSlice::subslice, not the &self-scoped narrowing used by ownership handles.

Required Methods§

Source

fn len(&self) -> u64

The length of the data in this guarded view.

This should return the length of the apparent slice returned by as_slice, not the underlying raw block length.

Source

unsafe fn raw_block(&self) -> BStackSlice<'a>

The raw I/O block for this guarded view.

A required method with no default: return the BStackSlice that hooks and I/O actually operate on. It coincides with the apparent as_slice view unless hooks operate on a coarser granularity than the slice — for example, a block cipher that must process aligned 16-byte blocks.

Can be used by custom subview implementations to issue reads against the full block rather than the narrowed sub-range.

§Safety

In general, calling this method is only safe when pre and post read/write hooks are not active or are called during the call, otherwise the caller may risk data corruption or undefined behavior. Prefer overriding as_slice when possible.

Provided Methods§

Source

fn as_slice(&self) -> Result<BStackSlice<'a>, Error>

The apparent slice for this guard view.

All I/O methods appears to operate within this slice, and all hooks receive offsets relative to this slice. The implementation should only return Some if the usage of this view is somehow safe and reflect the actual underlying data. For example, exposing a cyphertext for encrypted data does not help the caller to understand the actual plaintext data, so for a guard that performs decryption, this method should return None since there is no clear mapping between the apparent slice and the underlying data.

The returned slice should have length equal to called len().

§Mutability and safety

The returned slice is read-only. Mutating the returned slice may cause data corruption or violate allocator invariants, unless the implementation explicitly allows it and documents the safety contract. If the implementation allows mutation, it must ensure that all hooks are properly fired on subsequent reads and writes, and that any necessary synchronization is performed to prevent data races or undefined behavior.

Source

fn is_empty(&self) -> bool

Returns true if this guarded view contains no data.

This is a convenience method that defaults to self.len() == 0.

Source

fn decode<'d>(&self, data: &'d [u8]) -> Result<Cow<'d, [u8]>>

Transform raw bytes read from the underlying store into the apparent bytes.

The inverse of encode. Called by read with the whole raw block; return Cow::Borrowed to pass through without allocation, or Cow::Owned for decryption, decompression, or other transformations. The transformed length should equal len.

Defaults to the deprecated post_read (identity), for back-compat during the deprecation window.

Source

fn encode<'d>(&self, data: &'d [u8]) -> Result<Cow<'d, [u8]>>

Transform apparent bytes into the raw bytes written to the underlying store.

The inverse of decode. Called by write with the whole apparent block; return Cow::Borrowed to pass through, or Cow::Owned for encryption, compression, or other transformations.

Defaults to the deprecated pre_write (identity), for back-compat during the deprecation window.

Source

fn on_read(&self, offset: u64, len: u64) -> Result<()>

Observe or deny a read of len raw bytes at offset.

offset is relative to the start of the slice; len is the number of raw bytes about to be read (before decode). Return Err to deny.

Defaults to bridging the deprecated pre_read, whose offset was absolute: the bridge adds the slice start, so an implementor overriding only pre_read still receives the absolute offset it expects.

Source

fn on_write(&self, offset: u64, len: u64) -> Result<()>

Observe a completed write of len logical bytes at offset.

offset is relative to the start of the slice; len is the number of apparent bytes written (before encode). The write has already succeeded; use for auditing or metadata.

Defaults to the deprecated post_write, whose offset was already relative.

Source

fn pre_read(&self, _offset: u64, _len: u64) -> Result<()>

👎Deprecated since 0.4.4:

renamed to on_read; offset is now relative to the slice

Deprecated: renamed to on_read; its offset is now relative to the slice, not absolute.

Source

fn post_read<'d>(&self, data: &'d [u8]) -> Result<Cow<'d, [u8]>>

👎Deprecated since 0.4.4:

renamed to decode

Deprecated: renamed to decode.

Source

fn pre_write<'d>(&self, data: &'d [u8]) -> Result<Cow<'d, [u8]>>

👎Deprecated since 0.4.4:

renamed to encode

Deprecated: renamed to encode.

Source

fn post_write(&self, _offset: u64, _len: u64) -> Result<()>

👎Deprecated since 0.4.4:

renamed to on_write

Deprecated: renamed to on_write.

Source

fn start(&self) -> u64

Absolute start offset of the raw block (raw_block().start()) within the BStack payload.

This is a physical-storage coordinate. The apparent view is always addressed as [0, len()); start locates where the raw (stored) bytes actually live. For a pass-through guard (identity encode/decode) the two coincide, but for a transforming guard (encryption, compression) the raw span end - start is the encoded size and differs from the apparent len. Parity with BStackSlice::start.

Source

fn end(&self) -> u64

Absolute exclusive end offset of the raw block (start() + raw_block().len()).

A physical-storage coordinate; end - start is the encoded byte count, which may exceed or fall short of the apparent len for a transforming guard. Parity with BStackSlice::end.

Source

fn range(&self) -> Range<u64>

Half-open raw block byte range start()..end() within the BStack payload.

The physical span the encoded bytes occupy, not the apparent [0, len()) view. Parity with BStackSlice::range.

Source

fn as_range(&self) -> BStackRange

The raw block location as a BStackRange — the physical (offset, len) pair describing where the encoded bytes are stored.

Useful for recording or comparing storage locations; it is not the apparent view, and its len is the encoded size rather than the decoded len. Parity with BStackSlice::as_range.

Source

fn stack(&self) -> &'a BStack

The BStack backing this guard, borrowed for the full allocator lifetime 'a.

Every guard I/O method ultimately reads from and writes to this store; stack hands out the same reference for callers that need to issue their own operations against it (for example, cross-region atomics that take a &BStack). Parity with BStackSlice::stack.

Source

fn read(&self) -> Result<Vec<u8>>

Read the entire apparent slice — the decoded bytes — into a newly allocated Vec<u8>.

Fires on_read(0, raw_len), reads the raw block, then passes it through decode; the decoded length may differ from the raw length. Allocates up to twice the raw length — once for the raw read, and again for the decoded output whenever decode returns Cow::Owned. A pass-through guard (identity decode) returns Cow::Borrowed and so allocates only the raw read.

Source

fn read_into(&self, buf: &mut [u8]) -> Result<()>

Read the entire apparent slice (the decoded bytes) into buf.

buf.len() must equal the decoded length, otherwise returns InvalidInput.

Unlike BStackSlice::read_into, this does not avoid allocation. It reads the raw block into a temporary Vec and runs decode (which may allocate again) before copying the result into buf — the caller’s buffer is not read into directly. Use it for the exact-length delivery and length check, not to save an allocation; when you want the bytes owned anyway, prefer read.

Source

fn read_range(&self, start: u64, end: u64) -> Result<Vec<u8>>

Read the apparent sub-range [start, end) into a newly allocated Vec<u8>.

There is no partial decode: this reads and decodes the whole block (via read) and then copies out the requested sub-range. Returns InvalidInput if start > end or end exceeds the apparent len. Parity with BStackSlice::read_range, but note the whole-block read and the extra allocation.

Source

fn read_range_into(&self, start: u64, buf: &mut [u8]) -> Result<()>

Read the apparent sub-range [start, start + buf.len()) into buf.

Like read_range, this decodes the whole block into a temporary Vec first and then copies the sub-range into buf — so, unlike BStackSlice::read_range_into, it allocates and reads more than the requested range. Returns InvalidInput if the range exceeds the apparent len.

Source

fn get(&self, index: u64) -> Result<Option<u8>>

Read the byte at apparent index index, or None if out of range.

Like every scan/search convenience here (contains, find, position, and the rest), this reads and decodes the whole apparent block on each call. To run several queries, call read once and scan the returned Vec yourself. Parity with BStackSlice::get.

Source

fn contains(&self, needle: u8) -> Result<bool>

Whether the apparent bytes contain needle. Parity with BStackSlice::contains.

Source

fn starts_with(&self, prefix: &[u8]) -> Result<bool>

Whether the apparent bytes start with prefix. Parity with BStackSlice::starts_with.

Source

fn ends_with(&self, suffix: &[u8]) -> Result<bool>

Whether the apparent bytes end with suffix. Parity with BStackSlice::ends_with.

Source

fn find(&self, needle: u8) -> Result<Option<u64>>

Apparent index of the first byte equal to needle. Parity with BStackSlice::find.

Source

fn rfind(&self, needle: u8) -> Result<Option<u64>>

Apparent index of the last byte equal to needle. Parity with BStackSlice::rfind.

Source

fn position(&self, predicate: impl Fn(u8) -> bool) -> Result<Option<u64>>

Apparent index of the first byte satisfying predicate. Parity with BStackSlice::position.

Source

fn rposition(&self, predicate: impl Fn(u8) -> bool) -> Result<Option<u64>>

Apparent index of the last byte satisfying predicate. Parity with BStackSlice::rposition.

Source

fn write(&self, data: impl AsRef<[u8]>) -> Result<()>

Overwrite the whole apparent slice with data.

Passes data through encode, writes the result to the raw block, then fires on_write(0, data.len()). data is the full apparent block — for a length-preserving guard data.len() should equal len.

Requires feature set.

Source

fn copy_from_slice(&self, src: &[u8]) -> Result<()>

Overwrite the whole apparent slice with src; src.len() must equal len. Parity with BStackSlice::copy_from_slice (returns InvalidInput on mismatch rather than panicking). Requires feature set.

Source

fn write_range(&self, start: u64, data: impl AsRef<[u8]>) -> Result<()>

Overwrite the apparent sub-range at start with data, atomic read-modify-write.

One crash-atomic BStack::process_gen: decodes the whole block, splices data in at start, re-encodes, and writes — the only correct way to patch a transformed (e.g. AEAD) block, all under one write lock. The internal read does not fire on_read; only on_write(start, data.len()) fires. Parity with BStackSlice::write_range. Requires features set and atomic.

Source

fn zero(&self) -> Result<()>

Zero the whole apparent slice — writes encode(&[0; len]).

Zeroes the apparent (decoded) content, not the raw storage: for a transforming guard the bytes on disk become the encoding of zeros (e.g. the ciphertext of a zero block), not literal 0x00. To scrub the raw bytes, operate on the underlying BStackSlice directly. Requires feature set.

Source

fn zero_range(&self, start: u64, n: u64) -> Result<()>

Zero the apparent sub-range [start, start + n), atomic read-modify-write. Parity with BStackSlice::zero_range. Requires features set and atomic.

Source

fn fill(&self, value: u8) -> Result<()>

Fill the whole apparent slice with value — writes encode(&[value; len]).

Sets the apparent content; like zero, the raw bytes on disk are the encoding of the fill, not value repeated. Parity with BStackSlice::fill. Requires feature set.

Source

fn fill_with(&self, f: impl FnMut() -> u8) -> Result<()>

Fill the whole apparent slice by calling f once per apparent byte, then writing encode of the result.

f generates the apparent (decoded) bytes; the raw storage is their encoding. Parity with BStackSlice::fill_with. Requires feature set.

Source

fn process(&self, f: impl FnOnce(&mut [u8])) -> Result<()>

Transform the whole apparent block in place, atomic read-modify-write.

One crash-atomic BStack::process_gen: decodes the block, hands it to f as a length-preserving mutable slice, re-encodes, and writes — all under one write lock. The internal read does not fire on_read; only on_write(0, len) fires, after the write. The general form of write_range/zero/fill. Requires features set and atomic.

Source

fn copy_within(&self, src: Range<u64>, dest: u64) -> Result<()>

Copy the apparent sub-range src to dest within the slice, atomic read-modify-write. Parity with BStackSlice::copy_within. Requires features set and atomic.

Source

fn to_owned_in<'b, B: BStackOwnedSliceAllocator>( &self, allocator: &'b B, ) -> Result<BStackOwnedSlice<'b, B>>

Copy this view’s apparent bytes into a fresh allocation from allocator, returning a plain BStackOwnedSlice.

The bytes are decoded on the way out, so the result holds the apparent block, not the raw one, and is a plain region with no guard attached. Unlike BStackSlice::to_owned_in, which copies on disk via one atomic primitive, this necessarily routes through memory — decoding cannot happen on disk — so it needs only the set feature.

§Errors

Any io::Error from the read, the allocation, or the copy. If the copy fails after the allocation succeeds, the fresh region is freed on a best-effort basis before returning the copy error; if that free itself fails, the region is left allocated but unreferenced (reclaimable by the allocator’s recovery).

Source

fn to_owned_uninit_in<'b, B>( &self, allocator: &'b B, ) -> Result<BStackOwnedSlice<'b, B>>

Like to_owned_in, but skips the destination’s zero-fill via alloc_uninit.

The fresh region is fully overwritten by the copy, so the zero-fill alloc would perform is pure waste here.

§Errors

As to_owned_in.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§