Skip to content

Commit

Permalink
greater: move gread functions into Pread 😎
Browse files Browse the repository at this point in the history
  • Loading branch information
m4b committed Jul 21, 2017
1 parent c26b369 commit 6054557
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 129 deletions.
120 changes: 1 addition & 119 deletions src/greater.rs
Expand Up @@ -3,128 +3,10 @@ use core::fmt::Debug;
use core::ops::{Add, AddAssign};
use core::ops::{Index, IndexMut, RangeFrom};

use ctx::{TryFromCtx, TryIntoCtx, FromCtx, IntoCtx, SizeWith, MeasureWith};
use ctx::{TryIntoCtx, FromCtx, IntoCtx, SizeWith, MeasureWith};
use error;
use pread::Pread;
use pwrite::Pwrite;

/// Attempt to add an offset for a given `N`'s size, used to compute error values in `Gread`, _or_ return the `N`'s size in units the same as the offset
///
/// NB: this trait's name is likely to be changed, tweaked slightly, if you are implementing an entire `Pread` stack, beware this could change
pub trait TryOffsetWith<Ctx, E = error::Error, I = usize> {
/// Given the `offset`, see if a size + offset can safely be performed on `Self`, and return the resulting computed size
fn try_offset<N: SizeWith<Ctx, Units = I>>(&self, offset: I, ctx: &Ctx) -> result::Result<I, E>;
}

/// The Greater Read (`Gread`) reads a value at a mutable offset, and increments the offset by the size of the interpreted value.
///
/// `Gread` implements an immutable `Self`, `mutable` reference offset incrementor which uses `Pread` as its base.
/// If you are writing a custom `Gread` interface,
/// you should only need to implement `Pread` for a particular
/// `Ctx`, `Error`, `Index` target, _and_ implement `TryOffsetWith` to explain to the trait how it should increment the mutable offset,
/// and then a simple blanket `impl Gread<I, E, Ctx> for YourType`, etc.
pub trait Gread<Ctx, E, I = usize>: Pread<Ctx, E, I> + Index<RangeFrom<I>>
where Ctx: Copy,
I: AddAssign + Copy + Add + Default + Debug + PartialOrd,
E: From<error::Error<I>> + Debug,
{
#[inline]
/// Reads a value from `self` at `offset` with a default `Ctx`. For the primitive numeric values, this will read at the machine's endianness. Updates the offset
/// # Example
/// ```rust
/// use scroll::Gread;
/// let offset = &mut 0;
/// let bytes = [0x7fu8; 0x01];
/// let byte = bytes.gread::<u8>(offset).unwrap();
/// assert_eq!(*offset, 1);
fn gread<'a, N: TryFromCtx<'a, Ctx, <Self as Index<RangeFrom<I>>>::Output, Error = E, Size = I>>(&'a self, offset: &mut I) -> result::Result<N, E> where Ctx: Default, <Self as Index<RangeFrom<I>>>::Output: 'a {
let ctx = Ctx::default();
self.gread_with(offset, ctx)
}
/// Reads a value from `self` at `offset` with the given `ctx`, and updates the offset.
/// # Example
/// ```rust
/// use scroll::Gread;
/// let offset = &mut 0;
/// let bytes: [u8; 2] = [0xde, 0xad];
/// let dead: u16 = bytes.gread_with(offset, scroll::BE).unwrap();
/// assert_eq!(dead, 0xdeadu16);
/// assert_eq!(*offset, 2);
#[inline]
fn gread_with<'a, N: TryFromCtx<'a, Ctx, <Self as Index<RangeFrom<I>>>::Output, Error = E, Size = I>>
(&'a self, offset: &mut I, ctx: Ctx) ->
result::Result<N, E>
where <Self as Index<RangeFrom<I>>>::Output: 'a
{
let o = *offset;
// self.pread_with(o, ctx).and_then(|(n, size)| {
// *offset += size;
// Ok(n)
// })
let len = self.measure_with(&ctx);
if o >= len {
return Err(error::Error::BadOffset(o).into())
}
N::try_from_ctx(&self[o..], ctx).and_then(|(n, size)| {
*offset += size;
Ok(n)
})
}

/// Trys to write `inout.len()` `N`s into `inout` from `Self` starting at `offset`, using the default context for `N`, and updates the offset.
/// # Example
/// ```rust
/// use scroll::Gread;
/// let mut bytes: Vec<u8> = vec![0, 0];
/// let offset = &mut 0;
/// let bytes_from: [u8; 2] = [0x48, 0x49];
/// bytes_from.gread_inout(offset, &mut bytes).unwrap();
/// assert_eq!(&bytes, &bytes_from);
/// assert_eq!(*offset, 2);
#[inline]
fn gread_inout<'a, N>(&'a self, offset: &mut I, inout: &mut [N]) -> result::Result<(), E>
where
N: TryFromCtx<'a, Ctx, <Self as Index<RangeFrom<I>>>::Output, Error = E, Size = I>,
Ctx: Default,
<Self as Index<RangeFrom<I>>>::Output: 'a
{
let len = inout.len();
for i in 0..len {
inout[i] = self.gread(offset)?;
}
Ok(())
}

/// Trys to write `inout.len()` `N`s into `inout` from `Self` starting at `offset`, using the context `ctx`
/// # Example
/// ```rust
/// use scroll::{ctx, LE, Gread};
/// let mut bytes: Vec<u8> = vec![0, 0];
/// let offset = &mut 0;
/// let bytes_from: [u8; 2] = [0x48, 0x49];
/// bytes_from.gread_inout_with(offset, &mut bytes, LE).unwrap();
/// assert_eq!(&bytes, &bytes_from);
/// assert_eq!(*offset, 2);
#[inline]
fn gread_inout_with<'a, N>(&'a self, offset: &mut I, inout: &mut [N], ctx: Ctx) -> result::Result<(), E>
where
N: TryFromCtx<'a, Ctx, <Self as Index<RangeFrom<I>>>::Output, Error = E, Size = I>,
<Self as Index<RangeFrom<I>>>::Output: 'a
{
let len = inout.len();
for i in 0..len {
inout[i] = self.gread_with(offset, ctx)?;
}
Ok(())
}
}

