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

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Performs the conversion.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.