1use std::fmt;
2
3use super::{FormattedOutput, MatcherFormat};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum MatchFailure<Pos, Neg = Pos> {
10 Pos(Pos),
12
13 Neg(Neg),
15}
16
17impl<Pos, Neg> From<MatchFailure<Pos, Neg>> for FormattedOutput
18where
19 Pos: Into<FormattedOutput>,
20 Neg: Into<FormattedOutput>,
21{
22 fn from(fail: MatchFailure<Pos, Neg>) -> Self {
23 match fail {
24 MatchFailure::Pos(fail) => fail.into(),
25 MatchFailure::Neg(fail) => fail.into(),
26 }
27 }
28}
29
30impl<Pos, Neg> MatchFailure<Pos, Neg> {
31 pub fn is_pos(&self) -> bool {
33 match self {
34 Self::Pos(_) => true,
35 Self::Neg(_) => false,
36 }
37 }
38
39 pub fn is_neg(&self) -> bool {
41 match self {
42 Self::Pos(_) => false,
43 Self::Neg(_) => true,
44 }
45 }
46}
47
48impl<T> MatchFailure<T, T> {
49 pub fn unwrap(&self) -> &T {
54 match self {
55 Self::Pos(value) => value,
56 Self::Neg(value) => value,
57 }
58 }
59
60 pub fn into_inner(self) -> T {
66 match self {
67 Self::Pos(value) => value,
68 Self::Neg(value) => value,
69 }
70 }
71}
72
73#[derive(Debug)]
83pub struct FormattedFailure {
84 inner: FormattedOutput,
85}
86
87impl FormattedFailure {
88 pub fn new<Fmt, Pos, Neg>(fail: MatchFailure<Pos, Neg>, format: Fmt) -> crate::Result<Self>
90 where
91 Fmt: MatcherFormat<Pos = Pos, Neg = Neg>,
92 {
93 Ok(Self {
94 inner: FormattedOutput::new(fail, format)?,
95 })
96 }
97}
98
99impl From<FormattedFailure> for FormattedOutput {
100 fn from(fail: FormattedFailure) -> Self {
101 fail.inner
102 }
103}
104
105impl fmt::Display for FormattedFailure {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 self.inner.fmt(f)
108 }
109}
110
111impl std::error::Error for FormattedFailure {}
112
113#[derive(Debug)]
115pub struct AssertionFailure<Ctx> {
116 pub ctx: Ctx,
127
128 pub error: MatchError,
130}
131
132#[derive(Debug, Clone, PartialEq, Eq)]
134pub enum MatchOutcome<Success, Fail> {
135 Success(Success),
137
138 Fail(Fail),
140}
141
142impl<Success, Fail> MatchOutcome<Success, Fail> {
143 pub fn is_success(&self) -> bool {
145 match self {
146 MatchOutcome::Success(_) => true,
147 MatchOutcome::Fail(_) => false,
148 }
149 }
150
151 pub fn is_fail(&self) -> bool {
153 match self {
154 MatchOutcome::Success(_) => false,
155 MatchOutcome::Fail(_) => true,
156 }
157 }
158}
159
160impl<Success, Fail> From<MatchOutcome<Success, Fail>> for Result<Success, Fail> {
161 fn from(result: MatchOutcome<Success, Fail>) -> Self {
162 match result {
163 MatchOutcome::Success(success) => Ok(success),
164 MatchOutcome::Fail(fail) => Err(fail),
165 }
166 }
167}
168
169#[derive(Debug)]
171pub enum MatchError {
172 Fail(FormattedFailure),
177
178 Err(crate::Error),
180}
181
182impl fmt::Display for MatchError {
183 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184 match self {
185 MatchError::Fail(fail) => fail.fmt(f),
186 MatchError::Err(error) => error.fmt(f),
187 }
188 }
189}
190
191impl std::error::Error for MatchError {
192 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
193 match self {
194 MatchError::Fail(_) => None,
195 MatchError::Err(error) => error.source(),
196 }
197 }
198}