Skip to main content

s2n_codec/decoder/
value.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{
5    decoder::{
6        buffer::{DecoderBuffer, DecoderBufferResult},
7        buffer_mut::{DecoderBufferMut, DecoderBufferMutResult},
8    },
9    unaligned::{i24, i48, u24, u48},
10    DecoderError,
11};
12use byteorder::{ByteOrder, NetworkEndian};
13use core::{marker::PhantomData, mem::size_of};
14use zerocopy::{FromBytes, Immutable, Unaligned};
15
16pub trait DecoderValue<'a>: Sized {
17    fn decode(bytes: DecoderBuffer<'a>) -> DecoderBufferResult<'a, Self>;
18}
19
20pub trait DecoderValueMut<'a>: Sized {
21    fn decode_mut(bytes: DecoderBufferMut<'a>) -> DecoderBufferMutResult<'a, Self>;
22}
23
24#[macro_export]
25macro_rules! decoder_value {
26    (impl<$lt:lifetime $(, $generic:ident)*> $ty:ty {
27        fn decode($buffer:ident: Buffer) -> Result<$ret:ty> $impl:block
28    }) => {
29        impl<$lt $(, $generic: $crate::DecoderValue<$lt>)*> $crate::DecoderValue<$lt> for $ty {
30            #[inline]
31            fn decode($buffer: $crate::DecoderBuffer<$lt>) -> $crate::DecoderBufferResult<$lt, $ret> $impl
32        }
33
34        impl<$lt $(, $generic: $crate::DecoderValueMut<$lt>)*> $crate::DecoderValueMut<$lt> for $ty {
35            #[inline]
36            fn decode_mut($buffer: $crate::DecoderBufferMut<$lt>) -> $crate::DecoderBufferMutResult<$lt, $ret> $impl
37        }
38    };
39}
40
41macro_rules! decoder_value_byte {
42    ($ty:ident) => {
43        decoder_value!(
44            impl<'a> $ty {
45                fn decode(buffer: Buffer) -> Result<Self> {
46                    let (value, buffer) = buffer.decode_slice(size_of::<Self>())?;
47                    let value = value.as_less_safe_slice()[0] as $ty;
48                    Ok((value, buffer))
49                }
50            }
51        );
52    };
53}
54
55decoder_value_byte!(u8);
56decoder_value_byte!(i8);
57
58macro_rules! decoder_value_network_endian {
59    ($call:ident, $ty:ty) => {
60        decoder_value!(
61            impl<'a> $ty {
62                fn decode(buffer: Buffer) -> Result<Self> {
63                    let (value, buffer) = buffer.decode_slice(size_of::<Self>())?;
64                    let value = value.as_less_safe_slice();
65                    let value = NetworkEndian::$call(value);
66                    Ok((value.into(), buffer))
67                }
68            }
69        );
70    };
71}
72
73decoder_value_network_endian!(read_u16, u16);
74decoder_value_network_endian!(read_i16, i16);
75decoder_value_network_endian!(read_u32, u32);
76decoder_value_network_endian!(read_i32, i32);
77decoder_value_network_endian!(read_u64, u64);
78decoder_value_network_endian!(read_i64, i64);
79decoder_value_network_endian!(read_u128, u128);
80decoder_value_network_endian!(read_i128, i128);
81decoder_value_network_endian!(read_f32, f32);
82decoder_value_network_endian!(read_f64, f64);
83
84macro_rules! decoder_value_unaligned_integer {
85    ($call:ident, $ty:ident, $bitsize:expr) => {
86        decoder_value!(
87            impl<'a> $ty {
88                fn decode(buffer: Buffer) -> Result<Self> {
89                    let (value, buffer) = buffer.decode_slice($bitsize / 8)?;
90                    let value = value.as_less_safe_slice();
91                    let value = NetworkEndian::$call(value);
92                    Ok(($ty::new_truncated(value), buffer))
93                }
94            }
95        );
96    };
97}
98
99decoder_value_unaligned_integer!(read_u24, u24, 24);
100decoder_value_unaligned_integer!(read_i24, i24, 24);
101decoder_value_unaligned_integer!(read_u48, u48, 48);
102decoder_value_unaligned_integer!(read_i48, i48, 48);
103
104decoder_value!(
105    impl<'a> DecoderBuffer<'a> {
106        fn decode(buffer: Buffer) -> Result<Self> {
107            let len = buffer.len();
108            let (slice, buffer) = buffer.decode_slice(len)?;
109            #[allow(clippy::useless_conversion)]
110            let slice = slice.into();
111            Ok((slice, buffer))
112        }
113    }
114);
115
116decoder_value!(
117    impl<'a> () {
118        fn decode(buffer: Buffer) -> Result<Self> {
119            Ok(((), buffer))
120        }
121    }
122);
123
124decoder_value!(
125    impl<'a, T> Option<T> {
126        fn decode(buffer: Buffer) -> Result<Self> {
127            if buffer.is_empty() {
128                Ok((None, buffer))
129            } else {
130                let (value, buffer) = buffer.decode()?;
131                Ok((Some(value), buffer))
132            }
133        }
134    }
135);
136
137impl<'a> DecoderValueMut<'a> for DecoderBufferMut<'a> {
138    #[inline]
139    fn decode_mut(buffer: DecoderBufferMut<'a>) -> DecoderBufferMutResult<'a, Self> {
140        let len = buffer.len();
141        buffer.decode_slice(len)
142    }
143}
144
145/// A value whose decoding implementation can be altered
146/// by a provided parameter.
147pub trait DecoderParameterizedValue<'a>: Sized {
148    type Parameter;
149
150    fn decode_parameterized(
151        parameter: Self::Parameter,
152        bytes: DecoderBuffer<'a>,
153    ) -> DecoderBufferResult<'a, Self>;
154}
155
156/// A mutable value whose decoding implementation can be altered
157/// by a provided parameter.
158pub trait DecoderParameterizedValueMut<'a>: Sized {
159    type Parameter;
160
161    fn decode_parameterized_mut(
162        parameter: Self::Parameter,
163        bytes: DecoderBufferMut<'a>,
164    ) -> DecoderBufferMutResult<'a, Self>;
165}
166
167#[macro_export]
168macro_rules! decoder_parameterized_value {
169    (impl<$lt:lifetime $(, $generic:ident)*> $ty:ty {
170        fn decode($tag:ident: $tag_ty:ty, $buffer:ident: Buffer) -> Result<$ret:ty> $impl:block
171    }) => {
172        impl<$lt $(, $generic: $crate::DecoderValue<$lt>)*> $crate::DecoderParameterizedValue<$lt> for $ty {
173            type Parameter = $tag_ty;
174
175            #[inline]
176            fn decode_parameterized($tag: Self::Parameter, $buffer: $crate::DecoderBuffer<$lt>) -> $crate::DecoderBufferResult<$lt, $ret> $impl
177        }
178
179        impl<$lt $(, $generic: $crate::DecoderValueMut<$lt>)*> $crate::DecoderParameterizedValueMut<$lt> for $ty {
180            type Parameter = $tag_ty;
181
182            #[inline]
183            fn decode_parameterized_mut($tag: Self::Parameter, $buffer: $crate::DecoderBufferMut<$lt>) -> $crate::DecoderBufferMutResult<$lt, $ret> $impl
184        }
185    };
186}
187
188/// PrefixedBlob is a length-prefixed string of bytes.
189///
190/// This is particularly useful for TLS messages. For example, the
191/// `opaque legacy_compression_methods<1..2^8-1>` field from the TLS 1.3 RFC could
192/// be decoded as `PrefixedBlob<'a, u8>`.
193pub struct PrefixedBlob<'a, L> {
194    pub blob: &'a [u8],
195    phantom_length: PhantomData<L>,
196}
197
198impl<'a, L: Into<usize> + DecoderValue<'a>> DecoderValue<'a> for PrefixedBlob<'a, L> {
199    fn decode(bytes: DecoderBuffer<'a>) -> DecoderBufferResult<'a, Self> {
200        let (blob, remaining) = bytes.decode_slice_with_len_prefix::<L>()?;
201        let blob = blob.into_less_safe_slice();
202
203        let value = Self {
204            blob,
205            phantom_length: PhantomData,
206        };
207
208        Ok((value, remaining))
209    }
210}
211
212/// A PrefixedList represents a length prefixed list, with a length prefix of `L`
213/// and elements of type `T`.
214///
215/// Note that this will neither allocate nor copy `T`, so it must be valid to directly
216/// construct them from the underlying `&[u8]`.
217///
218/// This type is particularly useful for representing TLS messages, such as a list
219/// of supported `NamedGroup` items in the Supported Groups extension.
220pub struct PrefixedList<'a, L, T> {
221    pub list: &'a [T],
222    phantom_length: PhantomData<L>,
223}
224
225impl<'a, L: Into<usize> + DecoderValue<'a>, T: FromBytes + Immutable + Unaligned> DecoderValue<'a>
226    for PrefixedList<'a, L, T>
227{
228    fn decode(bytes: DecoderBuffer<'a>) -> DecoderBufferResult<'a, Self> {
229        let (blob, remaining) = bytes.decode_slice_with_len_prefix::<L>()?;
230        let blob = blob.into_less_safe_slice();
231        let list = FromBytes::ref_from_bytes(blob).map_err(|_| {
232            DecoderError::InvariantViolation("blob length is not a multiple of element size")
233        })?;
234
235        let value = Self {
236            list,
237            phantom_length: PhantomData,
238        };
239
240        Ok((value, remaining))
241    }
242}
243
244// This implementation will not allocate data, but will copy it onto the stack
245impl<'a, const N: usize> DecoderValue<'a> for [u8; N] {
246    fn decode(bytes: DecoderBuffer<'a>) -> DecoderBufferResult<'a, Self> {
247        let (value, buffer) = bytes.decode_slice(N)?;
248        let value = value.into_less_safe_slice().try_into().map_err(|_| {
249            DecoderError::InvariantViolation("decode_slice returned a slice of the wrong length")
250        })?;
251        Ok((value, buffer))
252    }
253}
254
255impl<'a, const N: usize> DecoderValue<'a> for &'a [u8; N] {
256    fn decode(bytes: DecoderBuffer<'a>) -> DecoderBufferResult<'a, Self> {
257        let (value, buffer) = bytes.decode_slice(N)?;
258        let slice = value.into_less_safe_slice();
259        let value = slice.try_into().map_err(|_| {
260            DecoderError::InvariantViolation("decode_slice returned a slice of the wrong length")
261        })?;
262        Ok((value, buffer))
263    }
264}
265
266#[cfg(test)]
267mod tests {
268    use super::*;
269    use crate::DecoderBuffer;
270
271    #[test]
272    fn array_decode() {
273        let buf = DecoderBuffer::new(&[1, 2, 3, 4, 5]);
274        let (val, remaining) = buf.decode::<[u8; 3]>().unwrap();
275        assert_eq!(val, [1, 2, 3]);
276        assert_eq!(remaining.into_less_safe_slice(), &[4, 5]);
277
278        let buf = DecoderBuffer::new(&[]);
279        let (val, remaining) = buf.decode::<[u8; 0]>().unwrap();
280        assert_eq!(val, []);
281        assert!(remaining.is_empty());
282
283        // error: insufficient data
284        assert!(DecoderBuffer::new(&[1, 2]).decode::<[u8; 4]>().is_err());
285    }
286
287    #[test]
288    fn ref_array_decode() {
289        let buf = DecoderBuffer::new(&[1, 2, 3, 4, 5]);
290        let (val, remaining) = buf.decode::<&[u8; 3]>().unwrap();
291        assert_eq!(val, &[1, 2, 3]);
292        assert_eq!(remaining.into_less_safe_slice(), &[4, 5]);
293
294        let buf = DecoderBuffer::new(&[]);
295        let (val, remaining) = buf.decode::<&[u8; 0]>().unwrap();
296        assert_eq!(val, &[]);
297        assert!(remaining.is_empty());
298
299        // error: insufficient data
300        assert!(DecoderBuffer::new(&[1, 2]).decode::<&[u8; 4]>().is_err());
301    }
302
303    #[test]
304    fn prefixed_blob_decode() {
305        // u8 length prefix
306        let buf = DecoderBuffer::new(&[3, 0xAA, 0xBB, 0xCC]);
307        let (blob, remaining) = buf.decode::<PrefixedBlob<u8>>().unwrap();
308        assert_eq!(blob.blob, &[0xAA, 0xBB, 0xCC]);
309        assert!(remaining.is_empty());
310
311        // u16 big-endian length = 256 (0x01, 0x00) — verifies endianness
312        let mut data = vec![0x01, 0x00];
313        data.extend(core::iter::repeat_n(0xFFu8, 256));
314        let buf = DecoderBuffer::new(&data);
315        let (blob, remaining) = buf.decode::<PrefixedBlob<u16>>().unwrap();
316        assert_eq!(blob.blob.len(), 256);
317        assert!(remaining.is_empty());
318
319        // errors: length exceeds data, missing/truncated length prefix
320        assert!(DecoderBuffer::new(&[5, 0x01, 0x02])
321            .decode::<PrefixedBlob<u8>>()
322            .is_err());
323        assert!(DecoderBuffer::new(&[0x01, 0x00, 0xAA])
324            .decode::<PrefixedBlob<u16>>()
325            .is_err());
326        assert!(DecoderBuffer::new(&[0x01])
327            .decode::<PrefixedBlob<u16>>()
328            .is_err());
329    }
330
331    #[test]
332    fn prefixed_list_decode() {
333        // u8 length prefix, u8 elements
334        let buf = DecoderBuffer::new(&[3, 10, 20, 30]);
335        let (list, remaining) = buf.decode::<PrefixedList<u8, u8>>().unwrap();
336        assert_eq!(list.list, &[10, 20, 30]);
337        assert!(remaining.is_empty());
338
339        // u16 length prefix, u16 big-endian elements — verifies endianness of both
340        let buf = DecoderBuffer::new(&[0x00, 0x04, 0x01, 0x02, 0x03, 0x04]);
341        let (list, remaining) = buf
342            .decode::<PrefixedList<u16, zerocopy::network_endian::U16>>()
343            .unwrap();
344        assert_eq!(list.list.len(), 2);
345        assert_eq!(list.list[0].get(), 0x0102);
346        assert_eq!(list.list[1].get(), 0x0304);
347        assert!(remaining.is_empty());
348
349        // errors: insufficient data
350        assert!(DecoderBuffer::new(&[5, 1, 2])
351            .decode::<PrefixedList<u8, u8>>()
352            .is_err());
353        assert!(DecoderBuffer::new(&[0x00, 0x03, 0x01, 0x02, 0x03])
354            .decode::<PrefixedList<u16, zerocopy::network_endian::U16>>()
355            .is_err());
356    }
357}