mqute_codec/protocol/v4/
connack.rs1use crate::codec::util::decode_byte;
8use crate::codec::{Decode, Encode, RawPacket};
9use crate::protocol::{FixedHeader, PacketType};
10use crate::Error;
11use bit_field::BitField;
12use bytes::{BufMut, BytesMut};
13
14#[derive(Debug, Copy, Clone, PartialEq, Eq)]
19#[repr(u8)]
20pub enum ConnectReturnCode {
21 Success = 0,
23
24 UnacceptableProtocolVersion,
26
27 IdentifierRejected,
29
30 ServerUnavailable,
32
33 BadAuthData,
35
36 NotAuthorized,
38}
39
40impl TryFrom<u8> for ConnectReturnCode {
41 type Error = Error;
42
43 fn try_from(value: u8) -> Result<Self, Self::Error> {
45 let code = match value {
46 0 => ConnectReturnCode::Success,
47 1 => ConnectReturnCode::UnacceptableProtocolVersion,
48 2 => ConnectReturnCode::IdentifierRejected,
49 3 => ConnectReturnCode::ServerUnavailable,
50 4 => ConnectReturnCode::BadAuthData,
51 5 => ConnectReturnCode::NotAuthorized,
52 _ => return Err(Error::InvalidConnectReturnCode(value)),
53 };
54
55 Ok(code)
56 }
57}
58
59impl From<ConnectReturnCode> for u8 {
60 fn from(value: ConnectReturnCode) -> Self {
62 value as u8
63 }
64}
65
66#[derive(Debug, Copy, Clone, PartialEq, Eq)]
77pub struct ConnAck {
78 code: ConnectReturnCode,
79 session_present: bool,
80}
81
82impl ConnAck {
83 pub fn new(code: ConnectReturnCode, session_present: bool) -> Self {
85 ConnAck {
86 code,
87 session_present,
88 }
89 }
90
91 pub fn code(&self) -> ConnectReturnCode {
93 self.code
94 }
95
96 pub fn session_present(&self) -> bool {
98 self.session_present
99 }
100}
101
102impl Decode for ConnAck {
103 fn decode(mut packet: RawPacket) -> Result<Self, Error> {
105 if packet.header.packet_type() != PacketType::ConnAck || !packet.header.flags().is_default()
106 {
107 return Err(Error::MalformedPacket);
108 }
109
110 let conn_ack_flag = decode_byte(&mut packet.payload)?;
111 let ret_code = decode_byte(&mut packet.payload)?;
112 let code = ret_code.try_into()?;
113 let session_present = conn_ack_flag.get_bit(0);
114
115 Ok(ConnAck {
116 code,
117 session_present,
118 })
119 }
120}
121
122impl Encode for ConnAck {
123 fn encode(&self, buf: &mut BytesMut) -> Result<(), Error> {
125 let header = FixedHeader::new(PacketType::ConnAck, self.payload_len());
126 header.encode(buf)?;
127
128 let mut flags = 0u8;
129 flags.set_bit(0, self.session_present);
130
131 buf.put_u8(flags);
133
134 buf.put_u8(self.code.into());
136 Ok(())
137 }
138
139 fn payload_len(&self) -> usize {
141 2
142 }
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148 use crate::codec::PacketCodec;
149 use bytes::BytesMut;
150 use tokio_util::codec::Decoder;
151
152 #[test]
153 fn connack_decode() {
154 let mut codec = PacketCodec::new(None, None);
155
156 let data = &[
157 (PacketType::ConnAck as u8) << 4, 0x02, 0x01, 0x00, ];
162
163 let mut stream = BytesMut::new();
164
165 stream.extend_from_slice(&data[..]);
166
167 let raw_packet = codec.decode(&mut stream).unwrap().unwrap();
168 let packet = ConnAck::decode(raw_packet).unwrap();
169
170 assert_eq!(packet, ConnAck::new(ConnectReturnCode::Success, true));
171 }
172
173 #[test]
174 fn connack_encode() {
175 let packet = ConnAck::new(ConnectReturnCode::Success, true);
176
177 let mut stream = BytesMut::new();
178 packet.encode(&mut stream).unwrap();
179 assert_eq!(
180 stream,
181 vec![(PacketType::ConnAck as u8) << 4, 0x02, 0x01, 0x00]
182 );
183 }
184}