walle_mqtt_protocol/v4/
conn_ack.rs1use bytes::{Buf, BufMut, Bytes, BytesMut};
2
3use crate::error::ProtoError;
4use crate::QoS;
5
6use super::{
7 decoder,
8 fixed_header::{FixedHeader, FixedHeaderBuilder},
9 Decoder, Encoder, VariableDecoder,
10};
11
12#[derive(Debug, PartialOrd, Clone, PartialEq)]
23pub struct ConnAck {
24 fixed_header: FixedHeader,
25 variable_header: ConnAckVariableHeader,
26}
27
28impl ConnAck {
29 pub fn new(conn_ack_type: ConnAckType) -> Result<ConnAck, ProtoError> {
30 let fixed_header = FixedHeaderBuilder::new().conn_ack().build();
31 match fixed_header {
32 Ok(f_header) => Ok(Self {
33 fixed_header: f_header,
34 variable_header: ConnAckVariableHeader::new(conn_ack_type),
35 }),
36 Err(e) => Err(e),
37 }
38 }
39 pub fn conn_ack_type(&self) -> ConnAckType {
41 self.variable_header.conn_ack_type.clone()
42 }
43}
44
45#[derive(PartialOrd, Debug, Clone, PartialEq)]
46pub enum ConnAckType {
47 Success,
49 ProtoVersionError,
51 IdentifierRejected,
53 ServiceUnavailable,
55 BadUsernameOrPassword,
57 NotAuthentication,
59}
60impl Encoder for ConnAck {
64 fn encode(&self, buffer: &mut BytesMut) -> Result<usize, ProtoError> {
65 let count = self.fixed_header.encode(buffer);
66 match count {
67 Ok(count) => {
68 if let Ok(v) = self.variable_header.encode(buffer) {
69 return Ok(count + v);
70 }
71 Err(ProtoError::EncodeVariableHeaderError)
72 }
73 Err(e) => Err(e),
74 }
75 }
76}
77impl Decoder for ConnAck {
81 type Item = ConnAck;
82 type Error = ProtoError;
83 fn decode(mut bytes: Bytes) -> Result<Self::Item, ProtoError> {
84 let resp = decoder::read_fixed_header(&mut bytes);
85 match resp {
86 Ok(fixed_header) => {
87 let qos = fixed_header.qos();
88 let variable_header_index = fixed_header.len();
89 bytes.advance(variable_header_index);
90 let resp = ConnAckVariableHeader::decode(&mut bytes, qos);
92 match resp {
93 Ok(variable_header) => Ok(ConnAck {
94 fixed_header,
95 variable_header,
96 }),
97 Err(e) => return Err(e),
98 }
99 }
100 Err(e) => Err(e),
101 }
102 }
103}
104
105#[derive(Debug, PartialOrd, Clone, PartialEq)]
106pub struct ConnAckVariableHeader {
107 session_present: bool,
108 conn_ack_type: ConnAckType,
109}
110
111impl ConnAckVariableHeader {
112 pub fn new(conn_ack_type: ConnAckType) -> Self {
113 Self {
114 session_present: false,
115 conn_ack_type,
116 }
117 }
118}
119
120impl Encoder for ConnAckVariableHeader {
124 fn encode(&self, buffer: &mut BytesMut) -> Result<usize, ProtoError> {
125 buffer.put_u8(0b0000_0000);
126 match &self.conn_ack_type {
127 ConnAckType::Success => {
128 buffer.put_u8(0b0000_0000);
129 Ok(2)
130 }
131 ConnAckType::ProtoVersionError => {
132 buffer.put_u8(0b0000_0001);
133 Ok(2)
134 }
135 ConnAckType::IdentifierRejected => {
136 buffer.put_u8(0b0000_0010);
137 Ok(2)
138 }
139 ConnAckType::ServiceUnavailable => {
140 buffer.put_u8(0b0000_0011);
141 Ok(2)
142 }
143 ConnAckType::BadUsernameOrPassword => {
144 buffer.put_u8(0b0000_0100);
145 Ok(2)
146 }
147 ConnAckType::NotAuthentication => {
148 buffer.put_u8(0b0000_0101);
149 Ok(2)
150 }
151 }
152 }
153}
154
155impl VariableDecoder for ConnAckVariableHeader {
159 type Item = ConnAckVariableHeader;
160
161 fn decode(bytes: &mut Bytes, _qos: Option<QoS>) -> Result<Self::Item, ProtoError> {
162 let b1 = bytes.get_u8();
163 if b1 == 0 {
164 let b2 = bytes.get_u8();
165 let con_ack_type = match b2 {
166 0b0000_0000 => ConnAckType::Success,
167 0b0000_0001 => ConnAckType::ProtoVersionError,
168 0b0000_0010 => ConnAckType::IdentifierRejected,
169 0b0000_0011 => ConnAckType::ServiceUnavailable,
170 0b0000_0100 => ConnAckType::BadUsernameOrPassword,
171 0b0000_0101 => ConnAckType::NotAuthentication,
172 _ => {
173 return Err(ProtoError::NotKnow);
174 }
175 };
176 Ok(ConnAckVariableHeader::new(con_ack_type))
177 } else {
178 Err(ProtoError::NotKnow)
179 }
180 }
181}
182
183#[cfg(test)]
184mod tests {
185 use bytes::BytesMut;
186
187 use crate::v4::{builder::MqttMessageBuilder, Decoder, Encoder};
188
189 use super::ConnAck;
190
191 #[test]
192 fn encode_and_decode_for_connack_should_be_work() {
193 let resp = MqttMessageBuilder::conn_ack()
194 .conn_ack_type(super::ConnAckType::NotAuthentication)
195 .build();
196 println!("conn_ack: {:?}", resp);
197 let mut buffer = BytesMut::new();
198 let _count = resp.encode(&mut buffer);
199 let conn_ack = ConnAck::decode(buffer.freeze()).unwrap();
200 println!("conn_ack: {:?}", conn_ack);
201 }
202}