1use core::{fmt, marker::PhantomData};
4
5use thiserror::Error;
6
7use crate::{core::Predicate, static_str::StaticStr};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
11pub struct True;
12
13#[derive(Debug, Error)]
17pub enum NeverError {}
18
19pub const ANYTHING: StaticStr = "anything";
21
22impl<T: ?Sized> Predicate<T> for True {
23 type Error = NeverError;
24
25 fn check(_value: &T) -> Result<(), Self::Error> {
26 Ok(())
27 }
28
29 fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
30 formatter.write_str(ANYTHING)
31 }
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
36pub struct False;
37
38#[derive(Debug, Error)]
40#[error("always errors")]
41pub struct AlwaysError;
42
43pub const NOTHING: StaticStr = "nothing";
45
46impl<T: ?Sized> Predicate<T> for False {
47 type Error = AlwaysError;
48
49 fn check(_value: &T) -> Result<(), Self::Error> {
50 Err(AlwaysError)
51 }
52
53 fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
54 formatter.write_str(NOTHING)
55 }
56}
57
58#[derive(Debug, Error)]
60pub enum EitherError<E, F> {
61 #[error("left error: {0}")]
63 Left(E),
64 #[error("right error: {0}")]
66 Right(F),
67}
68
69#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
71pub struct And<P: ?Sized, Q: ?Sized> {
72 left: PhantomData<P>,
73 right: PhantomData<Q>,
74}
75
76impl<T: ?Sized, P: Predicate<T> + ?Sized, Q: Predicate<T> + ?Sized> Predicate<T> for And<P, Q> {
77 type Error = EitherError<P::Error, Q::Error>;
78
79 fn check(value: &T) -> Result<(), Self::Error> {
80 P::check(value)
81 .map_err(EitherError::Left)
82 .and_then(|()| Q::check(value).map_err(EitherError::Right))
83 }
84
85 fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
86 write!(formatter, "({}) and ({})", P::expected(), Q::expected())
87 }
88}
89
90#[derive(Debug, Error)]
92#[error("both errors encountered: {left} and {right}")]
93pub struct BothError<E, F> {
94 pub left: E,
96 pub right: F,
98}
99
100impl<E, F> BothError<E, F> {
101 pub const fn new(left: E, right: F) -> Self {
103 Self { left, right }
104 }
105}
106
107#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
109pub struct Or<P: ?Sized, Q: ?Sized> {
110 left: PhantomData<P>,
111 right: PhantomData<Q>,
112}
113
114impl<T: ?Sized, P: Predicate<T> + ?Sized, Q: Predicate<T> + ?Sized> Predicate<T> for Or<P, Q> {
115 type Error = BothError<P::Error, Q::Error>;
116
117 fn check(value: &T) -> Result<(), Self::Error> {
118 P::check(value)
119 .or_else(|left| Q::check(value).map_err(|right| Self::Error::new(left, right)))
120 }
121
122 fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
123 write!(formatter, "({}) or ({})", P::expected(), Q::expected())
124 }
125}
126
127#[derive(Debug, Error)]
129#[error("negated error")]
130pub struct NotError;
131
132#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
134pub struct Not<P: ?Sized> {
135 predicate: PhantomData<P>,
136}
137
138impl<T: ?Sized, P: Predicate<T> + ?Sized> Predicate<T> for Not<P> {
139 type Error = NotError;
140
141 fn check(value: &T) -> Result<(), Self::Error> {
142 match P::check(value) {
143 Ok(()) => Err(NotError),
144 Err(_) => Ok(()),
145 }
146 }
147
148 fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
149 write!(formatter, "not ({})", P::expected())
150 }
151}
152
153#[derive(Debug, Error)]
155pub enum NeitherOrBoth<E, F> {
156 #[error("neither error encountered")]
158 Neither,
159 #[error(transparent)]
161 Both(BothError<E, F>),
162}
163
164#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
166pub struct Xor<P: ?Sized, Q: ?Sized> {
167 left: PhantomData<P>,
168 right: PhantomData<Q>,
169}
170
171impl<T: ?Sized, P: Predicate<T> + ?Sized, Q: Predicate<T> + ?Sized> Predicate<T> for Xor<P, Q> {
172 type Error = NeitherOrBoth<P::Error, Q::Error>;
173
174 fn check(value: &T) -> Result<(), Self::Error> {
175 match (P::check(value), Q::check(value)) {
176 (Ok(()), Ok(())) => Err(NeitherOrBoth::Neither),
177 (Err(left), Err(right)) => Err(NeitherOrBoth::Both(BothError::new(left, right))),
178 _ => Ok(()),
179 }
180 }
181
182 fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
183 write!(formatter, "({}) xor ({})", P::expected(), Q::expected())
184 }
185}
186
187pub type Nand<P, Q> = Not<And<P, Q>>;
189pub type Nor<P, Q> = Not<Or<P, Q>>;
191pub type Xnor<P, Q> = Not<Xor<P, Q>>;
193
194pub type Imply<P, Q> = Or<Not<P>, Q>;