equator/spec/
by_val.rs

1use crate::{
2    decompose::PtrToDeref,
3    spec::{debug::CmpDebugWrapper, sized::CmpSizedWrapper, Wrapper},
4    Cmp, CmpDisplay, CmpError,
5};
6use core::fmt;
7
8#[repr(transparent)]
9#[derive(Copy, Clone)]
10pub struct ByVal<T>(pub T);
11
12#[repr(transparent)]
13#[derive(Copy, Clone)]
14pub struct ByRef<T>(pub T);
15
16impl<T: fmt::Debug> fmt::Debug for ByVal<T> {
17    #[inline(always)]
18    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19        self.0.fmt(f)
20    }
21}
22
23impl<T: fmt::Debug> fmt::Debug for ByRef<T> {
24    #[inline(always)]
25    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26        self.0.fmt(f)
27    }
28}
29
30impl<T> ByRef<T> {
31    #[inline(always)]
32    pub fn get_ptr(&self) -> *const () {
33        self as *const _ as *const ()
34    }
35}
36
37impl<T: Copy> ByVal<T> {
38    const FIT_IN_PTR: bool = core::mem::size_of::<T>() <= core::mem::size_of::<*const ()>()
39        && core::mem::align_of::<T>() <= core::mem::align_of::<*const ()>();
40
41    #[inline(always)]
42    pub fn get_ptr(&self) -> *const () {
43        if Self::FIT_IN_PTR {
44            let mut out = core::ptr::null::<()>();
45            unsafe {
46                *((&mut out) as *mut *const () as *mut T) = self.0;
47            };
48            out
49        } else {
50            self as *const _ as *const ()
51        }
52    }
53}
54
55impl<
56        Lhs: ?Sized + core::ops::Deref,
57        Rhs: ?Sized + core::ops::Deref,
58        C: Cmp<Wrapper<Lhs::Target>, Wrapper<Rhs::Target>>,
59    > Cmp<Wrapper<Lhs>, Wrapper<Rhs>> for CmpByValWrapper<C>
60{
61    #[inline(always)]
62    fn test(&self, lhs: &Wrapper<Lhs>, rhs: &Wrapper<Rhs>) -> Result<(), Self::Error> {
63        self.0
64            .test(
65                unsafe { &*((&*lhs.0) as *const Lhs::Target as *const Wrapper<Lhs::Target>) },
66                unsafe { &*((&*rhs.0) as *const Rhs::Target as *const Wrapper<Rhs::Target>) },
67            )
68            .map_err(CmpByValWrapper)
69    }
70}
71
72impl<
73        Lhs: ?Sized + core::ops::Deref,
74        Rhs: ?Sized + core::ops::Deref,
75        C: CmpError<C, Wrapper<Lhs::Target>, Wrapper<Rhs::Target>>,
76    > CmpError<CmpByValWrapper<C>, Wrapper<Lhs>, Wrapper<Rhs>> for CmpByValWrapper<C>
77{
78    type Error = CmpByValWrapper<C::Error>;
79}
80
81impl<
82        Lhs: ?Sized + core::ops::Deref,
83        Rhs: ?Sized + core::ops::Deref,
84        C,
85        E: CmpDisplay<C, Wrapper<Lhs::Target>, Wrapper<Rhs::Target>>,
86    > CmpDisplay<CmpByValWrapper<C>, Wrapper<Lhs>, Wrapper<Rhs>> for CmpByValWrapper<E>
87{
88    fn fmt(
89        &self,
90        cmp: &CmpByValWrapper<C>,
91        lhs: &Wrapper<Lhs>,
92        lhs_source: &str,
93        lhs_debug: &dyn fmt::Debug,
94        rhs: &Wrapper<Rhs>,
95        rhs_source: &str,
96        rhs_debug: &dyn fmt::Debug,
97        f: &mut fmt::Formatter,
98    ) -> fmt::Result {
99        self.0.fmt(
100            &cmp.0,
101            unsafe { &*((&*lhs.0) as *const Lhs::Target as *const Wrapper<Lhs::Target>) },
102            lhs_source,
103            lhs_debug,
104            unsafe { &*((&*rhs.0) as *const Rhs::Target as *const Wrapper<Rhs::Target>) },
105            rhs_source,
106            rhs_debug,
107            f,
108        )
109    }
110}
111
112impl<T> core::ops::Deref for ByVal<T> {
113    type Target = T;
114
115    #[inline]
116    fn deref(&self) -> &Self::Target {
117        &self.0
118    }
119}
120
121impl<T> core::ops::Deref for ByRef<T> {
122    type Target = T;
123
124    #[inline]
125    fn deref(&self) -> &Self::Target {
126        &self.0
127    }
128}
129
130impl ByValWrap {
131    #[inline(always)]
132    pub fn do_wrap<T: Copy>(self, value: &T) -> &ByVal<T> {
133        unsafe { &*(value as *const T as *const _) }
134    }
135}
136impl ByRefWrap {
137    #[inline(always)]
138    pub fn do_wrap<T>(self, value: &T) -> &ByRef<T> {
139        unsafe { &*(value as *const T as *const _) }
140    }
141}
142
143impl<'a, C> CmpByValWrapper<CmpSizedWrapper<CmpDebugWrapper<&'a C>>> {
144    #[inline(always)]
145    pub fn __wrap_ref(self) -> &'a CmpByValWrapper<CmpSizedWrapper<CmpDebugWrapper<C>>> {
146        unsafe {
147            &*(self.0 .0 .0 as *const C
148                as *const CmpByValWrapper<CmpSizedWrapper<CmpDebugWrapper<C>>>)
149        }
150    }
151}
152impl<T: Copy> TryByValWrap for &Wrapper<&T> {
153    type Wrap = ByValWrap;
154
155    #[inline]
156    fn wrap_by_val(&self) -> Self::Wrap {
157        ByValWrap
158    }
159}
160impl<T> TryByValWrap for Wrapper<T> {
161    type Wrap = ByRefWrap;
162
163    #[inline]
164    fn wrap_by_val(&self) -> Self::Wrap {
165        ByRefWrap
166    }
167}
168
169pub struct ByValWrap;
170pub struct ByRefWrap;
171
172#[repr(transparent)]
173#[derive(Copy, Clone)]
174pub struct CmpByValWrapper<T: ?Sized>(pub T);
175
176pub trait TryByValWrap {
177    type Wrap;
178    fn wrap_by_val(&self) -> Self::Wrap;
179}
180
181pub(crate) trait DerefVTable {
182    const VTABLE: unsafe fn(*const *const ()) -> *const ();
183}
184
185unsafe fn no_deref(ptr: *const *const ()) -> *const () {
186    ptr as *const ()
187}
188unsafe fn deref(ptr: *const *const ()) -> *const () {
189    *ptr
190}
191
192impl<T: Copy> DerefVTable for ByVal<T> {
193    const VTABLE: PtrToDeref = {
194        if ByVal::<T>::FIT_IN_PTR {
195            no_deref
196        } else {
197            deref
198        }
199    };
200}
201impl<T> DerefVTable for ByRef<T> {
202    const VTABLE: PtrToDeref = { deref };
203}