1use thiserror::Error;
4
5pub type Result<T> = std::result::Result<T, Error>;
7
8#[derive(Error, Debug)]
10pub enum Error {
11 #[error("Transport error in {context}")]
13 Transport {
14 #[source]
15 source: zenoh::Error,
16 context: String,
17 },
18
19 #[error("Message serialization failed for type {type_name}")]
21 MessageSerialization {
22 #[source]
23 source: prost::EncodeError,
24 type_name: &'static str,
25 },
26
27 #[error("Message deserialization failed for type {type_name}")]
29 MessageDeserialization {
30 #[source]
31 source: prost::DecodeError,
32 type_name: &'static str,
33 },
34
35 #[error("Serialization error: {0}")]
37 Serialization(String),
38
39 #[error("Encoding error: {0}")]
41 Encoding(#[from] prost::EncodeError),
42
43 #[error("Decoding error: {0}")]
45 Decoding(#[from] prost::DecodeError),
46
47 #[error("Node '{name}' already exists")]
49 NodeAlreadyExists { name: String },
50
51 #[error("Topic '{topic}' already exists on node '{node}'")]
53 TopicAlreadyExists { topic: String, node: String },
54
55 #[error("Service '{service}' already exists on node '{node}'")]
57 ServiceAlreadyExists { service: String, node: String },
58
59 #[error("Service call to '{service}' timed out after {timeout_ms}ms")]
61 ServiceCallTimeout { service: String, timeout_ms: u64 },
62
63 #[error("Service call to '{service}' failed: {reason}")]
65 ServiceCallFailed { service: String, reason: String },
66
67 #[error("Parameter '{name}' error: {reason}")]
69 Parameter { name: String, reason: String },
70
71 #[error("Node '{node}' error: {reason}")]
73 Node { node: String, reason: String },
74
75 #[error("Publisher for topic '{topic}' error: {reason}")]
77 Publisher { topic: String, reason: String },
78
79 #[error("Subscriber for topic '{topic}' error: {reason}")]
81 Subscriber { topic: String, reason: String },
82
83 #[error("Service '{service}' error: {reason}")]
85 Service { service: String, reason: String },
86
87 #[error("Client for service '{service}' error: {reason}")]
89 Client { service: String, reason: String },
90
91 #[error("Operation '{operation}' not supported: {reason}")]
93 NotSupported { operation: String, reason: String },
94
95 #[error("Operation '{operation}' not implemented: {reason}")]
97 NotImplemented { operation: String, reason: String },
98
99 #[error("Configuration error: {reason}")]
101 Configuration { reason: String },
102
103 #[error("Network error: {reason}")]
105 Network { reason: String },
106
107 #[error("Error: {reason}")]
109 Other { reason: String },
110}
111
112impl From<zenoh::Error> for Error {
113 fn from(err: zenoh::Error) -> Self {
114 Error::Transport {
115 source: err,
116 context: "unknown".to_string(),
117 }
118 }
119}
120
121pub trait ErrorContext<T> {
123 fn with_context(self, context: &str) -> Result<T>;
125 fn with_context_f<F>(self, f: F) -> Result<T>
127 where
128 F: FnOnce() -> String;
129}
130
131impl<T> ErrorContext<T> for Result<T> {
132 fn with_context(self, context: &str) -> Result<T> {
133 self.map_err(|err| match err {
134 Error::Transport { source, .. } => Error::Transport {
135 source,
136 context: context.to_string(),
137 },
138 other => other,
139 })
140 }
141
142 fn with_context_f<F>(self, f: F) -> Result<T>
143 where
144 F: FnOnce() -> String,
145 {
146 self.map_err(|err| match err {
147 Error::Transport { source, .. } => Error::Transport {
148 source,
149 context: f(),
150 },
151 other => other,
152 })
153 }
154}
155
156impl Error {
158 pub fn transport(source: zenoh::Error, context: impl Into<String>) -> Self {
160 Error::Transport {
161 source,
162 context: context.into(),
163 }
164 }
165
166 pub fn message_serialization(source: prost::EncodeError, type_name: &'static str) -> Self {
168 Error::MessageSerialization { source, type_name }
169 }
170
171 pub fn message_deserialization(source: prost::DecodeError, type_name: &'static str) -> Self {
173 Error::MessageDeserialization { source, type_name }
174 }
175
176 pub fn node_already_exists(name: impl Into<String>) -> Self {
178 Error::NodeAlreadyExists { name: name.into() }
179 }
180
181 pub fn topic_already_exists(topic: impl Into<String>, node: impl Into<String>) -> Self {
183 Error::TopicAlreadyExists {
184 topic: topic.into(),
185 node: node.into(),
186 }
187 }
188
189 pub fn service_already_exists(service: impl Into<String>, node: impl Into<String>) -> Self {
191 Error::ServiceAlreadyExists {
192 service: service.into(),
193 node: node.into(),
194 }
195 }
196
197 pub fn service_call_timeout(service: impl Into<String>, timeout_ms: u64) -> Self {
199 Error::ServiceCallTimeout {
200 service: service.into(),
201 timeout_ms,
202 }
203 }
204
205 pub fn service_call_failed(service: impl Into<String>, reason: impl Into<String>) -> Self {
207 Error::ServiceCallFailed {
208 service: service.into(),
209 reason: reason.into(),
210 }
211 }
212
213 pub fn parameter(name: impl Into<String>, reason: impl Into<String>) -> Self {
215 Error::Parameter {
216 name: name.into(),
217 reason: reason.into(),
218 }
219 }
220
221 pub fn node(node: impl Into<String>, reason: impl Into<String>) -> Self {
223 Error::Node {
224 node: node.into(),
225 reason: reason.into(),
226 }
227 }
228
229 pub fn publisher(topic: impl Into<String>, reason: impl Into<String>) -> Self {
231 Error::Publisher {
232 topic: topic.into(),
233 reason: reason.into(),
234 }
235 }
236
237 pub fn subscriber(topic: impl Into<String>, reason: impl Into<String>) -> Self {
239 Error::Subscriber {
240 topic: topic.into(),
241 reason: reason.into(),
242 }
243 }
244
245 pub fn service(service: impl Into<String>, reason: impl Into<String>) -> Self {
247 Error::Service {
248 service: service.into(),
249 reason: reason.into(),
250 }
251 }
252
253 pub fn client(service: impl Into<String>, reason: impl Into<String>) -> Self {
255 Error::Client {
256 service: service.into(),
257 reason: reason.into(),
258 }
259 }
260
261 pub fn configuration(reason: impl Into<String>) -> Self {
263 Error::Configuration {
264 reason: reason.into(),
265 }
266 }
267
268 pub fn network(reason: impl Into<String>) -> Self {
270 Error::Network {
271 reason: reason.into(),
272 }
273 }
274
275 pub fn other(reason: impl Into<String>) -> Self {
277 Error::Other {
278 reason: reason.into(),
279 }
280 }
281}