embedded_mqtt/variable_header/
connack.rs1use core::{
2 fmt::Debug,
3 convert::{TryFrom, TryInto},
4 result::Result,
5};
6
7use crate::{
8 fixed_header::PacketFlags,
9 codec::{self, Encodable},
10 status::Status,
11 error::{DecodeError, EncodeError},
12};
13
14use super::HeaderDecode;
15
16#[derive(PartialEq, Clone, Copy)]
17pub struct Flags(u8);
18
19bitfield_bitrange! {
20 struct Flags(u8)
21}
22
23impl Flags {
24 bitfield_fields! {
25 bool;
26 pub session_present, _ : 1;
27 }
28}
29
30impl Debug for Flags {
31 bitfield_debug! {
32 struct Flags;
33 pub session_present, _ : 1;
34 }
35}
36
37impl TryFrom<u8> for Flags {
38 type Error = ();
39 fn try_from(from: u8) -> Result<Flags, ()> {
40 if 0b11111110 & from != 0 {
41 Err(())
42 } else {
43 Ok(Flags(from))
44 }
45 }
46}
47
48impl Encodable for Flags {
49 fn encoded_len(&self) -> usize {
50 1
51 }
52
53 fn encode(&self, bytes: &mut [u8]) -> Result<usize, EncodeError> {
54 if bytes.len() < 1 {
55 return Err(EncodeError::OutOfSpace)
56 }
57
58 bytes[0] = self.0;
59
60 Ok(1)
61 }
62}
63
64#[derive(PartialEq, Eq, Debug, Clone, Copy)]
65pub enum ReturnCode {
66 Accepted,
67 RefusedProtocolVersion,
68 RefusedClientIdentifier,
69 RefusedServerUnavailable,
70 RefusedUsernameOrPassword,
71 RefusedNotAuthorized,
72}
73
74impl TryFrom<u8> for ReturnCode {
75 type Error = ();
76 fn try_from(from: u8) -> Result<ReturnCode, ()> {
77 Ok(match from {
78 0 => ReturnCode::Accepted,
79 1 => ReturnCode::RefusedProtocolVersion,
80 2 => ReturnCode::RefusedClientIdentifier,
81 3 => ReturnCode::RefusedServerUnavailable,
82 4 => ReturnCode::RefusedUsernameOrPassword,
83 5 => ReturnCode::RefusedNotAuthorized,
84 _ => return Err(()),
85 })
86 }
87}
88
89impl Encodable for ReturnCode {
90 fn encoded_len(&self) -> usize {
91 1
92 }
93
94 fn encode(&self, bytes: &mut [u8]) -> Result<usize, EncodeError> {
95 if bytes.len() < 1 {
96 return Err(EncodeError::OutOfSpace)
97 }
98
99 let val = match self {
100 &ReturnCode::Accepted => 0,
101 &ReturnCode::RefusedProtocolVersion => 1,
102 &ReturnCode::RefusedClientIdentifier => 2,
103 &ReturnCode::RefusedServerUnavailable => 3,
104 &ReturnCode::RefusedUsernameOrPassword => 4,
105 &ReturnCode::RefusedNotAuthorized => 5,
106 };
107
108 bytes[0] = val;
109
110 Ok(1)
111 }
112}
113
114#[derive(PartialEq, Debug)]
116pub struct Connack {
117 flags: Flags,
118 return_code: ReturnCode,
119}
120
121impl Connack {
122 pub fn flags(&self) -> Flags {
123 self.flags
124 }
125
126 pub fn return_code(&self) -> ReturnCode {
127 self.return_code
128 }
129}
130
131impl<'buf> HeaderDecode<'buf> for Connack {
132 fn decode(_flags: PacketFlags, bytes: &[u8]) -> Result<Status<(usize, Self)>, DecodeError> {
133 if bytes.len() < 2 {
134 return Ok(Status::Partial(2 - bytes.len()));
135 }
136
137 let offset = 0;
138
139 let (offset, flags) = read!(codec::values::parse_u8, bytes, offset);
141 let flags = flags.try_into().map_err(|_| DecodeError::InvalidConnackFlag)?;
142
143 let (offset, return_code) = read!(codec::values::parse_u8, bytes, offset);
145 let return_code = return_code.try_into().map_err(|_| DecodeError::InvalidConnackReturnCode)?;
146
147 Ok(Status::Complete((offset, Connack {
148 flags,
149 return_code,
150 })))
151 }
152}
153
154impl Encodable for Connack {
155 fn encoded_len(&self) -> usize {
156 2
157 }
158
159 fn encode(&self, bytes: &mut [u8]) -> Result<usize, EncodeError> {
160 self.flags.encode(&mut bytes[0..])?;
161 self.return_code.encode(&mut bytes[1..])?;
162 Ok(2)
163 }
164}
165
166#[cfg(test)]
167mod tests {
168
169}