mqtt_packet_3_5/structure/
codes.rs

1use super::common::*;
2#[cfg(feature = "serde_support")]
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, PartialEq, Clone)]
6#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
7pub struct ReasonCode {}
8
9pub trait MqttCode<T> {
10    fn from_byte(byte: u8) -> Res<T>;
11    fn to_byte(&self) -> u8;
12}
13
14#[derive(Debug, PartialEq, Clone)]
15#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
16/// Use an enum to make setting the reason code easier and safer
17pub enum SubscriptionReasonCode {
18    /// 0x00  The subscription is accepted and the maximum QoS sent will be QoS 0. This might be a lower QoS than was requested.
19    GrantedQoS0,
20    /// 0x01  The subscription is accepted and the maximum QoS sent will be QoS 1. This might be a lower QoS than was requested.
21    GrantedQoS1,
22    /// 0x02  The subscription is accepted and any received QoS will be sent to this subscription.
23    GrantedQoS2,
24    /// 0x80 The subscription is not accepted and the Server either does not wish to reveal the reason or none of the other Reason Codes apply.
25    UnspecifiedError,
26    /// 0x83 The SUBSCRIBE is valid but the Server does not accept it.
27    ImplementationSpecificError,
28    /// 0x87  The Client is not authorized to make this subscription.
29    NotAuthorized,
30    /// 0x8F The Topic Filter is correctly formed but is not allowed for this Client.
31    TopicFilterInvalid,
32    /// 0x91 The specified Packet Identifier is already in use.
33    PacketIdentifierInUse,
34    /// 0x97  An implementation or administrative imposed limit has been exceeded.
35    QuotaExceeded,
36    /// 0x9E The Server does not support Shared Subscriptions for this Client.
37    SharedSubscriptionsNotSupported,
38    /// 0xA1 The Server does not support Subscription Identifiers; the subscription is not accepted.
39    SubscriptionIdentifiersNotSupported,
40    /// 0xA2 The Server does not support Wildcard Subscriptions; the subscription is not accepted.
41    WildcardSubscriptionsNotSupported,
42}
43
44impl MqttCode<SubscriptionReasonCode> for SubscriptionReasonCode {
45    fn from_byte(byte: u8) -> Res<SubscriptionReasonCode> {
46        match byte {
47            0x00 => Ok(SubscriptionReasonCode::GrantedQoS0),
48            0x01 => Ok(SubscriptionReasonCode::GrantedQoS1),
49            0x02 => Ok(SubscriptionReasonCode::GrantedQoS2),
50            0x80 => Ok(SubscriptionReasonCode::UnspecifiedError),
51            0x83 => Ok(SubscriptionReasonCode::ImplementationSpecificError),
52            0x87 => Ok(SubscriptionReasonCode::NotAuthorized),
53            0x8F => Ok(SubscriptionReasonCode::TopicFilterInvalid),
54            0x91 => Ok(SubscriptionReasonCode::PacketIdentifierInUse),
55            0x97 => Ok(SubscriptionReasonCode::QuotaExceeded),
56            0x9E => Ok(SubscriptionReasonCode::SharedSubscriptionsNotSupported),
57            0xA1 => Ok(SubscriptionReasonCode::SubscriptionIdentifiersNotSupported),
58            0xA2 => Ok(SubscriptionReasonCode::WildcardSubscriptionsNotSupported),
59            // fallback to unspecified error to keep function signature simple
60            _ => Err(format!("Invalid suback code {}", byte)),
61        }
62    }
63
64    fn to_byte(&self) -> u8 {
65        match self {
66            SubscriptionReasonCode::GrantedQoS0 => 0x00,
67            SubscriptionReasonCode::GrantedQoS1 => 0x01,
68            SubscriptionReasonCode::GrantedQoS2 => 0x02,
69            SubscriptionReasonCode::UnspecifiedError => 0x80,
70            SubscriptionReasonCode::ImplementationSpecificError => 0x83,
71            SubscriptionReasonCode::NotAuthorized => 0x87,
72            SubscriptionReasonCode::TopicFilterInvalid => 0x8F,
73            SubscriptionReasonCode::PacketIdentifierInUse => 0x91,
74            SubscriptionReasonCode::QuotaExceeded => 0x97,
75            SubscriptionReasonCode::SharedSubscriptionsNotSupported => 0x9E,
76            SubscriptionReasonCode::SubscriptionIdentifiersNotSupported => 0xA1,
77            SubscriptionReasonCode::WildcardSubscriptionsNotSupported => 0xA2,
78        }
79    }
80}
81
82#[derive(Debug, PartialEq, Clone)]
83#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
84pub enum DisconnectCode {
85    NormalDisconnection,                 //0x00
86    DisconnectWithWillMessage,           //0x04
87    UnspecifiedError,                    //0x80
88    MalformedPacket,                     //0x81
89    ProtocolError,                       //0x82
90    ImplementationSpecificError,         //0x83
91    NotAuthorized,                       //0x87
92    ServerBusy,                          //0x89
93    ServerShuttingDown,                  //0x8B
94    KeepAliveTimeout,                    //0x8D
95    SessionTakenVver,                    //0x8E
96    TopicFilterInvalid,                  //0x8F
97    TopicNameInvalid,                    //0x90
98    ReceiveMaximumExceeded,              //0x93
99    TopicAliasInvalid,                   //0x94
100    PacketTooLarge,                      //0x95
101    MessageRateTooHigh,                  //0x96
102    QuotaExceeded,                       //0x97
103    AdministrativeAction,                //0x98
104    PayloadFormatInvalid,                //0x99
105    RetainNotSupported,                  //0x9A
106    QoSNotSupported,                     //0x9B
107    UseAnotherServer,                    //0x9C
108    ServerMoved,                         //0x9D
109    SharedSubscriptionsNotSupported,     //0x9E
110    ConnectionRateExceeded,              //0x9F
111    MaximumConnectTime,                  //0xA0
112    SubscriptionIdentifiersNotSupported, //0xA1
113    WildcardSubscriptionsNotSupported,   //0xA2
114}
115
116impl MqttCode<DisconnectCode> for DisconnectCode {
117    fn from_byte(code: u8) -> Res<DisconnectCode> {
118        Ok(match code {
119            0x00 => DisconnectCode::NormalDisconnection, // 'Normal disconnection',
120            0x04 => DisconnectCode::DisconnectWithWillMessage, // 'Disconnect with Will Message',
121            0x80 => DisconnectCode::UnspecifiedError,    // 'Unspecified error',
122            0x81 => DisconnectCode::MalformedPacket,     // 'Malformed Packet',
123            0x82 => DisconnectCode::ProtocolError,       // 'Protocol Error',
124            0x83 => DisconnectCode::ImplementationSpecificError, // 'Implementation specific error',
125            0x87 => DisconnectCode::NotAuthorized,       // 'Not authorized',
126            0x89 => DisconnectCode::ServerBusy,          // 'Server busy',
127            0x8B => DisconnectCode::ServerShuttingDown,  // 'Server shutting down',
128            0x8D => DisconnectCode::KeepAliveTimeout,    // 'Keep Alive timeout',
129            0x8E => DisconnectCode::SessionTakenVver,    // 'Session taken over',
130            0x8F => DisconnectCode::TopicFilterInvalid,  // 'Topic Filter invalid',
131            0x90 => DisconnectCode::TopicNameInvalid,    // 'Topic Name invalid',
132            0x93 => DisconnectCode::ReceiveMaximumExceeded, // 'Receive Maximum exceeded',
133            0x94 => DisconnectCode::TopicAliasInvalid,   // 'Topic Alias invalid',
134            0x95 => DisconnectCode::PacketTooLarge,      // 'Packet too large',
135            0x96 => DisconnectCode::MessageRateTooHigh,  // 'Message rate too high',
136            0x97 => DisconnectCode::QuotaExceeded,       // 'Quota exceeded',
137            0x98 => DisconnectCode::AdministrativeAction, // 'Administrative action',
138            0x99 => DisconnectCode::PayloadFormatInvalid, // 'Payload format invalid',
139            0x9A => DisconnectCode::RetainNotSupported,  // 'Retain not supported',
140            0x9B => DisconnectCode::QoSNotSupported,     // 'QoS not supported',
141            0x9C => DisconnectCode::UseAnotherServer,    // 'Use another server',
142            0x9D => DisconnectCode::ServerMoved,         // 'Server moved',
143            0x9E => DisconnectCode::SharedSubscriptionsNotSupported, // 'Shared Subscriptions not supported',
144            0x9F => DisconnectCode::ConnectionRateExceeded,          // 'Connection rate exceeded',
145            0xA0 => DisconnectCode::MaximumConnectTime,              // 'Maximum connect time',
146            0xA1 => DisconnectCode::SubscriptionIdentifiersNotSupported, // 'Subscription Identifiers not supported',
147            0xA2 => DisconnectCode::WildcardSubscriptionsNotSupported, // 'Wildcard Subscriptions not supported'
148            _ => return Err(format!("Invalid disconnect code {}", code)),
149        })
150    }
151
152    fn to_byte(&self) -> u8 {
153        match self {
154            DisconnectCode::NormalDisconnection => 0x00, // 'Normal disconnection',
155            DisconnectCode::DisconnectWithWillMessage => 0x04, // 'Disconnect with Will Message',
156            DisconnectCode::UnspecifiedError => 0x80,    // 'Unspecified error',
157            DisconnectCode::MalformedPacket => 0x81,     // 'Malformed Packet',
158            DisconnectCode::ProtocolError => 0x82,       // 'Protocol Error',
159            DisconnectCode::ImplementationSpecificError => 0x83, // 'Implementation specific error',
160            DisconnectCode::NotAuthorized => 0x87,       // 'Not authorized',
161            DisconnectCode::ServerBusy => 0x89,          // 'Server busy',
162            DisconnectCode::ServerShuttingDown => 0x8B,  // 'Server shutting down',
163            DisconnectCode::KeepAliveTimeout => 0x8D,    // 'Keep Alive timeout',
164            DisconnectCode::SessionTakenVver => 0x8E,    // 'Session taken over',
165            DisconnectCode::TopicFilterInvalid => 0x8F,  // 'Topic Filter invalid',
166            DisconnectCode::TopicNameInvalid => 0x90,    // 'Topic Name invalid',
167            DisconnectCode::ReceiveMaximumExceeded => 0x93, // 'Receive Maximum exceeded',
168            DisconnectCode::TopicAliasInvalid => 0x94,   // 'Topic Alias invalid',
169            DisconnectCode::PacketTooLarge => 0x95,      // 'Packet too large',
170            DisconnectCode::MessageRateTooHigh => 0x96,  // 'Message rate too high',
171            DisconnectCode::QuotaExceeded => 0x97,       // 'Quota exceeded',
172            DisconnectCode::AdministrativeAction => 0x98, // 'Administrative action',
173            DisconnectCode::PayloadFormatInvalid => 0x99, // 'Payload format invalid',
174            DisconnectCode::RetainNotSupported => 0x9A,  // 'Retain not supported',
175            DisconnectCode::QoSNotSupported => 0x9B,     // 'QoS not supported',
176            DisconnectCode::UseAnotherServer => 0x9C,    // 'Use another server',
177            DisconnectCode::ServerMoved => 0x9D,         // 'Server moved',
178            DisconnectCode::SharedSubscriptionsNotSupported => 0x9E, // 'Shared Subscriptions not supported',
179            DisconnectCode::ConnectionRateExceeded => 0x9F,          // 'Connection rate exceeded',
180            DisconnectCode::MaximumConnectTime => 0xA0,              // 'Maximum connect time',
181            DisconnectCode::SubscriptionIdentifiersNotSupported => 0xA1, // 'Subscription Identifiers not supported',
182            DisconnectCode::WildcardSubscriptionsNotSupported => 0xA2, // 'Wildcard Subscriptions not supported'
183        }
184    }
185}
186
187#[derive(Debug, PartialEq, Clone)]
188#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
189pub enum UnsubackCode {
190    Success,
191    NoSubscriptionExisted,
192    UnspecifiedError,
193    ImplementationSpecificError,
194    NotAuthorized,
195    TopicFilterInvalid,
196    PacketIdentifierInUse,
197}
198
199impl MqttCode<UnsubackCode> for UnsubackCode {
200    fn from_byte(code: u8) -> Res<UnsubackCode> {
201        let c = match code {
202            0x00 => UnsubackCode::Success,                     // 'Success',
203            0x11 => UnsubackCode::NoSubscriptionExisted,       // 'No subscription existed',
204            0x80 => UnsubackCode::UnspecifiedError,            // 'Unspecified error',
205            0x83 => UnsubackCode::ImplementationSpecificError, // 'Implementation specific error',
206            0x87 => UnsubackCode::NotAuthorized,               // 'Not authorized',
207            0x8F => UnsubackCode::TopicFilterInvalid,          // 'Topic Filter invalid',
208            0x91 => UnsubackCode::PacketIdentifierInUse,       // 'Packet Identifier in use'
209            _ => return Err(format!("Invalid unsuback code {}", code)),
210        };
211        Ok(c)
212    }
213
214    fn to_byte(&self) -> u8 {
215        match self {
216            UnsubackCode::Success => 0x00,
217            UnsubackCode::NoSubscriptionExisted => 0x11,
218            UnsubackCode::UnspecifiedError => 0x80,
219            UnsubackCode::ImplementationSpecificError => 0x83,
220            UnsubackCode::NotAuthorized => 0x87,
221            UnsubackCode::TopicFilterInvalid => 0x8F,
222            UnsubackCode::PacketIdentifierInUse => 0x91,
223        }
224    }
225}
226
227#[derive(Debug, PartialEq, Clone)]
228#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
229pub enum AuthCode {
230    Success,                // 0x0
231    ContinueAuthentication, // 0x18
232    ReAuthenticate,         // 0x19
233}
234
235impl MqttCode<AuthCode> for AuthCode {
236    fn from_byte(byte: u8) -> Res<AuthCode> {
237        Ok(match byte {
238            0x00 => AuthCode::Success,
239            0x18 => AuthCode::ContinueAuthentication,
240            0x19 => AuthCode::ReAuthenticate,
241            _ => return Err(format!("Invalid auth code {}", byte)),
242        })
243    }
244
245    fn to_byte(&self) -> u8 {
246        match self {
247            AuthCode::Success => 0x00,
248            AuthCode::ContinueAuthentication => 0x18,
249            AuthCode::ReAuthenticate => 0x19,
250        }
251    }
252}
253
254#[derive(Debug, PartialEq, Clone)]
255#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
256/// PUMBCOMP/PUBREL codes enum
257pub enum PubcompPubrelCode {
258    Success,                  // 0x0
259    PacketIdentifierNotFound, // 0x92
260}
261
262impl MqttCode<PubcompPubrelCode> for PubcompPubrelCode {
263    fn from_byte(byte: u8) -> Res<PubcompPubrelCode> {
264        Ok(match byte {
265            0x00 => PubcompPubrelCode::Success,
266            0x92 => PubcompPubrelCode::PacketIdentifierNotFound,
267            _ => return Err(format!("Invalid pubcomp/pubrel code {}", byte)),
268        })
269    }
270
271    fn to_byte(&self) -> u8 {
272        match self {
273            PubcompPubrelCode::Success => 0x00,
274            PubcompPubrelCode::PacketIdentifierNotFound => 0x92,
275        }
276    }
277}
278
279#[derive(Debug, PartialEq, Clone)]
280#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
281/// PUBACK/PUBREC codes enum
282pub enum PubackPubrecCode {
283    Success,
284    NoMatchingSubscribers,
285    UnspecifiedError,
286    ImplementationSpecificError,
287    NotAuthorized,
288    TopicNameInvalid,
289    PacketIdentifierInUse,
290    QuotaExceeded,
291    PayloadFormatInvalid,
292}
293
294impl MqttCode<PubackPubrecCode> for PubackPubrecCode {
295    fn from_byte(byte: u8) -> Res<PubackPubrecCode> {
296        Ok(match byte {
297            0x00 => PubackPubrecCode::Success,
298            0x10 => PubackPubrecCode::NoMatchingSubscribers,
299            0x80 => PubackPubrecCode::UnspecifiedError,
300            0x83 => PubackPubrecCode::ImplementationSpecificError,
301            0x87 => PubackPubrecCode::NotAuthorized,
302            0x90 => PubackPubrecCode::TopicNameInvalid,
303            0x91 => PubackPubrecCode::PacketIdentifierInUse,
304            0x97 => PubackPubrecCode::QuotaExceeded,
305            0x99 => PubackPubrecCode::PayloadFormatInvalid,
306            _ => return Err(format!("Invalid puback/pubrec code {}", byte)),
307        })
308    }
309
310    fn to_byte(&self) -> u8 {
311        match self {
312            PubackPubrecCode::Success => 0x00,
313            PubackPubrecCode::NoMatchingSubscribers => 0x10,
314            PubackPubrecCode::UnspecifiedError => 0x80,
315            PubackPubrecCode::ImplementationSpecificError => 0x83,
316            PubackPubrecCode::NotAuthorized => 0x87,
317            PubackPubrecCode::TopicNameInvalid => 0x90,
318            PubackPubrecCode::PacketIdentifierInUse => 0x91,
319            PubackPubrecCode::QuotaExceeded => 0x97,
320            PubackPubrecCode::PayloadFormatInvalid => 0x99,
321        }
322    }
323}