Skip to main content

reliakit_retry/
error.rs

1//! The retry error type.
2
3use core::fmt;
4
5/// The error returned when a retried operation does not succeed.
6///
7/// It carries how many attempts were made and the last error the operation
8/// produced. There is intentionally no `E: core::error::Error` bound and no
9/// allocation: the failing value is moved in by value.
10///
11/// `#[non_exhaustive]`: new variants may be added in a future release, so match
12/// with a wildcard arm.
13#[non_exhaustive]
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
15pub enum RetryError<E> {
16    /// No further attempts will be made. This covers both running out of the
17    /// allowed attempts and the retry predicate declining to retry: in either
18    /// case `attempts` is the number of attempts actually made and `last_error`
19    /// is the error from the final attempt.
20    Exhausted {
21        /// The number of attempts made (always `>= 1`).
22        attempts: u32,
23        /// The error returned by the final attempt.
24        last_error: E,
25    },
26}
27
28impl<E> RetryError<E> {
29    /// The number of attempts that were made.
30    pub fn attempts(&self) -> u32 {
31        match self {
32            Self::Exhausted { attempts, .. } => *attempts,
33        }
34    }
35
36    /// A reference to the error returned by the final attempt.
37    pub fn last_error(&self) -> &E {
38        match self {
39            Self::Exhausted { last_error, .. } => last_error,
40        }
41    }
42
43    /// Consumes the error and returns the final attempt's error.
44    pub fn into_last_error(self) -> E {
45        match self {
46            Self::Exhausted { last_error, .. } => last_error,
47        }
48    }
49}
50
51impl<E: fmt::Display> fmt::Display for RetryError<E> {
52    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53        match self {
54            Self::Exhausted {
55                attempts,
56                last_error,
57            } => write!(f, "retry gave up after {attempts} attempt(s): {last_error}"),
58        }
59    }
60}
61
62#[cfg(feature = "std")]
63impl<E: std::error::Error + 'static> std::error::Error for RetryError<E> {
64    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
65        match self {
66            Self::Exhausted { last_error, .. } => Some(last_error),
67        }
68    }
69}