Struct binary_layout::FieldView [−][src]
pub struct FieldView<S, F: Field> { /* fields omitted */ }
Expand description
A field view represents the field metadata stored in a Field plus it stores the underlying
storage data it operates on, either as a reference to a slice &[u8]
, &mut [u8]
, or as
an owning Vec
Since this API remembers the underlying storage data in a view object, you don’t have to pass it in each time you’re accessing a field. If you rather prefer an API that does not do that, take a look at the Field API.
Example:
use binary_layout::prelude::*; define_layout!(my_layout, LittleEndian, { field_one: u16, another_field: [u8; 16], something_else: u32, tail_data: [u8], }); fn func(storage_data: &mut [u8]) { let mut view = my_layout::View::new(storage_data); // read some data let format_version_header: u16 = view.field_one().read(); // equivalent: let format_version_header = u16::from_le_bytes((&storage_data[0..2]).try_into().unwrap()); // write some data view.something_else_mut().write(10); // equivalent: data_slice[18..22].copy_from_slice(&10u32.to_le_bytes()); // access a data region let tail_data: &[u8] = view.tail_data().data(); // equivalent: let tail_data: &[u8] = &data_slice[22..]; // and modify it view.tail_data_mut().data_mut()[..5].copy_from_slice(&[1, 2, 3, 4, 5]); // equivalent: data_slice[18..22].copy_from_slice(&[1, 2, 3, 4, 5]); }
Implementations
Create a new view for a field over a given storage.
You probably shouldn’t call this directly but should instead call
your_layout::View::new()
, which is generated by the
define_layout! macro for you.
Read the field from a given data region, assuming the defined layout, using the FieldView API.
Example
use binary_layout::prelude::*; define_layout!(my_layout, LittleEndian, { //... other fields ... some_integer_field: i8 //... other fields ... }); fn func(storage_data: &[u8]) { let view = my_layout::View::new(storage_data); let read: i8 = view.some_integer_field().read(); }
Write the field to a given data region, assuming the defined layout, using the FieldView API.
Example
use binary_layout::prelude::*; define_layout!(my_layout, LittleEndian, { //... other fields ... some_integer_field: i8 //... other fields ... }); fn func(storage_data: &mut [u8]) { let mut view = my_layout::View::new(storage_data); view.some_integer_field_mut().write(10); }
Immutably borrow the field from the data region, assuming the defined layout, using the FieldView API. This returns a borrowed sub-slice over the storage that only contains the given field.
Example
use binary_layout::prelude::*; define_layout!(my_layout, LittleEndian, { //... other fields ... tail_data: [u8], }); fn func(storage_data: &[u8]) { let view = my_layout::View::new(storage_data); let tail_data: &[u8] = view.tail_data().data(); }
Similar to FieldView::data, but this also extracts the lifetime. The reference returned by FieldView::data can only life as long as the FieldView object lives.
The reference returned by this function can live for as long as the original packed_data
reference that as put into the FieldView lives.
However, you can only call this if you let the FieldView die, it takes the self
parameter by value.
Also note that this function can only be called when the FieldView was constructed with either a &[u8]
or a &mut [u8]
as underlying storage for the storage_data
.
If the FieldView was constructed based on Vec<u8>
storage, then this function semantically would have to return an owning subvector, but such a thing doesn’t exist in Rust.
Example:
use binary_layout::prelude::*; define_layout!(my_layout, LittleEndian, { another_field: u64, tail_data: [u8], }); fn func(storage_data: &[u8]) -> &[u8] { let view = my_layout::View::new(storage_data); let tail_data: &[u8] = view.into_tail_data().extract(); // Now we return tail_data. Note that the view object doesn't survive // this function but we can still return the `tail_data` reference. // This wouldn't be possible with `FieldView::data`. tail_data }
Similar to FieldView::data, but this also extracts the lifetime. The reference returned by FieldView::data can only life as long as the FieldView object lives.
The reference returned by this function can live for as long as the original packed_data
reference that as put into the FieldView lives.
However, you can only call this if you let the FieldView die, it takes the self
parameter by value.
Also note that this function can only be called when the FieldView was constructed with either a &[u8]
or a &mut [u8]
as underlying storage for the storage_data
.
If the FieldView was constructed based on Vec<u8>
storage, then this function semantically would have to return an owning subvector, but such a thing doesn’t exist in Rust.
Example:
use binary_layout::prelude::*; define_layout!(my_layout, LittleEndian, { another_field: u64, tail_data: [u8], }); fn func(storage_data: &[u8]) -> &[u8] { let view = my_layout::View::new(storage_data); let tail_data: &[u8] = view.into_tail_data().extract(); // Now we return tail_data. Note that the view object doesn't survive // this function but we can still return the `tail_data` reference. // This wouldn't be possible with `FieldView::data`. tail_data }
Mutably borrow the field from the data region, assuming the defined layout, using the FieldView API. This returns a borrowed sub-slice over the storage that only contains the given field.
Example
use binary_layout::prelude::*; define_layout!(my_layout, LittleEndian, { //... other fields ... tail_data: [u8], }); fn func(storage_data: &mut [u8]) { let mut view = my_layout::View::new(storage_data); let tail_data: &mut [u8] = view.tail_data_mut().data_mut(); }
Similar to FieldView::data, but this also extracts the lifetime. The reference returned by FieldView::data can only life as long as the FieldView object lives.
The reference returned by this function can live for as long as the original packed_data
reference that as put into the FieldView lives.
However, you can only call this if you let the FieldView die, it takes the self
parameter by value.
Also note that this function can only be called when the FieldView was constructed with either a &[u8]
or a &mut [u8]
as underlying storage for the storage_data
.
If the FieldView was constructed based on Vec<u8>
storage, then this function semantically would have to return an owning subvector, but such a thing doesn’t exist in Rust.
Example:
use binary_layout::prelude::*; define_layout!(my_layout, LittleEndian, { another_field: u64, tail_data: [u8], }); fn func(storage_data: &[u8]) -> &[u8] { let view = my_layout::View::new(storage_data); let tail_data: &[u8] = view.into_tail_data().extract(); // Now we return tail_data. Note that the view object doesn't survive // this function but we can still return the `tail_data` reference. // This wouldn't be possible with `FieldView::data`. tail_data }
Auto Trait Implementations
impl<S, F> RefUnwindSafe for FieldView<S, F> where
F: RefUnwindSafe,
S: RefUnwindSafe,
impl<S, F> UnwindSafe for FieldView<S, F> where
F: UnwindSafe,
S: UnwindSafe,