1use core::convert::Infallible;
2use core::fmt::{self, Display};
3
4#[cfg(feature = "std")]
5use std::error::Error as StdError;
6
7#[derive(Debug)]
9pub struct RetryError<E = Infallible> {
10 inner: RetryErrorKind<E>,
11}
12
13#[derive(Debug)]
14enum RetryErrorKind<E> {
15 Aborted(E),
16 Timeout,
17 #[allow(dead_code)]
18 TimerShutdown,
19}
20
21impl<E> From<Infallible> for RetryError<E> {
22 fn from(e: Infallible) -> Self {
23 match e {}
24 }
25}
26
27impl<E: Display> Display for RetryError<E> {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 use RetryErrorKind::*;
30 match &self.inner {
31 Aborted(e) => e.fmt(f),
32 Timeout => "Timeout reached".fmt(f),
33 TimerShutdown => "Timer has gone".fmt(f),
34 }
35 }
36}
37
38#[cfg(feature = "std")]
39impl<E: StdError + 'static> StdError for RetryError<E> {
40 fn source(&self) -> Option<&(dyn StdError + 'static)> {
41 use RetryErrorKind::*;
42 match &self.inner {
43 Aborted(e) => Some(&*e),
44 _ => None,
45 }
46 }
47}
48
49impl<E> RetryError<E> {
50 pub fn from_err(e: E) -> Self {
51 RetryError {
52 inner: RetryErrorKind::Aborted(e),
53 }
54 }
55
56 pub(crate) const fn timeout() -> Self {
57 RetryError {
58 inner: RetryErrorKind::Timeout,
59 }
60 }
61
62 #[allow(dead_code)]
63 pub(crate) const fn shutdown() -> Self {
64 RetryError {
65 inner: RetryErrorKind::TimerShutdown,
66 }
67 }
68
69 pub fn as_inner(&self) -> Option<&E> {
70 if let RetryErrorKind::Aborted(e) = &self.inner {
71 Some(e)
72 } else {
73 None
74 }
75 }
76
77 pub fn into_inner(self) -> Option<E> {
78 if let RetryErrorKind::Aborted(e) = self.inner {
79 Some(e)
80 } else {
81 None
82 }
83 }
84
85 pub fn is_aborted(&self) -> bool {
87 self.as_inner().is_some()
88 }
89
90 pub fn is_timeout(&self) -> bool {
92 if let RetryErrorKind::Timeout = &self.inner {
93 true
94 } else {
95 false
96 }
97 }
98
99 pub fn is_shutdown(&self) -> bool {
106 if let RetryErrorKind::TimerShutdown = &self.inner {
107 true
108 } else {
109 false
110 }
111 }
112}
113
114impl RetryError {
115 pub(crate) fn transform<E>(self) -> RetryError<E> {
116 use RetryErrorKind::*;
117 let inner = match self.inner {
118 Aborted(_) => unreachable!(),
119 Timeout => Timeout,
120 TimerShutdown => TimerShutdown,
121 };
122 RetryError { inner }
123 }
124}