Macro tarrasque_macro::extract
source · extract!() { /* proc-macro */ }
Expand description
Generates a struct and an implementation of Extract
(and optionally
Span
) for that struct.
Example
The following code is an example of the usage of the extract!
macro:
use tarrasque::{Endianness, extract};
extract! {
/// A 2D point.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Point[4](endianness: Endianness) {
/// The x-coordinate of this point.
pub x: u16 = [endianness],
/// The y-coordinate of this point.
pub y: u16 = [endianness],
}
}
The [4]
that follows Point
is an optional component that statically
defines the number of bytes consumed by the generated Extract
implementation. When this component is present, a Span
implementation is
generated using the specified span.
The (endianness: Endianness)
that follows [4]
is another optional
component that defines the parameter used by the Extract
implementation.
In this case, a specified endianness is used to extract the u16
s instead
of using the default (big-endian). When this component is omitted, a
placeholder parameter of type ()
is used instead.
Though not shown here, structs may also make use of generics and lifetimes. See below for an example.
Each field has a corresponding expression which is used to populate it in
the Extract
implementation. Square brackets indicate that the field is to
be populated by extracting a value of that type from the stream. The
expression in the square brackets is used as the argument for the extract
method. If the square brackets do not contain an expression, ()
is used as
the argument.
Expressions not wrapped in square brackets are treated as normal
expressions. The [endianness]
expression could be replaced with the
equivalent stream.extract(endianness)?
. Note the usage of stream
which
is implicitly available in these expressions.
Expansion
The usage of extract!
shown above generates the following code:
use tarrasque::{Endianness, extract};
/// A 2D point.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Point {
/// The x-coordinate of this point.
pub x: u16,
/// The y-coordinate of this point.
pub y: u16,
}
impl<'s> ::tarrasque::Extract<'s, Endianness> for Point {
#[inline]
fn extract(
mut stream: &mut ::tarrasque::Stream<'s>, endianness: Endianness
) -> ::tarrasque::ExtractResult<'s, Self> {
let x = stream.extract(endianness)?;
let y = stream.extract(endianness)?;
Ok(Point { x, y })
}
}
impl ::tarrasque::Span for Point {
const SPAN: usize = 4;
}
Generics and Lifetimes
The following code is an example of the usage of the extract!
macro with
generics and lifetimes.
use tarrasque::{Extract, Span, extract};
extract! {
/// A pair of values.
pub struct Pair<'s, T>[2 * T::SPAN] where T: Extract<'s, ()> + Span {
pub bytes: &'s [u8] = &stream[..],
pub left: T = [],
pub right: T = [],
}
}
Note: As shown above, the lifetime 's
must be used to refer to the
lifetime of the stream.