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}