use crate::stats::StopReason;
use core::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RetryError<T, E> {
Exhausted {
last: Result<T, E>,
},
Rejected {
last: E,
},
}
pub type RetryResult<T, E> = core::result::Result<T, RetryError<T, E>>;
impl<T, E> RetryError<T, E> {
#[must_use]
pub fn last(&self) -> Option<&Result<T, E>> {
match self {
RetryError::Exhausted { last } => Some(last),
RetryError::Rejected { .. } => None,
}
}
#[must_use]
pub fn into_last(self) -> Option<Result<T, E>> {
match self {
RetryError::Exhausted { last } => Some(last),
RetryError::Rejected { .. } => None,
}
}
#[must_use]
pub fn last_error(&self) -> Option<&E> {
match self {
RetryError::Exhausted { last } => last.as_ref().err(),
RetryError::Rejected { last } => Some(last),
}
}
#[must_use]
pub fn into_last_error(self) -> Option<E> {
match self {
RetryError::Exhausted { last } => last.err(),
RetryError::Rejected { last } => Some(last),
}
}
#[must_use]
pub fn stop_reason(&self) -> StopReason {
match self {
RetryError::Exhausted { .. } => StopReason::Exhausted,
RetryError::Rejected { .. } => StopReason::Accepted,
}
}
}
impl<T, E: fmt::Display> fmt::Display for RetryError<T, E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RetryError::Exhausted { last } => match last {
Err(error) => write!(f, "retries exhausted: {error}"),
Ok(_) => f.write_str("retries exhausted"),
},
RetryError::Rejected { last } => write!(f, "rejected: {last}"),
}
}
}
#[cfg(feature = "std")]
impl<T, E> std::error::Error for RetryError<T, E>
where
E: std::error::Error + 'static,
T: fmt::Debug + 'static,
{
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
RetryError::Exhausted { last } => match last {
Err(error) => Some(error as _),
_ => None,
},
RetryError::Rejected { last } => Some(last as _),
}
}
}