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: {raw} - body: {body}")]
26    Http {
27        /// The HTTP error.
28        raw: ReqwError,
29        /// The response body.
30        body: String,
31    },
32    /// URL parsing error.
33    #[error("URL parse error: {0}")]
34    UrlParse(ParseError),
35    /// WebSocket error.
36    #[error("WebSocket error: {0}")]
37    Websocket(WSError),
38    /// Internal error.
39    #[error("Internal error: {0}")]
40    Internal(String),
41}
42
43impl AriError {
44    /// Creates a new `AriError` with the given status code and optional content.
45    ///
46    /// # Arguments
47    ///
48    /// * `code` - The HTTP status code.
49    /// * `content` - Optional content associated with the error.
50    ///
51    /// # Returns
52    ///
53    /// A new instance of `AriError`.
54    pub fn new(code: StatusCode, content: Option<String>) -> Self {
55        AriError::Api(ApiError { code, content })
56    }
57}
58
59/// Result type alias for operations that can return an `AriError`.
60pub type Result<T> = result::Result<T, AriError>;
61
62/// Represents an API-specific error.
63#[derive(Debug)]
64pub struct ApiError {
65    /// The HTTP status code associated with the error.
66    pub code: StatusCode,
67    /// Optional content associated with the error.
68    pub content: Option<String>,
69}
70
71impl From<ParseError> for AriError {
72    /// Converts a `ParseError` into an `AriError`.
73    ///
74    /// # Arguments
75    ///
76    /// * `e` - The `ParseError` to convert.
77    ///
78    /// # Returns
79    ///
80    /// An `AriError` representing the URL parsing error.
81    fn from(e: ParseError) -> Self {
82        AriError::UrlParse(e)
83    }
84}
85
86impl From<WSError> for AriError {
87    /// Converts a `WSError` into an `AriError`.
88    ///
89    /// # Arguments
90    ///
91    /// * `e` - The `WSError` to convert.
92    ///
93    /// # Returns
94    ///
95    /// An `AriError` representing the WebSocket error.
96    fn from(e: WSError) -> Self {
97        AriError::Websocket(e)
98    }
99}
100
101impl<T: std::fmt::Display> From<tokio::sync::MutexGuard<'_, T>> for AriError {
102    /// Converts a `tokio::sync::MutexGuard<'_, T>` into an `AriError`.
103    ///
104    /// # Arguments
105    ///
106    /// * `e` - The `tokio::sync::MutexGuard<'_, T>` to convert.
107    ///
108    /// # Returns
109    ///
110    /// An `AriError` representing the poisoned mutex error.
111    fn from(e: tokio::sync::MutexGuard<'_, T>) -> Self {
112        AriError::Internal(format!("{}", e))
113    }
114}
115
116impl<T> From<PoisonError<MutexGuard<'_, T>>> for AriError {
117    /// Converts a `PoisonError<MutexGuard<'_, T>>` into an `AriError`.
118    ///
119    /// # Arguments
120    ///
121    /// * `e` - The `PoisonError<MutexGuard<'_, T>>` to convert.
122    ///
123    /// # Returns
124    ///
125    /// An `AriError` representing the poisoned mutex error.
126    fn from(e: PoisonError<MutexGuard<'_, T>>) -> Self {
127        AriError::Internal(format!("{}", e))
128    }
129}
130
131impl Display for ApiError {
132    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
133        match &self.content {
134            Some(content) => write!(f, "API error (status {}): {}", self.code, content),
135            None => write!(f, "API error (status {})", self.code),
136        }
137    }
138}
139
140impl Error for ApiError {}