use crate::binary::BinaryError;
use crate::ordered_pair::IntervalError;
use std::fmt;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ComputableError {
InvalidBoundsOrder,
BoundsWorsened,
StateUnchanged,
ExcludedValueUnreachable,
RefinementChannelClosed,
MaxRefinementIterations { max: usize },
Binary(BinaryError),
DomainError,
InfiniteBounds,
}
impl fmt::Display for ComputableError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidBoundsOrder => write!(f, "computed bounds are not ordered"),
Self::BoundsWorsened => write!(f, "refinement produced worse bounds"),
Self::StateUnchanged => write!(f, "refinement did not change state"),
Self::ExcludedValueUnreachable => write!(f, "cannot refine bounds to exclude value"),
Self::RefinementChannelClosed => {
write!(f, "refinement coordination channel closed")
}
Self::MaxRefinementIterations { max } => {
write!(f, "maximum refinement iterations ({max}) reached")
}
Self::Binary(err) => write!(f, "{err}"),
Self::DomainError => write!(f, "input is outside the domain of the operation"),
Self::InfiniteBounds => write!(
f,
"input bounds are infinite where finite bounds are required"
),
}
}
}
impl std::error::Error for ComputableError {}
impl From<BinaryError> for ComputableError {
fn from(error: BinaryError) -> Self {
Self::Binary(error)
}
}
impl From<IntervalError> for ComputableError {
fn from(error: IntervalError) -> Self {
match error {
IntervalError::InvalidOrder => Self::InvalidBoundsOrder,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn binary_error_converts_to_computable_error() {
let binary_err = BinaryError::NegativeMantissa;
let computable_err: ComputableError = binary_err.into();
assert!(matches!(
computable_err,
ComputableError::Binary(BinaryError::NegativeMantissa)
));
}
#[test]
fn computable_error_implements_std_error() {
let err: &dyn std::error::Error = &ComputableError::DomainError;
assert!(err.source().is_none());
}
}