astarte_device_sdk/
error.rs1use std::convert::Infallible;
22use std::fmt::{Display, Formatter};
23
24use astarte_interfaces::error::Error as InterfaceError;
25use astarte_interfaces::mapping::path::MappingPathError;
26use astarte_interfaces::schema::{Aggregation, InterfaceType, Ownership};
27
28use crate::builder::BuilderError;
29use crate::introspection::AddInterfaceError;
30use crate::properties::PropertiesError;
31use crate::retention::RetentionError;
32use crate::session::SessionError;
33use crate::store::error::StoreError;
34use crate::transport::mqtt::error::MqttError;
35use crate::types::TypeError;
36use crate::validate::UserValidationError;
37
38pub(crate) type DynError = Box<dyn std::error::Error + Send + Sync + 'static>;
40
41#[non_exhaustive]
45#[derive(thiserror::Error, Debug)]
46pub enum Error {
47 #[error("connection reached max retries")]
49 ConnectionTimeout,
50 #[error("couldn't parse interface")]
52 Interface(#[from] InterfaceError),
53 #[error("couldn't complete introspection operation")]
55 AddInterface(#[from] AddInterfaceError),
56 #[error("couldn't find interface '{name}'")]
58 InterfaceNotFound {
59 name: String,
61 },
62 #[error("couldn't find mapping {mapping} in interface {interface}")]
64 MappingNotFound {
65 interface: String,
67 mapping: String,
69 },
70 #[error("invalid mapping path")]
72 InvalidEndpoint(#[from] MappingPathError),
73 #[error("couldn't convert to Astarte Type")]
75 Types(#[from] TypeError),
76 #[error("couldn't handle properties")]
78 Properties(#[from] PropertiesError),
79 #[error("couldn't complete store operation")]
81 Store(#[from] StoreError),
82 #[error("validation of the send payload failed")]
84 Validation(#[from] UserValidationError),
85 #[error(transparent)]
87 Aggregation(#[from] AggregationError),
88 #[error(transparent)]
90 InterfaceType(#[from] InterfaceTypeError),
91 #[error("couldn't build the device connection and client")]
93 Builder(#[from] BuilderError),
94 #[error(transparent)]
96 Mqtt(#[from] MqttError),
97 #[error("disconnected from Astarte")]
101 Disconnected,
102 #[error("retention operation failed")]
104 Retention(#[from] RetentionError),
105 #[error("persistent session operation failed")]
107 Session(#[from] SessionError),
108 #[cfg(feature = "message-hub")]
110 #[cfg_attr(astarte_device_sdk_docsrs, doc(cfg(feature = "message-hub")))]
111 #[error(transparent)]
112 Grpc(#[from] crate::transport::grpc::GrpcError),
113 #[doc(hidden)]
115 #[error(transparent)]
116 Infallible(#[from] Infallible),
117}
118
119#[derive(Debug, thiserror::Error)]
123#[error("invalid aggregation for {interface}{path}, expected {exp} but got {got}")]
124#[non_exhaustive]
125pub struct AggregationError {
126 interface: String,
128 path: String,
130 exp: Aggregation,
132 got: Aggregation,
134}
135
136impl AggregationError {
137 #[doc(hidden)]
139 pub fn new(
140 interface: impl Into<String>,
141 path: impl Into<String>,
142 exp: Aggregation,
143 got: Aggregation,
144 ) -> Self {
145 Self {
146 interface: interface.into(),
147 path: path.into(),
148 exp,
149 got,
150 }
151 }
152}
153
154#[derive(Debug, thiserror::Error)]
156#[error("invalid interface type for {name}{}, expected {exp} but got {got}", path.as_deref().unwrap_or_default())]
157pub struct InterfaceTypeError {
158 name: String,
160 path: Option<String>,
162 exp: InterfaceType,
164 got: InterfaceType,
166}
167
168impl InterfaceTypeError {
169 pub(crate) fn new(name: impl Into<String>, exp: InterfaceType, got: InterfaceType) -> Self {
170 Self {
171 name: name.into(),
172 path: None,
173 exp,
174 got,
175 }
176 }
177
178 #[doc(hidden)]
180 pub fn with_path(
181 name: impl Into<String>,
182 path: impl Into<String>,
183 exp: InterfaceType,
184 got: InterfaceType,
185 ) -> Self {
186 Self {
187 name: name.into(),
188 path: Some(path.into()),
189 exp,
190 got,
191 }
192 }
193}
194
195#[derive(Debug, thiserror::Error)]
197#[error("invalid ownership for interface {name}, expected {exp} but got {got}")]
198pub struct OwnershipError {
199 name: String,
201 exp: Ownership,
203 got: Ownership,
205}
206
207impl OwnershipError {
208 pub(crate) fn new(name: impl Into<String>, exp: Ownership, got: Ownership) -> Self {
209 Self {
210 name: name.into(),
211 exp,
212 got,
213 }
214 }
215}
216
217pub(crate) struct Report<E = Box<dyn std::error::Error>> {
223 error: E,
225}
226
227impl<E> Report<E>
228where
229 Report<E>: From<E>,
230{
231 pub(crate) fn new(error: E) -> Self {
233 Self::from(error)
234 }
235}
236
237impl<E> From<E> for Report<E>
238where
239 E: std::error::Error,
240{
241 fn from(value: E) -> Self {
242 Self { error: value }
243 }
244}
245
246impl<E> Display for Report<E>
247where
248 E: std::error::Error,
249{
250 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
251 write!(f, "{}", self.error)?;
252
253 let mut cause: &dyn std::error::Error = &self.error;
254
255 while let Some(source) = cause.source() {
256 cause = source;
257
258 write!(f, ": {cause}")?;
259 }
260
261 Ok(())
262 }
263}
264
265impl<E> std::fmt::Debug for Report<E>
268where
269 Report<E>: Display,
270{
271 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
272 Display::fmt(self, f)
273 }
274}