substrate_data/wire/frame/
view.rs1use std::marker::PhantomData;
19
20use super::Unpacker;
21use super::sizes::{F32_BYTES, F64_BYTES};
22
23pub trait View<'a>: Sized {
26 type View;
28 type ListView;
30 fn unpack_view(u: &mut Unpacker<'a>) -> Option<Self::View>;
32 fn unpack_list_view(u: &mut Unpacker<'a>) -> Option<Self::ListView>;
34}
35
36#[must_use]
38pub fn read_view<'a, T: View<'a>>(bytes: &'a [u8]) -> Option<T::View> {
39 let mut u = Unpacker::open(bytes)?;
40 let v = T::unpack_view(&mut u)?;
41 u.at_end().then_some(v)
42}
43
44pub struct List<'a, T> {
47 u: Unpacker<'a>,
48 len: usize,
49 item: PhantomData<fn() -> T>,
50}
51
52impl<T> Clone for List<'_, T> {
53 fn clone(&self) -> Self {
54 List {
55 u: self.u.fork(self.u.position()),
56 len: self.len,
57 item: PhantomData,
58 }
59 }
60}
61
62impl<T> std::fmt::Debug for List<'_, T> {
63 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64 write!(f, "List({} items)", self.len)
65 }
66}
67
68impl<'a, T: View<'a>> List<'a, T> {
69 #[must_use]
71 pub fn len(&self) -> usize {
72 self.len
73 }
74
75 #[must_use]
77 pub fn is_empty(&self) -> bool {
78 self.len == 0
79 }
80
81 #[must_use]
83 pub fn iter(&self) -> ListIter<'a, T> {
84 ListIter {
85 u: self.u.fork(self.u.position()),
86 left: self.len,
87 item: PhantomData,
88 }
89 }
90
91 #[must_use]
93 pub fn get(&self, i: usize) -> Option<T::View> {
94 self.iter().nth(i)
95 }
96}
97
98impl<'a, T: View<'a>> IntoIterator for &List<'a, T> {
99 type Item = T::View;
100 type IntoIter = ListIter<'a, T>;
101 fn into_iter(self) -> ListIter<'a, T> {
102 self.iter()
103 }
104}
105
106#[derive(Debug)]
108pub struct ListIter<'a, T> {
109 u: Unpacker<'a>,
110 left: usize,
111 item: PhantomData<fn() -> T>,
112}
113
114impl<'a, T: View<'a>> Iterator for ListIter<'a, T> {
115 type Item = T::View;
116 fn next(&mut self) -> Option<T::View> {
117 self.left = self.left.checked_sub(1)?;
118 T::unpack_view(&mut self.u)
119 }
120}
121
122pub fn list<'a, T: View<'a>>(u: &mut Unpacker<'a>) -> Option<List<'a, T>> {
124 let (len, end) = u.list()?;
125 let at = u.position();
126 u.skip_to(end)?;
127 Some(List {
128 u: u.fork(at),
129 len,
130 item: PhantomData,
131 })
132}
133
134impl<'a> View<'a> for bool {
135 type View = bool;
136 type ListView = List<'a, bool>;
137 fn unpack_view(u: &mut Unpacker<'a>) -> Option<bool> {
138 u.bool()
139 }
140 fn unpack_list_view(u: &mut Unpacker<'a>) -> Option<Self::ListView> {
141 list(u)
142 }
143}
144
145impl<'a> View<'a> for String {
146 type View = &'a str;
147 type ListView = List<'a, Self>;
148 fn unpack_view(u: &mut Unpacker<'a>) -> Option<&'a str> {
149 u.str()
150 }
151 fn unpack_list_view(u: &mut Unpacker<'a>) -> Option<Self::ListView> {
152 list(u)
153 }
154}
155
156impl<'a> View<'a> for Box<str> {
157 type View = &'a str;
158 type ListView = List<'a, Self>;
159 fn unpack_view(u: &mut Unpacker<'a>) -> Option<&'a str> {
160 u.str()
161 }
162 fn unpack_list_view(u: &mut Unpacker<'a>) -> Option<Self::ListView> {
163 list(u)
164 }
165}
166
167impl<'a> View<'a> for crate::Atom {
168 type View = crate::Atom;
169 type ListView = List<'a, crate::Atom>;
170 fn unpack_view(u: &mut Unpacker<'a>) -> Option<crate::Atom> {
171 <crate::Atom as crate::Schema>::unpack(u)
172 }
173 fn unpack_list_view(u: &mut Unpacker<'a>) -> Option<Self::ListView> {
174 list(u)
175 }
176}
177
178impl<'a, T: View<'a>> View<'a> for Option<T> {
179 type View = Option<T::View>;
180 type ListView = List<'a, Option<T>>;
181 fn unpack_view(u: &mut Unpacker<'a>) -> Option<Option<T::View>> {
182 if u.bool()? {
183 T::unpack_view(u).map(Some)
184 } else {
185 Some(None)
186 }
187 }
188 fn unpack_list_view(u: &mut Unpacker<'a>) -> Option<Self::ListView> {
189 list(u)
190 }
191}
192
193impl<'a, T: View<'a>> View<'a> for Box<T> {
194 type View = T::View;
195 type ListView = T::ListView;
196 fn unpack_view(u: &mut Unpacker<'a>) -> Option<T::View> {
197 T::unpack_view(u)
198 }
199 fn unpack_list_view(u: &mut Unpacker<'a>) -> Option<T::ListView> {
200 T::unpack_list_view(u)
201 }
202}
203
204impl<'a, T: View<'a>> View<'a> for Vec<T> {
205 type View = T::ListView;
206 type ListView = List<'a, Vec<T>>;
207 fn unpack_view(u: &mut Unpacker<'a>) -> Option<T::ListView> {
208 T::unpack_list_view(u)
209 }
210 fn unpack_list_view(u: &mut Unpacker<'a>) -> Option<Self::ListView> {
211 list(u)
212 }
213}
214
215#[derive(Debug, Clone, Copy)]
217pub struct Ints<'a, T> {
218 bytes: &'a [u8],
219 len: usize,
220 bits: u32,
221 signed: bool,
222 item: PhantomData<fn() -> T>,
223}
224
225impl<T: TryFrom<i128>> Ints<'_, T> {
226 #[must_use]
228 pub fn len(&self) -> usize {
229 self.len
230 }
231
232 #[must_use]
234 pub fn is_empty(&self) -> bool {
235 self.len == 0
236 }
237
238 #[must_use]
240 pub fn get(&self, i: usize) -> Option<T> {
241 if i >= self.len {
242 return None;
243 }
244 let raw = super::lanes::get(self.bytes, self.len, self.bits, i);
245 let n = if self.signed {
246 i128::from(crate::binary::unzigzag(raw))
247 } else {
248 i128::from(raw)
249 };
250 T::try_from(n).ok()
251 }
252
253 pub fn iter(&self) -> impl Iterator<Item = T> + '_ {
255 (0..self.len).map_while(|i| self.get(i))
256 }
257}
258
259#[derive(Debug, Clone, Copy)]
261pub struct Floats<'a, T> {
262 bytes: &'a [u8],
263 len: usize,
264 narrow: bool,
266 item: PhantomData<fn() -> T>,
267}
268
269impl<T: From<f32> + FromF64> Floats<'_, T> {
270 #[must_use]
272 pub fn len(&self) -> usize {
273 self.len
274 }
275
276 #[must_use]
278 pub fn is_empty(&self) -> bool {
279 self.len == 0
280 }
281
282 #[must_use]
284 pub fn get(&self, i: usize) -> Option<T> {
285 if i >= self.len {
286 return None;
287 }
288 if self.narrow {
289 let b = self.bytes.get(i * F32_BYTES..(i + 1) * F32_BYTES)?;
290 Some(T::from(f32::from_le_bytes(b.try_into().ok()?)))
291 } else {
292 let b = self.bytes.get(i * F64_BYTES..(i + 1) * F64_BYTES)?;
293 Some(T::from_f64(f64::from_le_bytes(b.try_into().ok()?)))
294 }
295 }
296
297 pub fn iter(&self) -> impl Iterator<Item = T> + '_ {
299 (0..self.len).map_while(|i| self.get(i))
300 }
301}
302
303pub trait FromF64 {
305 fn from_f64(f: f64) -> Self;
307}
308
309impl FromF64 for f64 {
310 fn from_f64(f: f64) -> Self {
311 f
312 }
313}
314
315impl FromF64 for f32 {
316 #[expect(
317 clippy::cast_possible_truncation,
318 reason = "narrowing to the nearest `f32` is what's asked"
319 )]
320 fn from_f64(f: f64) -> Self {
321 f as f32
322 }
323}
324
325macro_rules! int_views {
326 ($($t:ty => $signed:expr),*) => {$(
327 impl<'a> View<'a> for $t {
328 type View = $t;
329 type ListView = Ints<'a, $t>;
330 fn unpack_view(u: &mut Unpacker<'a>) -> Option<$t> {
331 <$t as crate::Schema>::unpack(u)
332 }
333 fn unpack_list_view(u: &mut Unpacker<'a>) -> Option<Ints<'a, $t>> {
334 let (len, bits, bytes) = u.packed_ints()?;
335 Some(Ints { bytes, len, bits, signed: $signed, item: PhantomData })
336 }
337 }
338 )*};
339}
340int_views!(i8 => true, i16 => true, i32 => true, i64 => true, u8 => false, u16 => false, u32 => false, u64 => false, usize => false);
341
342macro_rules! float_views {
343 ($($t:ty => $wide:expr),*) => {$(
344 impl<'a> View<'a> for $t {
345 type View = $t;
346 type ListView = Floats<'a, $t>;
347 fn unpack_view(u: &mut Unpacker<'a>) -> Option<$t> {
348 <$t as crate::Schema>::unpack(u)
349 }
350 fn unpack_list_view(u: &mut Unpacker<'a>) -> Option<Floats<'a, $t>> {
351 let (len, narrow, bytes) = u.packed_floats($wide)?;
352 Some(Floats { bytes, len, narrow, item: PhantomData })
353 }
354 }
355 )*};
356}
357float_views!(f32 => false, f64 => true);