use crate::core::{AssertionFailure, MatchFailure};
use super::Formatter;
pub trait Format {
type Value;
fn fmt(&self, f: &mut Formatter, value: Self::Value) -> crate::Result<()>;
}
impl<T: ?Sized> Format for &T
where
T: Format,
{
type Value = T::Value;
fn fmt(&self, f: &mut Formatter, value: Self::Value) -> crate::Result<()> {
T::fmt(self, f, value)
}
}
pub trait MatcherFormat: Format<Value = MatchFailure<Self::Pos, Self::Neg>> {
type Pos;
type Neg;
}
impl<T, Pos, Neg> MatcherFormat for T
where
T: Format<Value = MatchFailure<Pos, Neg>>,
{
type Pos = Pos;
type Neg = Neg;
}
pub trait AssertionFormat: Format<Value = AssertionFailure<Self::Context>> {
type Context;
}
impl<T, Ctx> AssertionFormat for T
where
T: Format<Value = AssertionFailure<Ctx>>,
{
type Context = Ctx;
}
#[derive(Debug, Default)]
pub struct NegFormat<Fmt>(pub Fmt);
impl<Fmt, Pos, Neg> Format for NegFormat<Fmt>
where
Fmt: Format<Value = MatchFailure<Pos, Neg>>,
{
type Value = MatchFailure<Neg, Pos>;
fn fmt(&self, f: &mut super::Formatter, value: Self::Value) -> crate::Result<()> {
match value {
MatchFailure::Pos(fail) => self.0.fmt(f, MatchFailure::Neg(fail)),
MatchFailure::Neg(fail) => self.0.fmt(f, MatchFailure::Pos(fail)),
}
}
}
#[derive(Debug)]
pub struct DispatchFormat<PosFmt, NegFmt> {
pos_fmt: PosFmt,
neg_fmt: NegFmt,
}
impl<PosFmt, NegFmt> DispatchFormat<PosFmt, NegFmt> {
pub fn new(pos_fmt: PosFmt, neg_fmt: NegFmt) -> Self {
Self { pos_fmt, neg_fmt }
}
}
impl<PosFmt, NegFmt, PosFail, NegFail> Format for DispatchFormat<PosFmt, NegFmt>
where
PosFmt: Format<Value = MatchFailure<PosFail>>,
NegFmt: Format<Value = MatchFailure<NegFail>>,
{
type Value = MatchFailure<PosFail, NegFail>;
fn fmt(&self, f: &mut Formatter, value: Self::Value) -> crate::Result<()> {
match value {
MatchFailure::Pos(fail) => self.pos_fmt.fmt(f, MatchFailure::Pos(fail)),
MatchFailure::Neg(fail) => self.neg_fmt.fmt(f, MatchFailure::Neg(fail)),
}
}
}