kwap_msg/code.rs
1use kwap_macros::rfc_7252_doc;
2#[cfg(feature = "alloc")]
3use std_alloc::string::{String, ToString};
4
5#[doc = rfc_7252_doc!("12.1")]
6/// <details><summary><b>RFC7252 Section 12.1.1 Method Codes</b></summary>
7#[doc = concat!("\n#", rfc_7252_doc!("12.1.1"))]
8/// </details>
9/// <details><summary><b>RFC7252 Section 12.1.2 Response Codes</b></summary>
10#[doc = concat!("\n#", rfc_7252_doc!("12.1.2"))]
11/// </details>
12///
13/// # Examples
14/// ```
15/// use kwap_msg::Code;
16///
17/// assert_eq!(Code { class: 2,
18/// detail: 5 }.to_string(),
19/// "2.05".to_string());
20/// ```
21#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
22pub struct Code {
23 /// The "class" of message codes identify it as a request or response, and provides the class of response status:
24 ///
25 /// |class|meaning|
26 /// |---|---|
27 /// |`0`|Message is a request|
28 /// |`2`|Message is a success response|
29 /// |`4`|Message is a client error response|
30 /// |`5`|Message is a server error response|
31 pub class: u8,
32
33 /// 2-digit integer (range `[0, 32)`) that provides granular information about the response status.
34 ///
35 /// Will always be `0` for requests.
36 pub detail: u8,
37}
38
39/// Whether a code is for a request, response, or empty message
40#[derive(Clone, Copy, Debug, PartialEq, Eq)]
41pub enum CodeKind {
42 /// A request code (0.xx)
43 Request,
44 /// A response code ([2-5].xx)
45 Response,
46 /// EMPTY (0.00)
47 Empty,
48}
49
50impl Code {
51 /// Create a new Code
52 ///
53 /// ```
54 /// use kwap_msg::Code;
55 ///
56 /// let content = Code::new(2, 05);
57 /// ```
58 pub const fn new(class: u8, detail: u8) -> Self {
59 Self { class, detail }
60 }
61
62 /// Get the human string representation of a message code
63 ///
64 /// # Returns
65 /// A `char` array
66 ///
67 /// This is to avoid unnecessary heap allocation,
68 /// you can create a `String` with `FromIterator::<String>::from_iter`,
69 /// or if the `alloc` feature of `kwap` is enabled there is a `ToString` implementation provided for Code.
70 /// ```
71 /// use kwap_msg::Code;
72 ///
73 /// let code = Code { class: 2,
74 /// detail: 5 };
75 /// let chars = code.to_human();
76 /// let string = String::from_iter(chars);
77 /// assert_eq!(string, "2.05".to_string());
78 /// ```
79 pub fn to_human(&self) -> [char; 4] {
80 let to_char = |d: u8| char::from_digit(d.into(), 10).unwrap();
81 [to_char(self.class),
82 '.',
83 to_char(self.detail / 10),
84 to_char(self.detail % 10)]
85 }
86
87 /// Get whether this code is for a request, response, or empty message
88 ///
89 /// ```
90 /// use kwap_msg::{Code, CodeKind};
91 ///
92 /// let empty: Code = Code::new(0, 0);
93 /// assert_eq!(empty.kind(), CodeKind::Empty);
94 ///
95 /// let req = Code::new(1, 1); // GET
96 /// assert_eq!(req.kind(), CodeKind::Request);
97 ///
98 /// let resp = Code::new(2, 5); // OK CONTENT
99 /// assert_eq!(resp.kind(), CodeKind::Response);
100 /// ```
101 pub fn kind(&self) -> CodeKind {
102 match self.class {
103 | 0 => CodeKind::Empty,
104 | 1 => CodeKind::Request,
105 | _ => CodeKind::Response,
106 }
107 }
108}
109
110#[cfg(feature = "alloc")]
111#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
112impl ToString for Code {
113 fn to_string(&self) -> String {
114 String::from_iter(self.to_human())
115 }
116}
117
118impl From<u8> for Code {
119 fn from(b: u8) -> Self {
120 let class = b >> 5;
121 let detail = b & 0b0011111;
122
123 Code { class, detail }
124 }
125}
126
127impl From<Code> for u8 {
128 fn from(code: Code) -> u8 {
129 let class = code.class << 5;
130 let detail = code.detail;
131
132 class | detail
133 }
134}
135
136#[cfg(test)]
137mod tests {
138 use super::*;
139 use crate::assert_eqb;
140
141 #[test]
142 fn parse_code() {
143 let byte = 0b0100_0101_u8;
144 let code = Code::from(byte);
145 assert_eq!(code,
146 Code { class: 2,
147 detail: 5 })
148 }
149
150 #[test]
151 fn serialize_code() {
152 let code = Code { class: 2,
153 detail: 5 };
154 let actual: u8 = code.into();
155 let expected = 0b0100_0101_u8;
156 assert_eqb!(actual, expected)
157 }
158}