veecle_os_data_support_someip/
parse.rs1pub use veecle_os_data_support_someip_macros::Parse;
5
6#[derive(Debug, Clone, Copy, thiserror::Error, PartialEq, Eq)]
8pub enum ParseError {
9 #[error("the payload is too short")]
11 PayloadTooShort,
12 #[error("the payload is too long. Expected {expected} found {found}")]
14 PayloadTooLong {
15 expected: usize,
17 found: usize,
19 },
20 #[error("malformed message. Failed to parse {failed_at}")]
22 MalformedMessage {
23 failed_at: &'static str,
25 },
26}
27
28#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct ByteReader<'a> {
31 data: &'a [u8],
33 offset: usize,
35}
36
37impl<'a> ByteReader<'a> {
38 pub fn new(data: &'a [u8]) -> Self {
40 Self { data, offset: 0 }
41 }
42
43 pub fn sub_reader(&mut self, length: usize) -> Result<Self, ParseError> {
49 let Some(new_offset) = self.offset.checked_add(length) else {
50 return Err(ParseError::PayloadTooShort);
51 };
52
53 if new_offset > self.data.len() {
54 return Err(ParseError::PayloadTooShort);
55 }
56
57 let current_offset = self.offset;
58 self.offset = new_offset;
59
60 let data = &self.data[current_offset..self.offset];
61
62 Ok(Self { offset: 0, data })
63 }
64
65 pub fn take_remaining(&mut self) -> Self {
67 let data = &self.data[self.offset..];
68
69 self.offset = self.data.len();
70
71 Self { data, offset: 0 }
72 }
73
74 pub fn read_byte(&mut self) -> Result<u8, ParseError> {
76 if self.offset >= self.data.len() {
77 return Err(ParseError::PayloadTooShort);
78 }
79
80 let byte = self.data[self.offset];
81
82 self.offset += 1;
83
84 Ok(byte)
85 }
86
87 pub fn read_slice(&mut self, length: usize) -> Result<&'a [u8], ParseError> {
89 let Some(new_offset) = self.offset.checked_add(length) else {
90 return Err(ParseError::PayloadTooShort);
91 };
92
93 if new_offset > self.data.len() {
94 return Err(ParseError::PayloadTooShort);
95 }
96
97 let result = &self.data[self.offset..self.offset + length];
98
99 self.offset += length;
100
101 Ok(result)
102 }
103
104 pub fn read_array<const N: usize>(&mut self) -> Result<[u8; N], ParseError> {
106 let Some(new_offset) = self.offset.checked_add(N) else {
107 return Err(ParseError::PayloadTooShort);
108 };
109
110 if new_offset > self.data.len() {
111 return Err(ParseError::PayloadTooShort);
112 }
113
114 let result = self.data[self.offset..self.offset + N]
115 .try_into()
116 .expect("returned slice should always be N bytes long");
117
118 self.offset += N;
119
120 Ok(result)
121 }
122
123 pub fn remaining_slice(&self) -> &'a [u8] {
125 &self.data[self.offset..]
126 }
127
128 pub fn consume_matching_bytes(&mut self, compare_to: &[u8]) -> bool {
132 let length = compare_to.len();
133
134 let Some(new_offset) = self.offset.checked_add(length) else {
135 return false;
136 };
137
138 if new_offset > self.data.len() || &self.data[self.offset..][..length] != compare_to {
139 return false;
140 }
141
142 self.offset += length;
143
144 true
145 }
146
147 pub fn len(&self) -> usize {
149 self.data.len().saturating_sub(self.offset)
150 }
151
152 pub fn is_empty(&self) -> bool {
154 self.offset >= self.data.len()
155 }
156}
157
158pub trait Parse<'a>: Sized {
160 fn parse_partial(reader: &mut ByteReader<'a>) -> Result<Self, ParseError>;
164}
165
166pub trait ParseExt<'a>: Sized {
168 fn parse(slice: &'a [u8]) -> Result<Self, ParseError>;
171}
172
173impl<'a, T> ParseExt<'a> for T
174where
175 T: Parse<'a>,
176{
177 fn parse(slice: &'a [u8]) -> Result<Self, ParseError> {
178 let mut reader = ByteReader::new(slice);
179 let this = Self::parse_partial(&mut reader)?;
180
181 match reader.is_empty() {
182 true => Ok(this),
183 false => Err(ParseError::PayloadTooLong {
184 expected: reader.offset,
185 found: slice.len(),
186 }),
187 }
188 }
189}
190
191#[cfg(test)]
192#[cfg_attr(coverage_nightly, coverage(off))]
193mod parse_ext {
194 use pretty_assertions::assert_eq;
195
196 use super::{ParseError, ParseExt};
197
198 #[test]
199 fn payload_too_long() {
200 assert_eq!(
201 u32::parse(&[0xFF, 0xFF, 0xFF, 0xFF, 0xFF]),
202 Err(ParseError::PayloadTooLong {
203 expected: 4,
204 found: 5
205 })
206 );
207 }
208}