1use thiserror::Error;
2
3#[derive(Debug, Error)]
4pub enum CanvasError {
5 #[error("Bad request: {message}")]
6 BadRequest {
7 message: String,
8 errors: Vec<ApiError>,
9 },
10
11 #[error("Invalid access token: {0}")]
12 InvalidAccessToken(String),
13
14 #[error("Unauthorized: {0}")]
15 Unauthorized(String),
16
17 #[error("Forbidden: {0}")]
18 Forbidden(String),
19
20 #[error("Resource does not exist")]
21 ResourceDoesNotExist,
22
23 #[error("Conflict: {0}")]
24 Conflict(String),
25
26 #[error("Unprocessable entity: {0}")]
27 UnprocessableEntity(String),
28
29 #[error("Rate limit exceeded (X-Rate-Limit-Remaining: {remaining:?})")]
30 RateLimitExceeded { remaining: Option<String> },
31
32 #[error("Canvas API error (status {status}): {message}")]
33 ApiError { status: u16, message: String },
34
35 #[error(transparent)]
36 Http(#[from] reqwest::Error),
37
38 #[error(transparent)]
39 Json(#[from] serde_json::Error),
40
41 #[error(transparent)]
42 Url(#[from] url::ParseError),
43
44 #[error(transparent)]
45 Io(#[from] std::io::Error),
46}
47
48#[derive(Debug, Clone, serde::Deserialize)]
49pub struct ApiError {
50 pub message: Option<String>,
51 #[serde(rename = "type")]
52 pub error_type: Option<String>,
53}
54
55#[derive(Debug, serde::Deserialize)]
56pub(crate) struct CanvasErrorBody {
57 pub errors: Option<Vec<ApiError>>,
58 pub error: Option<String>,
59 #[allow(dead_code)] pub error_report_id: Option<u64>,
61}
62
63pub type Result<T> = std::result::Result<T, CanvasError>;