Skip to content

Commit

Permalink
pread, pwrite: do not error out if {p,g}{read,write}_with if the offs…
Browse files Browse the repository at this point in the history
…et is equal to slice len (#94)

We now allow reading zero-sized types (like possibly an empty array) from empty slice, or the exact end of a byte array,
and similarly, one can write a empty string or byte array into the tail end of a byte array (i.e., write nothing to nothing).

Co-authored-by: Nickie S <DCNick3@users.noreply.github.com>
  • Loading branch information
RaitoBezarius and DCNick3 authored Nov 21, 2023
1 parent 30f49c7 commit aa8df8e
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 3 deletions.
7 changes: 6 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,11 @@ mod tests {
assert!(error.is_ok());
}

/// In this test, we are testing preading
/// at length boundaries.
/// In the past, this test was supposed to test failures for `hello_world`.
/// Since PR#94, this test is unwrapping as we exploit
/// the fact that if you do &x[x.len()..] you get an empty slice.
#[test]
fn pread_str_weird() {
use super::ctx::*;
Expand All @@ -385,7 +390,7 @@ mod tests {
let hello_world = bytes.pread_with::<&str>(0, StrCtx::Delimiter(NULL));
#[cfg(feature = "std")]
println!("1 {hello_world:?}");
assert!(hello_world.is_err());
assert!(hello_world.unwrap().is_empty());
let error = bytes.pread_with::<&str>(7, StrCtx::Delimiter(SPACE));
#[cfg(feature = "std")]
println!("2 {error:?}");
Expand Down
7 changes: 6 additions & 1 deletion src/pread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ use crate::error;
/// over chunks of memory or any other indexable type — but scroll does come with a set of powerful
/// blanket implementations for data being a continous block of byte-addressable memory.
///
/// Note that in the particular case of the implementation of `Pread` for `[u8]`,
/// reading it at the length boundary of that slice will cause to read from an empty slice.
/// i.e. we make use of the fact that `&bytes[bytes.len()..]` will return an empty slice, rather
/// than returning an error. In the past, scroll returned an offset error.
///
/// Pread provides two main groups of functions: pread and gread.
///
/// `pread` is the basic function that simply extracts a given type from a given data store - either
Expand Down Expand Up @@ -167,7 +172,7 @@ impl<Ctx: Copy, E: From<error::Error>> Pread<Ctx, E> for [u8] {
ctx: Ctx,
) -> result::Result<N, E> {
let start = *offset;
if start >= self.len() {
if start > self.len() {
return Err(error::Error::BadOffset(start).into());
}
N::try_from_ctx(&self[start..], ctx).map(|(n, size)| {
Expand Down
9 changes: 8 additions & 1 deletion src/pwrite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ use crate::error;
/// with 'read' switched for 'write' and 'From' switched with 'Into' so if you haven't yet you
/// should read the documentation of `Pread` first.
///
/// As with `Pread`, note that in the particular case of the implementation of `Pwrite` for `[u8]`,
/// writing it at the length boundary of that slice will cause to write in an empty slice.
/// i.e. we make use of the fact that `&bytes[bytes.len()..]` will return an empty slice, rather
/// than returning an error. In the past, scroll returned an offset error.
/// In this case, this is relevant if you are writing an empty slice inside an empty slice and
/// expected this to work.
///
/// Unless you need to implement your own data store — that is either can't convert to `&[u8]` or
/// have a data that does not expose a `&mut [u8]` — you will probably want to implement
/// [TryIntoCtx](ctx/trait.TryIntoCtx.html) on your Rust types to be written.
Expand Down Expand Up @@ -87,7 +94,7 @@ impl<Ctx: Copy, E: From<error::Error>> Pwrite<Ctx, E> for [u8] {
offset: usize,
ctx: Ctx,
) -> result::Result<usize, E> {
if offset >= self.len() {
if offset > self.len() {
return Err(error::Error::BadOffset(offset).into());
}
let dst = &mut self[offset..];
Expand Down

0 comments on commit aa8df8e

Please sign in to comment.