encdec_base/decode/
ext.rs

1use core::{fmt::Debug, marker::PhantomData};
2
3use super::Decode;
4use crate::Error;
5
6/// Extensions to [`Decode`] trait for decodable objects
7pub trait DecodeExt<'a>: Decode<'a> {
8    /// Helper to iterate over decodable objects in a _sized_ buffer.
9    ///
10    /// Note that objects must be -internally- sized as this is a greedy operation
11    fn decode_iter(buff: &'a [u8]) -> DecodeIter<'a, Self::Output> {
12        DecodeIter {
13            buff,
14            index: 0,
15            _t: PhantomData,
16        }
17    }
18}
19
20/// Blanket implementation for all [`Decode`] types
21impl<'a, T: Decode<'a>> DecodeExt<'a> for T {}
22
23/// Helper type for parsing lists of decodable objects (with internal length delimiters)
24#[derive(Debug)]
25pub struct DecodeIter<'a, T> {
26    buff: &'a [u8],
27    index: usize,
28    _t: PhantomData<T>,
29}
30
31impl<'a, T> DecodeIter<'a, T>
32where
33    T: Decode<'a, Output = T>,
34    <T as Decode<'a>>::Error: From<Error> + Debug,
35{
36    /// Create a new [`DecodeIter`] instance over the provided buffer
37    pub fn new(buff: &'a [u8]) -> Self {
38        Self {
39            buff,
40            index: 0,
41            _t: PhantomData,
42        }
43    }
44}
45
46/// [`Iterator`] implementation
47impl<'a, T> Iterator for DecodeIter<'a, T>
48where
49    T: Decode<'a, Output = T>,
50    <T as Decode<'a>>::Error: From<Error> + Debug,
51{
52    type Item = Result<T, <T as Decode<'a>>::Error>;
53
54    /// Decode and fetch the next item
55    fn next(&mut self) -> Option<Self::Item> {
56        // Exit on buffer exhaustion
57        if self.index == self.buff.len() {
58            return None;
59        }
60
61        // Decode the next object
62        let (v, n) = match T::decode(&self.buff[self.index..]) {
63            Ok((v, n)) => (v, n),
64            Err(e) => return Some(Err(e)),
65        };
66
67        // Increment the index
68        self.index += n;
69
70        Some(Ok(v))
71    }
72}
73
74/// Clone a [`DecodeIter`] instance, note this resets the underlying iterator
75impl<'a, T> Clone for DecodeIter<'a, T>
76where
77    T: Decode<'a, Output = T>,
78    <T as Decode<'a>>::Error: From<Error> + Debug,
79{
80    fn clone(&self) -> Self {
81        Self {
82            buff: self.buff,
83            index: 0,
84            _t: PhantomData,
85        }
86    }
87}