Skip to main content

mbus_core/transport/
error.rs

1//! Transport-layer error and type-classification types.
2
3#[cfg(all(feature = "defmt-format", target_os = "none"))]
4use defmt;
5
6use crate::errors::MbusError;
7
8use super::config::SerialMode;
9
10/// Represents errors that can occur at the Modbus transport layer.
11#[derive(Debug, PartialEq, Eq)]
12pub enum TransportError {
13    /// The connection attempt failed.
14    ConnectionFailed,
15    /// The connection was unexpectedly closed.
16    ConnectionClosed,
17    /// An I/O error occurred during send or receive.
18    IoError,
19    /// A timeout occurred during a network operation.
20    Timeout,
21    /// The received data was too large for the buffer.
22    BufferTooSmall,
23    /// An unexpected error occurred.
24    Unexpected,
25    /// Invalid configuration.
26    InvalidConfiguration,
27    /// The transport detected a protocol-level framing or timing violation
28    /// (e.g., inter-character gap exceeding t1.5 on serial RTU).
29    FramingError,
30}
31
32#[cfg(all(feature = "defmt-format", target_os = "none"))]
33impl defmt::Format for TransportError {
34    fn format(&self, f: defmt::Formatter) {
35        match self {
36            TransportError::ConnectionFailed => defmt::write!(f, "Connection failed"),
37            TransportError::ConnectionClosed => defmt::write!(f, "Connection closed"),
38            TransportError::IoError => defmt::write!(f, "I/O error"),
39            TransportError::Timeout => defmt::write!(f, "Timeout"),
40            TransportError::BufferTooSmall => defmt::write!(f, "Buffer too small"),
41            TransportError::Unexpected => defmt::write!(f, "An unexpected error occurred"),
42            TransportError::InvalidConfiguration => defmt::write!(f, "Invalid configuration"),
43            TransportError::FramingError => {
44                defmt::write!(f, "Framing error: protocol timing violation")
45            }
46        }
47    }
48}
49
50#[cfg(feature = "error-trait")]
51impl core::fmt::Display for TransportError {
52    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
53        match self {
54            TransportError::ConnectionFailed => write!(f, "Connection failed"),
55            TransportError::ConnectionClosed => write!(f, "Connection closed"),
56            TransportError::IoError => write!(f, "I/O error"),
57            TransportError::Timeout => write!(f, "Timeout"),
58            TransportError::BufferTooSmall => write!(f, "Buffer too small"),
59            TransportError::Unexpected => write!(f, "Unexpected error"),
60            TransportError::InvalidConfiguration => write!(f, "Invalid configuration"),
61            TransportError::FramingError => write!(f, "Framing error"),
62        }
63    }
64}
65
66#[cfg(feature = "error-trait")]
67impl core::error::Error for TransportError {}
68
69impl From<TransportError> for MbusError {
70    fn from(err: TransportError) -> Self {
71        match err {
72            TransportError::ConnectionFailed => MbusError::ConnectionFailed,
73            TransportError::ConnectionClosed => MbusError::ConnectionClosed,
74            TransportError::IoError => MbusError::IoError,
75            TransportError::Timeout => MbusError::Timeout,
76            TransportError::BufferTooSmall => MbusError::BufferTooSmall,
77            TransportError::Unexpected => MbusError::Unexpected,
78            TransportError::InvalidConfiguration => MbusError::InvalidConfiguration,
79            TransportError::FramingError => MbusError::FramingError,
80        }
81    }
82}
83
84/// An enumeration to specify the type of transport to use.
85#[derive(Debug, Clone, Copy, PartialEq, Eq)]
86pub enum TransportType {
87    /// Standard library TCP transport implementation.
88    StdTcp,
89    /// Standard library Serial transport implementation.
90    StdSerial(SerialMode),
91    /// Custom TCP transport implementation.
92    CustomTcp,
93    /// Custom Serial transport implementation.
94    CustomSerial(SerialMode),
95}
96
97impl TransportType {
98    /// Returns `true` if the transport type is TCP (StdTcp or CustomTcp).
99    pub fn is_tcp_type(&self) -> bool {
100        matches!(self, TransportType::StdTcp | TransportType::CustomTcp)
101    }
102
103    /// Returns `true` if the transport type is serial (RTU or ASCII).
104    pub fn is_serial_type(&self) -> bool {
105        matches!(
106            self,
107            TransportType::StdSerial(_) | TransportType::CustomSerial(_)
108        )
109    }
110}