1use std::{cmp, fmt, mem};
2
3use super::{Message, MAX_LEN};
4use crate::{Error, Result};
5
6mod conf_id;
7mod message_code;
8mod message_type;
9
10pub use conf_id::*;
11pub use message_code::*;
12pub use message_type::*;
13
14pub const MAX_DATA_LEN: usize = MAX_LEN - MessageData::meta_len();
16
17#[repr(C)]
19#[derive(Clone, Debug, Eq, PartialEq)]
20pub struct MessageData {
21 conf_id: ConfId,
22 uid: u8,
23 message_type: MessageType,
24 message_code: MessageCode,
25 additional: Vec<u8>,
26}
27
28impl MessageData {
29 pub const fn new() -> Self {
31 Self {
32 conf_id: ConfId::new(),
33 uid: 0,
34 message_type: MessageType::new(),
35 message_code: MessageCode::new(),
36 additional: Vec::new(),
37 }
38 }
39
40 pub const fn conf_id(&self) -> ConfId {
42 self.conf_id
43 }
44
45 pub fn set_conf_id(&mut self, val: ConfId) {
47 self.conf_id = val;
48 }
49
50 pub fn with_conf_id(mut self, val: ConfId) -> Self {
52 self.set_conf_id(val);
53 self
54 }
55
56 pub const fn uid(&self) -> u8 {
61 self.uid
62 }
63
64 pub fn set_uid(&mut self, val: u8) {
66 self.uid = val;
67 }
68
69 pub fn with_uid(mut self, val: u8) -> Self {
71 self.set_uid(val);
72 self
73 }
74
75 pub const fn message_type(&self) -> MessageType {
77 self.message_type
78 }
79
80 pub fn set_message_type(&mut self, val: MessageType) {
82 self.message_type = val;
83 }
84
85 pub fn with_message_type(mut self, val: MessageType) -> Self {
87 self.set_message_type(val);
88 self
89 }
90
91 pub const fn message_code(&self) -> MessageCode {
93 self.message_code
94 }
95
96 pub fn set_message_code(&mut self, val: MessageCode) {
98 self.message_code = val;
99 }
100
101 pub fn with_message_code(mut self, val: MessageCode) -> Self {
103 self.set_message_code(val);
104 self
105 }
106
107 pub fn additional(&self) -> &[u8] {
109 &self.additional
110 }
111
112 pub fn set_additional(&mut self, additional: &[u8]) {
114 let len = cmp::min(additional.len(), MAX_DATA_LEN);
115 self.additional = additional[..len].into()
116 }
117
118 pub fn with_additional(mut self, additional: &[u8]) -> Self {
120 self.set_additional(additional);
121 self
122 }
123
124 pub fn len(&self) -> usize {
126 Self::meta_len() + self.additional.len()
127 }
128
129 pub(crate) const fn meta_len() -> usize {
130 ConfId::len() + mem::size_of::<u8>() + MessageType::len() + MessageCode::len()
131 }
132
133 pub fn is_empty(&self) -> bool {
135 self.conf_id.is_empty()
136 || self.message_type.is_empty()
137 || self.message_code.is_empty()
138 || self.message_code.func_id().is_empty()
139 || self.additional.is_empty()
140 }
141
142 pub fn to_bytes(&self, buf: &mut [u8]) -> Result<()> {
144 let len = self.len();
145 let buf_len = buf.len();
146
147 if buf_len < len {
148 Err(Error::InvalidMessageDataLen((buf_len, len)))
149 } else {
150 buf.iter_mut()
151 .take(len)
152 .zip(
153 [self.conf_id.into(), self.uid, self.message_type.into()]
154 .into_iter()
155 .chain(self.message_code.to_bytes())
156 .chain(self.additional.iter().cloned()),
157 )
158 .for_each(|(dst, src)| *dst = src);
159
160 Ok(())
161 }
162 }
163}
164
165impl From<&MessageData> for Vec<u8> {
166 fn from(val: &MessageData) -> Self {
167 [val.conf_id.into(), val.uid, val.message_type.into()]
168 .into_iter()
169 .chain(val.message_code.to_bytes())
170 .chain(val.additional.iter().cloned())
171 .collect()
172 }
173}
174
175impl From<MessageData> for Vec<u8> {
176 fn from(val: MessageData) -> Self {
177 [val.conf_id.into(), val.uid, val.message_type.into()]
178 .into_iter()
179 .chain(val.message_code.to_bytes())
180 .chain(val.additional)
181 .collect()
182 }
183}
184
185impl From<&MessageData> for Message {
186 fn from(val: &MessageData) -> Self {
187 Message::new().with_data(val.clone())
188 }
189}
190
191impl From<MessageData> for Message {
192 fn from(val: MessageData) -> Self {
193 Message::new().with_data(val)
194 }
195}
196
197impl TryFrom<&[u8]> for MessageData {
198 type Error = Error;
199
200 fn try_from(val: &[u8]) -> Result<Self> {
201 let len = val.len();
202 let meta_len = Self::meta_len();
203
204 if len < meta_len {
205 Err(Error::InvalidMessageDataLen((len, meta_len)))
206 } else if len > MAX_LEN {
207 Err(Error::InvalidMessageDataLen((len, MAX_LEN)))
208 } else {
209 let conf_id = ConfId::try_from(val[0])?;
210 let uid = val[1];
211 let message_type = MessageType::try_from(val[2])?;
212 let message_code = MessageCode::try_from(RawMessageCode::create(
213 message_type,
214 u16::from_le_bytes([val[3], val[4]]),
215 ))?;
216 let additional = val[5..].into();
217
218 Ok(Self {
219 conf_id,
220 uid,
221 message_type,
222 message_code,
223 additional,
224 })
225 }
226 }
227}
228
229impl Default for MessageData {
230 fn default() -> Self {
231 Self::new()
232 }
233}
234
235impl fmt::Display for MessageData {
236 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
237 write!(f, "{{")?;
238 write!(f, r#""conf_id": {},"#, self.conf_id)?;
239 write!(f, r#""uid": {},"#, self.uid)?;
240 write!(f, r#""message_type": {},"#, self.message_type)?;
241 write!(f, r#""message_code": {},"#, self.message_code)?;
242 write!(f, r#""additional": ["#)?;
243 for (i, d) in self.additional.iter().enumerate() {
244 if i != 0 {
245 write!(f, ",")?;
246 }
247 write!(f, "{d}")?;
248 }
249 write!(f, "]}}")
250 }
251}
252
253#[cfg(test)]
254mod tests {
255 use super::*;
256
257 #[test]
258 #[rustfmt::skip]
259 fn test_message_data() -> Result<()> {
260 let raw: [u8; 5] = [
261 0x10,
263 0x00,
265 0x00,
267 0x01, 0x00,
269 ];
271
272 let exp = MessageData::new();
273 let msg = MessageData::try_from(raw.as_ref())?;
274
275 assert_eq!(msg, exp);
276
277 Ok(())
278 }
279
280 #[test]
281 #[rustfmt::skip]
282 fn test_message_data_with_additional() -> Result<()> {
283 let raw: [u8; 13] = [
284 0x10,
286 0x00,
288 0x00,
290 0x01, 0x00,
292 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
294 ];
295
296 let exp = MessageData::new().with_additional(&raw[5..]);
297 let msg = MessageData::try_from(raw.as_ref())?;
298
299 assert_eq!(msg, exp);
300
301 Ok(())
302 }
303
304 #[test]
305 #[rustfmt::skip]
306 fn test_message_data_too_short() -> Result<()> {
307 let raw: [u8; 3] = [
308 0x10,
310 0x00,
312 0x00,
314 ];
315
316 assert!(MessageData::try_from(raw.as_ref()).is_err());
317
318 Ok(())
319 }
320
321 #[test]
322 #[rustfmt::skip]
323 fn test_message_data_too_long() -> Result<()> {
324 let raw: Vec<u8> = [
325 0x10,
327 0x00,
329 0x00,
331 0x01, 0x00,
333 ].into_iter().chain([0xff; MAX_LEN]).collect();
334
335 assert!(MessageData::try_from(raw.as_slice()).is_err());
336
337 Ok(())
338 }
339}