Skip to main content

entelix_cloud/
error.rs

1//! Crate-local error type. Surfaces to callers as
2//! `entelix_core::Error::Provider` (or `Config`) at the Transport
3//! boundary.
4
5use thiserror::Error;
6
7use entelix_core::error::Error;
8
9/// Failures emitted by cloud-layer machinery (credential resolution,
10/// signing, refreshable token plumbing, binary frame parsing).
11#[derive(Debug, Error)]
12#[non_exhaustive]
13pub enum CloudError {
14    /// Credential resolver returned an error or no credentials.
15    #[error("credential resolution failed: {message}")]
16    Credential {
17        /// Human-readable summary.
18        message: String,
19        /// Underlying credential-provider error.
20        #[source]
21        source: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
22    },
23
24    /// SigV4 / AAD signing failed.
25    #[error("signing failed: {message}")]
26    Signing {
27        /// Human-readable summary.
28        message: String,
29        /// Underlying signer error.
30        #[source]
31        source: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
32    },
33
34    /// Network / HTTP failure.
35    #[error("network failure: {message}")]
36    Network {
37        /// Human-readable summary.
38        message: String,
39        /// Underlying transport error.
40        #[source]
41        source: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
42    },
43
44    /// Configuration error — missing region, malformed URL, etc.
45    #[error("configuration error: {0}")]
46    Config(String),
47
48    /// Event-stream frame parser failure (Bedrock binary protocol).
49    #[cfg(feature = "aws")]
50    #[cfg_attr(docsrs, doc(cfg(feature = "aws")))]
51    #[error("event-stream decode failed: {0}")]
52    EventStream(#[from] crate::bedrock::event_stream::EventStreamParseError),
53}
54
55impl CloudError {
56    /// Wrap a credential-provider failure preserving the source chain.
57    pub fn credential<E>(source: E) -> Self
58    where
59        E: std::error::Error + Send + Sync + 'static,
60    {
61        Self::Credential {
62            message: source.to_string(),
63            source: Some(Box::new(source)),
64        }
65    }
66
67    /// Construct a [`CloudError::Credential`] from a bare message.
68    pub fn credential_msg(message: impl Into<String>) -> Self {
69        Self::Credential {
70            message: message.into(),
71            source: None,
72        }
73    }
74
75    /// Wrap a signer failure preserving the source chain.
76    pub fn signing<E>(source: E) -> Self
77    where
78        E: std::error::Error + Send + Sync + 'static,
79    {
80        Self::Signing {
81            message: source.to_string(),
82            source: Some(Box::new(source)),
83        }
84    }
85
86    /// Construct a [`CloudError::Signing`] from a bare message.
87    pub fn signing_msg(message: impl Into<String>) -> Self {
88        Self::Signing {
89            message: message.into(),
90            source: None,
91        }
92    }
93
94    /// Wrap a transport failure preserving the source chain.
95    pub fn network<E>(source: E) -> Self
96    where
97        E: std::error::Error + Send + Sync + 'static,
98    {
99        Self::Network {
100            message: source.to_string(),
101            source: Some(Box::new(source)),
102        }
103    }
104
105    /// Construct a [`CloudError::Network`] from a bare message.
106    pub fn network_msg(message: impl Into<String>) -> Self {
107        Self::Network {
108            message: message.into(),
109            source: None,
110        }
111    }
112}
113
114impl From<CloudError> for Error {
115    fn from(err: CloudError) -> Self {
116        match err {
117            CloudError::Config(msg) => Self::config(msg),
118            other => Self::provider_network_from(other),
119        }
120    }
121}