binary_layout/fields/primitive/
nested_access.rs

1use super::super::{StorageIntoFieldView, StorageToFieldView};
2use super::{Endianness, PrimitiveField};
3use crate::utils::data::Data;
4use crate::Field;
5
6// Nesting generally works by having the binary_layout! macro implement [OwningNestedView], [BorrowingNestedView]
7// and [NestedViewInfo] for a marker type "NestedLayout" it creates in the layout's generated code.
8// Then, the code in this module here creates implementations of [Field], [StorageToFieldView]
9// and [StorageIntoFieldView] for it so that it can be used as a field in other layouts.
10
11/// Internal type. Don't use this in user code.
12/// S is expected to be a non-reference type that can own things, e.g. `Data<S>`
13pub trait OwningNestedView<S>
14where
15    S: AsRef<[u8]>,
16{
17    /// A type representing an owning view of the nested field.
18    type View;
19
20    /// Takes a storage pointing only to the space of the subfield and returns a view to the subfield, with the view taking ownership of the storage.
21    fn into_view(storage: S) -> Self::View;
22}
23
24/// Internal type. Don't use this in user code.
25/// S is expected to be a reference type, e.g. &[u8] or &mut [u8]
26pub trait BorrowingNestedView<S> {
27    /// A type representing a borrowing view of the nested field.
28    type View;
29
30    /// Takes a storage pointing only to the space of the subfield and returns a view to the subfield, with the view not taking ownership of the storage.
31    fn view(storage: S) -> Self::View;
32}
33
34/// Internal trait. Don't use this in user code.
35pub trait NestedViewInfo {
36    /// Size of the nested field
37    const SIZE: Option<usize>;
38}
39
40// TODO FieldNestedAccess may be useful for the field API, but commented out for now since the field API doesn't support nesting yet
41// /// This trait is implemented for fields with "nested access",
42// /// i.e. fields that represent other layouts that are nested within
43// /// this layout.
44// pub trait FieldNestedAccess<'a, S>: Field {
45//     /// A view type for the nested field that owns its storage
46//     type OwningView;
47
48//     /// A view type for the nested field that immutably borrows its storage
49//     type BorrowedView;
50
51//     /// A view type for the nested field that mutably borrows its storage
52//     type BorrowedViewMut;
53
54//     fn into_view(storage: Data<S>) -> Self::OwningView;
55//     fn view(storage: &'a [u8]) -> Self::BorrowedView;
56//     fn view_mut(storage: &'a mut [u8]) -> Self::BorrowedViewMut;
57// }
58
59// impl<'a, S, T, E, const OFFSET_: usize> FieldNestedAccess<'a, S> for PrimitiveField<T, E, OFFSET_>
60// where
61//     S: AsRef<[u8]>,
62//     T: OwningNestedView<Data<S>>
63//         + BorrowingNestedView<&'a [u8]>
64//         + BorrowingNestedView<&'a mut [u8]>,
65//     E: Endianness,
66//     Self: Field,
67// {
68//     type OwningView = <T as OwningNestedView<Data<S>>>::View;
69//     type BorrowedView = <T as BorrowingNestedView<&'a [u8]>>::View;
70//     type BorrowedViewMut = <T as BorrowingNestedView<&'a mut [u8]>>::View;
71
72//     #[inline(always)]
73//     fn into_view(storage: Data<S>) -> Self::OwningView {
74//         let data = if let Some(size) = Self::SIZE {
75//             Data::from(storage).into_subregion(Self::OFFSET..(Self::OFFSET + size))
76//         } else {
77//             Data::from(storage).into_subregion(Self::OFFSET..)
78//         };
79//         T::into_view(data)
80//     }
81
82//     #[inline(always)]
83//     fn view(storage: &'a [u8]) -> Self::BorrowedView {
84//         let data = if let Some(size) = Self::SIZE {
85//             &storage[Self::OFFSET..(Self::OFFSET + size)]
86//         } else {
87//             &storage[Self::OFFSET..]
88//         };
89//         T::view(data)
90//     }
91
92//     #[inline(always)]
93//     fn view_mut(storage: &'a mut [u8]) -> Self::BorrowedViewMut {
94//         let data = if let Some(size) = Self::SIZE {
95//             &mut storage[Self::OFFSET..(Self::OFFSET + size)]
96//         } else {
97//             &mut storage[Self::OFFSET..]
98//         };
99//         T::view(data)
100//     }
101// }
102
103impl<N: NestedViewInfo, E: Endianness, const OFFSET_: usize> Field
104    for PrimitiveField<N, E, OFFSET_>
105{
106    /// See [Field::Endian]
107    type Endian = E;
108    /// See [Field::OFFSET]
109    const OFFSET: usize = OFFSET_;
110    /// See [Field::SIZE]
111    const SIZE: Option<usize> = N::SIZE;
112}
113
114impl<'a, N: BorrowingNestedView<&'a [u8]>, E: Endianness, const OFFSET_: usize>
115    StorageToFieldView<&'a [u8]> for PrimitiveField<N, E, OFFSET_>
116where
117    Self: Field,
118{
119    type View = N::View;
120
121    #[inline(always)]
122    fn view(storage: &'a [u8]) -> Self::View {
123        if let Some(size) = Self::SIZE {
124            N::view(&storage[Self::OFFSET..(Self::OFFSET + size)])
125        } else {
126            N::view(&storage[Self::OFFSET..])
127        }
128    }
129}
130impl<'a, N: BorrowingNestedView<&'a mut [u8]>, E: Endianness, const OFFSET_: usize>
131    StorageToFieldView<&'a mut [u8]> for PrimitiveField<N, E, OFFSET_>
132where
133    Self: Field,
134{
135    type View = N::View;
136
137    #[inline(always)]
138    fn view(storage: &'a mut [u8]) -> Self::View {
139        if let Some(size) = Self::SIZE {
140            N::view(&mut storage[Self::OFFSET..(Self::OFFSET + size)])
141        } else {
142            N::view(&mut storage[Self::OFFSET..])
143        }
144    }
145}
146
147impl<S: AsRef<[u8]>, N: OwningNestedView<Data<S>>, E: Endianness, const OFFSET_: usize>
148    StorageIntoFieldView<S> for PrimitiveField<N, E, OFFSET_>
149where
150    Self: Field,
151{
152    type View = N::View;
153
154    #[inline(always)]
155    fn into_view(storage: S) -> Self::View {
156        if let Some(size) = Self::SIZE {
157            N::into_view(Data::from(storage).into_subregion(Self::OFFSET..(Self::OFFSET + size)))
158        } else {
159            N::into_view(Data::from(storage).into_subregion(Self::OFFSET..))
160        }
161    }
162}