[−][src]Module scroll::ctx
Generic context-aware conversion traits, for automatic downstream extension of Pread
, et. al
Discussion
Implementors of TryFromCtx
automatically grant any client user of pread, pwrite, gread, gwrite
the ability to parse their structure out of the source it has been implemented for, typically &[u8]
.
The implementor only needs to specify the error type, and the type of their size, and then implement the parsing/marshalling logic given a byte sequence, starting at the offset pread
, et. al was called at, with the context you have implemented it for.
Returning the size allows dynamic content (e.g., &str
s) to be parsed alongside fixed size content (e.g., u64
). The parsing context is any information you the implementor need to correctly parse out your datatype - this could be the endianness of the type, more offsets, or other complex data. The only requirement is that your Ctx
be Copy
, and hence encourages lightweight contexts (but this isn't required of course).
Example
Suppose we have a datatype and we want to specify how to parse or serialize this datatype out of some arbitrary
byte buffer. In order to do this, we need to provide a TryFromCtx
impl for our datatype. In particular, if we
do this for the [u8]
target, with a "parsing contex", YourCtx
, you will automatically get access to
calling pread_with::<YourDatatype>(offset, your_ctx)
on arrays of bytes.
In the example below, we implement TryFromCtx
using the Endian
parsing context provided by scroll
, which is used to specifying the endianness at which numbers should be parsed, but you could provide anything, as long as it implements Copy
.
use scroll::{self, ctx, Endian, Pread, BE}; struct Data<'a> { name: &'a str, id: u32, } impl<'a> ctx::TryFromCtx<'a, Endian> for Data<'a> { type Error = scroll::Error; type Size = usize; fn try_from_ctx (src: &'a [u8], ctx: Endian) -> Result<(Self, Self::Size), Self::Error> { let name = src.pread::<&str>(0)?; let id = src.pread_with(name.len() + 1, ctx)?; Ok((Data { name: name, id: id }, name.len() + 1 + 4)) } } let bytes = b"UserName\x00\x01\x02\x03\x04"; let data = bytes.pread_with::<Data>(0, BE).unwrap(); assert_eq!(data.id, 0x01020304); assert_eq!(data.name.to_string(), "UserName".to_string());
Enums
StrCtx | The parsing context for converting a byte sequence to a |
Constants
NULL | A C-style, null terminator based delimiter |
RET | A newline-based delimiter |
SPACE | A space-based delimiter |
TAB | A tab-based delimiter |
Traits
FromCtx | Reads |
IntoCtx | Writes |
MeasureWith | A trait for measuring how large something is; for a byte sequence, it will be its length. |
SizeWith | Gets the size of |
TryFromCtx | Tries to read |
TryIntoCtx | Tries to write |