use std::{error::Error, fmt::Display, num::NonZeroU32};
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
pub struct BackoffError<E: Error> {
error: E,
kind: BackoffErrorKind,
}
impl<E: Error> BackoffError<E> {
pub fn new(error: E, kind: BackoffErrorKind) -> BackoffError<E> {
BackoffError { error, kind }
}
pub fn error(&self) -> &E {
&self.error
}
pub fn kind(&self) -> &BackoffErrorKind {
&self.kind
}
pub fn into_error_and_kind(self) -> (E, BackoffErrorKind) {
(self.error, self.kind)
}
pub fn into_error(self) -> E {
self.error
}
pub fn into_kind(self) -> BackoffErrorKind {
self.kind
}
}
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
pub enum BackoffErrorKind {
Unrecoverable(u32),
ExhaustedLimit(NonZeroU32),
UnrecoverableAndExhaustedLimit(NonZeroU32),
PeekTerminated(u32),
IntervalTerminated(u32),
}
impl<E: Error> Display for BackoffError<E> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.kind {
BackoffErrorKind::Unrecoverable(i) => write!(
f,
"After {i} attempt(s) the following unrecoverable error was encountered: {}",
self.error
),
BackoffErrorKind::ExhaustedLimit(i) => {
write!(f, "Limit of {} was exhausted. {}", i.get(), self.error)
}
BackoffErrorKind::UnrecoverableAndExhaustedLimit(i) => write!(
f,
"An unrecoverable error was encountered and the limit of {} was exhausted. {}",
i.get(),
self.error
),
BackoffErrorKind::PeekTerminated(i) => {
write!(
f,
"After {i} attempt(s), retrying was terminated by peek_retry"
)
}
BackoffErrorKind::IntervalTerminated(i) => write!(
f,
"After {i} attempt(s), retrying was terminated by BackoffStrategy::interval()."
),
}
}
}
impl<E: Error> Error for BackoffError<E> {}