1use alloc::{
2 string::{String, ToString},
3 vec::Vec,
4};
5use core::{convert::TryFrom, fmt};
6
7use crate::error::MessageError;
8
9#[derive(Debug, Clone)]
11pub struct HeaderRaw {
12 ver_type_tkl: u8,
13 code: u8,
14 message_id: u16,
15}
16
17impl HeaderRaw {
18 pub fn serialize_into(
21 &self,
22 buf: &mut Vec<u8>,
23 ) -> Result<(), MessageError> {
24 if buf.capacity() < 4 {
25 return Err(MessageError::InvalidPacketLength);
26 }
27
28 buf.push(self.ver_type_tkl);
29 buf.push(self.code);
30 let id_bytes = self.message_id.to_be_bytes();
31 buf.extend(&id_bytes);
32
33 Ok(())
34 }
35}
36
37impl Default for HeaderRaw {
38 fn default() -> HeaderRaw {
39 HeaderRaw {
40 ver_type_tkl: 0x40, code: 0x01, message_id: 0,
43 }
44 }
45}
46
47impl TryFrom<&[u8]> for HeaderRaw {
48 type Error = MessageError;
49
50 fn try_from(buf: &[u8]) -> Result<HeaderRaw, MessageError> {
51 if buf.len() < 4 {
52 return Err(MessageError::InvalidPacketLength);
53 }
54
55 let mut id_bytes = [0; 2];
56 id_bytes.copy_from_slice(&buf[2..4]);
57
58 Ok(HeaderRaw {
59 ver_type_tkl: buf[0],
60 code: buf[1],
61 message_id: u16::from_be_bytes(id_bytes),
62 })
63 }
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
68pub enum MessageClass {
69 Empty,
70 Request(RequestType),
71 Response(ResponseType),
72 Reserved(u8),
73}
74
75impl From<u8> for MessageClass {
76 fn from(number: u8) -> MessageClass {
77 match number {
78 0x00 => MessageClass::Empty,
79
80 0x01 => MessageClass::Request(RequestType::Get),
81 0x02 => MessageClass::Request(RequestType::Post),
82 0x03 => MessageClass::Request(RequestType::Put),
83 0x04 => MessageClass::Request(RequestType::Delete),
84 0x05 => MessageClass::Request(RequestType::Fetch),
85 0x06 => MessageClass::Request(RequestType::Patch),
86 0x07 => MessageClass::Request(RequestType::IPatch),
87
88 0x41 => MessageClass::Response(ResponseType::Created),
89 0x42 => MessageClass::Response(ResponseType::Deleted),
90 0x43 => MessageClass::Response(ResponseType::Valid),
91 0x44 => MessageClass::Response(ResponseType::Changed),
92 0x45 => MessageClass::Response(ResponseType::Content),
93 0x5F => MessageClass::Response(ResponseType::Continue),
94
95 0x80 => MessageClass::Response(ResponseType::BadRequest),
96 0x81 => MessageClass::Response(ResponseType::Unauthorized),
97 0x82 => MessageClass::Response(ResponseType::BadOption),
98 0x83 => MessageClass::Response(ResponseType::Forbidden),
99 0x84 => MessageClass::Response(ResponseType::NotFound),
100 0x85 => MessageClass::Response(ResponseType::MethodNotAllowed),
101 0x86 => MessageClass::Response(ResponseType::NotAcceptable),
102 0x89 => MessageClass::Response(ResponseType::Conflict),
103 0x8C => MessageClass::Response(ResponseType::PreconditionFailed),
104 0x8D => {
105 MessageClass::Response(ResponseType::RequestEntityTooLarge)
106 }
107 0x8F => {
108 MessageClass::Response(ResponseType::UnsupportedContentFormat)
109 }
110 0x88 => {
111 MessageClass::Response(ResponseType::RequestEntityIncomplete)
112 }
113 0x96 => MessageClass::Response(ResponseType::UnprocessableEntity),
114 0x9d => MessageClass::Response(ResponseType::TooManyRequests),
115
116 0xA0 => MessageClass::Response(ResponseType::InternalServerError),
117 0xA1 => MessageClass::Response(ResponseType::NotImplemented),
118 0xA2 => MessageClass::Response(ResponseType::BadGateway),
119 0xA3 => MessageClass::Response(ResponseType::ServiceUnavailable),
120 0xA4 => MessageClass::Response(ResponseType::GatewayTimeout),
121 0xA5 => MessageClass::Response(ResponseType::ProxyingNotSupported),
122 0xA8 => MessageClass::Response(ResponseType::HopLimitReached),
123
124 n => MessageClass::Reserved(n),
125 }
126 }
127}
128
129impl From<MessageClass> for u8 {
130 fn from(class: MessageClass) -> u8 {
131 match class {
132 MessageClass::Empty => 0x00,
133
134 MessageClass::Request(RequestType::Get) => 0x01,
135 MessageClass::Request(RequestType::Post) => 0x02,
136 MessageClass::Request(RequestType::Put) => 0x03,
137 MessageClass::Request(RequestType::Delete) => 0x04,
138 MessageClass::Request(RequestType::Fetch) => 0x05,
139 MessageClass::Request(RequestType::Patch) => 0x06,
140 MessageClass::Request(RequestType::IPatch) => 0x07,
141 MessageClass::Request(RequestType::UnKnown) => 0xFF,
142
143 MessageClass::Response(ResponseType::Created) => 0x41,
144 MessageClass::Response(ResponseType::Deleted) => 0x42,
145 MessageClass::Response(ResponseType::Valid) => 0x43,
146 MessageClass::Response(ResponseType::Changed) => 0x44,
147 MessageClass::Response(ResponseType::Content) => 0x45,
148 MessageClass::Response(ResponseType::Continue) => 0x5F,
149
150 MessageClass::Response(ResponseType::BadRequest) => 0x80,
151 MessageClass::Response(ResponseType::Unauthorized) => 0x81,
152 MessageClass::Response(ResponseType::BadOption) => 0x82,
153 MessageClass::Response(ResponseType::Forbidden) => 0x83,
154 MessageClass::Response(ResponseType::NotFound) => 0x84,
155 MessageClass::Response(ResponseType::MethodNotAllowed) => 0x85,
156 MessageClass::Response(ResponseType::NotAcceptable) => 0x86,
157 MessageClass::Response(ResponseType::Conflict) => 0x89,
158 MessageClass::Response(ResponseType::PreconditionFailed) => 0x8C,
159 MessageClass::Response(ResponseType::RequestEntityTooLarge) => {
160 0x8D
161 }
162 MessageClass::Response(ResponseType::UnsupportedContentFormat) => {
163 0x8F
164 }
165 MessageClass::Response(ResponseType::RequestEntityIncomplete) => {
166 0x88
167 }
168 MessageClass::Response(ResponseType::UnprocessableEntity) => 0x96,
169 MessageClass::Response(ResponseType::TooManyRequests) => 0x9d,
170
171 MessageClass::Response(ResponseType::InternalServerError) => 0xA0,
172 MessageClass::Response(ResponseType::NotImplemented) => 0xA1,
173 MessageClass::Response(ResponseType::BadGateway) => 0xA2,
174 MessageClass::Response(ResponseType::ServiceUnavailable) => 0xA3,
175 MessageClass::Response(ResponseType::GatewayTimeout) => 0xA4,
176 MessageClass::Response(ResponseType::ProxyingNotSupported) => 0xA5,
177 MessageClass::Response(ResponseType::HopLimitReached) => 0xA8,
178 MessageClass::Response(ResponseType::UnKnown) => 0xFF,
179
180 MessageClass::Reserved(c) => c,
181 }
182 }
183}
184
185impl fmt::Display for MessageClass {
186 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
187 let code: u8 = (*self).into();
188 let class_code = (0xE0 & code) >> 5;
189 let detail_code = 0x1F & code;
190 write!(f, "{}.{:02}", class_code, detail_code)
191 }
192}
193
194#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
196pub enum RequestType {
197 Get,
198 Post,
199 Put,
200 Delete,
201 Fetch,
202 Patch,
203 IPatch,
204 UnKnown,
205}
206
207#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
209pub enum ResponseType {
210 Created,
212 Deleted,
213 Valid,
214 Changed,
215 Content,
216 Continue,
217
218 BadRequest,
220 Unauthorized,
221 BadOption,
222 Forbidden,
223 NotFound,
224 MethodNotAllowed,
225 NotAcceptable,
226 Conflict,
227 PreconditionFailed,
228 RequestEntityTooLarge,
229 UnsupportedContentFormat,
230 RequestEntityIncomplete,
231 UnprocessableEntity,
232 TooManyRequests,
233
234 InternalServerError,
236 NotImplemented,
237 BadGateway,
238 ServiceUnavailable,
239 GatewayTimeout,
240 ProxyingNotSupported,
241 HopLimitReached,
242
243 UnKnown,
244}
245
246impl ResponseType {
247 pub fn is_error(&self) -> bool {
248 MessageClass::Response(*self)
249 >= MessageClass::Response(ResponseType::BadRequest)
250 }
251}
252
253#[derive(Debug, Clone, Copy, PartialEq)]
255pub enum MessageType {
256 Confirmable,
257 NonConfirmable,
258 Acknowledgement,
259 Reset,
260}
261
262#[derive(Debug, Clone, PartialEq)]
264pub struct Header {
265 ver_type_tkl: u8,
266 pub code: MessageClass,
267 pub message_id: u16,
268}
269
270impl Default for Header {
271 fn default() -> Header {
272 Header::from_raw(&HeaderRaw::default())
273 }
274}
275
276impl Header {
277 pub fn new() -> Header {
279 Default::default()
280 }
281
282 pub fn from_raw(raw: &HeaderRaw) -> Header {
284 Header {
285 ver_type_tkl: raw.ver_type_tkl,
286 code: raw.code.into(),
287 message_id: raw.message_id,
288 }
289 }
290
291 pub fn to_raw(&self) -> HeaderRaw {
293 HeaderRaw {
294 ver_type_tkl: self.ver_type_tkl,
295 code: self.code.into(),
296 message_id: self.message_id,
297 }
298 }
299
300 #[inline]
302 pub fn set_version(&mut self, v: u8) {
303 let type_tkl = 0x3F & self.ver_type_tkl;
304 self.ver_type_tkl = v << 6 | type_tkl;
305 }
306
307 #[inline]
309 pub fn get_version(&self) -> u8 {
310 self.ver_type_tkl >> 6
311 }
312
313 #[inline]
315 pub fn set_type(&mut self, t: MessageType) {
316 let tn = match t {
317 MessageType::Confirmable => 0,
318 MessageType::NonConfirmable => 1,
319 MessageType::Acknowledgement => 2,
320 MessageType::Reset => 3,
321 };
322
323 let ver_tkl = 0xCF & self.ver_type_tkl;
324 self.ver_type_tkl = tn << 4 | ver_tkl;
325 }
326
327 #[inline]
329 pub fn get_type(&self) -> MessageType {
330 let tn = (0x30 & self.ver_type_tkl) >> 4;
331 match tn {
332 0 => MessageType::Confirmable,
333 1 => MessageType::NonConfirmable,
334 2 => MessageType::Acknowledgement,
335 3 => MessageType::Reset,
336 _ => unreachable!(),
337 }
338 }
339
340 #[inline]
342 pub fn set_token_length(&mut self, tkl: u8) {
343 assert_eq!(0xF0 & tkl, 0);
344
345 let ver_type = 0xF0 & self.ver_type_tkl;
346 self.ver_type_tkl = tkl | ver_type;
347 }
348
349 #[inline]
351 pub fn get_token_length(&self) -> u8 {
352 0x0F & self.ver_type_tkl
353 }
354
355 pub fn set_code(&mut self, code: &str) {
357 let code_vec: Vec<&str> = code.split('.').collect();
358 assert_eq!(code_vec.len(), 2);
359
360 let class_code = code_vec[0].parse::<u8>().unwrap();
361 let detail_code = code_vec[1].parse::<u8>().unwrap();
362 assert_eq!(0xF8 & class_code, 0);
363 assert_eq!(0xE0 & detail_code, 0);
364
365 self.code = (class_code << 5 | detail_code).into();
366 }
367
368 pub fn get_code(&self) -> String {
370 self.code.to_string()
371 }
372}
373
374#[cfg(test)]
375mod test {
376 use super::*;
377
378 #[test]
379 fn test_header_codes() {
380 for code in 0..255 {
381 let class: MessageClass = code.into();
382 let code_str = class.to_string();
383
384 let mut header = Header::new();
385 header.set_code(&code_str);
386
387 if !matches!(class, MessageClass::Reserved(_)) {
390 assert_eq!(u8::from(class), code);
391 assert_eq!(class, header.code);
392 assert_eq!(code_str, header.get_code());
393 }
394 }
395 }
396
397 #[test]
398 fn serialize_raw_fail() {
399 let h = HeaderRaw::default();
400 let mut buf = Vec::with_capacity(3);
401 assert_eq!(
402 MessageError::InvalidPacketLength,
403 h.serialize_into(&mut buf).unwrap_err()
404 );
405 }
406
407 #[test]
408 fn from_bytes_fail() {
409 let b: &[u8] = &[1, 2, 3];
410 assert_eq!(
411 MessageError::InvalidPacketLength,
412 HeaderRaw::try_from(b).unwrap_err()
413 );
414 }
415
416 #[test]
417 fn types() {
418 let mut h = Header::new();
419 h.set_type(MessageType::Acknowledgement);
420 assert_eq!(MessageType::Acknowledgement, h.get_type());
421 h.set_type(MessageType::Confirmable);
422 assert_eq!(MessageType::Confirmable, h.get_type());
423 h.set_type(MessageType::NonConfirmable);
424 assert_eq!(MessageType::NonConfirmable, h.get_type());
425 h.set_type(MessageType::Reset);
426 assert_eq!(MessageType::Reset, h.get_type());
427 }
428
429 #[test]
430 fn is_error() {
431 assert!(!ResponseType::Created.is_error());
432 assert!(!ResponseType::Continue.is_error());
433 assert!(ResponseType::BadRequest.is_error());
434 assert!(ResponseType::TooManyRequests.is_error());
435 assert!(ResponseType::HopLimitReached.is_error());
436 }
437}