ingot_types/
util.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5//! Utilities for parsing more complex packet types or specific inputs.
6
7use super::*;
8use crate::{ParseError, ParseResult, Read};
9use zerocopy::SplitByteSlice;
10
11/// Convenience wrapper to use byte slices where a [`Read`] is expected.
12pub struct OneChunk<T>(Option<T>);
13
14impl<T: SplitByteSlice> Read for OneChunk<T> {
15    type Chunk = T;
16
17    fn next_chunk(&mut self) -> ParseResult<Self::Chunk> {
18        self.0.take().ok_or(ParseError::NoRemainingChunks)
19    }
20
21    fn chunks_len(&self) -> usize {
22        self.0.is_some() as usize
23    }
24}
25
26impl<T: SplitByteSlice> From<T> for OneChunk<T> {
27    fn from(value: T) -> Self {
28        Self(Some(value))
29    }
30}
31
32/// A owned block of headers whose elements are parsed identically (i.e., using the same
33/// `choice` or `Ingot type), and may be chained using `hint` values.
34///
35/// This is mostly useful for implementing extension headers.
36#[derive(Clone, Debug, Eq, PartialEq, Hash)]
37pub struct Repeated<T> {
38    inner: Vec<T>,
39}
40
41// Thanks to rustc's excellent Default generic detection...
42impl<T> Default for Repeated<T> {
43    fn default() -> Self {
44        Self { inner: Default::default() }
45    }
46}
47
48impl<T> Repeated<T> {
49    /// Wrap a list of `T`s in the [`Repeated`] newtype.
50    pub fn new(data: Vec<T>) -> Self {
51        Self { inner: data }
52    }
53
54    /// Unwrap a list of `T`s from the [`Repeated`] newtype.
55    pub fn into_inner(self) -> Vec<T> {
56        self.inner
57    }
58}
59
60impl<T> From<Vec<T>> for Repeated<T> {
61    fn from(value: Vec<T>) -> Self {
62        Self::new(value)
63    }
64}
65
66impl<T> Deref for Repeated<T> {
67    type Target = Vec<T>;
68
69    fn deref(&self) -> &Self::Target {
70        &self.inner
71    }
72}
73
74impl<T> DerefMut for Repeated<T> {
75    fn deref_mut(&mut self) -> &mut Self::Target {
76        &mut self.inner
77    }
78}
79
80impl<T: HeaderLen> HeaderLen for Repeated<T> {
81    const MINIMUM_LENGTH: usize = 0;
82
83    #[inline]
84    fn packet_length(&self) -> usize {
85        self.iter().map(|v| v.packet_length()).sum()
86    }
87}
88
89impl<T: Emit> Emit for Repeated<T> {
90    #[inline]
91    fn emit_raw<V: ByteSliceMut>(&self, buf: V) -> usize {
92        self.inner.emit_raw(buf)
93    }
94
95    #[inline]
96    fn needs_emit(&self) -> bool {
97        true
98    }
99}
100
101impl<T> NextLayer for Repeated<T>
102where
103    T: NextLayer<Hint = <T as NextLayer>::Denom>,
104{
105    type Denom = T::Denom;
106    type Hint = T::Hint;
107
108    fn next_layer_choice(
109        &self,
110        hint: Option<Self::Hint>,
111    ) -> Option<Self::Denom> {
112        // Choose the hint attached to the last item contained herein.
113        //
114        // If the inner Vec is empty, then return the outer hint
115        self.inner.last().and_then(|v| v.next_layer()).or(hint)
116    }
117}
118
119// Safety: We know this holds true for all our derived emits.
120unsafe impl<T: Emit> EmitDoesNotRelyOnBufContents for Repeated<T> where
121    Vec<T>: EmitDoesNotRelyOnBufContents
122{
123}
124
125/// A borrowed block of headers whose elements are parsed identically (i.e., using the same
126/// `choice` or `Ingot` type), and may be chained using `hint` values.
127pub struct RepeatedView<B, T: HasView<B> + NextLayer> {
128    inner: B,
129    marker: PhantomData<T>,
130}
131
132impl<B: ByteSlice, T: HasView<B> + NextLayer> AsRef<[u8]>
133    for RepeatedView<B, T>
134{
135    fn as_ref(&self) -> &[u8] {
136        &self.inner
137    }
138}
139
140impl<B: ByteSliceMut, T: HasView<B> + NextLayer> AsMut<[u8]>
141    for RepeatedView<B, T>
142{
143    fn as_mut(&mut self) -> &mut [u8] {
144        &mut self.inner
145    }
146}
147
148impl<B: ByteSlice, T: HeaderLen + NextLayer + HasView<B>> HeaderLen
149    for RepeatedView<B, T>
150{
151    const MINIMUM_LENGTH: usize = 0;
152
153    #[inline]
154    fn packet_length(&self) -> usize {
155        self.inner.len()
156    }
157}
158
159impl<B: ByteSlice, T: HeaderLen + NextLayer + HasView<B>> Emit
160    for RepeatedView<B, T>
161{
162    #[inline]
163    fn emit_raw<V: ByteSliceMut>(&self, mut buf: V) -> usize {
164        buf.copy_from_slice(&self.inner);
165
166        self.inner.len()
167    }
168
169    #[inline]
170    fn needs_emit(&self) -> bool {
171        false
172    }
173}
174
175impl<B: ByteSlice, T: HasView<B> + NextLayer> HasView<B> for Repeated<T>
176where
177    T::ViewType: NextLayer,
178{
179    type ViewType = RepeatedView<B, T>;
180}
181
182// 🧙‍♂️ Type magic abounds 🧙‍♂️
183// Effectively, this works by determining, for an owned type T, which
184// ViewType is associated with T and then validating that we can parse
185// it identically on B and &[u8]. This allows us to split B in
186// the right place by borrowing from its derived byteslice (noting that
187// it is very unsound to attempt to recombine slices in general, let alone
188// on arbitrary T with a deref).
189impl<
190        B: SplitByteSlice,
191        T: HasView<B> + NextLayer<Hint = <T as NextLayer>::Denom>,
192    > HeaderParse<B> for RepeatedView<B, T>
193where
194    T: for<'a> HasView<&'a [u8]>,
195    for<'a> <T as HasView<&'a [u8]>>::ViewType:
196        HeaderParse<&'a [u8]> + NextLayer<Denom = T::Denom, Hint = T::Hint>,
197{
198    #[inline]
199    fn parse_choice(
200        data: B,
201        mut hint: Option<T::Hint>,
202    ) -> ParseResult<Success<Self, B>> {
203        let original_len = data.deref().len();
204        let mut bytes_read = 0;
205
206        while bytes_read < original_len {
207            let slice = &data[bytes_read..];
208            match <T as HasView<&[u8]>>::ViewType::parse_choice(slice, hint) {
209                Ok((.., l_hint, remainder)) => {
210                    bytes_read = original_len - remainder.len();
211                    hint = l_hint;
212                }
213                Err(ParseError::Unwanted) => break,
214                Err(e) => return Err(e),
215            }
216        }
217
218        // SAFETY:
219        // We have read exactly bytes_read from data already, and
220        // ByteSlice requires the base ptr + len on derived byteslices
221        // to be identical/stable.
222        let (inner, remainder) = unsafe { data.split_at_unchecked(bytes_read) };
223
224        let val = Self { inner, marker: PhantomData };
225
226        Ok((val, hint, remainder))
227    }
228}
229
230// 🧙‍♂️ Type magic abounds 🧙‍♂️
231// This works on a similar trick as above: we reparse target Ts out from
232// the stored buffer and individually convert *those* to their owned types.
233// We do not go via B in practice.
234impl<
235        B: SplitByteSlice,
236        T: NextLayer<Hint = <T as NextLayer>::Denom> + HasView<B>,
237        E,
238    > ToOwnedPacket for RepeatedView<B, T>
239where
240    T: for<'a> HasView<&'a [u8]>,
241    for<'a> <T as HasView<&'a [u8]>>::ViewType:
242        HeaderParse<&'a [u8]> + NextLayer<Denom = T::Denom, Hint = T::Hint>,
243    for<'a, 'b> &'b <T as HasView<&'a [u8]>>::ViewType: TryInto<T, Error = E>,
244    // Bound needed to account for `Infallible` errors via pure `From`/`Into`.
245    ParseError: From<E>,
246{
247    type Target = Repeated<T>;
248
249    fn to_owned(&self, mut hint: Option<T::Hint>) -> ParseResult<Self::Target> {
250        let mut inner = vec![];
251        let mut slice = &self.inner[..];
252
253        while !slice.is_empty() {
254            let (pkt, h2, rest) =
255                <T as HasView<&[u8]>>::ViewType::parse_choice(slice, hint)?;
256            slice = rest;
257            hint = h2;
258
259            inner.push((&pkt).try_into()?);
260        }
261
262        Ok(Repeated { inner })
263    }
264}
265
266impl<B: ByteSlice, T: for<'a> HasView<&'a [u8]> + HasView<B> + NextLayer>
267    RepeatedView<B, T>
268{
269    /// Iterates over all sub-parsed elements.
270    ///
271    /// Offsets are not stored, so individual elements are re-parsed one by one.
272    pub fn iter(&self, hint: Option<T::Hint>) -> RepeatedViewIter<T> {
273        RepeatedViewIter { slice: &self.inner[..], hint }
274    }
275}
276
277/// An iterator over all parsable values contained within a [`RepeatedView`].
278///
279/// Offsets are not stored, so individual elements are re-parsed one by one.
280pub struct RepeatedViewIter<'a, T: HasView<&'a [u8]> + NextLayer> {
281    slice: &'a [u8],
282    hint: Option<T::Hint>,
283}
284
285impl<'a, T: HasView<&'a [u8]> + NextLayer<Hint = <T as NextLayer>::Denom>>
286    Iterator for RepeatedViewIter<'a, T>
287where
288    <T as HasView<&'a [u8]>>::ViewType:
289        HeaderParse<&'a [u8]> + NextLayer<Denom = T::Denom, Hint = T::Hint>,
290{
291    type Item = ParseResult<<T as HasView<&'a [u8]>>::ViewType>;
292
293    fn next(&mut self) -> Option<Self::Item> {
294        if self.slice.is_empty() {
295            return None;
296        }
297
298        match T::ViewType::parse_choice(self.slice, self.hint) {
299            Ok((item, hint, slice)) => {
300                self.hint = hint;
301                self.slice = slice;
302
303                Some(Ok(item))
304            }
305            Err(e) => {
306                self.slice = &[];
307                Some(Err(e))
308            }
309        }
310    }
311}
312
313impl<
314        B: ByteSlice,
315        T: for<'a> HasView<&'a [u8]>
316            + HasView<B>
317            + NextLayer<Hint = <T as NextLayer>::Denom>,
318    > NextLayer for RepeatedView<B, T>
319where
320    for<'a> <T as HasView<&'a [u8]>>::ViewType:
321        HeaderParse<&'a [u8]> + NextLayer<Denom = T::Denom, Hint = T::Hint>,
322{
323    type Denom = T::Denom;
324    type Hint = T::Hint;
325
326    fn next_layer_choice(
327        &self,
328        hint: Option<Self::Hint>,
329    ) -> Option<Self::Denom> {
330        self.iter(hint)
331            .last()
332            .and_then(|v| v.ok())
333            .and_then(|v| v.next_layer())
334            .or(hint)
335    }
336}
337
338/// Macro which declares a zerocopy-flavored type, which can be used in a field
339///
340/// The type implements all of the required `derive` traits, as well as
341/// `HeaderLen` and `Emit`.
342#[macro_export]
343macro_rules! zerocopy_type {
344    (
345        $(#[$meta:meta])*
346        $vis:vis struct $name:ident($inner_vis:vis $t:ty) $(;)?
347    ) => {
348        $crate::zerocopy_struct!(
349            $(#[$meta])*
350            $vis struct $name($inner_vis $t);
351        );
352
353        impl From<$t> for $name {
354            fn from(t: $t) -> Self {
355                Self(t)
356            }
357        }
358        $crate::zerocopy_impls!($name);
359    };
360    (
361        $(#[$meta:meta])*
362        $vis:vis struct $name:ident {
363            $inner_vis:vis $inner_name:ident: $t:ty $(,)?
364        }
365    ) => {
366        $crate::zerocopy_struct!(
367            $(#[$meta])*
368            $vis struct $name { $inner_vis $inner_name: $t }
369        );
370
371        impl From<$t> for $name {
372            fn from(t: $t) -> Self {
373                Self { $inner_name: t }
374            }
375        }
376        $crate::zerocopy_impls!($name);
377    };
378}
379
380/// Macro which defines `HeaderLen` and `Emit` for a zerocopy-type
381///
382/// These are necessary for the type to be used in a variable-length field.
383#[macro_export]
384macro_rules! zerocopy_impls {
385    ($t:ty) => {
386        impl $crate::HeaderLen for $t {
387            const MINIMUM_LENGTH: usize = core::mem::size_of::<Self>();
388            #[inline]
389            fn packet_length(&self) -> usize {
390                Self::MINIMUM_LENGTH
391            }
392        }
393
394        impl $crate::Emit for $t {
395            #[inline]
396            fn emit_raw<V: zerocopy::ByteSliceMut>(&self, mut buf: V) -> usize {
397                use zerocopy::IntoBytes;
398                let len = core::mem::size_of::<Self>();
399                buf[..len].copy_from_slice(self.as_bytes());
400                len
401            }
402            #[inline]
403            fn needs_emit(&self) -> bool {
404                false
405            }
406        }
407    };
408}
409
410/// Helper to build a struct with all zerocopy derives
411///
412/// This is overly general to capture both tuple and named-field structs, so
413/// it's hidden in the docs.
414#[macro_export]
415#[doc(hidden)]
416macro_rules! zerocopy_struct {
417    (
418        $(#[$meta:meta])*
419        $vis:vis struct $name:ident $($body:tt)*
420    ) => {
421        $(#[$meta])*
422        #[derive(
423            Clone,
424            Copy,
425            Debug,
426            Eq,
427            Hash,
428            Ord,
429            PartialEq,
430            PartialOrd,
431            ::zerocopy::FromBytes,
432            ::zerocopy::IntoBytes,
433            ::zerocopy::KnownLayout,
434            ::zerocopy::Immutable,
435        )]
436        $vis struct $name $($body)*
437    }
438}