equator/
traits.rs

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}