modbus_relay/errors/
relay.rs1use thiserror::Error;
2
3use super::{
4 BackoffError, ClientErrorKind, ConfigValidationError, ConnectionError, FrameError,
5 FrameErrorKind, FrameFormatKind, FrameSizeKind, InitializationError, ProtocolErrorKind,
6 RtsError, TransportError,
7};
8
9#[derive(Error, Debug)]
10pub enum RelayError {
11 #[error("Transport error: {0}")]
12 Transport(#[from] TransportError),
13
14 #[error("Protocol error: {kind} - {details}")]
15 Protocol {
16 kind: ProtocolErrorKind,
17 details: String,
18 source: Option<Box<dyn std::error::Error + Send + Sync>>,
19 },
20
21 #[error("Configuration error: {0}")]
22 Config(#[from] ConfigValidationError),
23
24 #[error("Frame error: {0}")]
25 Frame(#[from] FrameError),
26
27 #[error("Connection error: {0}")]
28 Connection(#[from] ConnectionError),
29
30 #[error("Client error: {kind} from {client_addr} - {details}")]
31 Client {
32 kind: ClientErrorKind,
33 client_addr: std::net::SocketAddr,
34 details: String,
35 },
36
37 #[error("Initialization error: {0}")]
38 Init(#[from] InitializationError),
39}
40
41impl RelayError {
42 pub fn protocol(kind: ProtocolErrorKind, details: impl Into<String>) -> Self {
43 RelayError::Protocol {
44 kind,
45 details: details.into(),
46 source: None,
47 }
48 }
49
50 pub fn protocol_with_source(
51 kind: ProtocolErrorKind,
52 details: impl Into<String>,
53 source: impl Into<Box<dyn std::error::Error + Send + Sync>>,
54 ) -> Self {
55 RelayError::Protocol {
56 kind,
57 details: details.into(),
58 source: Some(source.into()),
59 }
60 }
61
62 pub fn connection(kind: ConnectionError) -> Self {
63 RelayError::Connection(kind)
64 }
65
66 pub fn config(kind: ConfigValidationError) -> Self {
67 RelayError::Config(kind)
68 }
69
70 pub fn frame(
71 kind: FrameErrorKind,
72 details: impl Into<String>,
73 frame_data: Option<Vec<u8>>,
74 ) -> Self {
75 let details = details.into();
76 match kind {
77 FrameErrorKind::TooShort | FrameErrorKind::TooLong => {
78 RelayError::Frame(FrameError::Size {
79 kind: match kind {
80 FrameErrorKind::TooShort => FrameSizeKind::TooShort,
81 FrameErrorKind::TooLong => FrameSizeKind::TooLong,
82 _ => unreachable!(),
83 },
84 details,
85 frame_data,
86 })
87 }
88 FrameErrorKind::InvalidFormat
89 | FrameErrorKind::InvalidUnitId
90 | FrameErrorKind::InvalidHeader
91 | FrameErrorKind::UnexpectedResponse => RelayError::Frame(FrameError::Format {
92 kind: match kind {
93 FrameErrorKind::InvalidFormat => FrameFormatKind::InvalidFormat,
94 FrameErrorKind::InvalidHeader => FrameFormatKind::InvalidHeader,
95 FrameErrorKind::UnexpectedResponse => FrameFormatKind::UnexpectedResponse,
96 _ => unreachable!(),
97 },
98 details,
99 frame_data,
100 }),
101 FrameErrorKind::InvalidCrc => {
102 if let Some(frame_data) = frame_data {
103 let frame_hex = hex::encode(&frame_data);
104 RelayError::Frame(FrameError::Crc {
105 calculated: 0, received: 0, frame_hex,
108 })
109 } else {
110 RelayError::Frame(FrameError::Format {
111 kind: FrameFormatKind::InvalidFormat,
112 details,
113 frame_data: None,
114 })
115 }
116 }
117 }
118 }
119
120 pub fn client(
121 kind: ClientErrorKind,
122 client_addr: std::net::SocketAddr,
123 details: impl Into<String>,
124 ) -> Self {
125 RelayError::Client {
126 kind,
127 client_addr,
128 details: details.into(),
129 }
130 }
131}
132
133impl From<BackoffError> for RelayError {
134 fn from(err: BackoffError) -> Self {
135 RelayError::Connection(ConnectionError::Backoff(err))
136 }
137}
138
139impl From<RtsError> for RelayError {
140 fn from(err: RtsError) -> Self {
141 RelayError::Transport(TransportError::Rts(err))
142 }
143}
144
145impl From<config::ConfigError> for RelayError {
146 fn from(err: config::ConfigError) -> Self {
147 Self::Config(ConfigValidationError::config(err.to_string()))
148 }
149}