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