s2n_codec/decoder/
mod.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4macro_rules! doc_comment {
5    ($($x:expr)*; $($tt:tt)*) => {
6        doc_comment!(@doc concat!($($x, "\n",)*), $($tt)*);
7    };
8    (@doc $x:expr, $($tt:tt)*) => {
9        #[doc = $x]
10        $($tt)*
11    };
12}
13
14macro_rules! impl_buffer {
15    ($name:ident, $result:ident, $value:ident, $value_call:ident, $parameterized:ident, $parameterized_call:ident, $split:ident) => {
16        impl<'a> $name<'a> {
17            doc_comment! {
18                "Decode a slice of bytes by `count`, removing the slice from the current buffer"
19
20                "```"
21                "# use s2n_codec::*;"
22                "let mut data = [0, 1, 2, 3, 4];"
23                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
24                ""
25                "let (slice, buffer) = buffer.decode_slice(5).unwrap();"
26                "assert_eq!(slice, [0u8, 1, 2, 3, 4][..]);"
27                ""
28                "assert!(buffer.is_empty());"
29                "```";
30
31                #[inline]
32                pub fn decode_slice(self, count: usize) -> $result<'a, $name<'a>> {
33                    self.ensure_len(count)?;
34
35                    let (slice, remaining) = self.bytes.$split(count);
36
37                    Ok((Self::new(slice), Self::new(remaining)))
38                }
39            }
40
41            doc_comment! {
42                "Decode a value of type `T`, splitting the data from the current buffer"
43
44                "```"
45                "# use s2n_codec::*;"
46                "let mut data = [0, 1, 2, 3, 4, 5, 6];"
47                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
48                ""
49                "let (value, buffer) = buffer.decode::<u8>().unwrap();"
50                "assert_eq!(value, 0);"
51                ""
52                "let (value, buffer) = buffer.decode::<u16>().unwrap();"
53                "assert_eq!(value, 258);"
54                ""
55                "let (value, buffer) = buffer.decode::<u32>().unwrap();"
56                "assert_eq!(value, 50_595_078);"
57                ""
58                "assert!(buffer.is_empty());"
59                "```";
60
61                #[inline]
62                pub fn decode<T: $value<'a>>(self) -> $result<'a, T> {
63                    T::$value_call(self)
64                }
65            }
66
67            doc_comment! {
68                "Decode a slice prefixed by type `Length`, splitting the data from the"
69                "current buffer."
70
71                "With a `Length` as encoded `u8`:"
72                "```rust"
73                "# use s2n_codec::*;"
74                "let mut data = [5, 0, 1, 2, 3, 4];"
75                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
76                "let (slice, buffer) = buffer.decode_slice_with_len_prefix::<u8>().unwrap();"
77                "assert_eq!(slice, [0u8, 1, 2, 3, 4][..]);"
78                "assert!(buffer.is_empty())"
79                "```"
80
81                "With a `Length` as encoded `u16`:"
82                "```rust"
83                "# use s2n_codec::*;"
84                "let mut data = [0, 5, 0, 1, 2, 3, 4];"
85                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
86                "let (slice, buffer) = buffer.decode_slice_with_len_prefix::<u16>().unwrap();"
87                "assert_eq!(slice, [0u8, 1, 2, 3, 4][..]);"
88                "assert!(buffer.is_empty())"
89                "```";
90
91                #[inline]
92                pub fn decode_slice_with_len_prefix<Length: $value<'a> + core::convert::TryInto<usize>>(
93                    self,
94                ) -> $result<'a, Self> {
95                    let (len, buffer) = self.decode::<Length>()?;
96                    let len = len.try_into().map_err(|_| DecoderError::LengthCapacityExceeded)?;
97                    buffer.decode_slice(len)
98                }
99            }
100
101            doc_comment! {
102                "Decode a value of type `T` prefixed by type `Length`, splitting the data from the"
103                "current buffer."
104
105                "With a `Length` as encoded `u8` and `T` as `u16`:"
106                "```rust"
107                "# use s2n_codec::*;"
108                "let mut data = [2, 0, 1, 2, 3];"
109                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
110                "let (value, buffer) = buffer.decode_with_len_prefix::<u8, u16>().unwrap();"
111                "assert_eq!(value, 1);"
112                "assert_eq!(buffer, [2, 3][..])"
113                "```"
114
115                concat!("The `", stringify!($value) ,"` implementation of `T` must consume the entire subslice")
116                "otherwise an error will be returned."
117
118                "```rust"
119                "# use s2n_codec::*;"
120                "let mut data = [3, 0, 1, 2];"
121                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
122                "let result = buffer.decode_with_len_prefix::<u8, u16>();"
123                "assert!(result.is_err())"
124                "```";
125
126                #[inline]
127                pub fn decode_with_len_prefix<Length: $value<'a> + core::convert::TryInto<usize>, T: $value<'a>>(
128                    self,
129                ) -> $result<'a, T> {
130                    let (slice, buffer) = self.decode_slice_with_len_prefix::<Length>()?;
131                    let (value, slice) = slice.decode::<T>()?;
132                    slice.ensure_empty()?;
133                    Ok((value, buffer))
134                }
135            }
136
137            doc_comment! {
138                "Decode a parameterized value of type `T` implementing `"
139                stringify!($parameterized) "`";
140
141                #[inline]
142                pub fn decode_parameterized<T: $parameterized<'a>>(
143                    self,
144                    parameter: T::Parameter,
145                ) -> $result<'a, T> {
146                    T::$parameterized_call(parameter, self)
147                }
148            }
149
150            doc_comment! {
151                "Skip a `count` of bytes, discarding the bytes"
152
153                "```rust"
154                "# use s2n_codec::*;"
155                "let mut data = [0, 1, 2, 3, 4];"
156                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
157                "let buffer = buffer.skip(3).unwrap();"
158                "assert_eq!(buffer, [3, 4][..]);"
159                "```";
160
161                #[inline]
162                pub fn skip(self, count: usize) -> Result<$name<'a>, DecoderError> {
163                    self.decode_slice(count).map(|(_, buffer)| buffer)
164                }
165            }
166
167            doc_comment! {
168                "Skip a number of bytes encoded as a length prefix of type `Length`"
169
170                "With a `Length` encoded as `u8`:"
171                "```rust"
172                "# use s2n_codec::*;"
173                "let mut data = [5, 0, 1, 2, 3, 4];"
174                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
175                "let buffer = buffer.skip_with_len_prefix::<u8>().unwrap();"
176                "assert!(buffer.is_empty());"
177                "```";
178
179                #[inline]
180                pub fn skip_with_len_prefix<Length: $value<'a> + core::convert::TryInto<usize>>(
181                    self,
182                ) -> Result<$name<'a>, DecoderError> {
183                    let (len, buffer) = self.decode::<Length>()?;
184                    let len = len.try_into().map_err(|_| DecoderError::LengthCapacityExceeded)?;
185                    buffer.skip(len)
186                }
187            }
188
189            doc_comment! {
190                "Skip a `count` of bytes, returning a `CheckedRange` for later access";
191                // TODO add doctest
192
193                #[inline]
194                pub fn skip_into_range(
195                    self,
196                    count: usize,
197                    original_buffer: &crate::DecoderBufferMut,
198                ) -> $result<'a, crate::CheckedRange> {
199                    let start = original_buffer.len() - self.len();
200                    let (slice, buffer) = self.decode_slice(count)?;
201                    let end = start + count;
202                    Ok((
203                        crate::CheckedRange::new(start, end, slice.bytes.as_ptr()),
204                        buffer,
205                    ))
206                }
207            }
208
209            doc_comment! {
210                "Skip a number of bytes encoded as a length prefix of type `Length`"
211                "into a `CheckedRange` for later access";
212                // TODO add doctest
213
214                #[inline]
215                pub fn skip_into_range_with_len_prefix<Length: $value<'a> + core::convert::TryInto<usize>>(
216                    self,
217                    original_buffer: &crate::DecoderBufferMut,
218                ) -> $result<'a, crate::CheckedRange> {
219                    let (len, buffer) = self.decode::<Length>()?;
220                    let len = len.try_into().map_err(|_| DecoderError::LengthCapacityExceeded)?;
221                    buffer.skip_into_range(len, original_buffer)
222                }
223            }
224
225            doc_comment! {
226                "Reads data from a `CheckedRange`";
227                // TODO add doctest
228
229                #[inline]
230                pub fn get_checked_range(&self, range: &crate::CheckedRange) -> DecoderBuffer<'_> {
231                    range.get(self.bytes).into()
232                }
233            }
234
235            doc_comment! {
236                "Create a peeking `DecoderBuffer` from the current buffer view"
237
238                "```rust"
239                "# use s2n_codec::*;"
240                "let mut data = [0, 1];"
241                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
242                ""
243                "let peek = buffer.peek();"
244                "let (value, peek) = peek.decode::<u16>().unwrap();"
245                "assert_eq!(value, 1);"
246                "assert!(peek.is_empty());"
247                ""
248                "// `buffer` still contains the previous view"
249                "assert_eq!(buffer, [0, 1][..]);"
250                "```";
251
252                #[inline]
253                #[must_use]
254                pub fn peek(&'a self) -> crate::DecoderBuffer<'a> {
255                    crate::DecoderBuffer::new(self.bytes)
256                }
257            }
258
259            doc_comment! {
260                "Returns a single byte at `index`"
261
262                "```rust"
263                "# use s2n_codec::*;"
264                "let mut data = [0, 1, 2];"
265                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
266                ""
267                "assert_eq!(buffer.peek_byte(0).unwrap(), 0);"
268                "assert_eq!(buffer.peek_byte(1).unwrap(), 1);"
269                "assert_eq!(buffer.peek_byte(2).unwrap(), 2);"
270                ""
271                "// `buffer` has not changed"
272                "assert_eq!(buffer, [0, 1, 2][..]);"
273                "```";
274
275                #[inline]
276                pub fn peek_byte(&self, index: usize) -> Result<u8, DecoderError> {
277                    self.bytes
278                        .get(index)
279                        .cloned()
280                        .ok_or_else(|| DecoderError::UnexpectedEof(index))
281                }
282            }
283
284            /// Returns a `PeekBuffer` by `range`
285            #[inline]
286            pub fn peek_range(
287                &self,
288                range: core::ops::Range<usize>,
289            ) -> Result<crate::DecoderBuffer<'_>, DecoderError> {
290                let end = range.end;
291                self.bytes
292                    .get(range)
293                    .map(|bytes| bytes.into())
294                    .ok_or_else(|| DecoderError::UnexpectedEof(end))
295            }
296
297            doc_comment! {
298                "Returns an error if the buffer is not empty."
299
300                "```rust"
301                "# use s2n_codec::*;"
302                "let mut data = [1];"
303                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
304                ""
305                "assert!(buffer.ensure_empty().is_err());"
306                "let (_, buffer) = buffer.decode::<u8>().unwrap();"
307                "assert!(buffer.ensure_empty().is_ok());"
308                "```";
309
310                #[inline]
311                pub fn ensure_empty(&self) -> Result<(), DecoderError> {
312                    if !self.is_empty() {
313                        Err(DecoderError::UnexpectedBytes(self.len()))
314                    } else {
315                        Ok(())
316                    }
317                }
318            }
319
320            doc_comment! {
321                "Returns an error if the buffer does not have at least `len` bytes."
322
323                "```rust"
324                "# use s2n_codec::*;"
325                "let mut data = [0, 1, 2];"
326                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
327                ""
328                "assert!(buffer.ensure_len(2).is_ok());"
329                "assert!(buffer.ensure_len(5).is_err());"
330                "```";
331
332                #[inline]
333                pub fn ensure_len(&self, len: usize) -> Result<(), DecoderError> {
334                    if self.len() < len {
335                        Err(DecoderError::UnexpectedEof(len))
336                    } else {
337                        Ok(())
338                    }
339                }
340            }
341
342            doc_comment! {
343                "Returns the number of bytes in the buffer."
344
345                "```rust"
346                "# use s2n_codec::*;"
347                "let mut data = [0, 1, 2];"
348                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
349                ""
350                "assert_eq!(buffer.len(), 3);"
351                "let (_, buffer) = buffer.decode::<u8>().unwrap();"
352                "assert_eq!(buffer.len(), 2);"
353                "```";
354
355                #[inline]
356                pub fn len(&self) -> usize {
357                    self.bytes.len()
358                }
359            }
360
361            doc_comment! {
362                "Returns true if the buffer has a length of 0."
363
364                "```rust"
365                "# use s2n_codec::*;"
366                "let mut data = [1];"
367                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
368                ""
369                "assert!(!buffer.is_empty());"
370                "let (_, buffer) = buffer.decode::<u8>().unwrap();"
371                "assert!(buffer.is_empty());"
372                "```";
373
374                #[inline]
375                pub fn is_empty(&self) -> bool {
376                    self.bytes.is_empty()
377                }
378            }
379
380            /// Borrows the buffer's slice. This should be used with caution, as it
381            /// removes any panic protection this struct provides.
382            #[inline]
383            pub fn as_less_safe_slice(&'a self) -> &'a [u8] {
384                self.bytes
385            }
386        }
387
388        impl<'a> From<&'a mut [u8]> for $name<'a> {
389            #[inline]
390            fn from(bytes: &'a mut [u8]) -> Self {
391                Self::new(bytes)
392            }
393        }
394
395        impl<'a> PartialEq<[u8]> for $name<'a> {
396            #[inline]
397            fn eq(&self, rhs: &[u8]) -> bool {
398                let bytes: &[u8] = self.bytes.as_ref();
399                bytes.eq(rhs)
400            }
401        }
402    };
403}
404
405pub mod buffer;
406pub mod buffer_mut;
407pub mod checked_range;
408#[macro_use]
409pub mod value;
410
411pub use buffer::*;
412pub use buffer_mut::*;
413pub use checked_range::*;
414pub use value::*;
415
416#[derive(Clone, Copy, Debug)]
417pub enum DecoderError {
418    UnexpectedEof(usize),
419    UnexpectedBytes(usize),
420    LengthCapacityExceeded,
421    InvariantViolation(&'static str), // TODO replace with a &'static Invariant
422}
423
424use core::fmt;
425impl fmt::Display for DecoderError {
426    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
427        // https://github.com/model-checking/kani/issues/1767#issuecomment-1275449305
428        if cfg!(kani) {
429            return Ok(());
430        }
431
432        match self {
433            Self::UnexpectedEof(len) => write!(f, "unexpected eof: {len}"),
434            Self::UnexpectedBytes(len) => write!(f, "unexpected bytes: {len}"),
435            Self::LengthCapacityExceeded => write!(
436                f,
437                "length could not be represented in platform's usize type"
438            ),
439            Self::InvariantViolation(msg) => write!(f, "{msg}"),
440        }
441    }
442}
443
444impl From<DecoderError> for &'static str {
445    fn from(error: DecoderError) -> Self {
446        match error {
447            DecoderError::UnexpectedEof(_len) => "unexpected eof",
448            DecoderError::UnexpectedBytes(_len) => "unexpected bytes",
449            DecoderError::LengthCapacityExceeded => {
450                "length could not be represented in platform's usize type"
451            }
452            DecoderError::InvariantViolation(msg) => msg,
453        }
454    }
455}
456
457#[macro_export]
458macro_rules! decoder_invariant {
459    ($expr:expr, $invariant:expr) => {
460        if !($expr) {
461            return ::core::result::Result::Err(
462                $crate::decoder::DecoderError::InvariantViolation($invariant).into(),
463            );
464        }
465    };
466}