binary_layout/fields/primitive/copy_access/
mod.rs

1use super::super::Field;
2use super::PrimitiveField;
3
4/// This trait is implemented for fields with "try copy access",
5/// i.e. fields that read/write data by copying it from/to the
6/// binary blob, but where reading or writing can fail.
7/// Examples of this are primitive types like NonZeroU8, NonZeroI32, ...
8pub trait FieldCopyAccess: Field {
9    /// Error type that can be thrown from [FieldCopyAccess::try_read]. You can set this to [Infallible](core::convert::Infallible) if the function does not throw an error.
10    type ReadError;
11
12    /// Error type that can be thrown from [FieldCopyAccess::try_write]. You can set this to [Infallible](core::convert::Infallible) if the function does not throw an error.
13    type WriteError;
14
15    /// The data type that is returned from read calls and has to be
16    /// passed in to write calls. This can be different from the primitive
17    /// type used in the binary blob, since that primitive type can be
18    /// wrapped (see [WrappedField](crate::WrappedField) ) into a high level type before being returned from read
19    /// calls (or vice versa unwrapped when writing).
20    type HighLevelType;
21
22    /// Read the field from a given data region, assuming the defined layout, using the [Field] API.
23    ///
24    /// # Example:
25    /// ```
26    /// use binary_layout::prelude::*;
27    /// use core::num::NonZeroU16;
28    ///
29    /// binary_layout!(my_layout, LittleEndian, {
30    ///   //... other fields ...
31    ///   some_integer_field: core::num::NonZeroU16,
32    ///   //... other fields ...
33    /// });
34    ///
35    /// fn func(storage_data: &[u8]) -> Result<NonZeroU16, NonZeroIsZeroError> {
36    ///   let read: NonZeroU16 = my_layout::some_integer_field::try_read(storage_data)?;
37    ///   Ok(read)
38    /// }
39    /// ```
40    fn try_read(storage: &[u8]) -> Result<Self::HighLevelType, Self::ReadError>;
41
42    /// Write the field to a given data region, assuming the defined layout, using the [Field] API.
43    ///
44    /// # Example:
45    ///
46    /// ```
47    /// use binary_layout::prelude::*;
48    /// use core::num::NonZeroU16;
49    /// use core::convert::Infallible;
50    ///
51    /// binary_layout!(my_layout, LittleEndian, {
52    ///   //... other fields ...
53    ///   some_integer_field: core::num::NonZeroU16,
54    ///   //... other fields ...
55    /// });
56    ///
57    /// fn func(storage_data: &mut [u8]) -> Result<(), Infallible> {
58    ///   let value = NonZeroU16::new(10).unwrap();
59    ///   my_layout::some_integer_field::try_write(storage_data, value)?;
60    ///   Ok(())
61    /// }
62    /// ```
63    fn try_write(storage: &mut [u8], v: Self::HighLevelType) -> Result<(), Self::WriteError>;
64}
65
66macro_rules! impl_field_traits {
67    ($type: ty) => {
68        impl<E: Endianness, const OFFSET_: usize> Field for PrimitiveField<$type, E, OFFSET_> {
69            /// See [Field::Endian]
70            type Endian = E;
71            /// See [Field::OFFSET]
72            const OFFSET: usize = OFFSET_;
73            /// See [Field::SIZE]
74            const SIZE: Option<usize> = Some(core::mem::size_of::<$type>());
75        }
76
77        impl<'a, E: Endianness, const OFFSET_: usize> StorageToFieldView<&'a [u8]>
78            for PrimitiveField<$type, E, OFFSET_>
79        {
80            type View = FieldView<&'a [u8], Self>;
81
82            #[inline(always)]
83            fn view(storage: &'a [u8]) -> Self::View {
84                Self::View::new(storage)
85            }
86        }
87
88        impl<'a, E: Endianness, const OFFSET_: usize> StorageToFieldView<&'a mut [u8]>
89            for PrimitiveField<$type, E, OFFSET_>
90        {
91            type View = FieldView<&'a mut [u8], Self>;
92
93            #[inline(always)]
94            fn view(storage: &'a mut [u8]) -> Self::View {
95                Self::View::new(storage)
96            }
97        }
98
99        impl<S: AsRef<[u8]>, E: Endianness, const OFFSET_: usize> StorageIntoFieldView<S>
100            for PrimitiveField<$type, E, OFFSET_>
101        {
102            type View = FieldView<S, Self>;
103
104            #[inline(always)]
105            fn into_view(storage: S) -> Self::View {
106                Self::View::new(storage)
107            }
108        }
109    };
110}
111
112mod primitive_float;
113mod primitive_int;
114mod primitive_nonzero_int;
115mod primitive_unit;
116mod read_write_ext;
117
118pub use primitive_nonzero_int::NonZeroIsZeroError;
119pub use read_write_ext::{FieldReadExt, FieldWriteExt};