1use bytes::Bytes;
2use bytestring::ByteString;
3
4use crate::proto::{Protocol, QoS};
5
6#[repr(u8)]
7#[derive(Debug, Eq, PartialEq, Copy, Clone)]
8pub enum ConnectCode {
10 ConnectionAccepted = 0,
12 UnacceptableProtocolVersion = 1,
14 IdentifierRejected = 2,
16 ServiceUnavailable = 3,
18 BadUserNameOrPassword = 4,
20 NotAuthorized = 5,
22 Reserved = 6,
24}
25
26const_enum!(ConnectCode: u8);
27
28impl ConnectCode {
29 pub fn reason(self) -> &'static str {
30 match self {
31 ConnectCode::ConnectionAccepted => "Connection Accepted",
32 ConnectCode::UnacceptableProtocolVersion => {
33 "Connection Refused, unacceptable protocol version"
34 }
35 ConnectCode::IdentifierRejected => "Connection Refused, identifier rejected",
36 ConnectCode::ServiceUnavailable => "Connection Refused, Server unavailable",
37 ConnectCode::BadUserNameOrPassword => {
38 "Connection Refused, bad user name or password"
39 }
40 ConnectCode::NotAuthorized => "Connection Refused, not authorized",
41 _ => "Connection Refused",
42 }
43 }
44}
45
46#[derive(Debug, PartialEq, Clone)]
47pub struct LastWill {
49 pub qos: QoS,
51 pub retain: bool,
53 pub topic: ByteString,
55 pub message: Bytes,
57}
58
59#[derive(Debug, PartialEq, Clone)]
60pub struct Connect {
62 pub protocol: Protocol,
64 pub clean_session: bool,
66 pub keep_alive: u16,
68 pub last_will: Option<LastWill>,
70 pub client_id: ByteString,
72 pub username: Option<ByteString>,
74 pub password: Option<Bytes>,
76}
77
78#[derive(Debug, PartialEq, Clone)]
79pub struct Publish {
81 pub dup: bool,
83 pub retain: bool,
84 pub qos: QoS,
86 pub topic: ByteString,
88 pub packet_id: Option<u16>,
90 pub payload: Bytes,
92}
93
94#[derive(Debug, PartialEq, Copy, Clone)]
95pub enum SubscribeReturnCode {
97 Success(QoS),
98 Failure,
99}
100
101#[derive(Debug, PartialEq, Clone)]
102pub enum Packet {
104 Connect(Connect),
106
107 ConnectAck {
109 session_present: bool,
112 return_code: ConnectCode,
113 },
114
115 Publish(Publish),
117
118 PublishAck {
120 packet_id: u16,
122 },
123 PublishReceived {
125 packet_id: u16,
127 },
128 PublishRelease {
130 packet_id: u16,
132 },
133 PublishComplete {
135 packet_id: u16,
137 },
138
139 Subscribe {
141 packet_id: u16,
143 topic_filters: Vec<(ByteString, QoS)>,
145 },
146 SubscribeAck {
148 packet_id: u16,
149 status: Vec<SubscribeReturnCode>,
151 },
152
153 Unsubscribe {
155 packet_id: u16,
157 topic_filters: Vec<ByteString>,
159 },
160 UnsubscribeAck {
162 packet_id: u16,
164 },
165
166 PingRequest,
168 PingResponse,
170
171 Disconnect,
173}
174
175impl Packet {
176 #[inline]
177 pub fn packet_type(&self) -> u8 {
179 match *self {
180 Packet::Connect { .. } => CONNECT,
181 Packet::ConnectAck { .. } => CONNACK,
182 Packet::Publish { .. } => PUBLISH,
183 Packet::PublishAck { .. } => PUBACK,
184 Packet::PublishReceived { .. } => PUBREC,
185 Packet::PublishRelease { .. } => PUBREL,
186 Packet::PublishComplete { .. } => PUBCOMP,
187 Packet::Subscribe { .. } => SUBSCRIBE,
188 Packet::SubscribeAck { .. } => SUBACK,
189 Packet::Unsubscribe { .. } => UNSUBSCRIBE,
190 Packet::UnsubscribeAck { .. } => UNSUBACK,
191 Packet::PingRequest => PINGREQ,
192 Packet::PingResponse => PINGRESP,
193 Packet::Disconnect => DISCONNECT,
194 }
195 }
196
197 pub fn packet_flags(&self) -> u8 {
199 match *self {
200 Packet::Publish(Publish {
201 dup, qos, retain, ..
202 }) => {
203 let mut b = qos.into();
204
205 b <<= 1;
206
207 if dup {
208 b |= 0b1000;
209 }
210
211 if retain {
212 b |= 0b0001;
213 }
214
215 b
216 }
217 Packet::PublishRelease { .. }
218 | Packet::Subscribe { .. }
219 | Packet::Unsubscribe { .. } => 0b0010,
220 _ => 0,
221 }
222 }
223}
224
225impl From<Connect> for Packet {
226 fn from(val: Connect) -> Packet {
227 Packet::Connect(val)
228 }
229}
230
231impl From<Publish> for Packet {
232 fn from(val: Publish) -> Packet {
233 Packet::Publish(val)
234 }
235}
236
237pub const CONNECT: u8 = 1;
238pub const CONNACK: u8 = 2;
239pub const PUBLISH: u8 = 3;
240pub const PUBACK: u8 = 4;
241pub const PUBREC: u8 = 5;
242pub const PUBREL: u8 = 6;
243pub const PUBCOMP: u8 = 7;
244pub const SUBSCRIBE: u8 = 8;
245pub const SUBACK: u8 = 9;
246pub const UNSUBSCRIBE: u8 = 10;
247pub const UNSUBACK: u8 = 11;
248pub const PINGREQ: u8 = 12;
249pub const PINGRESP: u8 = 13;
250pub const DISCONNECT: u8 = 14;