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}