impl<Ctx: Copy,
I: Add + Copy + PartialOrd + AddAssign + Default + Debug,
E: From<error::Error<I>> + Debug,
R: ?Sized + Index<I> + Index<RangeFrom<I>> + MeasureWith<Ctx, Units = I>>
Gread<Ctx, E, I> for R {}

/// The Greater Write (`Gwrite`) writes a value into its mutable insides, at a mutable offset
pub trait Gwrite<Ctx, E, I = usize>: Pwrite<Ctx, E, I>
where Ctx: Copy,
Expand Down
1 change: 0 additions & 1 deletion src/leb128.rs
Expand Up @@ -125,7 +125,6 @@ impl<'a> TryFromCtx<'a> for Sleb128 {
type Size = usize;
#[inline]
fn try_from_ctx(src: &'a [u8], _ctx: ()) -> result::Result<(Self, Self::Size), Self::Error> {
use greater::Gread;
let o = 0;
let offset = &mut 0;
let mut result = 0;
Expand Down
14 changes: 7 additions & 7 deletions src/lib.rs
Expand Up @@ -374,7 +374,7 @@ mod tests {
($read:ident, $deadbeef:expr, $typ:ty) => {
#[test]
fn $read() {
use super::Gread;
use super::Pread;
let bytes: [u8; 8] = [0xf, 0xe, 0xe, 0xb, 0xd, 0xa, 0xe, 0xd];
let mut offset = 0;
let deadbeef: $typ = bytes.gread_with(&mut offset, LE).unwrap();
Expand All @@ -393,7 +393,7 @@ mod tests {
($read:ident, $deadbeef:expr, $typ:ty) => {
#[test]
fn $read() {
use super::Gread;
use super::Pread;
let bytes: [u8; 8] = [0u8, 0, 0, 0, 0, 0, 224, 63];
let mut offset = 0;
let deadbeef: $typ = bytes.gread_with(&mut offset, LE).unwrap();
Expand All @@ -410,7 +410,7 @@ mod tests {
($read:ident, $val:expr, $typ:ty) => {
#[test]
fn $read() {
use super::{LE, BE, Gread, Gwrite};
use super::{LE, BE, Pread, Gwrite};
let mut buffer = [0u8; 16];
let mut offset = &mut 0;
buffer.gwrite_with($val.clone(), offset, LE).unwrap();
Expand Down Expand Up @@ -446,7 +446,7 @@ mod tests {
// useful for ferreting out problems with impls
#[test]
fn gread_with_iter_bytes() {
use super::{Gread};
use super::{Pread};
let mut bytes_to: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0];
let bytes_from: [u8; 8] = [1, 2, 3, 4, 5, 6, 7, 8];
let mut bytes_to = &mut bytes_to[..];
Expand All @@ -461,7 +461,7 @@ mod tests {

#[test]
fn gread_inout() {
use super::{Gread};
use super::{Pread};
let mut bytes_to: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0];
let bytes_from: [u8; 8] = [1, 2, 3, 4, 5, 6, 7, 8];
let bytes = &bytes_from[..];
Expand All @@ -473,7 +473,7 @@ mod tests {

#[test]
fn gread_with_byte() {
use super::{Gread};
use super::{Pread};
let bytes: [u8; 1] = [0x7f];
let b = &bytes[..];
let mut offset = &mut 0;
Expand All @@ -485,7 +485,7 @@ mod tests {
/*
#[test]
fn gread_slice() {
use super::{Gread, ctx};
use super::{Pread, ctx};
let bytes: [u8; 2] = [0x7e, 0xef];
let b = &bytes[..];
let mut offset = &mut 0;
Expand Down
93 changes: 92 additions & 1 deletion src/pread.rs
@@ -1,5 +1,5 @@
use core::result;
use core::ops::{Index, RangeFrom, Add};
use core::ops::{Index, RangeFrom, Add, AddAssign};

use ctx::{TryFromCtx, MeasureWith};
use error;
Expand Down Expand Up @@ -112,6 +112,97 @@ pub trait Pread<Ctx, E, I = usize> : Index<I> + Index<RangeFrom<I>> + MeasureWit
}
N::try_from_ctx(&self[offset..], ctx).and_then(|(n, _)| Ok(n))
}
#[inline]
/// Reads a value from `self` at `offset` with a default `Ctx`. For the primitive numeric values, this will read at the machine's endianness. Updates the offset
/// # Example
/// ```rust
/// use scroll::Gread;
/// let offset = &mut 0;
/// let bytes = [0x7fu8; 0x01];
/// let byte = bytes.gread::<u8>(offset).unwrap();
/// assert_eq!(*offset, 1);
fn gread<'a, N: TryFromCtx<'a, Ctx, <Self as Index<RangeFrom<I>>>::Output, Error = E, Size = I>>(&'a self, offset: &mut I) -> result::Result<N, E> where I: AddAssign, Ctx: Default, <Self as Index<RangeFrom<I>>>::Output: 'a {
let ctx = Ctx::default();
self.gread_with(offset, ctx)
}
/// Reads a value from `self` at `offset` with the given `ctx`, and updates the offset.
/// # Example
/// ```rust
/// use scroll::Gread;
/// let offset = &mut 0;
/// let bytes: [u8; 2] = [0xde, 0xad];
/// let dead: u16 = bytes.gread_with(offset, scroll::BE).unwrap();
/// assert_eq!(dead, 0xdeadu16);
/// assert_eq!(*offset, 2);
#[inline]
fn gread_with<'a, N: TryFromCtx<'a, Ctx, <Self as Index<RangeFrom<I>>>::Output, Error = E, Size = I>>
(&'a self, offset: &mut I, ctx: Ctx) ->
result::Result<N, E>
where I: AddAssign, <Self as Index<RangeFrom<I>>>::Output: 'a
{
let o = *offset;
// self.pread_with(o, ctx).and_then(|(n, size)| {
// *offset += size;
// Ok(n)
// })
let len = self.measure_with(&ctx);
if o >= len {
return Err(error::Error::BadOffset(o).into())
}
N::try_from_ctx(&self[o..], ctx).and_then(|(n, size)| {
*offset += size;
Ok(n)
})
}

/// Trys to write `inout.len()` `N`s into `inout` from `Self` starting at `offset`, using the default context for `N`, and updates the offset.
/// # Example
/// ```rust
/// use scroll::Gread;
/// let mut bytes: Vec<u8> = vec![0, 0];
/// let offset = &mut 0;
/// let bytes_from: [u8; 2] = [0x48, 0x49];
/// bytes_from.gread_inout(offset, &mut bytes).unwrap();
/// assert_eq!(&bytes, &bytes_from);
/// assert_eq!(*offset, 2);
#[inline]
fn gread_inout<'a, N>(&'a self, offset: &mut I, inout: &mut [N]) -> result::Result<(), E>
where
I: AddAssign,
N: TryFromCtx<'a, Ctx, <Self as Index<RangeFrom<I>>>::Output, Error = E, Size = I>,
Ctx: Default,
<Self as Index<RangeFrom<I>>>::Output: 'a
{
let len = inout.len();
for i in 0..len {
inout[i] = self.gread(offset)?;
}
Ok(())
}

/// Trys to write `inout.len()` `N`s into `inout` from `Self` starting at `offset`, using the context `ctx`
/// # Example
/// ```rust
/// use scroll::{ctx, LE, Gread};
/// let mut bytes: Vec<u8> = vec![0, 0];
/// let offset = &mut 0;
/// let bytes_from: [u8; 2] = [0x48, 0x49];
/// bytes_from.gread_inout_with(offset, &mut bytes, LE).unwrap();
/// assert_eq!(&bytes, &bytes_from);
/// assert_eq!(*offset, 2);
#[inline]
fn gread_inout_with<'a, N>(&'a self, offset: &mut I, inout: &mut [N], ctx: Ctx) -> result::Result<(), E>
where
I: AddAssign,
N: TryFromCtx<'a, Ctx, <Self as Index<RangeFrom<I>>>::Output, Error = E, Size = I>,
<Self as Index<RangeFrom<I>>>::Output: 'a
{
let len = inout.len();
for i in 0..len {
inout[i] = self.gread_with(offset, ctx)?;
}
Ok(())
}
}

impl<Ctx: Copy,
Expand Down
2 changes: 1 addition & 1 deletion tests/api.rs
Expand Up @@ -5,7 +5,7 @@ extern crate scroll;
// #[macro_use] extern crate scroll_derive;

use std::ops::{Deref, DerefMut};
use scroll::{ctx, Result, Cread, Pread, Gread};
use scroll::{ctx, Result, Cread, Pread};
use scroll::ctx::SizeWith;

pub struct Section<'a> {
Expand Down

0 comments on commit 6054557

Please sign in to comment.