Macro format_struct::format_struct
source · macro_rules! format_struct { ($($(#[$m:meta])* $vis:vis struct $endian:tt $name:ident {$($field_name:ident: $ty:tt),*,})+) => { ... }; (@store_type [u8; $sz:literal]) => { ... }; (@store_type $ty:ty) => { ... }; (@getter $endian:tt $field_name:ident [u8; $sz:literal]) => { ... }; (@getter little $field_name:ident $ty:ty) => { ... }; (@getter big $field_name:ident $ty:ty) => { ... }; (@setter_or_mut $endian:tt $field_name:ident [u8; $sz:literal]) => { ... }; (@setter_or_mut little $field_name:ident $ty:ty) => { ... }; (@setter_or_mut big $field_name:ident $ty:ty) => { ... }; (@debug_target $self:ident.$field_name:ident [u8; $sz:literal]) => { ... }; (@debug_target $self:ident.$field_name:ident $ty:ty) => { ... }; }
Expand description
Defines a structure that can be transmuted from/into a byte slice for parsing/constructing binary formats in a
zero-copy way. That works due to the generated structure having alignment of 1 byte and no internal padding.
Generated structures will have the FromByteSlice
trait implemented on them.
The macro accepts syntax similar to a standard structure definition in Rust with some differences:
- The
struct
keyword is followed by eitherlittle
orbig
keywords that specify which endianness to use for the structure’s integer fields. - Fields of the generated structure may not have any meta attached to them which includes the docs. This may be changed in the future.
Examples
format_struct! {
/// A little-endian test structure.
#[derive(Default, Clone)]
pub struct little Test {
byte: u8,
short: u16,
word: i32,
dword: i64,
qword: u128,
byte_arr: [u8; 16],
}
}
It is also possible to define multiple structures in one macro invocation:
format_struct! {
struct little Foo {
byte: u8,
}
struct big Bar {
a: u64,
}
pub struct little Baz {
z: [u8; 33],
}
}
Allowed field types
Currently only integer types (u8
, u16
, u32
, u64
, u128
and their signed counterparts) are allowed and
statically sized byte arrays ([u8; N]
).
Layout
The fields in the structure are laid out in declaration order without any padding. That means that the following structure will take 7 bytes instead of 16 you might expect:
format_struct! {
struct little SmallStruct {
byte: u8,
dword: u64,
}
}
Inner workings
Structures generated by this macro will have their integer fields replaced with appropriately sized byte arrays.
Integer fields will be exposed by generated getters and setters which use from_(le|be)_bytes
and
to_(le|be)_bytes
to convert between the integer types and byte arrays. Byte array fields will be stored as is and
exposed using references.