embedded_tls/
parse_buffer.rs

1use crate::TlsError;
2use heapless::{CapacityError, Vec};
3
4#[derive(Debug, Copy, Clone)]
5#[cfg_attr(feature = "defmt", derive(defmt::Format))]
6pub enum ParseError {
7    InsufficientBytes,
8    InsufficientSpace,
9    InvalidData,
10}
11
12pub struct ParseBuffer<'b> {
13    pos: usize,
14    buffer: &'b [u8],
15}
16
17impl<'b> From<&'b [u8]> for ParseBuffer<'b> {
18    fn from(val: &'b [u8]) -> Self {
19        ParseBuffer::new(val)
20    }
21}
22
23impl<'b, const N: usize> From<ParseBuffer<'b>> for Result<Vec<u8, N>, CapacityError> {
24    fn from(val: ParseBuffer<'b>) -> Self {
25        Vec::from_slice(&val.buffer[val.pos..])
26    }
27}
28
29impl<'b> ParseBuffer<'b> {
30    pub fn new(buffer: &'b [u8]) -> Self {
31        Self { pos: 0, buffer }
32    }
33
34    pub fn is_empty(&self) -> bool {
35        self.pos == self.buffer.len()
36    }
37
38    pub fn remaining(&self) -> usize {
39        self.buffer.len() - self.pos
40    }
41
42    pub fn offset(&self) -> usize {
43        self.pos
44    }
45
46    pub fn as_slice(&self) -> &'b [u8] {
47        self.buffer
48    }
49
50    pub fn slice(&mut self, len: usize) -> Result<ParseBuffer<'b>, ParseError> {
51        if self.pos + len <= self.buffer.len() {
52            let slice = ParseBuffer::new(&self.buffer[self.pos..self.pos + len]);
53            self.pos += len;
54            Ok(slice)
55        } else {
56            Err(ParseError::InsufficientBytes)
57        }
58    }
59
60    pub fn read_u8(&mut self) -> Result<u8, ParseError> {
61        if self.pos < self.buffer.len() {
62            let value = self.buffer[self.pos];
63            self.pos += 1;
64            Ok(value)
65        } else {
66            Err(ParseError::InsufficientBytes)
67        }
68    }
69
70    pub fn read_u16(&mut self) -> Result<u16, ParseError> {
71        //info!("pos={} len={}", self.pos, self.buffer.len());
72        if self.pos + 2 <= self.buffer.len() {
73            let value = u16::from_be_bytes([self.buffer[self.pos], self.buffer[self.pos + 1]]);
74            self.pos += 2;
75            Ok(value)
76        } else {
77            Err(ParseError::InsufficientBytes)
78        }
79    }
80
81    pub fn read_u24(&mut self) -> Result<u32, ParseError> {
82        if self.pos + 3 <= self.buffer.len() {
83            let value = u32::from_be_bytes([
84                0,
85                self.buffer[self.pos],
86                self.buffer[self.pos + 1],
87                self.buffer[self.pos + 2],
88            ]);
89            self.pos += 3;
90            Ok(value)
91        } else {
92            Err(ParseError::InsufficientBytes)
93        }
94    }
95
96    pub fn read_u32(&mut self) -> Result<u32, ParseError> {
97        if self.pos + 4 <= self.buffer.len() {
98            let value = u32::from_be_bytes([
99                self.buffer[self.pos],
100                self.buffer[self.pos + 1],
101                self.buffer[self.pos + 2],
102                self.buffer[self.pos + 3],
103            ]);
104            self.pos += 4;
105            Ok(value)
106        } else {
107            Err(ParseError::InsufficientBytes)
108        }
109    }
110
111    pub fn fill(&mut self, dest: &mut [u8]) -> Result<(), ParseError> {
112        if self.pos + dest.len() <= self.buffer.len() {
113            dest.copy_from_slice(&self.buffer[self.pos..self.pos + dest.len()]);
114            self.pos += dest.len();
115            // info!("Copied {} bytes", dest.len());
116            Ok(())
117        } else {
118            Err(ParseError::InsufficientBytes)
119        }
120    }
121
122    pub fn copy<const N: usize>(
123        &mut self,
124        dest: &mut Vec<u8, N>,
125        num_bytes: usize,
126    ) -> Result<(), ParseError> {
127        let space = dest.capacity() - dest.len();
128        if space < num_bytes {
129            error!(
130                "Insufficient space in destination buffer. Space: {} required: {}",
131                space, num_bytes
132            );
133            Err(ParseError::InsufficientSpace)
134        } else if self.pos + num_bytes <= self.buffer.len() {
135            dest.extend_from_slice(&self.buffer[self.pos..self.pos + num_bytes])
136                .map_err(|_| {
137                    error!(
138                        "Failed to extend destination buffer. Space: {} required: {}",
139                        space, num_bytes
140                    );
141                    ParseError::InsufficientSpace
142                })?;
143            self.pos += num_bytes;
144            Ok(())
145        } else {
146            Err(ParseError::InsufficientBytes)
147        }
148    }
149
150    pub fn read_list<T, const N: usize>(
151        &mut self,
152        data_length: usize,
153        read: impl Fn(&mut ParseBuffer<'b>) -> Result<T, ParseError>,
154    ) -> Result<Vec<T, N>, ParseError> {
155        let mut result = Vec::new();
156
157        let mut data = self.slice(data_length)?;
158        while !data.is_empty() {
159            result.push(read(&mut data)?).map_err(|_| {
160                error!("Failed to store parse result");
161                ParseError::InsufficientSpace
162            })?;
163        }
164
165        Ok(result)
166    }
167}
168
169impl From<ParseError> for TlsError {
170    fn from(e: ParseError) -> Self {
171        TlsError::ParseError(e)
172    }
173}