1use std::fmt;
2
3use crate::models::{EnterpriseErrorBody, ErrorBody};
4
5pub type Result<T> = std::result::Result<T, Error>;
6
7#[derive(Debug)]
8pub enum Error {
9 Api {
10 status: u16,
11 error: Option<ErrorBody>,
12 body: Option<String>,
13 },
14 Transport(ureq::Error),
15 InvalidBaseUrl(String),
16 MissingLocationHeader,
17}
18
19impl Error {
20 pub fn status(&self) -> Option<u16> {
22 match self {
23 Error::Api { status, .. } => Some(*status),
24 _ => None,
25 }
26 }
27
28 pub fn api_error(&self) -> Option<&ErrorBody> {
30 match self {
31 Error::Api { error, .. } => error.as_ref(),
32 _ => None,
33 }
34 }
35
36 pub fn enterprise_error(&self) -> Option<EnterpriseErrorBody> {
38 match self {
39 Error::Api { body, .. } => body
40 .as_ref()
41 .and_then(|body| serde_json::from_str::<EnterpriseErrorBody>(body).ok()),
42 _ => None,
43 }
44 }
45
46 pub fn body(&self) -> Option<&str> {
48 match self {
49 Error::Api { body, .. } => body.as_deref(),
50 _ => None,
51 }
52 }
53}
54
55impl fmt::Display for Error {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 match self {
58 Error::Api {
59 status,
60 error: Some(error),
61 ..
62 } => write!(
63 f,
64 "api error (status {}): {} ({})",
65 status, error.error.code, error.error.message
66 ),
67 Error::Api { status, .. } => write!(f, "api error (status {})", status),
68 Error::Transport(err) => write!(f, "transport error: {}", err),
69 Error::InvalidBaseUrl(url) => write!(f, "invalid base url: {}", url),
70 Error::MissingLocationHeader => {
71 write!(f, "missing Location header in redirect response")
72 }
73 }
74 }
75}
76
77impl std::error::Error for Error {}
78
79impl From<ureq::Error> for Error {
80 fn from(err: ureq::Error) -> Self {
81 Error::Transport(err)
82 }
83}