mqtt_async_embedded/error.rs
1//! # Error Types
2//!
3//! This module defines the error types used throughout the MQTT client library,
4//! providing detailed information about potential failures, from transport issues
5//! to protocol violations.
6
7use crate::transport;
8
9/// A placeholder error type used in generic contexts where the specific transport
10/// error is not yet known. This is a common pattern for implementing `encode` methods
11/// that need to return a `Result` compatible with the client's error type.
12#[derive(Debug)]
13pub struct ErrorPlaceHolder;
14
15impl transport::TransportError for ErrorPlaceHolder {
16 // This is a marker implementation and doesn't need a body.
17}
18
19/// The primary error enum for the MQTT client.
20///
21/// It is generic over the transport error type `T`, allowing it to wrap
22/// specific errors from the underlying network transport (e.g., TCP, UART).
23#[derive(Debug)]
24#[cfg_attr(feature = "defmt", derive(defmt::Format))]
25pub enum MqttError<T> {
26 /// An error occurred in the underlying transport layer.
27 Transport(T),
28 /// A protocol-level error occurred, indicating a violation of the MQTT specification.
29 Protocol(ProtocolError),
30 /// The connection was refused by the broker. The enclosed code provides the reason.
31 ConnectionRefused(ConnectReasonCode),
32 /// The client is not currently connected to the broker.
33 NotConnected,
34 /// The buffer provided for an operation was too small.
35 BufferTooSmall,
36 /// An operation timed out.
37 Timeout,
38}
39
40/// Implements the `From` trait to allow for automatic conversion of any transport
41/// error into an `MqttError`. This is what allows the `?` operator to work
42/// seamlessly on `Result`s from the transport layer.
43impl<T: transport::TransportError> From<T> for MqttError<T> {
44 fn from(err: T) -> Self {
45 MqttError::Transport(err)
46 }
47}
48
49impl<T: transport::TransportError> MqttError<T> {
50 /// A helper method to convert an `MqttError` with a placeholder transport error
51 /// into an `MqttError` with a specific transport error type `T`.
52 ///
53 /// This is used to bridge the gap between generic packet encoding functions
54 /// and the specific error type required by the client's `Result`.
55 pub fn cast_transport_error<E: transport::TransportError>(
56 other: MqttError<E>,
57 ) -> MqttError<T> {
58 match other {
59 MqttError::Protocol(p) => MqttError::Protocol(p),
60 MqttError::ConnectionRefused(c) => MqttError::ConnectionRefused(c),
61 MqttError::NotConnected => MqttError::NotConnected,
62 MqttError::BufferTooSmall => MqttError::BufferTooSmall,
63 MqttError::Timeout => MqttError::Timeout,
64 // The transport variant can't be cast, as we don't know the concrete type `E`.
65 // This method is designed for errors originating from packet logic, which
66 // should not produce transport errors directly.
67 MqttError::Transport(_) => panic!("Cannot cast a transport error"),
68 }
69 }
70}
71
72/// Represents the reason codes for a connection refusal (`CONNACK`).
73#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74#[cfg_attr(feature = "defmt", derive(defmt::Format))]
75#[repr(u8)]
76pub enum ConnectReasonCode {
77 /// The connection was accepted.
78 Success = 0,
79 /// The broker does not support the requested MQTT protocol version.
80 UnacceptableProtocolVersion = 1,
81 /// The client identifier is not valid.
82 IdentifierRejected = 2,
83 /// The broker is unavailable.
84 ServerUnavailable = 3,
85 /// The username or password is not valid.
86 BadUserNameOrPassword = 4,
87 /// The client is not authorized to connect.
88 NotAuthorized = 5,
89 /// An unknown or unspecified error occurred.
90 Other(u8),
91}
92
93impl From<u8> for ConnectReasonCode {
94 fn from(val: u8) -> Self {
95 match val {
96 0 => Self::Success,
97 1 => Self::UnacceptableProtocolVersion,
98 2 => Self::IdentifierRejected,
99 3 => Self::ServerUnavailable,
100 4 => Self::BadUserNameOrPassword,
101 5 => Self::NotAuthorized,
102 _ => Self::Other(val),
103 }
104 }
105}
106
107/// Enumerates specific MQTT protocol errors.
108#[derive(Debug, Clone, Copy, PartialEq, Eq)]
109#[cfg_attr(feature = "defmt", derive(defmt::Format))]
110pub enum ProtocolError {
111 /// An invalid packet type was received.
112 InvalidPacketType(u8),
113 /// The server sent an invalid or unexpected response.
114 InvalidResponse,
115 /// A packet was received that was not correctly formed.
116 MalformedPacket,
117 /// The payload of a message exceeds the maximum allowable size.
118 PayloadTooLarge,
119 /// A string was not valid UTF-8.
120 InvalidUtf8String,
121 /// An MQTT v5 packet contained too many properties.
122 #[cfg(feature = "v5")]
123 TooManyProperties,
124}
125