1use std::error;
2use std::fmt;
3
4use instant::Duration;
5
6pub enum Error<E> {
12 Permanent(E),
15
16 Transient {
20 err: E,
21 retry_after: Option<Duration>,
22 },
23}
24
25impl<E> Error<E> {
26 pub fn permanent(err: E) -> Self {
28 Error::Permanent(err)
29 }
30
31 pub fn transient(err: E) -> Self {
34 Error::Transient {
35 err,
36 retry_after: None,
37 }
38 }
39
40 pub fn retry_after(err: E, duration: Duration) -> Self {
43 Error::Transient {
44 err,
45 retry_after: Some(duration),
46 }
47 }
48}
49
50impl<E> fmt::Display for Error<E>
51where
52 E: fmt::Display,
53{
54 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
55 match *self {
56 Error::Permanent(ref err)
57 | Error::Transient {
58 ref err,
59 retry_after: _,
60 } => err.fmt(f),
61 }
62 }
63}
64
65impl<E> fmt::Debug for Error<E>
66where
67 E: fmt::Debug,
68{
69 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
70 let (name, err) = match *self {
71 Error::Permanent(ref err) => ("Permanent", err as &dyn fmt::Debug),
72 Error::Transient {
73 ref err,
74 retry_after: _,
75 } => ("Transient", err as &dyn fmt::Debug),
76 };
77 f.debug_tuple(name).field(err).finish()
78 }
79}
80
81impl<E> error::Error for Error<E>
82where
83 E: error::Error,
84{
85 fn description(&self) -> &str {
86 match *self {
87 Error::Permanent(_) => "permanent error",
88 Error::Transient { .. } => "transient error",
89 }
90 }
91
92 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
93 match *self {
94 Error::Permanent(ref err)
95 | Error::Transient {
96 ref err,
97 retry_after: _,
98 } => err.source(),
99 }
100 }
101
102 fn cause(&self) -> Option<&dyn error::Error> {
103 self.source()
104 }
105}
106
107impl<E> From<E> for Error<E> {
111 fn from(err: E) -> Error<E> {
112 Error::Transient {
113 err,
114 retry_after: None,
115 }
116 }
117}
118
119impl<E> PartialEq for Error<E>
120where
121 E: PartialEq,
122{
123 fn eq(&self, other: &Self) -> bool {
124 match (self, other) {
125 (Error::Permanent(ref self_err), Error::Permanent(ref other_err)) => {
126 self_err == other_err
127 }
128 (
129 Error::Transient {
130 err: self_err,
131 retry_after: self_retry_after,
132 },
133 Error::Transient {
134 err: other_err,
135 retry_after: other_retry_after,
136 },
137 ) => self_err == other_err && self_retry_after == other_retry_after,
138 _ => false,
139 }
140 }
141}
142
143#[test]
144fn create_permanent_error() {
145 let e = Error::permanent("err");
146 assert_eq!(e, Error::Permanent("err"));
147}
148
149#[test]
150fn create_transient_error() {
151 let e = Error::transient("err");
152 assert_eq!(
153 e,
154 Error::Transient {
155 err: "err",
156 retry_after: None
157 }
158 );
159}
160
161#[test]
162fn create_transient_error_with_retry_after() {
163 let retry_after = Duration::from_secs(42);
164 let e = Error::retry_after("err", retry_after);
165 assert_eq!(
166 e,
167 Error::Transient {
168 err: "err",
169 retry_after: Some(retry_after),
170 }
171 );
172}