Expand description
Slice adapters — view a byte sub-range of any BlockRead as its own
device. Useful any time you want to feed a fragment of a larger
device to a consumer that expects a whole block source — partition
probes, image-file extents, mmap-style views, fuzzer harnesses.
Three variants:
SliceReaderborrows the parent, lifetime-tied. Cheaper when the parent outlives the slice and you can express that statically.OwnedSliceholds anArcto the parent. Use when the parent’s lifetime can’t be expressed in a borrow (FFI handles, slice handed across thread boundaries, etc.).OwnedRwSliceholds anArc<dyn BlockDevice>and propagates writes to the parent.
The first two are strictly read-only: the default Err(ReadOnly)
write path from BlockDevice applies.
§Which error an out-of-range request gets
All three share one range check — SliceGeometry::rebase — and it
answers in two different currencies depending on the direction of the
request:
request outside [0, length) | error |
|---|---|
| read | Error::ShortRead with got: 0 |
| write | Error::OutOfBounds |
The asymmetry is deliberate. A slice exists to be substitutable for a
real device of size length, and a real device — FileDevice —
answers a read that begins at or past its end with exactly
ShortRead { offset, want, got: 0 }. A slice that answered
OutOfBounds would be distinguishable from the thing it stands in
for, and every caller that already handles end-of-device would need a
second arm to cope with slices. Writes have no partial-write variant
to stay consistent with, and a caller that overran a write needs the
device size in order to clamp and retry — which is what
Error::OutOfBounds carries and Error::ShortRead does not.
The match is on the variant, not on got. A slice refuses an
out-of-range read before it touches the parent, so it reports got: 0
and leaves the buffer untouched — including for a read that begins
inside the slice and runs off its end, where FileDevice would have
copied the readable prefix and reported its length. got counts bytes
actually delivered, and a slice delivers none.
This governs the slice’s own range only. A request that is inside
[0, length) is forwarded to the parent, and whatever the parent says
about it — including Error::OutOfBounds from a container reader
that knows its virtual size — comes back unchanged.
§A slice cannot report more device than its parent holds
All three constructors ask the parent its size and CLAMP length to
what is actually there — see window_on_parent for the rule and
why it clamps rather than refuses. So size_bytes() is the truth
about how much is readable, not a number the caller asserted.
That is load-bearing rather than tidy. size_bytes() is “used for
bounds checks” (BlockRead::size_bytes), and a driver mounted on a
slice sizes its own structures from it. A slice that claimed a
megabyte over a hundred-byte parent kept both promises of the section
above and broke them in the same breath: a read inside the declared
length but past the real end was forwarded, and the parent — being
a real device — answered with a ShortRead carrying its own absolute
offset and a non-zero got, having already copied the readable prefix
into the caller’s buffer. Substitutable for a real device of size
length is exactly what that is not.
A slice whose start is at or past the parent’s end has nothing
behind it at all. The constructors are infallible and give it
length = 0, which behaves as a zero-byte device does: every read is
ShortRead { got: 0 } and every write is OutOfBounds { size: 0 }.
The C ABI, which can afford to be fallible, refuses it instead —
fs_core_device_slice_ro/_rw return NULL with a message.
Structs§
- Owned
RwSlice - Owned, read-WRITE slice over an
Arc<dyn BlockDevice>. Use when the parent is writable and the slice should propagate writes (e.g. an individual partition handed to a filesystem driver). - Owned
Slice - Owned slice over an
Arc<dyn BlockRead>. Use when the parent’s lifetime can’t be expressed in a borrow — e.g. when the slice is handed across an FFI boundary or stored in a long-lived struct. - Slice
Reader - Borrowed slice of a parent
BlockRead.
Functions§
- window_
on_ parent - How much of the window
[start, start + length)is actually on a parent ofparent_sizebytes, orNonewhen the window begins at or past the parent’s end and there is nothing on it to slice.