use std::fmt;
use super::{FormattedOutput, MatcherFormat};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum MatchFailure<Pos, Neg = Pos> {
Pos(Pos),
Neg(Neg),
}
impl<Pos, Neg> From<MatchFailure<Pos, Neg>> for FormattedOutput
where
Pos: Into<FormattedOutput>,
Neg: Into<FormattedOutput>,
{
fn from(fail: MatchFailure<Pos, Neg>) -> Self {
match fail {
MatchFailure::Pos(fail) => fail.into(),
MatchFailure::Neg(fail) => fail.into(),
}
}
}
impl<Pos, Neg> MatchFailure<Pos, Neg> {
pub fn is_pos(&self) -> bool {
match self {
Self::Pos(_) => true,
Self::Neg(_) => false,
}
}
pub fn is_neg(&self) -> bool {
match self {
Self::Pos(_) => false,
Self::Neg(_) => true,
}
}
}
impl<T> MatchFailure<T, T> {
pub fn unwrap(&self) -> &T {
match self {
Self::Pos(value) => value,
Self::Neg(value) => value,
}
}
pub fn into_inner(self) -> T {
match self {
Self::Pos(value) => value,
Self::Neg(value) => value,
}
}
}
#[derive(Debug)]
pub struct FormattedFailure {
inner: FormattedOutput,
}
impl FormattedFailure {
pub fn new<Fmt, Pos, Neg>(fail: MatchFailure<Pos, Neg>, format: Fmt) -> crate::Result<Self>
where
Fmt: MatcherFormat<Pos = Pos, Neg = Neg>,
{
Ok(Self {
inner: FormattedOutput::new(fail, format)?,
})
}
}
impl From<FormattedFailure> for FormattedOutput {
fn from(fail: FormattedFailure) -> Self {
fail.inner
}
}
impl fmt::Display for FormattedFailure {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f)
}
}
impl std::error::Error for FormattedFailure {}
#[derive(Debug)]
pub struct AssertionFailure<Ctx> {
pub ctx: Ctx,
pub error: MatchError,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum MatchOutcome<Success, Fail> {
Success(Success),
Fail(Fail),
}
impl<Success, Fail> MatchOutcome<Success, Fail> {
pub fn is_success(&self) -> bool {
match self {
MatchOutcome::Success(_) => true,
MatchOutcome::Fail(_) => false,
}
}
pub fn is_fail(&self) -> bool {
match self {
MatchOutcome::Success(_) => false,
MatchOutcome::Fail(_) => true,
}
}
}
impl<Success, Fail> From<MatchOutcome<Success, Fail>> for Result<Success, Fail> {
fn from(result: MatchOutcome<Success, Fail>) -> Self {
match result {
MatchOutcome::Success(success) => Ok(success),
MatchOutcome::Fail(fail) => Err(fail),
}
}
}
#[derive(Debug)]
pub enum MatchError {
Fail(FormattedFailure),
Err(crate::Error),
}
impl fmt::Display for MatchError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
MatchError::Fail(fail) => fail.fmt(f),
MatchError::Err(error) => error.fmt(f),
}
}
}
impl std::error::Error for MatchError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
MatchError::Fail(_) => None,
MatchError::Err(error) => error.source(),
}
}
}