1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
use crate::fields::{primitive::copy_access::FieldCopyAccess, Field};
use crate::utils::infallible::{InfallibleResultExt, IsInfallible};
/// This extension trait adds a [FieldReadExt::read] method to any type
/// supporting [FieldCopyAccess::try_read] that has an implementation
/// that cannot throw errors. This is a convenience function so that callers
/// can just call [FieldReadExt::read] instead of having to call [FieldCopyAccess::try_read]
/// and then calling [Result::unwrap] on the returned value.
pub trait FieldReadExt: Field {
/// The data type that is returned from read calls and has to be
/// passed in to write calls. This can be different from the primitive
/// type used in the binary blob, since that primitive type can be
/// wrapped (see [WrappedField](crate::WrappedField) ) into a high level type before being returned from read
/// calls (or vice versa unwrapped when writing).
type HighLevelType;
/// Read the field from a given data region, assuming the defined layout, using the [Field] API.
///
/// # Example:
/// ```
/// use binary_layout::prelude::*;
///
/// binary_layout!(my_layout, LittleEndian, {
/// //... other fields ...
/// some_integer_field: u16,
/// //... other fields ...
/// });
///
/// fn func(storage_data: &[u8]) {
/// let read: u16 = my_layout::some_integer_field::read(storage_data);
/// }
/// ```
fn read(storage: &[u8]) -> Self::HighLevelType;
}
/// This extension trait adds a [FieldWriteExt::write] method to any type
/// supporting [FieldCopyAccess::try_write] that has an implementation
/// that cannot throw errors. This is a convenience function so that callers
/// can just call [FieldWriteExt::write] instead of having to call [FieldCopyAccess::try_write]
/// and then calling [Result::unwrap] on the returned value.
pub trait FieldWriteExt: Field {
/// The data type that is returned from read calls and has to be
/// passed in to write calls. This can be different from the primitive
/// type used in the binary blob, since that primitive type can be
/// wrapped (see [WrappedField](crate::WrappedField) ) into a high level type before being returned from read
/// calls (or vice versa unwrapped when writing).
type HighLevelType;
/// Write the field to a given data region, assuming the defined layout, using the [Field] API.
///
/// # Example:
///
/// ```
/// use binary_layout::prelude::*;
///
/// binary_layout!(my_layout, LittleEndian, {
/// //... other fields ...
/// some_integer_field: u16,
/// //... other fields ...
/// });
///
/// fn func(storage_data: &mut [u8]) {
/// my_layout::some_integer_field::write(storage_data, 10);
/// }
/// ```
fn write(storage: &mut [u8], v: Self::HighLevelType);
}
impl<F> FieldReadExt for F
where
F: FieldCopyAccess,
F::ReadError: IsInfallible,
{
type HighLevelType = F::HighLevelType;
/// This implements a convenience method for reading any data type whose [FieldCopyAccess::try_read]
/// does not throw errors.
/// See [FieldCopyAccess::try_read].
#[inline(always)]
fn read(storage: &[u8]) -> Self::HighLevelType {
F::try_read(storage).infallible_unwrap()
}
}
impl<F> FieldWriteExt for F
where
F: FieldCopyAccess,
F::WriteError: IsInfallible,
{
type HighLevelType = F::HighLevelType;
/// This implements a convenience method for writing any data type whose [FieldCopyAccess::try_write]
/// does not throw errors.
/// See [FieldCopyAccess::try_write].
#[inline(always)]
fn write(storage: &mut [u8], value: Self::HighLevelType) {
F::try_write(storage, value).infallible_unwrap()
}
}