coil_customer_sdk/
error.rs1use std::error::Error;
2use std::fmt;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum BackendErrorKind {
6 InvalidInput,
7 Unauthorized,
8 Forbidden,
9 Conflict,
10 Unavailable,
11 Timeout,
12 Unsupported,
13 Internal,
14}
15
16impl BackendErrorKind {
17 pub const fn as_str(self) -> &'static str {
18 match self {
19 Self::InvalidInput => "invalid_input",
20 Self::Unauthorized => "unauthorized",
21 Self::Forbidden => "forbidden",
22 Self::Conflict => "conflict",
23 Self::Unavailable => "unavailable",
24 Self::Timeout => "timeout",
25 Self::Unsupported => "unsupported",
26 Self::Internal => "internal",
27 }
28 }
29}
30
31#[derive(Debug, Clone, PartialEq, Eq)]
32pub struct BackendError {
33 kind: BackendErrorKind,
34 code: String,
35 message: String,
36 detail: Option<String>,
37}
38
39impl BackendError {
40 pub fn new(
41 kind: BackendErrorKind,
42 code: impl Into<String>,
43 message: impl Into<String>,
44 ) -> Self {
45 Self {
46 kind,
47 code: code.into(),
48 message: message.into(),
49 detail: None,
50 }
51 }
52
53 pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
54 self.detail = Some(detail.into());
55 self
56 }
57
58 pub const fn kind(&self) -> BackendErrorKind {
59 self.kind
60 }
61
62 pub fn code(&self) -> &str {
63 self.code.as_str()
64 }
65
66 pub fn message(&self) -> &str {
67 self.message.as_str()
68 }
69
70 pub fn detail(&self) -> Option<&str> {
71 self.detail.as_deref()
72 }
73}
74
75impl fmt::Display for BackendError {
76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77 match &self.detail {
78 Some(detail) => write!(
79 f,
80 "{}:{}: {} ({detail})",
81 self.kind.as_str(),
82 self.code,
83 self.message
84 ),
85 None => write!(f, "{}:{}: {}", self.kind.as_str(), self.code, self.message),
86 }
87 }
88}
89
90impl Error for BackendError {}