Trait scroll::Pread[][src]

pub trait Pread<Ctx, E, I = usize>: Index<I> + Index<RangeFrom<I>> + MeasureWith<Ctx, Units = I> where
    Ctx: Copy,
    I: Add + Copy + PartialOrd,
    E: From<Error<I>>, 
{ fn pread<'a, N: TryFromCtx<'a, Ctx, Self::Output, Error = E, Size = I>>(
        &'a self,
        offset: I
    ) -> Result<N, E>
    where
        Self::Output: 'a,
        Ctx: Default
, { ... }
fn pread_with<'a, N: TryFromCtx<'a, Ctx, Self::Output, Error = E, Size = I>>(
        &'a self,
        offset: I,
        ctx: Ctx
    ) -> Result<N, E>
    where
        Self::Output: 'a
, { ... }
fn gread<'a, N: TryFromCtx<'a, Ctx, Self::Output, Error = E, Size = I>>(
        &'a self,
        offset: &mut I
    ) -> Result<N, E>
    where
        I: AddAssign,
        Ctx: Default,
        Self::Output: 'a
, { ... }
fn gread_with<'a, N: TryFromCtx<'a, Ctx, Self::Output, Error = E, Size = I>>(
        &'a self,
        offset: &mut I,
        ctx: Ctx
    ) -> Result<N, E>
    where
        I: AddAssign,
        Self::Output: 'a
, { ... }
fn gread_inout<'a, N>(
        &'a self,
        offset: &mut I,
        inout: &mut [N]
    ) -> Result<(), E>
    where
        I: AddAssign,
        N: TryFromCtx<'a, Ctx, Self::Output, Error = E, Size = I>,
        Ctx: Default,
        Self::Output: 'a
, { ... }
fn gread_inout_with<'a, N>(
        &'a self,
        offset: &mut I,
        inout: &mut [N],
        ctx: Ctx
    ) -> Result<(), E>
    where
        I: AddAssign,
        N: TryFromCtx<'a, Ctx, Self::Output, Error = E, Size = I>,
        Self::Output: 'a
, { ... } }

A very generic, contextual pread interface in Rust. Allows completely parallelized reads, as Self is immutable

Don't be scared! The Pread definition is terrifying, but it is definitely tractable. Essentially, E is the error, Ctx the parsing context, I is the indexing type, TryCtx is the "offset + ctx" Context given to the TryFromCtx trait bounds, and SliceCtx is the "offset + size + ctx" context given to the TryRefFromCtx trait bound.

Implementing Your Own Reader

If you want to implement your own reader for a type Foo from some kind of buffer (say [u8]), then you need to implement TryFromCtx

use scroll::{self, ctx, Pread};
#[derive(Debug, PartialEq, Eq)]
pub struct Foo(u16);

impl<'a> ctx::TryFromCtx<'a, scroll::Endian> for Foo {
     type Error = scroll::Error;
     type Size = usize;
     fn try_from_ctx(this: &'a [u8], le: scroll::Endian) -> Result<(Self, Self::Size), Self::Error> {
         if this.len() < 2 { return Err((scroll::Error::Custom("whatever".to_string())).into()) }
         let n = this.pread_with(0, le)?;
         Ok((Foo(n), 2))
     }
}

let bytes: [u8; 4] = [0xde, 0xad, 0, 0];
let foo = bytes.pread_with::<Foo>(0, scroll::LE).unwrap();
assert_eq!(Foo(0xadde), foo);

let foo2 = bytes.pread_with::<Foo>(0, scroll::BE).unwrap();
assert_eq!(Foo(0xdeadu16), foo2);

Advanced: Using Your Own Error in TryFromCtx

 use scroll::{self, ctx, Pread};
 use std::error;
 use std::fmt::{self, Display};
 // make some kind of normal error which also can transform a scroll error ideally (quick_error, error_chain allow this automatically nowadays)
 #[derive(Debug)]
 pub struct ExternalError {}

 impl Display for ExternalError {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         write!(fmt, "ExternalError")
     }
 }

 impl error::Error for ExternalError {
     fn description(&self) -> &str {
         "ExternalError"
     }
     fn cause(&self) -> Option<&error::Error> { None}
 }

 impl From<scroll::Error> for ExternalError {
     fn from(err: scroll::Error) -> Self {
         match err {
             _ => ExternalError{},
         }
     }
 }
 #[derive(Debug, PartialEq, Eq)]
 pub struct Foo(u16);

 impl<'a> ctx::TryFromCtx<'a, scroll::Endian> for Foo {
     type Error = ExternalError;
     type Size = usize;
     fn try_from_ctx(this: &'a [u8], le: scroll::Endian) -> Result<(Self, Self::Size), Self::Error> {
         if this.len() <= 2 { return Err((ExternalError {}).into()) }
         let offset = &mut 0;
         let n = this.gread_with(offset, le)?;
         Ok((Foo(n), *offset))
     }
 }

let bytes: [u8; 4] = [0xde, 0xad, 0, 0];
let foo: Result<Foo, ExternalError> = bytes.pread(0);

Provided Methods

Reads a value from self at offset with a default Ctx. For the primitive numeric values, this will read at the machine's endianness.

Example

use scroll::Pread;
let bytes = [0x7fu8; 0x01];
let byte = bytes.pread::<u8>(0).unwrap();

Reads a value from self at offset with the given ctx

Example

use scroll::Pread;
let bytes: [u8; 2] = [0xde, 0xad];
let dead: u16 = bytes.pread_with(0, scroll::BE).unwrap();
assert_eq!(dead, 0xdeadu16);

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

use scroll::Pread;
let offset = &mut 0;
let bytes = [0x7fu8; 0x01];
let byte = bytes.gread::<u8>(offset).unwrap();
assert_eq!(*offset, 1);

Reads a value from self at offset with the given ctx, and updates the offset.

Example

use scroll::Pread;
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);

Trys to write inout.len() Ns into inout from Self starting at offset, using the default context for N, and updates the offset.

Example

use scroll::Pread;
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);

Trys to write inout.len() Ns into inout from Self starting at offset, using the context ctx

Example

use scroll::{ctx, LE, Pread};
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);

Implementors