1use crate::util::CRC_X25;
6
7use super::{
8 common::{CloseResponse, EndOfSmlMessage, ListEntry, OpenResponse, Signature, Time},
9 octet_string::OctetStr,
10 tlf::{self, Ty, TypeLengthField},
11 OctetStrFormatter, ParseError, ResTy, SmlParse, SmlParseTlf,
12};
13
14pub struct Parser<'i> {
18 input: &'i [u8],
19 msg_input: &'i [u8],
20 pending_list_entries: u32,
21}
22
23impl<'i> Parser<'i> {
24 pub fn new(input: &'i [u8]) -> Self {
26 Parser {
27 input,
28 msg_input: &[],
29 pending_list_entries: 0,
30 }
31 }
32
33 fn parse_next(&mut self) -> Result<Option<ParseEvent<'i>>, ParseError> {
34 if self.input.is_empty() && self.pending_list_entries == 0 {
35 return Ok(None);
36 }
37
38 Ok(Some(match self.pending_list_entries {
39 0 => {
40 self.msg_input = self.input;
41 let (input, msg) = MessageStart::parse(self.input)?;
42 self.input = input;
43 if let MessageBody::GetListResponse(glr) = &msg.message_body {
44 self.pending_list_entries = glr.num_vals + 2;
45 } else {
46 self.pending_list_entries = 1;
47 }
48 ParseEvent::MessageStart(msg)
49 }
50 1 => {
51 let num_bytes_read = self.msg_input.len() - self.input.len();
52
53 let (input, crc) = u16::parse(self.input)?;
54 let (input, _) = EndOfSmlMessage::parse(input)?;
55 self.input = input;
56
57 let digest = CRC_X25
59 .checksum(&self.msg_input[0..num_bytes_read])
60 .swap_bytes();
61 if digest != crc {
62 return Err(ParseError::CrcMismatch);
63 }
64
65 self.pending_list_entries = 0;
66 return self.parse_next();
67 }
68 2 => {
69 let (input, glre) = GetListResponseEnd::parse(self.input)?;
70 self.input = input;
71 self.pending_list_entries = 1;
72 ParseEvent::GetListResponseEnd(glre)
73 }
74 x => {
75 let (input, le) = ListEntry::parse(self.input)?;
76 self.input = input;
77 self.pending_list_entries = x - 1;
78 ParseEvent::ListEntry(le)
79 }
80 }))
81 }
82}
83
84impl<'i> Iterator for Parser<'i> {
85 type Item = Result<ParseEvent<'i>, ParseError>;
86
87 fn next(&mut self) -> Option<Self::Item> {
88 let res = self.parse_next();
89 if res.is_err() {
90 self.input = &[];
91 }
92 match res {
93 Ok(None) => None,
94 Ok(Some(x)) => Some(Ok(x)),
95 Err(e) => Some(Err(e)),
96 }
97 }
98}
99
100#[derive(Debug)]
102pub enum ParseEvent<'i> {
103 MessageStart(MessageStart<'i>),
105 GetListResponseEnd(GetListResponseEnd<'i>),
107 ListEntry(ListEntry<'i>),
109}
110
111#[derive(PartialEq, Eq, Clone)]
121pub struct MessageStart<'i> {
122 pub transaction_id: OctetStr<'i>,
124 pub group_no: u8,
126 pub abort_on_error: u8,
129 pub message_body: MessageBody<'i>,
131}
132
133impl<'i> SmlParse<'i> for MessageStart<'i> {
134 fn parse(input: &'i [u8]) -> ResTy<Self> {
135 let (input, tlf) = TypeLengthField::parse(input)?;
136 if tlf.ty != Ty::ListOf || tlf.len != 6 {
137 return Err(ParseError::TlfMismatch("Message"));
138 }
139 let (input, transaction_id) = OctetStr::parse(input)?;
140 let (input, group_no) = u8::parse(input)?;
141 let (input, abort_on_error) = u8::parse(input)?;
142 let (input, message_body) = MessageBody::parse(input)?;
143
144 let val = MessageStart {
145 transaction_id,
146 group_no,
147 abort_on_error,
148 message_body,
149 };
150 Ok((input, val))
151 }
152}
153
154impl<'i> core::fmt::Debug for MessageStart<'i> {
155 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
156 let mut x = f.debug_struct("MessageStart");
157 x.field("transaction_id", &OctetStrFormatter(self.transaction_id));
158 x.field("group_no", &self.group_no);
159 x.field("abort_on_error", &self.abort_on_error);
160 x.field("message_body", &self.message_body);
161 x.finish()
162 }
163}
164
165#[derive(PartialEq, Eq, Clone)]
166pub enum MessageBody<'i> {
171 OpenResponse(OpenResponse<'i>),
173 CloseResponse(CloseResponse<'i>),
175 GetListResponse(GetListResponseStart<'i>),
177}
178
179impl<'i> core::fmt::Debug for MessageBody<'i> {
180 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
181 match self {
182 Self::OpenResponse(arg0) => arg0.fmt(f),
183 Self::CloseResponse(arg0) => arg0.fmt(f),
184 Self::GetListResponse(arg0) => arg0.fmt(f),
185 }
186 }
187}
188
189impl<'i> SmlParseTlf<'i> for MessageBody<'i> {
190 fn check_tlf(tlf: &TypeLengthField) -> bool {
191 tlf.ty == tlf::Ty::ListOf && tlf.len == 2
192 }
193
194 fn parse_with_tlf(input: &'i [u8], _tlf: &TypeLengthField) -> ResTy<'i, Self> {
195 let (input, tag) = u32::parse(input)?;
196 match tag {
197 0x00000101 => {
198 let (input, x) = <OpenResponse<'i>>::parse(input)?;
199 Ok((input, MessageBody::OpenResponse(x)))
200 }
201 0x00000201 => {
202 let (input, x) = <CloseResponse<'i>>::parse(input)?;
203 Ok((input, MessageBody::CloseResponse(x)))
204 }
205 0x00000701 => {
206 let (input, x) = <GetListResponseStart<'i>>::parse(input)?;
207 Ok((input, MessageBody::GetListResponse(x)))
208 }
209 _ => Err(ParseError::UnexpectedVariant),
210 }
211 }
212}
213
214#[derive(PartialEq, Eq, Clone)]
215pub struct GetListResponseStart<'i> {
217 pub client_id: Option<OctetStr<'i>>,
219 pub server_id: OctetStr<'i>,
221 pub list_name: Option<OctetStr<'i>>,
223 pub act_sensor_time: Option<Time>,
225 pub num_vals: u32,
227}
228
229impl<'i> crate::parser::SmlParseTlf<'i> for GetListResponseStart<'i> {
230 fn check_tlf(tlf: &TypeLengthField) -> bool {
231 *tlf == crate::parser::tlf::TypeLengthField::new(
232 crate::parser::tlf::Ty::ListOf,
233 7usize as u32,
234 )
235 }
236 fn parse_with_tlf(input: &'i [u8], _tlf: &TypeLengthField) -> ResTy<'i, Self> {
237 let (input, client_id) = <Option<OctetStr<'i>>>::parse(input)?;
238 let (input, server_id) = <OctetStr<'i>>::parse(input)?;
239 let (input, list_name) = <Option<OctetStr<'i>>>::parse(input)?;
240 let (input, act_sensor_time) = <Option<Time>>::parse(input)?;
241 let (input, tlf) = TypeLengthField::parse(input)?;
242 if !matches!(tlf.ty, Ty::ListOf) {
243 return Err(ParseError::TlfMismatch(core::any::type_name::<Self>()));
244 }
245 let val = GetListResponseStart {
246 client_id,
247 server_id,
248 list_name,
249 act_sensor_time,
250 num_vals: tlf.len,
251 };
252 Ok((input, val))
253 }
254}
255
256impl<'i> core::fmt::Debug for GetListResponseStart<'i> {
257 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
258 let mut x = f.debug_struct("GetListResponseStart");
259 if let Some(e) = &self.client_id {
260 x.field("client_id", &OctetStrFormatter(e));
261 }
262 x.field("server_id", &OctetStrFormatter(self.server_id));
263 if let Some(e) = &self.list_name {
264 x.field("list_name", &OctetStrFormatter(e));
265 }
266 if let Some(e) = &self.act_sensor_time {
267 x.field("act_sensor_time", &e);
268 }
269 x.field("num_values", &self.num_vals);
270 x.finish()
271 }
272}
273
274#[derive(PartialEq, Eq, Clone)]
276pub struct GetListResponseEnd<'i> {
277 pub list_signature: Option<Signature<'i>>,
279 pub act_gateway_time: Option<Time>,
281}
282
283impl<'i> crate::parser::SmlParse<'i> for GetListResponseEnd<'i> {
284 fn parse(input: &'i [u8]) -> ResTy<'i, Self> {
285 let (input, list_signature) = <Option<Signature<'i>>>::parse(input)?;
286 let (input, act_gateway_time) = <Option<Time>>::parse(input)?;
287 let val = GetListResponseEnd {
288 list_signature,
289 act_gateway_time,
290 };
291 Ok((input, val))
292 }
293}
294
295impl<'i> core::fmt::Debug for GetListResponseEnd<'i> {
296 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
297 let mut x = f.debug_struct("GetListResponseEnd");
298 if let Some(e) = &self.list_signature {
299 x.field("list_signature", &e);
300 }
301 if let Some(e) = &self.act_gateway_time {
302 x.field("act_gateway_time", &e);
303 }
304 x.finish()
305 }
306}