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