1mod decode;
4mod status;
5mod value_error;
6
7use core::convert::Infallible;
8use core::fmt::{self, Debug, Display, Formatter};
9
10pub use decode::Decode;
11pub use status::Status;
12#[allow(clippy::module_name_repetitions)]
13pub use value_error::ValueError;
14
15use crate::frame::parameters::configuration::version;
16use crate::frame::parameters::utilities::invalid_command;
17use crate::parameters::utilities;
18use crate::{Parameters, Response, ember, ezsp};
19
20#[derive(Debug)]
22pub enum Error {
23 Io(std::io::Error),
25 Decode(Decode),
27 Status(Status),
29 UnexpectedResponse(Box<Parameters>),
31 ValueError(ValueError),
33 InvalidCommand(invalid_command::Response),
35 ProtocolVersionMismatch {
37 desired: u8,
39 negotiated: version::Response,
41 },
42}
43
44impl Display for Error {
45 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
46 match self {
47 Self::Io(error) => Display::fmt(error, f),
48 Self::Decode(decode) => Display::fmt(decode, f),
49 Self::Status(status) => Display::fmt(status, f),
50 Self::UnexpectedResponse(response) => write!(f, "Unexpected response: {response:?}"),
51 Self::ValueError(status) => Display::fmt(status, f),
52 Self::InvalidCommand(response) => write!(f, "Invalid command: {response}"),
53 Self::ProtocolVersionMismatch {
54 desired,
55 negotiated,
56 } => {
57 write!(
58 f,
59 "Protocol negotiation failed: {desired:#04X} (desired) != {:#04X} (negotiated)",
60 negotiated.protocol_version()
61 )
62 }
63 }
64 }
65}
66
67impl core::error::Error for Error {
68 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
69 match self {
70 Self::Io(error) => Some(error),
71 Self::Decode(decode) => Some(decode),
72 Self::Status(status) => Some(status),
73 Self::ValueError(value_error) => Some(value_error),
74 Self::UnexpectedResponse(_)
75 | Self::InvalidCommand(_)
76 | Self::ProtocolVersionMismatch { .. } => None,
77 }
78 }
79}
80
81impl From<std::io::Error> for Error {
82 fn from(error: std::io::Error) -> Self {
83 Self::Io(error)
84 }
85}
86
87impl From<Decode> for Error {
88 fn from(decode: Decode) -> Self {
89 Self::Decode(decode)
90 }
91}
92
93impl From<le_stream::Error> for Error {
94 fn from(error: le_stream::Error) -> Self {
95 Self::Decode(error.into())
96 }
97}
98
99impl From<Status> for Error {
100 fn from(status: Status) -> Self {
101 Self::Status(status)
102 }
103}
104
105impl From<Result<ezsp::Status, u8>> for Error {
106 fn from(status: Result<ezsp::Status, u8>) -> Self {
107 Self::Status(status.into())
108 }
109}
110
111impl From<Result<ember::Status, u8>> for Error {
112 fn from(status: Result<ember::Status, u8>) -> Self {
113 Self::Status(status.into())
114 }
115}
116
117impl From<Result<silizium::Status, u32>> for Error {
118 fn from(status: Result<silizium::Status, u32>) -> Self {
119 Self::Status(status.into())
120 }
121}
122
123impl From<ezsp::Status> for Error {
124 fn from(status: ezsp::Status) -> Self {
125 Self::Status(status.into())
126 }
127}
128
129impl From<ember::Status> for Error {
130 fn from(status: ember::Status) -> Self {
131 Self::Status(status.into())
132 }
133}
134
135impl From<silizium::Status> for Error {
136 fn from(status: silizium::Status) -> Self {
137 Self::Status(status.into())
138 }
139}
140
141impl From<Parameters> for Error {
142 fn from(parameters: Parameters) -> Self {
143 if let Parameters::Response(Response::Utilities(utilities::Response::InvalidCommand(
144 invalid_command,
145 ))) = parameters
146 {
147 Self::InvalidCommand(invalid_command)
148 } else {
149 Self::UnexpectedResponse(parameters.into())
150 }
151 }
152}
153
154impl From<ValueError> for Error {
155 fn from(status: ValueError) -> Self {
156 Self::ValueError(status)
157 }
158}
159
160impl From<invalid_command::Response> for Error {
161 fn from(response: invalid_command::Response) -> Self {
162 Self::InvalidCommand(response)
163 }
164}
165
166impl From<Infallible> for Error {
167 fn from(infallible: Infallible) -> Self {
168 match infallible {}
169 }
170}