ingot_types/
header.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//! An abstraction layer over in-buffer and owned packets and headers.
6
7use super::*;
8
9#[cfg(feature = "alloc")]
10use alloc::boxed::Box;
11#[cfg(feature = "alloc")]
12use alloc::vec::Vec;
13use primitives::RawBytes;
14
15#[cfg(not(feature = "alloc"))]
16/// Convenience type choosing [`InlineHeader`] when `BoxedHeader` is
17/// unavailable.
18pub type Header<O, B> = InlineHeader<O, B>;
19
20#[cfg(feature = "alloc")]
21/// Convenience type preferring [`BoxedHeader`] when available.
22pub type Header<O, B> = BoxedHeader<O, B>;
23
24/// The [`Header`] type corresponding to an owned representation
25/// type `T` on buffer `B`.
26pub type HeaderOf<T, B> = Header<T, <T as HasView<B>>::ViewType>;
27
28/// A header which is either owned or read from a buffer.
29///
30/// Generated traits which allow reading/modifying/emitting either type
31/// are re-implemented on the `Packet` types.
32#[derive(Clone, Debug, Eq, Hash, PartialEq)]
33pub enum InlineHeader<O, B> {
34    /// Owned representation of a header.
35    Repr(O),
36    /// Packed representation of a header, read from an existing buffer.
37    Raw(B),
38}
39
40/// A header which is either owned or read from a buffer, which
41/// heap-allocates if the data is owned.
42///
43/// Generally, use of boxed `Repr` values reduces output struct sizes
44/// when parsing full packets and is preferred when compiling with the
45/// `alloc` feature. See [`InlineHeader`] if stack allocation is needed.
46#[cfg(feature = "alloc")]
47#[derive(Clone, Debug, Eq, Hash, PartialEq)]
48pub enum BoxedHeader<O, B> {
49    /// Owned, in-memory representation of a header.
50    #[cfg(feature = "alloc")]
51    Repr(Box<O>),
52    /// Packed representation of a header, read from an existing buffer.
53    Raw(B),
54}
55
56#[cfg(feature = "alloc")]
57impl<O, B> From<InlineHeader<O, B>> for BoxedHeader<O, B> {
58    fn from(value: InlineHeader<O, B>) -> Self {
59        match value {
60            InlineHeader::Repr(o) => Self::Repr(o.into()),
61            InlineHeader::Raw(b) => Self::Raw(b),
62        }
63    }
64}
65
66#[cfg(feature = "alloc")]
67impl<O, B> From<BoxedHeader<O, B>> for InlineHeader<O, B> {
68    fn from(value: BoxedHeader<O, B>) -> Self {
69        match value {
70            BoxedHeader::Repr(o) => Self::Repr(*o),
71            BoxedHeader::Raw(b) => Self::Raw(b),
72        }
73    }
74}
75
76//
77// Indirect impls.
78//
79#[cfg(feature = "alloc")]
80impl<O, B> BoxedHeader<O, B> {
81    /// Return a reference to this packet's contents if
82    /// they are owned.
83    pub fn repr(&self) -> Option<&O> {
84        match self {
85            Self::Repr(o) => Some(o),
86            _ => None,
87        }
88    }
89
90    /// Return a mutable reference to this packet's contents if
91    /// they are owned.
92    pub fn repr_mut(&mut self) -> Option<&mut O> {
93        match self {
94            Self::Repr(o) => Some(o),
95            _ => None,
96        }
97    }
98
99    /// Return a reference to this packet's contents if
100    /// they are borrowed.
101    pub fn raw(&self) -> Option<&B> {
102        match self {
103            Self::Raw(b) => Some(b),
104            _ => None,
105        }
106    }
107
108    /// Return a mutable reference to this packet's contents if
109    /// they are borrowed.
110    pub fn raw_mut(&mut self) -> Option<&mut B> {
111        match self {
112            Self::Raw(b) => Some(b),
113            _ => None,
114        }
115    }
116}
117
118#[cfg(feature = "alloc")]
119impl<
120        O: NextLayer + Clone,
121        B: NextLayer<Denom = O::Denom, Hint = O::Hint> + ToOwnedPacket<Target = O>,
122    > ToOwnedPacket for BoxedHeader<O, B>
123{
124    type Target = O;
125
126    fn to_owned(&self, hint: Option<Self::Hint>) -> ParseResult<Self::Target> {
127        match self {
128            Header::Repr(o) => Ok(*o.clone()),
129            Header::Raw(v) => v.to_owned(hint),
130        }
131    }
132}
133
134#[cfg(feature = "alloc")]
135impl<B: ByteSlice, T> From<&BoxedHeader<Vec<T>, RawBytes<B>>> for Vec<T>
136where
137    T: FromBytes + IntoBytes + KnownLayout + Immutable + Clone,
138{
139    fn from(value: &Header<Vec<T>, RawBytes<B>>) -> Self {
140        match value {
141            Header::Repr(v) => v.deref().clone(),
142            Header::Raw(v) => {
143                <[T]>::ref_from_bytes(v.as_ref()).unwrap().to_vec()
144            }
145        }
146    }
147}
148
149#[cfg(feature = "alloc")]
150impl<O: HasView<V, ViewType = B>, B, V> HasView<V> for BoxedHeader<O, B> {
151    type ViewType = B;
152}
153
154#[cfg(feature = "alloc")]
155impl<O, B> HasRepr for BoxedHeader<O, B> {
156    type ReprType = O;
157}
158
159#[cfg(feature = "alloc")]
160impl<O, B> HeaderLen for BoxedHeader<O, B>
161where
162    O: HeaderLen,
163    B: HeaderLen,
164{
165    const MINIMUM_LENGTH: usize = O::MINIMUM_LENGTH;
166
167    #[inline]
168    fn packet_length(&self) -> usize {
169        match self {
170            Self::Repr(o) => o.packet_length(),
171            Self::Raw(b) => b.packet_length(),
172        }
173    }
174}
175
176// This implementation allows us to call e.g. Packet<A,ValidA>::parse
177// if ValidA is also Parse, and its owned type has a matching next layer
178// Denom.
179#[cfg(feature = "alloc")]
180impl<
181        V: SplitByteSlice,
182        B: HeaderParse<V> + HasRepr + NextLayer + Into<Self>,
183    > HeaderParse<V> for BoxedHeader<B::ReprType, B>
184where
185    B: NextLayer,
186    B::ReprType: NextLayer<Denom = B::Denom, Hint = B::Hint>,
187{
188    #[inline]
189    fn parse_choice(
190        from: V,
191        hint: Option<Self::Hint>,
192    ) -> ParseResult<Success<Self, V>> {
193        <B as HeaderParse<V>>::parse_choice(from, hint)
194            .map(|(val, hint, remainder)| (val.into(), hint, remainder))
195    }
196}
197
198#[cfg(feature = "alloc")]
199impl<O: NextLayer, B> NextLayer for BoxedHeader<O, B>
200where
201    B: NextLayer<Denom = O::Denom, Hint = O::Hint>,
202{
203    type Denom = O::Denom;
204    type Hint = O::Hint;
205
206    #[inline]
207    fn next_layer_choice(
208        &self,
209        hint: Option<Self::Hint>,
210    ) -> Option<Self::Denom> {
211        match self {
212            Self::Repr(v) => v.next_layer_choice(hint),
213            Self::Raw(v) => v.next_layer_choice(hint),
214        }
215    }
216}
217
218#[cfg(feature = "alloc")]
219unsafe impl<O: EmitDoesNotRelyOnBufContents, B: EmitDoesNotRelyOnBufContents>
220    EmitDoesNotRelyOnBufContents for BoxedHeader<O, B>
221{
222}
223
224#[cfg(feature = "alloc")]
225impl<O: Emit, B: Emit> Emit for BoxedHeader<O, B> {
226    #[inline]
227    fn emit_raw<V: ByteSliceMut>(&self, buf: V) -> usize {
228        match self {
229            Self::Repr(o) => o.emit_raw(buf),
230            Self::Raw(b) => b.emit_raw(buf),
231        }
232    }
233
234    #[inline]
235    fn needs_emit(&self) -> bool {
236        match self {
237            Self::Repr(_) => true,
238            Self::Raw(b) => b.needs_emit(),
239        }
240    }
241}
242
243//
244// Direct impls.
245//
246impl<O, B> InlineHeader<O, B> {
247    /// Return a reference to this packet's contents if
248    /// they are owned.
249    pub fn repr(&self) -> Option<&O> {
250        match self {
251            Self::Repr(o) => Some(o),
252            _ => None,
253        }
254    }
255
256    /// Return a mutable reference to this packet's contents if
257    /// they are owned.
258    pub fn repr_mut(&mut self) -> Option<&mut O> {
259        match self {
260            Self::Repr(o) => Some(o),
261            _ => None,
262        }
263    }
264
265    /// Return a reference to this packet's contents if
266    /// they are borrowed.
267    pub fn raw(&self) -> Option<&B> {
268        match self {
269            Self::Raw(b) => Some(b),
270            _ => None,
271        }
272    }
273
274    /// Return a mutable reference to this packet's contents if
275    /// they are borrowed.
276    pub fn raw_mut(&mut self) -> Option<&mut B> {
277        match self {
278            Self::Raw(b) => Some(b),
279            _ => None,
280        }
281    }
282}
283
284impl<
285        O: NextLayer + Clone,
286        B: NextLayer<Denom = O::Denom, Hint = O::Hint> + ToOwnedPacket<Target = O>,
287    > ToOwnedPacket for InlineHeader<O, B>
288{
289    type Target = O;
290
291    fn to_owned(&self, hint: Option<Self::Hint>) -> ParseResult<Self::Target> {
292        match self {
293            Self::Repr(o) => Ok(o.clone()),
294            Self::Raw(v) => v.to_owned(hint),
295        }
296    }
297}
298
299impl<O: HasView<V, ViewType = B>, B, V> HasView<V> for InlineHeader<O, B> {
300    type ViewType = B;
301}
302
303impl<O, B> HasRepr for InlineHeader<O, B> {
304    type ReprType = O;
305}
306
307impl<O, B> HeaderLen for InlineHeader<O, B>
308where
309    O: HeaderLen,
310    B: HeaderLen,
311{
312    const MINIMUM_LENGTH: usize = O::MINIMUM_LENGTH;
313
314    #[inline]
315    fn packet_length(&self) -> usize {
316        match self {
317            Self::Repr(o) => o.packet_length(),
318            Self::Raw(b) => b.packet_length(),
319        }
320    }
321}
322
323// This implementation allows us to call e.g. Packet<A,ValidA>::parse
324// if ValidA is also Parse, and its owned type has a matching next layer
325// Denom.
326impl<
327        V: SplitByteSlice,
328        B: HeaderParse<V> + HasRepr + NextLayer + Into<Self>,
329    > HeaderParse<V> for InlineHeader<B::ReprType, B>
330where
331    B: NextLayer,
332    B::ReprType: NextLayer<Denom = B::Denom, Hint = B::Hint>,
333{
334    #[inline]
335    fn parse_choice(
336        from: V,
337        hint: Option<Self::Hint>,
338    ) -> ParseResult<Success<Self, V>> {
339        <B as HeaderParse<V>>::parse_choice(from, hint)
340            .map(|(val, hint, remainder)| (val.into(), hint, remainder))
341    }
342}
343
344impl<O: NextLayer, B> NextLayer for InlineHeader<O, B>
345where
346    B: NextLayer<Denom = O::Denom, Hint = O::Hint>,
347{
348    type Denom = O::Denom;
349    type Hint = O::Hint;
350
351    #[inline]
352    fn next_layer_choice(
353        &self,
354        hint: Option<Self::Hint>,
355    ) -> Option<Self::Denom> {
356        match self {
357            Self::Repr(v) => v.next_layer_choice(hint),
358            Self::Raw(v) => v.next_layer_choice(hint),
359        }
360    }
361}
362
363unsafe impl<O: EmitDoesNotRelyOnBufContents, B: EmitDoesNotRelyOnBufContents>
364    EmitDoesNotRelyOnBufContents for InlineHeader<O, B>
365{
366}
367
368impl<O: Emit, B: Emit> Emit for InlineHeader<O, B> {
369    #[inline]
370    fn emit_raw<V: ByteSliceMut>(&self, buf: V) -> usize {
371        match self {
372            Self::Repr(o) => o.emit_raw(buf),
373            Self::Raw(b) => b.emit_raw(buf),
374        }
375    }
376
377    #[inline]
378    fn needs_emit(&self) -> bool {
379        match self {
380            Self::Repr(_) => true,
381            Self::Raw(b) => b.needs_emit(),
382        }
383    }
384}