1use alloc::vec::Vec;
29use core::fmt::Debug;
30
31use super::{
32 common::{CloseResponse, EndOfSmlMessage, ListEntry, OpenResponse, Signature, Time},
33 tlf::{Ty, TypeLengthField},
34 OctetStr, OctetStrFormatter, ParseError, ResTy, SmlParse, SmlParseTlf,
35};
36
37#[derive(Debug, PartialEq, Eq, Clone)]
38pub struct File<'i> {
40 pub messages: Vec<Message<'i>>,
42}
43
44impl<'i> SmlParse<'i> for File<'i> {
45 fn parse(mut input: &'i [u8]) -> ResTy<Self> {
46 let mut messages = Vec::new();
47 while !input.is_empty() {
48 let (new_input, msg) = Message::parse(input)?;
49 messages.push(msg);
50 input = new_input;
51 }
52
53 Ok((input, File { messages }))
54 }
55}
56
57#[derive(PartialEq, Eq, Clone)]
58pub struct Message<'i> {
60 pub transaction_id: OctetStr<'i>,
62 pub group_no: u8,
64 pub abort_on_error: u8,
67 pub message_body: MessageBody<'i>,
69}
70
71impl<'i> SmlParse<'i> for Message<'i> {
72 fn parse(input: &'i [u8]) -> ResTy<Self> {
73 let input_orig = input;
74 let (input, tlf) = TypeLengthField::parse(input)?;
75 if tlf.ty != super::tlf::Ty::ListOf || tlf.len != 6 {
76 return Err(ParseError::TlfMismatch("Message"));
77 }
78 let (input, transaction_id) = OctetStr::parse(input)?;
79 let (input, group_no) = u8::parse(input)?;
80 let (input, abort_on_error) = u8::parse(input)?;
81 let (input, message_body) = MessageBody::parse(input)?;
82
83 let num_bytes_read = input_orig.len() - input.len();
84
85 let (input, crc) = u16::parse(input)?;
86 let (input, _) = EndOfSmlMessage::parse(input)?;
87
88 let digest = crate::util::CRC_X25
90 .checksum(&input_orig[0..num_bytes_read])
91 .swap_bytes();
92 if digest != crc {
93 return Err(ParseError::CrcMismatch);
94 }
95
96 let val = Message {
97 transaction_id,
98 group_no,
99 abort_on_error,
100 message_body,
101 };
102 Ok((input, val))
103 }
104}
105
106impl<'i> Debug for Message<'i> {
107 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
108 let mut x = f.debug_struct("Message");
109 x.field("transaction_id", &OctetStrFormatter(self.transaction_id));
110 x.field("group_no", &self.group_no);
111 x.field("abort_on_error", &self.abort_on_error);
112 x.field("message_body", &self.message_body);
113 x.finish()
114 }
115}
116
117#[cfg(feature = "alloc")]
118#[derive(PartialEq, Eq, Clone)]
119pub enum MessageBody<'i> {
124 OpenResponse(OpenResponse<'i>),
126 CloseResponse(CloseResponse<'i>),
128 GetListResponse(GetListResponse<'i>),
130}
131
132#[cfg(feature = "alloc")]
133impl<'i> core::fmt::Debug for MessageBody<'i> {
134 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
135 match self {
136 Self::OpenResponse(arg0) => arg0.fmt(f),
137 Self::CloseResponse(arg0) => arg0.fmt(f),
138 Self::GetListResponse(arg0) => arg0.fmt(f),
139 }
140 }
141}
142
143impl<'i> SmlParseTlf<'i> for MessageBody<'i> {
144 fn check_tlf(tlf: &TypeLengthField) -> bool {
145 tlf.ty == Ty::ListOf && tlf.len == 2
146 }
147
148 fn parse_with_tlf(input: &'i [u8], _tlf: &TypeLengthField) -> ResTy<'i, Self> {
149 let (input, tag) = u32::parse(input)?;
150 match tag {
151 0x00000101 => {
152 let (input, x) = <OpenResponse<'i>>::parse(input)?;
153 Ok((input, MessageBody::OpenResponse(x)))
154 }
155 0x00000201 => {
156 let (input, x) = <CloseResponse<'i>>::parse(input)?;
157 Ok((input, MessageBody::CloseResponse(x)))
158 }
159 0x00000701 => {
160 let (input, x) = <GetListResponse<'i>>::parse(input)?;
161 Ok((input, MessageBody::GetListResponse(x)))
162 }
163 _ => Err(ParseError::UnexpectedVariant),
164 }
165 }
166}
167
168#[derive(PartialEq, Eq, Clone)]
169pub struct GetListResponse<'i> {
171 pub client_id: Option<OctetStr<'i>>,
173 pub server_id: OctetStr<'i>,
175 pub list_name: Option<OctetStr<'i>>,
177 pub act_sensor_time: Option<Time>,
179 pub val_list: List<'i>,
181 pub list_signature: Option<Signature<'i>>,
183 pub act_gateway_time: Option<Time>,
185}
186
187impl<'i> SmlParseTlf<'i> for GetListResponse<'i> {
188 fn check_tlf(tlf: &TypeLengthField) -> bool {
189 *tlf == TypeLengthField::new(Ty::ListOf, 7usize as u32)
190 }
191
192 fn parse_with_tlf(input: &'i [u8], _tlf: &TypeLengthField) -> ResTy<'i, Self> {
193 let (input, client_id) = <Option<OctetStr<'i>>>::parse(input)?;
194 let (input, server_id) = <OctetStr<'i>>::parse(input)?;
195 let (input, list_name) = <Option<OctetStr<'i>>>::parse(input)?;
196 let (input, act_sensor_time) = <Option<Time>>::parse(input)?;
197 let (input, val_list) = <List<'i>>::parse(input)?;
198 let (input, list_signature) = <Option<Signature<'i>>>::parse(input)?;
199 let (input, act_gateway_time) = <Option<Time>>::parse(input)?;
200 let val = GetListResponse {
201 client_id,
202 server_id,
203 list_name,
204 act_sensor_time,
205 val_list,
206 list_signature,
207 act_gateway_time,
208 };
209 Ok((input, val))
210 }
211}
212
213impl<'i> core::fmt::Debug for GetListResponse<'i> {
214 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
215 let mut x = f.debug_struct("GetListResponse");
216 if let Some(e) = &self.client_id {
217 x.field("client_id", &OctetStrFormatter(e));
218 }
219 x.field("server_id", &OctetStrFormatter(self.server_id));
220 if let Some(e) = &self.list_name {
221 x.field("list_name", &OctetStrFormatter(e));
222 }
223 if let Some(e) = &self.act_sensor_time {
224 x.field("act_sensor_time", &e);
225 }
226 x.field("val_list", &self.val_list);
227 if let Some(e) = &self.list_signature {
228 x.field("list_signature", &e);
229 }
230 if let Some(e) = &self.act_gateway_time {
231 x.field("act_gateway_time", &e);
232 }
233 x.finish()
234 }
235}
236
237pub type List<'i> = Vec<ListEntry<'i>>;
239
240impl<'i> SmlParseTlf<'i> for List<'i> {
241 fn check_tlf(tlf: &TypeLengthField) -> bool {
242 matches!(tlf.ty, super::tlf::Ty::ListOf)
243 }
244
245 fn parse_with_tlf(mut input: &'i [u8], tlf: &TypeLengthField) -> ResTy<'i, Self> {
246 let mut v = Vec::with_capacity(tlf.len as usize);
247 for _ in 0..tlf.len {
248 let (new_input, x) = ListEntry::parse(input)?;
249 v.push(x);
250 input = new_input;
251 }
252 Ok((input, v))
253 }
254}
255
256pub fn parse(input: &[u8]) -> Result<File, ParseError> {
260 File::parse_complete(input)
261}