1use std::{
5 borrow::{Borrow, Cow},
6 convert::Infallible,
7 fmt,
8};
9
10pub type Result<T> = std::result::Result<T, Error>;
11
12#[derive(Clone, Debug, PartialEq, Eq)]
13pub enum ErrorKind {
14 InvalidData,
15 Io,
16 Other,
17}
18
19impl fmt::Display for ErrorKind {
20 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21 match self {
23 ErrorKind::InvalidData => f.write_str("InvalidData"),
24 ErrorKind::Io => f.write_str("Io"),
25 ErrorKind::Other => f.write_str("Other"),
26 }
27 }
28}
29
30#[derive(Debug)]
31pub struct Error {
32 repr: Repr,
33}
34
35impl Error {
36 pub fn new<E>(kind: ErrorKind, error: E) -> Self
38 where
39 E: Into<Box<dyn std::error::Error + Send + Sync>>,
40 {
41 Self {
42 repr: Repr::Custom(Custom {
43 kind,
44 error: error.into(),
45 }),
46 }
47 }
48
49 pub fn kind(&self) -> &ErrorKind {
51 match &self.repr {
52 Repr::Simple(kind)
53 | Repr::SimpleMessage(kind, ..)
54 | Repr::Custom(Custom { kind, .. }) => kind,
55 }
56 }
57
58 pub fn message(&self) -> Option<&str> {
60 match &self.repr {
61 Repr::SimpleMessage(_, message) => Some(message.borrow()),
62 _ => None,
63 }
64 }
65
66 #[must_use]
67 pub fn with_message<C>(kind: ErrorKind, message: C) -> Self
68 where
69 C: Into<Cow<'static, str>>,
70 {
71 Self {
72 repr: Repr::SimpleMessage(kind, message.into()),
73 }
74 }
75
76 #[must_use]
77 pub fn with_message_fn<F, C>(kind: ErrorKind, message: F) -> Self
78 where
79 Self: Sized,
80 F: FnOnce() -> C,
81 C: Into<Cow<'static, str>>,
82 {
83 Self {
84 repr: Repr::SimpleMessage(kind, message().into()),
85 }
86 }
87}
88
89impl fmt::Display for Error {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 match &self.repr {
92 Repr::Simple(kind) => write!(f, "{kind}"),
93 Repr::SimpleMessage(_, message) => write!(f, "{message}"),
94 Repr::Custom(Custom { error, .. }) => write!(f, "{error}"),
95 }
96 }
97}
98
99impl std::error::Error for Error {
100 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
101 match &self.repr {
102 Repr::Custom(Custom { error, .. }) => Some(&**error),
103 _ => None,
104 }
105 }
106}
107
108impl From<ErrorKind> for Error {
109 fn from(kind: ErrorKind) -> Self {
110 Self {
111 repr: Repr::Simple(kind),
112 }
113 }
114}
115
116impl From<String> for Error {
117 fn from(value: String) -> Self {
118 Self::with_message(ErrorKind::Other, value)
119 }
120}
121
122impl From<Infallible> for Error {
123 fn from(_: Infallible) -> Self {
124 panic!("inconceivable")
125 }
126}
127
128impl From<std::io::Error> for Error {
129 fn from(error: std::io::Error) -> Self {
130 Self::new(ErrorKind::Io, error)
131 }
132}
133
134impl From<std::num::ParseIntError> for Error {
135 fn from(error: std::num::ParseIntError) -> Self {
136 Self::new(ErrorKind::InvalidData, error)
137 }
138}
139
140impl From<std::env::VarError> for Error {
141 fn from(error: std::env::VarError) -> Self {
142 Self::new(ErrorKind::Other, error)
143 }
144}
145
146impl From<azure_core::Error> for Error {
147 fn from(error: azure_core::Error) -> Self {
148 Self::new(ErrorKind::Other, error)
149 }
150}
151
152impl From<dotenvy::Error> for Error {
153 fn from(error: dotenvy::Error) -> Self {
154 Self::new(ErrorKind::Other, error)
155 }
156}
157
158impl From<url::ParseError> for Error {
159 fn from(error: url::ParseError) -> Self {
160 Self::new(ErrorKind::InvalidData, error)
161 }
162}
163
164#[derive(Debug)]
165enum Repr {
166 Simple(ErrorKind),
167 SimpleMessage(ErrorKind, Cow<'static, str>),
168 Custom(Custom),
169}
170
171#[derive(Debug)]
172struct Custom {
173 kind: ErrorKind,
174 error: Box<dyn std::error::Error + Send + Sync>,
175}