asterisk_ari/
errors.rs

1use reqwest::Error as ReqwError;
2use reqwest::StatusCode;
3use std::error::Error;
4use std::fmt::Display;
5use std::fmt::{Formatter, Result as FmtResult};
6use std::result;
7use std::sync::{MutexGuard, PoisonError};
8use thiserror::Error;
9use tokio_tungstenite::tungstenite::Error as WSError;
10use url::ParseError;
11
12/// Represents various errors that can occur in the ARI client.
13#[derive(Debug, Error)]
14pub enum AriError {
15    /// Error during JSON serialization/deserialization.
16    #[error("serde error: {0}")]
17    Serde(#[from] serde_json::Error),
18    /// Error converting a byte array to a UTF-8 string.
19    #[error("Conversion error: {0}")]
20    Utf8(#[from] std::string::FromUtf8Error),
21    /// API-specific error.
22    #[error("Api Error: {0}")]
23    Api(ApiError),
24    /// General HTTP error.
25    #[error("HTTP error: {0}")]
26    Http(ReqwError),
27    /// URL parsing error.
28    #[error("URL parse error: {0}")]
29    UrlParse(ParseError),
30    /// WebSocket error.
31    #[error("WebSocket error: {0}")]
32    Websocket(WSError),
33    /// Internal error.
34    #[error("Internal error: {0}")]
35    Internal(String),
36}
37
38impl AriError {
39    /// Creates a new `AriError` with the given status code and optional content.
40    ///
41    /// # Arguments
42    ///
43    /// * `code` - The HTTP status code.
44    /// * `content` - Optional content associated with the error.
45    ///
46    /// # Returns
47    ///
48    /// A new instance of `AriError`.
49    pub fn new(code: StatusCode, content: Option<String>) -> Self {
50        AriError::Api(ApiError { code, content })
51    }
52}
53
54/// Result type alias for operations that can return an `AriError`.
55pub type Result<T> = result::Result<T, AriError>;
56
57/// Represents an API-specific error.
58#[derive(Debug)]
59pub struct ApiError {
60    /// The HTTP status code associated with the error.
61    pub code: StatusCode,
62    /// Optional content associated with the error.
63    pub content: Option<String>,
64}
65
66impl From<ParseError> for AriError {
67    /// Converts a `ParseError` into an `AriError`.
68    ///
69    /// # Arguments
70    ///
71    /// * `e` - The `ParseError` to convert.
72    ///
73    /// # Returns
74    ///
75    /// An `AriError` representing the URL parsing error.
76    fn from(e: ParseError) -> Self {
77        AriError::UrlParse(e)
78    }
79}
80
81impl From<WSError> for AriError {
82    /// Converts a `WSError` into an `AriError`.
83    ///
84    /// # Arguments
85    ///
86    /// * `e` - The `WSError` to convert.
87    ///
88    /// # Returns
89    ///
90    /// An `AriError` representing the WebSocket error.
91    fn from(e: WSError) -> Self {
92        AriError::Websocket(e)
93    }
94}
95
96impl From<ReqwError> for AriError {
97    /// Converts a `ReqwError` into an `AriError`.
98    ///
99    /// # Arguments
100    ///
101    /// * `e` - The `ReqwError` to convert.
102    ///
103    /// # Returns
104    ///
105    /// An `AriError` representing the HTTP error.
106    fn from(e: ReqwError) -> Self {
107        AriError::Http(e)
108    }
109}
110
111impl<T: std::fmt::Display> From<tokio::sync::MutexGuard<'_, T>> for AriError {
112    /// Converts a `tokio::sync::MutexGuard<'_, T>` into an `AriError`.
113    ///
114    /// # Arguments
115    ///
116    /// * `e` - The `tokio::sync::MutexGuard<'_, T>` to convert.
117    ///
118    /// # Returns
119    ///
120    /// An `AriError` representing the poisoned mutex error.
121    fn from(e: tokio::sync::MutexGuard<'_, T>) -> Self {
122        AriError::Internal(format!("{}", e))
123    }
124}
125
126impl<T> From<PoisonError<MutexGuard<'_, T>>> for AriError {
127    /// Converts a `PoisonError<MutexGuard<'_, T>>` into an `AriError`.
128    ///
129    /// # Arguments
130    ///
131    /// * `e` - The `PoisonError<MutexGuard<'_, T>>` to convert.
132    ///
133    /// # Returns
134    ///
135    /// An `AriError` representing the poisoned mutex error.
136    fn from(e: PoisonError<MutexGuard<'_, T>>) -> Self {
137        AriError::Internal(format!("{}", e))
138    }
139}
140
141impl Display for ApiError {
142    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
143        match &self.content {
144            Some(content) => write!(f, "API error (status {}): {}", self.code, content),
145            None => write!(f, "API error (status {})", self.code),
146        }
147    }
148}
149
150impl Error for ApiError {}