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};