Skip to main content

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 value of type `T` from a buffer that is exactly the length of `T`."
69                ""
70                "Returns an error if any data remains.";
71                #[inline]
72                pub fn decode_exact<T: $value<'a>>(self) -> Result<T, DecoderError> {
73                    let (value, remaining) = T::$value_call(self)?;
74                    if !remaining.is_empty() {
75                        Err(DecoderError::UnexpectedBytes(remaining.len()))
76                    } else {
77                        Ok(value)
78                    }
79                }
80            }
81
82            doc_comment! {
83                "Decode a slice prefixed by type `Length`, splitting the data from the"
84                "current buffer."
85
86                "With a `Length` as encoded `u8`:"
87                "```rust"
88                "# use s2n_codec::*;"
89                "let mut data = [5, 0, 1, 2, 3, 4];"
90                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
91                "let (slice, buffer) = buffer.decode_slice_with_len_prefix::<u8>().unwrap();"
92                "assert_eq!(slice, [0u8, 1, 2, 3, 4][..]);"
93                "assert!(buffer.is_empty())"
94                "```"
95
96                "With a `Length` as encoded `u16`:"
97                "```rust"
98                "# use s2n_codec::*;"
99                "let mut data = [0, 5, 0, 1, 2, 3, 4];"
100                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
101                "let (slice, buffer) = buffer.decode_slice_with_len_prefix::<u16>().unwrap();"
102                "assert_eq!(slice, [0u8, 1, 2, 3, 4][..]);"
103                "assert!(buffer.is_empty())"
104                "```";
105
106                #[inline]
107                pub fn decode_slice_with_len_prefix<Length: $value<'a> + core::convert::TryInto<usize>>(
108                    self,
109                ) -> $result<'a, Self> {
110                    let (len, buffer) = self.decode::<Length>()?;
111                    let len = len.try_into().map_err(|_| DecoderError::LengthCapacityExceeded)?;
112                    buffer.decode_slice(len)
113                }
114            }
115
116            doc_comment! {
117                "Decode a value of type `T` prefixed by type `Length`, splitting the data from the"
118                "current buffer."
119
120                "With a `Length` as encoded `u8` and `T` as `u16`:"
121                "```rust"
122                "# use s2n_codec::*;"
123                "let mut data = [2, 0, 1, 2, 3];"
124                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
125                "let (value, buffer) = buffer.decode_with_len_prefix::<u8, u16>().unwrap();"
126                "assert_eq!(value, 1);"
127                "assert_eq!(buffer, [2, 3][..])"
128                "```"
129
130                concat!("The `", stringify!($value) ,"` implementation of `T` must consume the entire subslice")
131                "otherwise an error will be returned."
132
133                "```rust"
134                "# use s2n_codec::*;"
135                "let mut data = [3, 0, 1, 2];"
136                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
137                "let result = buffer.decode_with_len_prefix::<u8, u16>();"
138                "assert!(result.is_err())"
139                "```";
140
141                #[inline]
142                pub fn decode_with_len_prefix<Length: $value<'a> + core::convert::TryInto<usize>, T: $value<'a>>(
143                    self,
144                ) -> $result<'a, T> {
145                    let (slice, buffer) = self.decode_slice_with_len_prefix::<Length>()?;
146                    let (value, slice) = slice.decode::<T>()?;
147                    slice.ensure_empty()?;
148                    Ok((value, buffer))
149                }
150            }
151
152            doc_comment! {
153                "Decode a parameterized value of type `T` implementing `"
154                stringify!($parameterized) "`";
155
156                #[inline]
157                pub fn decode_parameterized<T: $parameterized<'a>>(
158                    self,
159                    parameter: T::Parameter,
160                ) -> $result<'a, T> {
161                    T::$parameterized_call(parameter, self)
162                }
163            }
164
165            doc_comment! {
166                "Skip a `count` of bytes, discarding the bytes"
167
168                "```rust"
169                "# use s2n_codec::*;"
170                "let mut data = [0, 1, 2, 3, 4];"
171                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
172                "let buffer = buffer.skip(3).unwrap();"
173                "assert_eq!(buffer, [3, 4][..]);"
174                "```";
175
176                #[inline]
177                pub fn skip(self, count: usize) -> Result<$name<'a>, DecoderError> {
178                    self.decode_slice(count).map(|(_, buffer)| buffer)
179                }
180            }
181
182            doc_comment! {
183                "Skip a number of bytes encoded as a length prefix of type `Length`"
184
185                "With a `Length` encoded as `u8`:"
186                "```rust"
187                "# use s2n_codec::*;"
188                "let mut data = [5, 0, 1, 2, 3, 4];"
189                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
190                "let buffer = buffer.skip_with_len_prefix::<u8>().unwrap();"
191                "assert!(buffer.is_empty());"
192                "```";
193
194                #[inline]
195                pub fn skip_with_len_prefix<Length: $value<'a> + core::convert::TryInto<usize>>(
196                    self,
197                ) -> Result<$name<'a>, DecoderError> {
198                    let (len, buffer) = self.decode::<Length>()?;
199                    let len = len.try_into().map_err(|_| DecoderError::LengthCapacityExceeded)?;
200                    buffer.skip(len)
201                }
202            }
203
204            doc_comment! {
205                "Skip a `count` of bytes, returning a `CheckedRange` for later access";
206                // TODO add doctest
207
208                #[inline]
209                pub fn skip_into_range(
210                    self,
211                    count: usize,
212                    original_buffer: &crate::DecoderBufferMut,
213                ) -> $result<'a, crate::CheckedRange> {
214                    let start = original_buffer.len() - self.len();
215                    let (slice, buffer) = self.decode_slice(count)?;
216                    let end = start + count;
217                    Ok((
218                        crate::CheckedRange::new(start, end, slice.bytes.as_ptr()),
219                        buffer,
220                    ))
221                }
222            }
223
224            doc_comment! {
225                "Skip a number of bytes encoded as a length prefix of type `Length`"
226                "into a `CheckedRange` for later access";
227                // TODO add doctest
228
229                #[inline]
230                pub fn skip_into_range_with_len_prefix<Length: $value<'a> + core::convert::TryInto<usize>>(
231                    self,
232                    original_buffer: &crate::DecoderBufferMut,
233                ) -> $result<'a, crate::CheckedRange> {
234                    let (len, buffer) = self.decode::<Length>()?;
235                    let len = len.try_into().map_err(|_| DecoderError::LengthCapacityExceeded)?;
236                    buffer.skip_into_range(len, original_buffer)
237                }
238            }
239
240            doc_comment! {
241                "Reads data from a `CheckedRange`";
242                // TODO add doctest
243
244                #[inline]
245                pub fn get_checked_range(&self, range: &crate::CheckedRange) -> DecoderBuffer<'_> {
246                    range.get(self.bytes).into()
247                }
248            }
249
250            doc_comment! {
251                "Create a peeking `DecoderBuffer` from the current buffer view"
252
253                "```rust"
254                "# use s2n_codec::*;"
255                "let mut data = [0, 1];"
256                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
257                ""
258                "let peek = buffer.peek();"
259                "let (value, peek) = peek.decode::<u16>().unwrap();"
260                "assert_eq!(value, 1);"
261                "assert!(peek.is_empty());"
262                ""
263                "// `buffer` still contains the previous view"
264                "assert_eq!(buffer, [0, 1][..]);"
265                "```";
266
267                #[inline]
268                #[must_use]
269                pub fn peek(&'a self) -> crate::DecoderBuffer<'a> {
270                    crate::DecoderBuffer::new(self.bytes)
271                }
272            }
273
274            doc_comment! {
275                "Returns a single byte at `index`"
276
277                "```rust"
278                "# use s2n_codec::*;"
279                "let mut data = [0, 1, 2];"
280                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
281                ""
282                "assert_eq!(buffer.peek_byte(0).unwrap(), 0);"
283                "assert_eq!(buffer.peek_byte(1).unwrap(), 1);"
284                "assert_eq!(buffer.peek_byte(2).unwrap(), 2);"
285                ""
286                "// `buffer` has not changed"
287                "assert_eq!(buffer, [0, 1, 2][..]);"
288                "```";
289
290                #[inline]
291                pub fn peek_byte(&self, index: usize) -> Result<u8, DecoderError> {
292                    self.bytes
293                        .get(index)
294                        .cloned()
295                        .ok_or_else(|| DecoderError::UnexpectedEof(index))
296                }
297            }
298
299            /// Returns a `PeekBuffer` by `range`
300            #[inline]
301            pub fn peek_range(
302                &self,
303                range: core::ops::Range<usize>,
304            ) -> Result<crate::DecoderBuffer<'_>, DecoderError> {
305                let end = range.end;
306                self.bytes
307                    .get(range)
308                    .map(|bytes| bytes.into())
309                    .ok_or_else(|| DecoderError::UnexpectedEof(end))
310            }
311
312            doc_comment! {
313                "Returns an error if the buffer is not empty."
314
315                "```rust"
316                "# use s2n_codec::*;"
317                "let mut data = [1];"
318                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
319                ""
320                "assert!(buffer.ensure_empty().is_err());"
321                "let (_, buffer) = buffer.decode::<u8>().unwrap();"
322                "assert!(buffer.ensure_empty().is_ok());"
323                "```";
324
325                #[inline]
326                pub fn ensure_empty(&self) -> Result<(), DecoderError> {
327                    if !self.is_empty() {
328                        Err(DecoderError::UnexpectedBytes(self.len()))
329                    } else {
330                        Ok(())
331                    }
332                }
333            }
334
335            doc_comment! {
336                "Returns an error if the buffer does not have at least `len` bytes."
337
338                "```rust"
339                "# use s2n_codec::*;"
340                "let mut data = [0, 1, 2];"
341                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
342                ""
343                "assert!(buffer.ensure_len(2).is_ok());"
344                "assert!(buffer.ensure_len(5).is_err());"
345                "```";
346
347                #[inline]
348                pub fn ensure_len(&self, len: usize) -> Result<(), DecoderError> {
349                    if self.len() < len {
350                        Err(DecoderError::UnexpectedEof(len))
351                    } else {
352                        Ok(())
353                    }
354                }
355            }
356
357            doc_comment! {
358                "Returns the number of bytes in the buffer."
359
360                "```rust"
361                "# use s2n_codec::*;"
362                "let mut data = [0, 1, 2];"
363                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
364                ""
365                "assert_eq!(buffer.len(), 3);"
366                "let (_, buffer) = buffer.decode::<u8>().unwrap();"
367                "assert_eq!(buffer.len(), 2);"
368                "```";
369
370                #[inline]
371                pub fn len(&self) -> usize {
372                    self.bytes.len()
373                }
374            }
375
376            doc_comment! {
377                "Returns true if the buffer has a length of 0."
378
379                "```rust"
380                "# use s2n_codec::*;"
381                "let mut data = [1];"
382                concat!("let buffer = ", stringify!($name), "::new(&mut data);")
383                ""
384                "assert!(!buffer.is_empty());"
385                "let (_, buffer) = buffer.decode::<u8>().unwrap();"
386                "assert!(buffer.is_empty());"
387                "```";
388
389                #[inline]
390                pub fn is_empty(&self) -> bool {
391                    self.bytes.is_empty()
392                }
393            }
394
395            /// Borrows the buffer's slice. This should be used with caution, as it
396            /// removes any panic protection this struct provides.
397            #[inline]
398            pub fn as_less_safe_slice(&'a self) -> &'a [u8] {
399                self.bytes
400            }
401        }
402
403        impl<'a> From<&'a mut [u8]> for $name<'a> {
404            #[inline]
405            fn from(bytes: &'a mut [u8]) -> Self {
406                Self::new(bytes)
407            }
408        }
409
410        impl<'a> PartialEq<[u8]> for $name<'a> {
411            #[inline]
412            fn eq(&self, rhs: &[u8]) -> bool {
413                let bytes: &[u8] = self.bytes.as_ref();
414                bytes.eq(rhs)
415            }
416        }
417    };
418}
419
420pub mod buffer;
421pub mod buffer_mut;
422pub mod checked_range;
423#[macro_use]
424pub mod value;
425
426pub use buffer::*;
427pub use buffer_mut::*;
428pub use checked_range::*;
429pub use value::*;
430
431#[derive(Clone, Copy, Debug)]
432pub enum DecoderError {
433    UnexpectedEof(usize),
434    UnexpectedBytes(usize),
435    LengthCapacityExceeded,
436    InvariantViolation(&'static str), // TODO replace with a &'static Invariant
437}
438
439impl core::error::Error for DecoderError {}
440
441use core::fmt;
442impl fmt::Display for DecoderError {
443    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
444        // https://github.com/model-checking/kani/issues/1767#issuecomment-1275449305
445        if cfg!(kani) {
446            return Ok(());
447        }
448
449        match self {
450            Self::UnexpectedEof(len) => write!(f, "unexpected eof: {len}"),
451            Self::UnexpectedBytes(len) => write!(f, "unexpected bytes: {len}"),
452            Self::LengthCapacityExceeded => write!(
453                f,
454                "length could not be represented in platform's usize type"
455            ),
456            Self::InvariantViolation(msg) => write!(f, "{msg}"),
457        }
458    }
459}
460
461impl From<DecoderError> for &'static str {
462    fn from(error: DecoderError) -> Self {
463        match error {
464            DecoderError::UnexpectedEof(_len) => "unexpected eof",
465            DecoderError::UnexpectedBytes(_len) => "unexpected bytes",
466            DecoderError::LengthCapacityExceeded => {
467                "length could not be represented in platform's usize type"
468            }
469            DecoderError::InvariantViolation(msg) => msg,
470        }
471    }
472}
473
474#[macro_export]
475macro_rules! decoder_invariant {
476    ($expr:expr, $invariant:expr) => {
477        if !($expr) {
478            return ::core::result::Result::Err(
479                $crate::decoder::DecoderError::InvariantViolation($invariant).into(),
480            );
481        }
482    };
483}
484
485#[cfg(test)]
486mod tests {
487    use super::*;
488
489    // === decode_exact tests ===
490
491    #[test]
492    fn decode_exact_success() {
493        let buf = DecoderBuffer::new(&[0, 42]);
494        let val: u16 = buf.decode_exact().unwrap();
495        assert_eq!(val, 42);
496    }
497
498    #[test]
499    fn decode_exact_trailing_bytes_error() {
500        let buf = DecoderBuffer::new(&[1, 2, 3]);
501        assert!(buf.decode_exact::<u8>().is_err());
502    }
503
504    #[test]
505    fn decode_exact_too_short_error() {
506        let buf = DecoderBuffer::new(&[1]);
507        assert!(buf.decode_exact::<u32>().is_err());
508    }
509
510    #[test]
511    fn decode_exact_empty_buffer_error() {
512        let buf = DecoderBuffer::new(&[]);
513        assert!(buf.decode_exact::<u8>().is_err());
514    }
515
516    // === DecoderError as std::error::Error ===
517
518    #[test]
519    fn decoder_error_implements_std_error() {
520        fn takes_error(_: &dyn std::error::Error) {}
521        let err = DecoderError::UnexpectedEof(0);
522        takes_error(&err);
523    }
524
525    #[test]
526    fn decoder_error_display() {
527        let err = DecoderError::UnexpectedEof(5);
528        assert_eq!(format!("{err}"), "unexpected eof: 5");
529
530        let err = DecoderError::UnexpectedBytes(3);
531        assert_eq!(format!("{err}"), "unexpected bytes: 3");
532
533        let err = DecoderError::InvariantViolation("bad");
534        assert_eq!(format!("{err}"), "bad");
535    }
536
537    #[test]
538    fn decoder_error_in_box_dyn() -> Result<(), Box<dyn std::error::Error>> {
539        let buf = DecoderBuffer::new(&[0, 1]);
540        let _: u16 = buf.decode_exact()?;
541        Ok(())
542    }
543}