Macro binary_layout::define_layout [−][src]
macro_rules! define_layout { ($name: ident, $endianness: ident, {$($field_name: ident : $field_type: ty),* $(,)?}) => { ... }; (_impl_fields $endianness: ty, $offset_accumulator: expr, {}) => { ... }; (_impl_fields $endianness: ty, $offset_accumulator: expr, {$name: ident : $type: ty $(, $name_tail: ident : $type_tail: ty)*}) => { ... }; (_impl_view_asref {}) => { ... }; (_impl_view_asref {$name: ident $(, $name_tail: ident)*}) => { ... }; (_impl_view_asmut {}) => { ... }; (_impl_view_asmut {$name: ident $(, $name_tail: ident)*}) => { ... }; (_impl_view_into {}) => { ... }; (_impl_view_into {$name: ident $(, $name_tail: ident)*}) => { ... }; }
This macro defines a data layout. Given such a layout, the Field or FieldView APIs can be used to access data based on it.
Data layouts define
- a name for the layout
- and endianness for its fields (BigEndian or LittleEndian)
- and an ordered collection of typed fields.
See supported field types for a list of supported field types.
API
define_layout!(<<Name>>, <<Endianness>>, {
<<FieldName>>: <<FieldType>>,
<<FieldName>>: <<FieldType>>,
...
});
Field names
Field names can be any valid Rust identifiers, but it is recommended to avoid names that contain storage
, into_
or _mut
.
This is because the define_layout! macro creates a View class with several accessors for each field that contain those identifier parts.
Example
use binary_layout::prelude::*; define_layout!(icmp_packet, BigEndian, { packet_type: u8, code: u8, checksum: u16, rest_of_header: [u8; 4], data_section: [u8], // open ended byte array, matches until the end of the packet });
Generated code
See icmp_packet for an example.
This macro will define a module for you with several members:
- For each field, there will be a struct containing
- The module will also contain a
View
struct that offers the FieldView API.
Metadata Example
use binary_layout::prelude::*; define_layout!(my_layout, LittleEndian, { field1: u16, field2: u32, }); assert_eq!(2, my_layout::field2::OFFSET); assert_eq!(4, my_layout::field2::SIZE);
struct View
See icmp_packet::View for an example.
You can create views over a storage by calling View::new
. Views can be created based on
- Immutable borrowed storage:
&[u8]
- Mutable borrowed storage:
&mut [u8]
- Owning storage: impl
AsRef<u8>
(for example:Vec<u8>
)
The generated View
struct will offer
View::new(storage)
to create aView
View::into_storage(self)
to destroy aView
and return the storage held
and it will offer the following accessors for each field
${field_name}()
: Read access. This returns a FieldView instance with read access.${field_name}_mut()
: Read access. This returns a FieldView instance with write access.into_${field_name}
: Extract access. This destroys theView
and returns a FieldView instance owning the storage. Mostly useful for FieldView::extract.