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
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,
&'a self,
offset: I
) -> Result<N, E> where
Self::Output: 'a,
Ctx: Default,
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();
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,
&'a self,
offset: I,
ctx: Ctx
) -> Result<N, E> where
Self::Output: 'a,
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);
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,
&'a self,
offset: &mut I
) -> Result<N, E> where
I: AddAssign,
Ctx: Default,
Self::Output: 'a,
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);
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,
&'a self,
offset: &mut I,
ctx: Ctx
) -> Result<N, E> where
I: AddAssign,
Self::Output: 'a,
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);
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,
&'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,
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
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);
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 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,
Trys to write inout.len()
N
s 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);