use super::Stop;
use super::strategies::{StopAfterAttempts, StopAfterElapsed, StopNever};
use crate::state::RetryState;
use core::ops::{BitAnd, BitOr};
#[derive(Debug, Clone)]
pub struct StopAny<A, B> {
left: A,
right: B,
}
impl<A, B> StopAny<A, B> {
#[must_use]
pub fn new(left: A, right: B) -> Self {
Self { left, right }
}
}
impl<A: Stop, B: Stop> Stop for StopAny<A, B> {
fn should_stop(&self, state: &RetryState) -> bool {
let left = self.left.should_stop(state);
let right = self.right.should_stop(state);
left || right
}
}
impl<A: Stop, B: Stop, Rhs: Stop> BitOr<Rhs> for StopAny<A, B> {
type Output = StopAny<Self, Rhs>;
fn bitor(self, rhs: Rhs) -> Self::Output {
StopAny::new(self, rhs)
}
}
impl<A: Stop, B: Stop, Rhs: Stop> BitAnd<Rhs> for StopAny<A, B> {
type Output = StopAll<Self, Rhs>;
fn bitand(self, rhs: Rhs) -> Self::Output {
StopAll::new(self, rhs)
}
}
#[derive(Debug, Clone)]
pub struct StopAll<A, B> {
left: A,
right: B,
}
impl<A, B> StopAll<A, B> {
#[must_use]
pub fn new(left: A, right: B) -> Self {
Self { left, right }
}
}
impl<A: Stop, B: Stop> Stop for StopAll<A, B> {
fn should_stop(&self, state: &RetryState) -> bool {
let left = self.left.should_stop(state);
let right = self.right.should_stop(state);
left && right
}
}
impl<A: Stop, B: Stop, Rhs: Stop> BitAnd<Rhs> for StopAll<A, B> {
type Output = StopAll<Self, Rhs>;
fn bitand(self, rhs: Rhs) -> Self::Output {
StopAll::new(self, rhs)
}
}
impl<A: Stop, B: Stop, Rhs: Stop> BitOr<Rhs> for StopAll<A, B> {
type Output = StopAny<Self, Rhs>;
fn bitor(self, rhs: Rhs) -> Self::Output {
StopAny::new(self, rhs)
}
}
macro_rules! impl_stop_ops {
($($ty:ty),+ $(,)?) => {
$(
impl<Rhs: Stop> BitOr<Rhs> for $ty {
type Output = StopAny<Self, Rhs>;
fn bitor(self, rhs: Rhs) -> Self::Output {
StopAny::new(self, rhs)
}
}
impl<Rhs: Stop> BitAnd<Rhs> for $ty {
type Output = StopAll<Self, Rhs>;
fn bitand(self, rhs: Rhs) -> Self::Output {
StopAll::new(self, rhs)
}
}
)+
};
}
impl_stop_ops!(StopAfterAttempts, StopAfterElapsed, StopNever);