1use core::{fmt, marker::PhantomData};
4
5use crate::predicate::{Predicate, PredicateExpected};
6
7pub const NOTHING: &str = "nothing";
9
10pub const ANYTHING: &str = "anything";
12
13pub const FALSE: &str = "false";
15
16pub const TRUE: &str = "true";
18
19pub struct False {
21 private: PhantomData<()>,
22}
23
24pub struct True {
26 private: PhantomData<()>,
27}
28
29impl<T: ?Sized> Predicate<T> for False {
30 fn check(_value: &T) -> bool {
31 false
32 }
33
34 fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
35 formatter.write_str(NOTHING)
36 }
37
38 fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
39 formatter.write_str(FALSE)
40 }
41}
42
43impl<T: ?Sized> Predicate<T> for True {
44 fn check(_value: &T) -> bool {
45 true
46 }
47
48 fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
49 formatter.write_str(ANYTHING)
50 }
51
52 fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
53 formatter.write_str(TRUE)
54 }
55}
56
57pub const NOT: &str = "not";
59
60pub struct Not<P: ?Sized> {
62 predicate: PhantomData<P>,
63}
64
65impl<T: ?Sized, P: Predicate<T> + ?Sized> Predicate<T> for Not<P> {
66 fn check(value: &T) -> bool {
67 !P::check(value)
68 }
69
70 fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
71 write!(formatter, "{NOT} ({expected})", expected = P::expected())
72 }
73
74 fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
75 write!(formatter, "{NOT}<{expected:?}>", expected = P::expected())
76 }
77}
78
79pub const AND: &str = "and";
81
82pub struct And<P: ?Sized, Q: ?Sized> {
84 left: PhantomData<P>,
85 right: PhantomData<Q>,
86}
87
88impl<T: ?Sized, P: Predicate<T> + ?Sized, Q: Predicate<T> + ?Sized> Predicate<T> for And<P, Q> {
89 fn check(value: &T) -> bool {
90 P::check(value) && Q::check(value)
91 }
92
93 fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
94 write!(
95 formatter,
96 "({left}) {AND} ({right})",
97 left = P::expected(),
98 right = Q::expected(),
99 )
100 }
101
102 fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
103 write!(
104 formatter,
105 "{AND}<{left:?}, {right:?}>",
106 left = P::expected(),
107 right = Q::expected(),
108 )
109 }
110}
111
112pub const OR: &str = "or";
114
115pub struct Or<P: ?Sized, Q: ?Sized> {
117 left: PhantomData<P>,
118 right: PhantomData<Q>,
119}
120
121impl<T: ?Sized, P: Predicate<T> + ?Sized, Q: Predicate<T> + ?Sized> Predicate<T> for Or<P, Q> {
122 fn check(value: &T) -> bool {
123 P::check(value) || Q::check(value)
124 }
125
126 fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
127 write!(
128 formatter,
129 "({left}) {OR} ({right})",
130 left = P::expected(),
131 right = Q::expected(),
132 )
133 }
134
135 fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
136 write!(
137 formatter,
138 "{OR}<{left:?}, {right:?}>",
139 left = P::expected(),
140 right = Q::expected(),
141 )
142 }
143}
144
145pub const XOR: &str = "xor";
147
148pub struct Xor<P: ?Sized, Q: ?Sized> {
150 left: PhantomData<P>,
151 right: PhantomData<Q>,
152}
153
154impl<T: ?Sized, P: Predicate<T> + ?Sized, Q: Predicate<T> + ?Sized> Predicate<T> for Xor<P, Q> {
155 fn check(value: &T) -> bool {
156 P::check(value) ^ Q::check(value)
157 }
158
159 fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
160 write!(
161 formatter,
162 "({left}) {XOR} ({right})",
163 left = P::expected(),
164 right = Q::expected(),
165 )
166 }
167
168 fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
169 write!(
170 formatter,
171 "{XOR}<{left:?}, {right:?}>",
172 left = P::expected(),
173 right = Q::expected(),
174 )
175 }
176}
177
178pub type Nand<P, Q> = Not<And<P, Q>>;
180
181pub type Nor<P, Q> = Not<Or<P, Q>>;
183
184pub type Xnor<P, Q> = Not<Xor<P, Q>>;
186
187pub type Implies<P, Q> = Or<Not<P>, Q>;
189
190#[macro_export]
194macro_rules! not {
195 ($predicate: ty) => {
196 $crate::logical::Not<$predicate>
197 };
198}
199
200#[macro_export]
208macro_rules! and {
209 ($left: ty, $right: ty) => {
210 $crate::logical::And<$left, $right>
211 };
212 ($first: ty, $second: ty, $($rest: ty),+ $(,)?) => {
213 $crate::and!($first, $crate::and!($second, $($rest),+))
214 };
215}
216
217#[macro_export]
225macro_rules! or {
226 ($left: ty, $right: ty) => {
227 $crate::logical::Or<$left, $right>
228 };
229 ($first: ty, $second: ty, $($rest: ty),+ $(,)?) => {
230 $crate::or!($first, $crate::or!($second, $($rest),+))
231 };
232}
233
234#[macro_export]
242macro_rules! xor {
243 ($left: ty, $right: ty) => {
244 $crate::logical::Xor<$left, $right>
245 };
246 ($first: ty, $second: ty, $($rest: ty),+ $(,)?) => {
247 $crate::xor!($first, $crate::xor!($second, $($rest),+))
248 };
249}