1use crate::{
2 decompose::{PtrToCmp, PtrToDebug, PtrToDeref, PtrToDisplay},
3 expr, spec,
4 spec::by_val::{ByVal, DerefVTable},
5 spec::Wrapper,
6 Cmp, CmpDisplay,
7};
8use core::{fmt, ops::Deref};
9
10pub trait Expr {
11 type Result: Eval;
12 type Marker;
13
14 fn eval_expr(&self) -> bool;
15 #[inline(always)]
16 fn __marker(&self) -> core::marker::PhantomData<Self::Marker> {
17 core::marker::PhantomData
18 }
19}
20
21pub trait Eval {
22 fn eval(&self) -> bool;
23}
24
25impl<E> Eval for Result<(), E> {
26 #[inline(always)]
27 fn eval(&self) -> bool {
28 self.is_ok()
29 }
30}
31impl<Lhs: Eval, Rhs: Eval> Eval for expr::AndExpr<Lhs, Rhs> {
32 #[inline(always)]
33 fn eval(&self) -> bool {
34 self.lhs.eval() && self.rhs.eval()
35 }
36}
37impl<Lhs: Eval, Rhs: Eval> Eval for expr::OrExpr<Lhs, Rhs> {
38 #[inline(always)]
39 fn eval(&self) -> bool {
40 self.lhs.eval() || self.rhs.eval()
41 }
42}
43
44impl Expr for bool {
45 type Result = Result<(), ()>;
46 type Marker = bool;
47
48 #[inline(always)]
49 fn eval_expr(&self) -> bool {
50 *self
51 }
52}
53
54impl<
55 Lhs3: Deref,
56 Rhs3: Deref,
57 C: Cmp<
58 <<<Lhs3 as Deref>::Target as Deref>::Target as Deref>::Target,
59 <<<Rhs3 as Deref>::Target as Deref>::Target as Deref>::Target,
60 >,
61 > Expr
62 for expr::CmpExpr<
63 &spec::by_val::CmpByValWrapper<
64 spec::sized::CmpSizedWrapper<spec::debug::CmpDebugWrapper<C>>,
65 >,
66 &Lhs3,
67 &Rhs3,
68 >
69where
70 Lhs3::Target: Deref,
71 Rhs3::Target: Deref,
72 <Lhs3::Target as Deref>::Target: Deref,
73 <Rhs3::Target as Deref>::Target: Deref,
74{
75 type Result = Result<(), C::Error>;
76 type Marker = crate::CmpExpr;
77
78 #[inline(always)]
79 fn eval_expr(&self) -> bool {
80 self.cmp.0 .0 .0.test(&***self.lhs, &***self.rhs).is_ok()
81 }
82}
83
84impl<
85 Lhs3: Deref,
86 Rhs3: Deref,
87 C: Cmp<
88 <<<Lhs3 as Deref>::Target as Deref>::Target as Deref>::Target,
89 <<<Rhs3 as Deref>::Target as Deref>::Target as Deref>::Target,
90 >,
91 > Expr
92 for expr::CustomCmpExpr<
93 &spec::by_val::CmpByValWrapper<
94 spec::sized::CmpSizedWrapper<spec::debug::CmpDebugWrapper<C>>,
95 >,
96 &Lhs3,
97 &Rhs3,
98 >
99where
100 Lhs3::Target: Deref,
101 Rhs3::Target: Deref,
102 <Lhs3::Target as Deref>::Target: Deref,
103 <Rhs3::Target as Deref>::Target: Deref,
104{
105 type Result = Result<(), C::Error>;
106 type Marker = crate::CustomCmpExpr<C::Error>;
107
108 #[inline(always)]
109 fn eval_expr(&self) -> bool {
110 self.cmp.0 .0 .0.test(&***self.lhs, &***self.rhs).is_ok()
111 }
112}
113
114impl<Lhs: Expr, Rhs: Expr> Expr for expr::AndExpr<Lhs, Rhs> {
115 type Result = expr::AndExpr<Lhs::Result, Rhs::Result>;
116 type Marker = crate::AndExpr<Lhs::Marker, Rhs::Marker>;
117
118 #[inline(always)]
119 fn eval_expr(&self) -> bool {
120 self.lhs.eval_expr() && self.rhs.eval_expr()
121 }
122}
123
124impl<Lhs: Expr, Rhs: Expr> Expr for expr::OrExpr<Lhs, Rhs> {
125 type Result = expr::OrExpr<Lhs::Result, Rhs::Result>;
126 type Marker = crate::OrExpr<Lhs::Marker, Rhs::Marker>;
127
128 #[inline(always)]
129 fn eval_expr(&self) -> bool {
130 self.lhs.eval_expr() || self.rhs.eval_expr()
131 }
132}
133
134pub trait DynInfoType {
135 type VTable: Copy + 'static;
136 const NULL_VTABLE: &'static Self::VTable;
137}
138
139pub trait DynInfo: DynInfoType {
140 const VTABLE: &'static Self::VTable;
141
142 #[inline(always)]
143 fn vtable(&self) -> &'static Self::VTable {
144 Self::VTABLE
145 }
146}
147
148impl DynInfoType for bool {
149 type VTable = ();
150 const NULL_VTABLE: &'static Self::VTable = &();
151}
152impl DynInfo for bool {
153 const VTABLE: &'static Self::VTable = &();
154}
155
156impl<Lhs: DynInfoType, Rhs: DynInfoType> DynInfoType for expr::AndExpr<Lhs, Rhs> {
157 type VTable = expr::AndExpr<&'static Lhs::VTable, &'static Rhs::VTable>;
158 const NULL_VTABLE: &'static Self::VTable = &expr::AndExpr {
159 lhs: Lhs::NULL_VTABLE,
160 rhs: Rhs::NULL_VTABLE,
161 };
162}
163impl<Lhs: DynInfoType, Rhs: DynInfoType> DynInfoType for expr::OrExpr<Lhs, Rhs> {
164 type VTable = expr::OrExpr<&'static Lhs::VTable, &'static Rhs::VTable>;
165 const NULL_VTABLE: &'static Self::VTable = &expr::OrExpr {
166 lhs: Lhs::NULL_VTABLE,
167 rhs: Rhs::NULL_VTABLE,
168 };
169}
170
171impl<Lhs: DynInfo, Rhs: DynInfo> DynInfo for expr::AndExpr<Lhs, Rhs> {
172 const VTABLE: &'static Self::VTable = &expr::AndExpr {
173 lhs: Lhs::VTABLE,
174 rhs: Rhs::VTABLE,
175 };
176}
177impl<Lhs: DynInfo, Rhs: DynInfo> DynInfo for expr::OrExpr<Lhs, Rhs> {
178 const VTABLE: &'static Self::VTable = &expr::OrExpr {
179 lhs: Lhs::VTABLE,
180 rhs: Rhs::VTABLE,
181 };
182}
183
184unsafe fn as_display_vptr<'a, C, Lhs, Rhs, E: CmpDisplay<C, Lhs, Rhs>>(
185 ptr: *const (),
186) -> &'a dyn CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug> {
187 #[repr(transparent)]
188 struct DynDisplay<E, C, Lhs, Rhs>(
189 E,
190 core::marker::PhantomData<C>,
191 core::marker::PhantomData<Lhs>,
192 core::marker::PhantomData<Rhs>,
193 );
194
195 impl<Lhs, Rhs, C, E: CmpDisplay<C, Lhs, Rhs>>
196 CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug> for DynDisplay<E, C, Lhs, Rhs>
197 {
198 fn fmt(
199 &self,
200 cmp: &*const (),
201 lhs: &dyn fmt::Debug,
202 lhs_source: &str,
203 lhs_debug: &dyn fmt::Debug,
204 rhs: &dyn fmt::Debug,
205 rhs_source: &str,
206 rhs_debug: &dyn fmt::Debug,
207 f: &mut fmt::Formatter,
208 ) -> fmt::Result {
209 unsafe {
210 let lhs = &*(lhs as *const dyn fmt::Debug as *const Lhs);
211 let rhs = &*(rhs as *const dyn fmt::Debug as *const Rhs);
212 let cmp = &*((*cmp) as *const C);
213 let err = &self.0;
214
215 err.fmt(
216 cmp, lhs, lhs_source, lhs_debug, rhs, rhs_source, rhs_debug, f,
217 )
218 }
219 }
220 }
221
222 core::mem::transmute::<
223 &'_ dyn CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug>,
224 &'static dyn CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug>,
225 >(
226 (&*(ptr as *const DynDisplay<E, C, Lhs, Rhs>))
227 as &dyn CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug>,
228 )
229}
230
231unsafe fn as_dyn_display_vptr<'a, C, E: CmpDisplay<C, dyn fmt::Debug, dyn fmt::Debug>>(
232 ptr: *const (),
233) -> &'a dyn CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug> {
234 #[repr(transparent)]
235 struct DynDisplay<E, C>(E, core::marker::PhantomData<C>);
236
237 impl<C, E: CmpDisplay<C, dyn fmt::Debug, dyn fmt::Debug>>
238 CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug> for DynDisplay<E, C>
239 {
240 fn fmt(
241 &self,
242 cmp: &*const (),
243 lhs: &(dyn fmt::Debug + 'static),
244 lhs_source: &str,
245 lhs_debug: &dyn fmt::Debug,
246 rhs: &(dyn fmt::Debug + 'static),
247 rhs_source: &str,
248 rhs_debug: &dyn fmt::Debug,
249 f: &mut fmt::Formatter,
250 ) -> fmt::Result {
251 unsafe {
252 let cmp = &*((*cmp) as *const C);
253 let err = &self.0;
254 err.fmt(
255 cmp, lhs, lhs_source, lhs_debug, rhs, rhs_source, rhs_debug, f,
256 )
257 }
258 }
259 }
260
261 core::mem::transmute::<
262 &'_ dyn CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug>,
263 &'static dyn CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug>,
264 >(
265 (&*(ptr as *const DynDisplay<E, C>))
266 as &dyn CmpDisplay<*const (), dyn fmt::Debug, dyn fmt::Debug>,
267 )
268}
269
270unsafe fn as_cmp_vptr<
271 Lhs2: Deref,
272 Rhs2: Deref,
273 C: Cmp<<Lhs2::Target as Deref>::Target, <Rhs2::Target as Deref>::Target>,
274>(
275 out: *mut (),
276 cmp: *const (),
277 lhs: *const (),
278 rhs: *const (),
279) where
280 Lhs2::Target: Deref,
281 Rhs2::Target: Deref,
282{
283 let out = out as *mut Result<(), C::Error>;
284 let cmp = &*(cmp as *const C);
285 let lhs = &*(lhs as *const Lhs2);
286 let rhs = &*(rhs as *const Rhs2);
287 out.write(cmp.test(&**lhs, &**rhs));
288}
289
290unsafe fn as_debug_vptr<T: fmt::Debug>(ptr: *const ()) -> &'static dyn fmt::Debug {
291 core::mem::transmute::<&'_ dyn fmt::Debug, &'static dyn fmt::Debug>(
292 (&*(ptr as *const T)) as &dyn fmt::Debug,
293 )
294}
295
296impl<
297 Lhs3: Deref + fmt::Debug + DerefVTable,
298 Rhs3: Deref + fmt::Debug + DerefVTable,
299 C: Cmp<
300 <<<Lhs3 as Deref>::Target as Deref>::Target as Deref>::Target,
301 <<<Rhs3 as Deref>::Target as Deref>::Target as Deref>::Target,
302 >,
303 > DynInfoType
304 for expr::CmpExpr<
305 &spec::by_val::CmpByValWrapper<
306 spec::sized::CmpSizedWrapper<spec::debug::CmpDebugWrapper<C>>,
307 >,
308 &Lhs3,
309 &Rhs3,
310 >
311where
312 C::Error: CmpDisplay<C, dyn fmt::Debug, dyn fmt::Debug>,
313 Lhs3::Target: Deref,
314 Rhs3::Target: Deref,
315 <Lhs3::Target as Deref>::Target: Deref,
316 <Rhs3::Target as Deref>::Target: Deref,
317{
318 type VTable =
319 expr::CmpExpr<(PtrToDisplay, PtrToCmp), (PtrToDebug, PtrToDeref), (PtrToDebug, PtrToDeref)>;
320 const NULL_VTABLE: &'static Self::VTable = &expr::CmpExpr {
321 cmp: (
322 as_dyn_display_vptr::<
323 spec::by_val::CmpByValWrapper<
324 spec::sized::CmpSizedWrapper<spec::debug::CmpDebugWrapper<C>>,
325 >,
326 spec::by_val::CmpByValWrapper<
327 spec::sized::CmpSizedWrapper<spec::debug::CmpDebugWrapper<C::Error>>,
328 >,
329 >,
330 as_cmp_vptr::<ByVal<ByVal<()>>, ByVal<ByVal<()>>, crate::Eq>,
331 ),
332 lhs: (as_debug_vptr::<Lhs3>, Lhs3::VTABLE),
333 rhs: (as_debug_vptr::<Rhs3>, Rhs3::VTABLE),
334 };
335}
336
337impl<
338 Lhs3: Deref + fmt::Debug + DerefVTable,
339 Rhs3: Deref + fmt::Debug + DerefVTable,
340 C: Cmp<
341 <<<Lhs3 as Deref>::Target as Deref>::Target as Deref>::Target,
342 <<<Rhs3 as Deref>::Target as Deref>::Target as Deref>::Target,
343 >,
344 > DynInfoType
345 for expr::CustomCmpExpr<
346 &spec::by_val::CmpByValWrapper<
347 spec::sized::CmpSizedWrapper<spec::debug::CmpDebugWrapper<C>>,
348 >,
349 &Lhs3,
350 &Rhs3,
351 >
352where
353 C::Error: CmpDisplay<
354 C,
355 <<<Lhs3 as Deref>::Target as Deref>::Target as Deref>::Target,
356 <<<Rhs3 as Deref>::Target as Deref>::Target as Deref>::Target,
357 >,
358 Lhs3::Target: Deref,
359 Rhs3::Target: Deref,
360 <Lhs3::Target as Deref>::Target: Deref,
361 <Rhs3::Target as Deref>::Target: Deref,
362{
363 type VTable = expr::CustomCmpExpr<
364 (PtrToDisplay, PtrToCmp),
365 (PtrToDebug, PtrToDeref),
366 (PtrToDebug, PtrToDeref),
367 >;
368 const NULL_VTABLE: &'static Self::VTable = &expr::CustomCmpExpr {
369 cmp: (
370 as_display_vptr::<
371 spec::by_val::CmpByValWrapper<
372 spec::sized::CmpSizedWrapper<spec::debug::CmpDebugWrapper<C>>,
373 >,
374 Wrapper<Lhs3>,
375 Wrapper<Rhs3>,
376 spec::by_val::CmpByValWrapper<
377 spec::sized::CmpSizedWrapper<spec::debug::CmpDebugWrapper<C::Error>>,
378 >,
379 >,
380 as_cmp_vptr::<ByVal<ByVal<()>>, ByVal<ByVal<()>>, crate::Eq>,
381 ),
382 lhs: (as_debug_vptr::<Lhs3>, Lhs3::VTABLE),
383 rhs: (as_debug_vptr::<Rhs3>, Rhs3::VTABLE),
384 };
385}
386
387impl<
388 Lhs3: Deref + fmt::Debug + DerefVTable,
389 Rhs3: Deref + fmt::Debug + DerefVTable,
390 C: Cmp<
391 <<<Lhs3 as Deref>::Target as Deref>::Target as Deref>::Target,
392 <<<Rhs3 as Deref>::Target as Deref>::Target as Deref>::Target,
393 >,
394 > DynInfo
395 for expr::CmpExpr<
396 &spec::by_val::CmpByValWrapper<
397 spec::sized::CmpSizedWrapper<spec::debug::CmpDebugWrapper<C>>,
398 >,
399 &Lhs3,
400 &Rhs3,
401 >
402where
403 C::Error: CmpDisplay<C, dyn fmt::Debug, dyn fmt::Debug>,
404 Lhs3::Target: Sized + Deref,
405 Rhs3::Target: Sized + Deref,
406 <Lhs3::Target as Deref>::Target: Deref,
407 <Rhs3::Target as Deref>::Target: Deref,
408{
409 const VTABLE: &'static Self::VTable = &expr::CmpExpr {
410 cmp: (
411 as_dyn_display_vptr::<
412 spec::by_val::CmpByValWrapper<
413 spec::sized::CmpSizedWrapper<spec::debug::CmpDebugWrapper<C>>,
414 >,
415 spec::by_val::CmpByValWrapper<
416 spec::sized::CmpSizedWrapper<spec::debug::CmpDebugWrapper<C::Error>>,
417 >,
418 >,
419 as_cmp_vptr::<Lhs3::Target, Rhs3::Target, C>,
420 ),
421 lhs: (as_debug_vptr::<Lhs3>, Lhs3::VTABLE),
422 rhs: (as_debug_vptr::<Rhs3>, Rhs3::VTABLE),
423 };
424}
425
426impl<
427 Lhs3: Deref + fmt::Debug + DerefVTable,
428 Rhs3: Deref + fmt::Debug + DerefVTable,
429 C: Cmp<
430 <<<Lhs3 as Deref>::Target as Deref>::Target as Deref>::Target,
431 <<<Rhs3 as Deref>::Target as Deref>::Target as Deref>::Target,
432 >,
433 > DynInfo
434 for expr::CustomCmpExpr<
435 &spec::by_val::CmpByValWrapper<
436 spec::sized::CmpSizedWrapper<spec::debug::CmpDebugWrapper<C>>,
437 >,
438 &Lhs3,
439 &Rhs3,
440 >
441where
442 C::Error: CmpDisplay<
443 C,
444 <<<Lhs3 as Deref>::Target as Deref>::Target as Deref>::Target,
445 <<<Rhs3 as Deref>::Target as Deref>::Target as Deref>::Target,
446 >,
447 Lhs3::Target: Sized + Deref,
448 Rhs3::Target: Sized + Deref,
449 <Lhs3::Target as Deref>::Target: Deref,
450 <Rhs3::Target as Deref>::Target: Deref,
451{
452 const VTABLE: &'static Self::VTable = &expr::CustomCmpExpr {
453 cmp: (
454 as_display_vptr::<
455 spec::by_val::CmpByValWrapper<
456 spec::sized::CmpSizedWrapper<spec::debug::CmpDebugWrapper<C>>,
457 >,
458 Wrapper<Lhs3>,
459 Wrapper<Rhs3>,
460 spec::by_val::CmpByValWrapper<
461 spec::sized::CmpSizedWrapper<spec::debug::CmpDebugWrapper<C::Error>>,
462 >,
463 >,
464 as_cmp_vptr::<Lhs3::Target, Rhs3::Target, C>,
465 ),
466 lhs: (as_debug_vptr::<Lhs3>, Lhs3::VTABLE),
467 rhs: (as_debug_vptr::<Rhs3>, Rhs3::VTABLE),
468 };
469}