Skip to main content

cloudconvert_sdk/
error.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4use crate::jobs::RateLimit;
5
6pub type Result<T, E = Error> = std::result::Result<T, E>;
7
8#[derive(Debug, thiserror::Error)]
9#[non_exhaustive]
10pub enum Error {
11    #[error("CloudConvert API returned HTTP {status}: {message}")]
12    Api {
13        status: u16,
14        message: String,
15        code: Option<String>,
16        errors: Option<Box<Value>>,
17        rate_limit: Option<Box<RateLimit>>,
18    },
19
20    #[error("HTTP request failed: {0}")]
21    Http(#[from] reqwest::Error),
22
23    #[error("local IO failed: {0}")]
24    Io(#[from] std::io::Error),
25
26    #[error("URL parsing failed: {0}")]
27    Url(#[from] url::ParseError),
28
29    #[error("JSON serialization failed: {0}")]
30    Json(#[from] serde_json::Error),
31
32    #[error("missing required environment variable {0}")]
33    MissingEnv(&'static str),
34
35    #[error("task is not an import/upload task that is ready for upload")]
36    UploadTaskNotReady,
37
38    #[error("CloudConvert redirect response did not include a valid Location header")]
39    MissingRedirectLocation,
40
41    #[error("webhook signature is not valid hex")]
42    InvalidSignatureHex,
43
44    #[error("invalid CloudConvert API path")]
45    InvalidApiPath,
46
47    #[error("invalid CloudConvert resource id")]
48    InvalidResourceId,
49
50    #[error("invalid CloudConvert region")]
51    InvalidRegion,
52
53    #[cfg(feature = "socket")]
54    #[error("Socket.IO operation failed: {0}")]
55    Socket(String),
56}
57
58impl Error {
59    pub fn api_error(&self) -> Option<ApiError<'_>> {
60        match self {
61            Self::Api {
62                status,
63                message,
64                code,
65                errors,
66                rate_limit,
67            } => Some(ApiError {
68                status: *status,
69                message,
70                code: code.as_deref(),
71                errors: errors.as_deref(),
72                rate_limit: rate_limit.as_deref(),
73                retry_after: rate_limit
74                    .as_ref()
75                    .and_then(|rate_limit| rate_limit.retry_after),
76            }),
77            _ => None,
78        }
79    }
80}
81
82#[derive(Clone, Copy, Debug)]
83#[non_exhaustive]
84pub struct ApiError<'a> {
85    pub status: u16,
86    pub message: &'a str,
87    pub code: Option<&'a str>,
88    pub errors: Option<&'a Value>,
89    pub rate_limit: Option<&'a RateLimit>,
90    pub retry_after: Option<u64>,
91}
92
93#[derive(Debug, Deserialize, Serialize)]
94pub(crate) struct ApiErrorBody {
95    pub message: Option<String>,
96    pub code: Option<String>,
97    pub errors: Option<Value>,
98}