1use core::fmt;
24use derive_builder::UninitializedFieldError;
25use num_enum::TryFromPrimitive;
26use serde::{Serialize, Serializer};
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
29#[cfg_attr(feature = "defmt", derive(defmt::Format))]
30#[repr(u16)]
31pub enum MqttError {
32 UnspecifiedError = 0x0080,
34 MalformedPacket = 0x0081,
35 ProtocolError = 0x0082,
36 ImplementationSpecificError = 0x0083,
37 UnsupportedProtocolVersion = 0x0084,
38 ClientIdentifierNotValid = 0x0085,
39 BadUserNameOrPassword = 0x0086,
40 NotAuthorized = 0x0087,
41 ServerUnavailable = 0x0088,
42 ServerBusy = 0x0089,
43 Banned = 0x008A,
44 ServerShuttingDown = 0x008B,
45 BadAuthenticationMethod = 0x008C,
46 KeepAliveTimeout = 0x008D,
47 SessionTakenOver = 0x008E,
48 TopicFilterInvalid = 0x008F,
49 TopicNameInvalid = 0x0090,
50 ReceiveMaximumExceeded = 0x0093,
51 TopicAliasInvalid = 0x0094,
52 PacketTooLarge = 0x0095,
53 MessageRateTooHigh = 0x0096,
54 QuotaExceeded = 0x0097,
55 AdministrativeAction = 0x0098,
56 PayloadFormatInvalid = 0x0099,
57 RetainNotSupported = 0x009A,
58 QosNotSupported = 0x009B,
59 UseAnotherServer = 0x009C,
60 ServerMoved = 0x009D,
61 SharedSubscriptionsNotSupported = 0x009E,
62 ConnectionRateExceeded = 0x009F,
63 MaximumConnectTime = 0x00A0,
64 SubscriptionIdentifiersNotSupported = 0x00A1,
65 WildcardSubscriptionsNotSupported = 0x00A2,
66
67 PartialErrorDetected = 0x0101,
69 PacketEnqueued = 0x0102,
70 AllErrorDetected = 0x0180,
71 PacketIdentifierFullyUsed = 0x0181,
72 PacketIdentifierConflict = 0x0182,
73 PacketIdentifierInvalid = 0x0183,
74 PacketNotAllowedToSend = 0x0184,
75 PacketNotAllowedToStore = 0x0185,
76 PacketNotRegulated = 0x0186,
77 InsufficientBytes = 0x0187,
78 InvalidPacketForRole = 0x0188,
79 VersionMismatch = 0x0189,
80 PacketConversionFailed = 0x018A,
81 PacketProcessFailed = 0x018B,
82 ValueOutOfRange = 0x018C,
83 InvalidQos = 0x018D,
84}
85
86impl From<UninitializedFieldError> for MqttError {
88 fn from(_: UninitializedFieldError) -> Self {
89 MqttError::MalformedPacket
91 }
92}
93
94impl From<core::convert::Infallible> for MqttError {
96 fn from(_: core::convert::Infallible) -> Self {
97 unreachable!()
99 }
100}
101
102impl core::fmt::Display for MqttError {
103 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
104 let s = match self {
105 Self::UnspecifiedError => "UnspecifiedError",
106 Self::MalformedPacket => "MalformedPacket",
107 Self::ProtocolError => "ProtocolError",
108 Self::ImplementationSpecificError => "ImplementationSpecificError",
109 Self::UnsupportedProtocolVersion => "UnsupportedProtocolVersion",
110 Self::ClientIdentifierNotValid => "ClientIdentifierNotValid",
111 Self::BadUserNameOrPassword => "BadUserNameOrPassword",
112 Self::NotAuthorized => "NotAuthorized",
113 Self::ServerUnavailable => "ServerUnavailable",
114 Self::ServerBusy => "ServerBusy",
115 Self::Banned => "Banned",
116 Self::ServerShuttingDown => "ServerShuttingDown",
117 Self::BadAuthenticationMethod => "BadAuthenticationMethod",
118 Self::KeepAliveTimeout => "KeepAliveTimeout",
119 Self::SessionTakenOver => "SessionTakenOver",
120 Self::TopicFilterInvalid => "TopicFilterInvalid",
121 Self::TopicNameInvalid => "TopicNameInvalid",
122 Self::ReceiveMaximumExceeded => "ReceiveMaximumExceeded",
123 Self::TopicAliasInvalid => "TopicAliasInvalid",
124 Self::PacketTooLarge => "PacketTooLarge",
125 Self::MessageRateTooHigh => "MessageRateTooHigh",
126 Self::QuotaExceeded => "QuotaExceeded",
127 Self::AdministrativeAction => "AdministrativeAction",
128 Self::PayloadFormatInvalid => "PayloadFormatInvalid",
129 Self::RetainNotSupported => "RetainNotSupported",
130 Self::QosNotSupported => "QosNotSupported",
131 Self::UseAnotherServer => "UseAnotherServer",
132 Self::ServerMoved => "ServerMoved",
133 Self::SharedSubscriptionsNotSupported => "SharedSubscriptionsNotSupported",
134 Self::ConnectionRateExceeded => "ConnectionRateExceeded",
135 Self::MaximumConnectTime => "MaximumConnectTime",
136 Self::SubscriptionIdentifiersNotSupported => "SubscriptionIdentifiersNotSupported",
137 Self::WildcardSubscriptionsNotSupported => "WildcardSubscriptionsNotSupported",
138
139 Self::PartialErrorDetected => "PartialErrorDetected",
140 Self::PacketEnqueued => "PacketEnqueued",
141 Self::AllErrorDetected => "AllErrorDetected",
142 Self::PacketIdentifierFullyUsed => "PacketIdentifierFullyUsed",
143 Self::PacketIdentifierConflict => "PacketIdentifierConflict",
144 Self::PacketIdentifierInvalid => "PacketIdentifierInvalid",
145 Self::PacketNotAllowedToSend => "PacketNotAllowedToSend",
146 Self::PacketNotAllowedToStore => "PacketNotAllowedToStore",
147 Self::PacketNotRegulated => "PacketNotRegulated",
148 Self::InsufficientBytes => "InsufficientBytes",
149 Self::InvalidPacketForRole => "InvalidPacketForRole",
150 Self::VersionMismatch => "VersionMismatch",
151 Self::PacketConversionFailed => "PacketConversionFailed",
152 Self::PacketProcessFailed => "PacketProcessFailed",
153 Self::ValueOutOfRange => "ValueOutOfRange",
154 Self::InvalidQos => "InvalidQos",
155 };
156 write!(f, "{s}")
157 }
158}
159
160impl Serialize for MqttError {
161 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
162 where
163 S: Serializer,
164 {
165 serializer.serialize_str(&alloc::format!("{self}"))
166 }
167}
168
169impl core::convert::TryFrom<u8> for MqttError {
170 type Error = u8;
171
172 fn try_from(code: u8) -> Result<Self, Self::Error> {
173 match code {
174 0x80 => Ok(Self::UnspecifiedError),
175 0x81 => Ok(Self::MalformedPacket),
176 0x82 => Ok(Self::ProtocolError),
177 0x83 => Ok(Self::ImplementationSpecificError),
178 0x84 => Ok(Self::UnsupportedProtocolVersion),
179 0x85 => Ok(Self::ClientIdentifierNotValid),
180 0x86 => Ok(Self::BadUserNameOrPassword),
181 0x87 => Ok(Self::NotAuthorized),
182 0x88 => Ok(Self::ServerUnavailable),
183 0x89 => Ok(Self::ServerBusy),
184 0x8A => Ok(Self::Banned),
185 0x8B => Ok(Self::ServerShuttingDown),
186 0x8C => Ok(Self::BadAuthenticationMethod),
187 0x8D => Ok(Self::KeepAliveTimeout),
188 0x8E => Ok(Self::SessionTakenOver),
189 0x8F => Ok(Self::TopicFilterInvalid),
190 0x90 => Ok(Self::TopicNameInvalid),
191 0x93 => Ok(Self::ReceiveMaximumExceeded),
192 0x94 => Ok(Self::TopicAliasInvalid),
193 0x95 => Ok(Self::PacketTooLarge),
194 0x96 => Ok(Self::MessageRateTooHigh),
195 0x97 => Ok(Self::QuotaExceeded),
196 0x98 => Ok(Self::AdministrativeAction),
197 0x99 => Ok(Self::PayloadFormatInvalid),
198 0x9A => Ok(Self::RetainNotSupported),
199 0x9B => Ok(Self::QosNotSupported),
200 0x9C => Ok(Self::UseAnotherServer),
201 0x9D => Ok(Self::ServerMoved),
202 0x9E => Ok(Self::SharedSubscriptionsNotSupported),
203 0x9F => Ok(Self::ConnectionRateExceeded),
204 0xA0 => Ok(Self::MaximumConnectTime),
205 0xA1 => Ok(Self::SubscriptionIdentifiersNotSupported),
206 0xA2 => Ok(Self::WildcardSubscriptionsNotSupported),
207 other => Err(other),
208 }
209 }
210}
211
212#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
214#[cfg_attr(feature = "defmt", derive(defmt::Format))]
215#[repr(u8)]
216pub enum ConnectReturnCode {
217 Accepted = 0, UnacceptableProtocolVersion = 1, IdentifierRejected = 2, ServerUnavailable = 3, BadUserNameOrPassword = 4, NotAuthorized = 5, }
224
225impl ConnectReturnCode {
226 pub fn is_success(&self) -> bool {
227 matches!(self, Self::Accepted)
228 }
229 pub fn is_failure(&self) -> bool {
230 !self.is_success()
231 }
232}
233
234impl fmt::Display for ConnectReturnCode {
235 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
236 let s = match self {
237 Self::Accepted => "Accepted",
238 Self::UnacceptableProtocolVersion => "UnacceptableProtocolVersion",
239 Self::IdentifierRejected => "IdentifierRejected",
240 Self::ServerUnavailable => "ServerUnavailable",
241 Self::BadUserNameOrPassword => "BadUserNameOrPassword",
242 Self::NotAuthorized => "NotAuthorized",
243 };
244 write!(f, "{s}")
245 }
246}
247
248impl Serialize for ConnectReturnCode {
249 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
250 where
251 S: Serializer,
252 {
253 serializer.serialize_str(&alloc::format!("{self}"))
254 }
255}
256
257#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
259#[cfg_attr(feature = "defmt", derive(defmt::Format))]
260#[repr(u8)]
261pub enum SubackReturnCode {
262 SuccessMaximumQos0 = 0x00, SuccessMaximumQos1 = 0x01, SuccessMaximumQos2 = 0x02, Failure = 0x80, }
267
268impl SubackReturnCode {
269 pub fn is_success(&self) -> bool {
270 matches!(
271 self,
272 Self::SuccessMaximumQos0 | Self::SuccessMaximumQos1 | Self::SuccessMaximumQos2
273 )
274 }
275 pub fn is_failure(&self) -> bool {
276 !self.is_success()
277 }
278}
279
280impl fmt::Display for SubackReturnCode {
281 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
282 let s = match self {
283 Self::SuccessMaximumQos0 => "SuccessMaximumQos0",
284 Self::SuccessMaximumQos1 => "SuccessMaximumQos1",
285 Self::SuccessMaximumQos2 => "SuccessMaximumQos2",
286 Self::Failure => "Failure",
287 };
288 write!(f, "{s}")
289 }
290}
291
292impl Serialize for SubackReturnCode {
293 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
294 where
295 S: Serializer,
296 {
297 serializer.serialize_str(&alloc::format!("{self}"))
298 }
299}
300
301#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
303#[cfg_attr(feature = "defmt", derive(defmt::Format))]
304#[repr(u8)]
305pub enum ConnectReasonCode {
306 Success = 0x00, UnspecifiedError = 0x80, MalformedPacket = 0x81, ProtocolError = 0x82, ImplementationSpecificError = 0x83, UnsupportedProtocolVersion = 0x84, ClientIdentifierNotValid = 0x85, BadUserNameOrPassword = 0x86, NotAuthorized = 0x87, ServerUnavailable = 0x88, ServerBusy = 0x89, Banned = 0x8a, BadAuthenticationMethod = 0x8c, TopicNameInvalid = 0x90, PacketTooLarge = 0x95, QuotaExceeded = 0x97, PayloadFormatInvalid = 0x99, RetainNotSupported = 0x9a, QosNotSupported = 0x9b, UseAnotherServer = 0x9c, ServerMoved = 0x9d, ConnectionRateExceeded = 0x9f, }
329
330impl fmt::Display for ConnectReasonCode {
331 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
332 let s = match self {
333 Self::Success => "Success",
334 Self::UnspecifiedError => "UnspecifiedError",
335 Self::MalformedPacket => "MalformedPacket",
336 Self::ProtocolError => "ProtocolError",
337 Self::ImplementationSpecificError => "ImplementationSpecificError",
338 Self::UnsupportedProtocolVersion => "UnsupportedProtocolVersion",
339 Self::ClientIdentifierNotValid => "ClientIdentifierNotValid",
340 Self::BadUserNameOrPassword => "BadUserNameOrPassword",
341 Self::NotAuthorized => "NotAuthorized",
342 Self::ServerUnavailable => "ServerUnavailable",
343 Self::ServerBusy => "ServerBusy",
344 Self::Banned => "Banned",
345 Self::BadAuthenticationMethod => "BadAuthenticationMethod",
346 Self::TopicNameInvalid => "TopicNameInvalid",
347 Self::PacketTooLarge => "PacketTooLarge",
348 Self::QuotaExceeded => "QuotaExceeded",
349 Self::PayloadFormatInvalid => "PayloadFormatInvalid",
350 Self::RetainNotSupported => "RetainNotSupported",
351 Self::QosNotSupported => "QosNotSupported",
352 Self::UseAnotherServer => "UseAnotherServer",
353 Self::ServerMoved => "ServerMoved",
354 Self::ConnectionRateExceeded => "ConnectionRateExceeded",
355 };
356 write!(f, "{s}")
357 }
358}
359
360impl Serialize for ConnectReasonCode {
361 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
362 where
363 S: Serializer,
364 {
365 serializer.serialize_str(&alloc::format!("{self}"))
366 }
367}
368
369impl From<ConnectReasonCode> for MqttError {
370 fn from(code: ConnectReasonCode) -> Self {
371 MqttError::try_from(code as u8).unwrap_or(MqttError::ProtocolError)
373 }
374}
375
376#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
377#[cfg_attr(feature = "defmt", derive(defmt::Format))]
378#[repr(u8)]
379pub enum DisconnectReasonCode {
380 NormalDisconnection = 0x00,
381 DisconnectWithWillMessage = 0x04,
382 UnspecifiedError = 0x80,
383 MalformedPacket = 0x81,
384 ProtocolError = 0x82,
385 ImplementationSpecificError = 0x83,
386 NotAuthorized = 0x87,
387 ServerBusy = 0x89,
388 ServerShuttingDown = 0x8b,
389 KeepAliveTimeout = 0x8d,
390 SessionTakenOver = 0x8e,
391 TopicFilterInvalid = 0x8f,
392 TopicNameInvalid = 0x90,
393 ReceiveMaximumExceeded = 0x93,
394 TopicAliasInvalid = 0x94,
395 PacketTooLarge = 0x95,
396 MessageRateTooHigh = 0x96,
397 QuotaExceeded = 0x97,
398 AdministrativeAction = 0x98,
399 PayloadFormatInvalid = 0x99,
400 RetainNotSupported = 0x9a,
401 QosNotSupported = 0x9b,
402 UseAnotherServer = 0x9c,
403 ServerMoved = 0x9d,
404 SharedSubscriptionsNotSupported = 0x9e,
405 ConnectionRateExceeded = 0x9f,
406 MaximumConnectTime = 0xa0,
407 SubscriptionIdentifiersNotSupported = 0xa1,
408 WildcardSubscriptionsNotSupported = 0xa2,
409}
410
411impl core::fmt::Display for DisconnectReasonCode {
412 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
413 let s = match self {
414 Self::NormalDisconnection => "NormalDisconnection",
415 Self::DisconnectWithWillMessage => "DisconnectWithWillMessage",
416 Self::UnspecifiedError => "UnspecifiedError",
417 Self::MalformedPacket => "MalformedPacket",
418 Self::ProtocolError => "ProtocolError",
419 Self::ImplementationSpecificError => "ImplementationSpecificError",
420 Self::NotAuthorized => "NotAuthorized",
421 Self::ServerBusy => "ServerBusy",
422 Self::ServerShuttingDown => "ServerShuttingDown",
423 Self::KeepAliveTimeout => "KeepAliveTimeout",
424 Self::SessionTakenOver => "SessionTakenOver",
425 Self::TopicFilterInvalid => "TopicFilterInvalid",
426 Self::TopicNameInvalid => "TopicNameInvalid",
427 Self::ReceiveMaximumExceeded => "ReceiveMaximumExceeded",
428 Self::TopicAliasInvalid => "TopicAliasInvalid",
429 Self::PacketTooLarge => "PacketTooLarge",
430 Self::MessageRateTooHigh => "MessageRateTooHigh",
431 Self::QuotaExceeded => "QuotaExceeded",
432 Self::AdministrativeAction => "AdministrativeAction",
433 Self::PayloadFormatInvalid => "PayloadFormatInvalid",
434 Self::RetainNotSupported => "RetainNotSupported",
435 Self::QosNotSupported => "QosNotSupported",
436 Self::UseAnotherServer => "UseAnotherServer",
437 Self::ServerMoved => "ServerMoved",
438 Self::SharedSubscriptionsNotSupported => "SharedSubscriptionsNotSupported",
439 Self::ConnectionRateExceeded => "ConnectionRateExceeded",
440 Self::MaximumConnectTime => "MaximumConnectTime",
441 Self::SubscriptionIdentifiersNotSupported => "SubscriptionIdentifiersNotSupported",
442 Self::WildcardSubscriptionsNotSupported => "WildcardSubscriptionsNotSupported",
443 };
444 write!(f, "{s}")
445 }
446}
447
448impl Serialize for DisconnectReasonCode {
449 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
450 where
451 S: Serializer,
452 {
453 serializer.serialize_str(&alloc::format!("{self}"))
454 }
455}
456
457impl From<DisconnectReasonCode> for MqttError {
458 fn from(code: DisconnectReasonCode) -> Self {
459 MqttError::try_from(code as u8).unwrap_or(MqttError::ProtocolError)
461 }
462}
463
464impl From<MqttError> for DisconnectReasonCode {
465 fn from(error: MqttError) -> Self {
466 match error {
467 MqttError::UnspecifiedError => DisconnectReasonCode::UnspecifiedError,
468 MqttError::MalformedPacket => DisconnectReasonCode::MalformedPacket,
469 MqttError::ProtocolError => DisconnectReasonCode::ProtocolError,
470 MqttError::ImplementationSpecificError => {
471 DisconnectReasonCode::ImplementationSpecificError
472 }
473 MqttError::NotAuthorized => DisconnectReasonCode::NotAuthorized,
474 MqttError::ServerBusy => DisconnectReasonCode::ServerBusy,
475 MqttError::ServerShuttingDown => DisconnectReasonCode::ServerShuttingDown,
476 MqttError::KeepAliveTimeout => DisconnectReasonCode::KeepAliveTimeout,
477 MqttError::SessionTakenOver => DisconnectReasonCode::SessionTakenOver,
478 MqttError::TopicFilterInvalid => DisconnectReasonCode::TopicFilterInvalid,
479 MqttError::TopicNameInvalid => DisconnectReasonCode::TopicNameInvalid,
480 MqttError::ReceiveMaximumExceeded => DisconnectReasonCode::ReceiveMaximumExceeded,
481 MqttError::TopicAliasInvalid => DisconnectReasonCode::TopicAliasInvalid,
482 MqttError::PacketTooLarge => DisconnectReasonCode::PacketTooLarge,
483 MqttError::MessageRateTooHigh => DisconnectReasonCode::MessageRateTooHigh,
484 MqttError::QuotaExceeded => DisconnectReasonCode::QuotaExceeded,
485 MqttError::AdministrativeAction => DisconnectReasonCode::AdministrativeAction,
486 MqttError::PayloadFormatInvalid => DisconnectReasonCode::PayloadFormatInvalid,
487 MqttError::RetainNotSupported => DisconnectReasonCode::RetainNotSupported,
488 MqttError::QosNotSupported => DisconnectReasonCode::QosNotSupported,
489 MqttError::UseAnotherServer => DisconnectReasonCode::UseAnotherServer,
490 MqttError::ServerMoved => DisconnectReasonCode::ServerMoved,
491 MqttError::SharedSubscriptionsNotSupported => {
492 DisconnectReasonCode::SharedSubscriptionsNotSupported
493 }
494 MqttError::ConnectionRateExceeded => DisconnectReasonCode::ConnectionRateExceeded,
495 MqttError::MaximumConnectTime => DisconnectReasonCode::MaximumConnectTime,
496 MqttError::SubscriptionIdentifiersNotSupported => {
497 DisconnectReasonCode::SubscriptionIdentifiersNotSupported
498 }
499 MqttError::WildcardSubscriptionsNotSupported => {
500 DisconnectReasonCode::WildcardSubscriptionsNotSupported
501 }
502 _ => DisconnectReasonCode::UnspecifiedError,
504 }
505 }
506}
507
508#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
509#[cfg_attr(feature = "defmt", derive(defmt::Format))]
510#[repr(u8)]
511pub enum SubackReasonCode {
512 GrantedQos0 = 0x00,
513 GrantedQos1 = 0x01,
514 GrantedQos2 = 0x02,
515 UnspecifiedError = 0x80,
516 ImplementationSpecificError = 0x83,
517 NotAuthorized = 0x87,
518 TopicFilterInvalid = 0x8f,
519 PacketIdentifierInUse = 0x91,
520 QuotaExceeded = 0x97,
521 SharedSubscriptionsNotSupported = 0x9e,
522 SubscriptionIdentifiersNotSupported = 0xa1,
523 WildcardSubscriptionsNotSupported = 0xa2,
524}
525
526impl SubackReasonCode {
527 pub fn is_success(&self) -> bool {
528 matches!(
529 self,
530 Self::GrantedQos0 | Self::GrantedQos1 | Self::GrantedQos2
531 )
532 }
533 pub fn is_failure(&self) -> bool {
534 !self.is_success()
535 }
536}
537
538impl core::fmt::Display for SubackReasonCode {
539 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
540 let s = match self {
541 Self::GrantedQos0 => "GrantedQos0",
542 Self::GrantedQos1 => "GrantedQos1",
543 Self::GrantedQos2 => "GrantedQos2",
544 Self::UnspecifiedError => "UnspecifiedError",
545 Self::ImplementationSpecificError => "ImplementationSpecificError",
546 Self::NotAuthorized => "NotAuthorized",
547 Self::TopicFilterInvalid => "TopicFilterInvalid",
548 Self::PacketIdentifierInUse => "PacketIdentifierInUse",
549 Self::QuotaExceeded => "QuotaExceeded",
550 Self::SharedSubscriptionsNotSupported => "SharedSubscriptionsNotSupported",
551 Self::SubscriptionIdentifiersNotSupported => "SubscriptionIdentifiersNotSupported",
552 Self::WildcardSubscriptionsNotSupported => "WildcardSubscriptionsNotSupported",
553 };
554 write!(f, "{s}")
555 }
556}
557
558impl Serialize for SubackReasonCode {
559 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
560 where
561 S: Serializer,
562 {
563 serializer.serialize_str(&alloc::format!("{self}"))
564 }
565}
566
567impl From<SubackReasonCode> for MqttError {
568 fn from(code: SubackReasonCode) -> Self {
569 MqttError::try_from(code as u8).unwrap_or(MqttError::ProtocolError)
571 }
572}
573
574#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
575#[cfg_attr(feature = "defmt", derive(defmt::Format))]
576#[repr(u8)]
577pub enum UnsubackReasonCode {
578 Success = 0x00,
579 NoSubscriptionExisted = 0x11,
580 UnspecifiedError = 0x80,
581 ImplementationSpecificError = 0x83,
582 NotAuthorized = 0x87,
583 TopicFilterInvalid = 0x8f,
584 PacketIdentifierInUse = 0x91,
585}
586
587impl UnsubackReasonCode {
588 pub fn is_success(&self) -> bool {
589 matches!(self, Self::Success | Self::NoSubscriptionExisted)
590 }
591 pub fn is_failure(&self) -> bool {
592 !self.is_success()
593 }
594}
595
596impl core::fmt::Display for UnsubackReasonCode {
597 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
598 let s = match self {
599 Self::Success => "Success",
600 Self::NoSubscriptionExisted => "NoSubscriptionExisted",
601 Self::UnspecifiedError => "UnspecifiedError",
602 Self::ImplementationSpecificError => "ImplementationSpecificError",
603 Self::NotAuthorized => "NotAuthorized",
604 Self::TopicFilterInvalid => "TopicFilterInvalid",
605 Self::PacketIdentifierInUse => "PacketIdentifierInUse",
606 };
607 write!(f, "{s}")
608 }
609}
610
611impl Serialize for UnsubackReasonCode {
612 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
613 where
614 S: Serializer,
615 {
616 serializer.serialize_str(&alloc::format!("{self}"))
617 }
618}
619
620impl From<UnsubackReasonCode> for MqttError {
621 fn from(code: UnsubackReasonCode) -> Self {
622 MqttError::try_from(code as u8).unwrap_or(MqttError::ProtocolError)
624 }
625}
626
627#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
628#[cfg_attr(feature = "defmt", derive(defmt::Format))]
629#[repr(u8)]
630pub enum PubackReasonCode {
631 Success = 0x00,
632 NoMatchingSubscribers = 0x10,
633 UnspecifiedError = 0x80,
634 ImplementationSpecificError = 0x83,
635 NotAuthorized = 0x87,
636 TopicNameInvalid = 0x90,
637 PacketIdentifierInUse = 0x91,
638 QuotaExceeded = 0x97,
639 PayloadFormatInvalid = 0x99,
640}
641
642impl PubackReasonCode {
643 pub fn is_success(&self) -> bool {
644 matches!(self, Self::Success | Self::NoMatchingSubscribers)
645 }
646 pub fn is_failure(&self) -> bool {
647 !self.is_success()
648 }
649}
650
651impl core::fmt::Display for PubackReasonCode {
652 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
653 let s = match self {
654 Self::Success => "Success",
655 Self::NoMatchingSubscribers => "NoMatchingSubscribers",
656 Self::UnspecifiedError => "UnspecifiedError",
657 Self::ImplementationSpecificError => "ImplementationSpecificError",
658 Self::NotAuthorized => "NotAuthorized",
659 Self::TopicNameInvalid => "TopicNameInvalid",
660 Self::PacketIdentifierInUse => "PacketIdentifierInUse",
661 Self::QuotaExceeded => "QuotaExceeded",
662 Self::PayloadFormatInvalid => "PayloadFormatInvalid",
663 };
664 write!(f, "{s}")
665 }
666}
667
668impl Serialize for PubackReasonCode {
669 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
670 where
671 S: Serializer,
672 {
673 serializer.serialize_str(&alloc::format!("{self}"))
674 }
675}
676
677impl From<PubackReasonCode> for MqttError {
678 fn from(code: PubackReasonCode) -> Self {
679 MqttError::try_from(code as u8).unwrap_or(MqttError::ProtocolError)
681 }
682}
683
684#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
685#[cfg_attr(feature = "defmt", derive(defmt::Format))]
686#[repr(u8)]
687pub enum PubrecReasonCode {
688 Success = 0x00,
689 NoMatchingSubscribers = 0x10,
690 UnspecifiedError = 0x80,
691 ImplementationSpecificError = 0x83,
692 NotAuthorized = 0x87,
693 TopicNameInvalid = 0x90,
694 PacketIdentifierInUse = 0x91,
695 QuotaExceeded = 0x97,
696 PayloadFormatInvalid = 0x99,
697}
698
699impl PubrecReasonCode {
700 pub fn is_success(&self) -> bool {
701 matches!(self, Self::Success | Self::NoMatchingSubscribers)
702 }
703 pub fn is_failure(&self) -> bool {
704 !self.is_success()
705 }
706}
707impl core::fmt::Display for PubrecReasonCode {
708 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
709 let s = match self {
710 Self::Success => "Success",
711 Self::NoMatchingSubscribers => "NoMatchingSubscribers",
712 Self::UnspecifiedError => "UnspecifiedError",
713 Self::ImplementationSpecificError => "ImplementationSpecificError",
714 Self::NotAuthorized => "NotAuthorized",
715 Self::TopicNameInvalid => "TopicNameInvalid",
716 Self::PacketIdentifierInUse => "PacketIdentifierInUse",
717 Self::QuotaExceeded => "QuotaExceeded",
718 Self::PayloadFormatInvalid => "PayloadFormatInvalid",
719 };
720 write!(f, "{s}")
721 }
722}
723
724impl Serialize for PubrecReasonCode {
725 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
726 where
727 S: Serializer,
728 {
729 serializer.serialize_str(&alloc::format!("{self}"))
730 }
731}
732
733impl From<PubrecReasonCode> for MqttError {
734 fn from(code: PubrecReasonCode) -> Self {
735 MqttError::try_from(code as u8).unwrap_or(MqttError::ProtocolError)
737 }
738}
739
740#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
741#[cfg_attr(feature = "defmt", derive(defmt::Format))]
742#[repr(u8)]
743pub enum PubrelReasonCode {
744 Success = 0x00,
745 PacketIdentifierNotFound = 0x92,
746}
747
748impl PubrelReasonCode {
749 pub fn is_success(&self) -> bool {
750 matches!(self, Self::Success)
751 }
752 pub fn is_failure(&self) -> bool {
753 !self.is_success()
754 }
755}
756
757impl core::fmt::Display for PubrelReasonCode {
758 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
759 let s = match self {
760 Self::Success => "Success",
761 Self::PacketIdentifierNotFound => "PacketIdentifierNotFound",
762 };
763 write!(f, "{s}")
764 }
765}
766
767impl Serialize for PubrelReasonCode {
768 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
769 where
770 S: Serializer,
771 {
772 serializer.serialize_str(&alloc::format!("{self}"))
773 }
774}
775
776impl From<PubrelReasonCode> for MqttError {
777 fn from(code: PubrelReasonCode) -> Self {
778 MqttError::try_from(code as u8).unwrap_or(MqttError::ProtocolError)
780 }
781}
782
783#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
784#[cfg_attr(feature = "defmt", derive(defmt::Format))]
785#[repr(u8)]
786pub enum PubcompReasonCode {
787 Success = 0x00,
788 PacketIdentifierNotFound = 0x92,
789}
790
791impl PubcompReasonCode {
792 pub fn is_success(&self) -> bool {
793 matches!(self, Self::Success)
794 }
795 pub fn is_failure(&self) -> bool {
796 !self.is_success()
797 }
798}
799
800impl core::fmt::Display for PubcompReasonCode {
801 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
802 let s = match self {
803 Self::Success => "Success",
804 Self::PacketIdentifierNotFound => "PacketIdentifierNotFound",
805 };
806 write!(f, "{s}")
807 }
808}
809
810impl Serialize for PubcompReasonCode {
811 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
812 where
813 S: Serializer,
814 {
815 serializer.serialize_str(&alloc::format!("{self}"))
816 }
817}
818
819impl From<PubcompReasonCode> for MqttError {
820 fn from(code: PubcompReasonCode) -> Self {
821 MqttError::try_from(code as u8).unwrap_or(MqttError::ProtocolError)
823 }
824}
825
826#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
827#[cfg_attr(feature = "defmt", derive(defmt::Format))]
828#[repr(u8)]
829pub enum AuthReasonCode {
830 Success = 0x00,
831 ContinueAuthentication = 0x18,
832 ReAuthenticate = 0x19,
833}
834
835impl AuthReasonCode {
836 pub fn is_success(&self) -> bool {
837 matches!(
838 self,
839 Self::Success | Self::ContinueAuthentication | Self::ReAuthenticate
840 )
841 }
842 pub fn is_failure(&self) -> bool {
843 !self.is_success()
844 }
845}
846
847impl core::fmt::Display for AuthReasonCode {
848 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
849 let s = match self {
850 Self::Success => "Success",
851 Self::ContinueAuthentication => "ContinueAuthentication",
852 Self::ReAuthenticate => "ReAuthenticate",
853 };
854 write!(f, "{s}")
855 }
856}
857
858impl Serialize for AuthReasonCode {
859 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
860 where
861 S: Serializer,
862 {
863 serializer.serialize_str(&alloc::format!("{self}"))
864 }
865}
866
867impl From<AuthReasonCode> for MqttError {
868 fn from(code: AuthReasonCode) -> Self {
869 MqttError::try_from(code as u8).unwrap_or(MqttError::ProtocolError)
871 }
872}