1use core::ptr::NonNull;
16
17use crate as stabby;
18use crate::vtable::*;
19
20#[stabby::stabby]
22#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
23pub struct AnonymRef<'a> {
24 pub ptr: NonNull<()>,
26 pub _marker: core::marker::PhantomData<&'a ()>,
28}
29impl<T> From<&T> for AnonymRef<'_> {
30 fn from(value: &T) -> Self {
31 Self {
32 ptr: NonNull::from(value).cast(),
33 _marker: core::marker::PhantomData,
34 }
35 }
36}
37impl core::ops::Deref for AnonymRef<'_> {
38 type Target = NonNull<()>;
39 fn deref(&self) -> &Self::Target {
40 &self.ptr
41 }
42}
43
44#[stabby::stabby]
46#[derive(Debug, PartialEq, Eq, Hash)]
47pub struct AnonymRefMut<'a> {
48 pub ptr: NonNull<()>,
50 pub _marker: core::marker::PhantomData<&'a mut ()>,
52}
53impl<T> From<&mut T> for AnonymRefMut<'_> {
54 fn from(value: &mut T) -> Self {
55 Self {
56 ptr: NonNull::from(value).cast(),
57 _marker: core::marker::PhantomData,
58 }
59 }
60}
61impl core::ops::Deref for AnonymRefMut<'_> {
62 type Target = NonNull<()>;
63 fn deref(&self) -> &Self::Target {
64 &self.ptr
65 }
66}
67impl core::ops::DerefMut for AnonymRefMut<'_> {
68 fn deref_mut(&mut self) -> &mut Self::Target {
69 &mut self.ptr
70 }
71}
72impl IPtrOwned for AnonymRefMut<'_> {
73 fn drop(_: &mut core::mem::ManuallyDrop<Self>, _: unsafe extern "C" fn(AnonymRefMut<'_>)) {}
74}
75impl IPtr for AnonymRefMut<'_> {
76 unsafe fn as_ref(&self) -> AnonymRef<'_> {
77 AnonymRef {
78 ptr: self.ptr,
79 _marker: core::marker::PhantomData,
80 }
81 }
82}
83impl IPtrMut for AnonymRefMut<'_> {
84 unsafe fn as_mut(&mut self) -> AnonymRefMut<'_> {
85 AnonymRefMut {
86 ptr: self.ptr,
87 _marker: core::marker::PhantomData,
88 }
89 }
90}
91
92pub trait IPtr {
94 unsafe fn as_ref(&self) -> AnonymRef<'_>;
97}
98pub trait IPtrMut: IPtr {
100 unsafe fn as_mut(&mut self) -> AnonymRefMut<'_>;
103}
104pub trait IPtrTryAsMut {
106 unsafe fn try_as_mut(&mut self) -> Option<AnonymRefMut<'_>>;
109}
110impl<T: IPtrMut> IPtrTryAsMut for T {
111 unsafe fn try_as_mut(&mut self) -> Option<AnonymRefMut<'_>> {
112 Some(self.into())
113 }
114}
115pub trait IPtrOwned {
119 fn drop(this: &mut core::mem::ManuallyDrop<Self>, drop: unsafe extern "C" fn(AnonymRefMut<'_>));
121}
122pub trait IPtrClone: IPtrOwned {
124 fn clone(this: &Self) -> Self;
126}
127impl<T> IPtr for &T {
128 unsafe fn as_ref(&self) -> AnonymRef<'_> {
129 self.into()
130 }
131}
132impl<T> IPtr for &mut T {
133 unsafe fn as_ref(&self) -> AnonymRef<'_> {
134 self.into()
135 }
136}
137impl<T> IPtrMut for &mut T {
138 unsafe fn as_mut(&mut self) -> AnonymRefMut<'_> {
139 self.into()
140 }
141}
142impl<T> IPtrOwned for &mut T {
143 fn drop(_: &mut core::mem::ManuallyDrop<Self>, _: unsafe extern "C" fn(AnonymRefMut<'_>)) {}
144}
145
146pub trait IntoDyn {
148 type Anonymized;
150 type Target;
152 fn anonimize(self) -> Self::Anonymized;
154}
155impl<'a, T> IntoDyn for &'a T {
156 type Anonymized = &'a ();
157 type Target = T;
158 fn anonimize(self) -> Self::Anonymized {
159 unsafe { core::mem::transmute(self) }
160 }
161}
162impl<'a, T> IntoDyn for &'a mut T {
163 type Anonymized = &'a mut ();
164 type Target = T;
165 fn anonimize(self) -> Self::Anonymized {
166 unsafe { core::mem::transmute(self) }
167 }
168}
169
170#[stabby::stabby]
171#[derive(Clone, Copy)]
172pub struct DynRef<'a, Vt: 'static> {
174 ptr: AnonymRef<'a>,
175 vtable: &'a Vt,
176 unsend: core::marker::PhantomData<*mut ()>,
177}
178
179impl<'a, Vt: Copy + 'a> DynRef<'a, Vt> {
180 pub const fn ptr(&self) -> AnonymRef<'a> {
182 self.ptr
183 }
184 pub const fn vtable(&self) -> &Vt {
186 self.vtable
187 }
188
189 pub fn into_super<Super>(self) -> Super
194 where
195 Self: IntoSuperTrait<Super>,
196 {
197 IntoSuperTrait::into_super(self)
198 }
199 pub unsafe fn downcast<T>(&self) -> Option<&T>
214 where
215 Vt: PartialEq + IConstConstructor<'a, T>,
216 {
217 (self.vtable == Vt::vtable()).then(|| unsafe { self.ptr.cast().as_ref() })
218 }
219 pub fn stable_downcast<T: crate::IStable, Path>(&self) -> Option<&T>
221 where
222 Vt: TransitiveDeref<crate::vtable::StabbyVtableAny<'a>, Path>,
223 {
224 (self.report() == T::REPORT).then(|| unsafe { self.ptr.cast().as_ref() })
225 }
226}
227#[stabby::stabby]
228pub struct Dyn<'a, P: IPtrOwned + 'a, Vt: HasDropVt + 'static> {
230 pub(crate) ptr: core::mem::ManuallyDrop<P>,
231 pub(crate) vtable: &'static Vt,
232 pub(crate) unsend: core::marker::PhantomData<&'a P>,
233}
234
235pub trait IntoSuperTrait<Super> {
237 fn into_super(this: Self) -> Super;
239}
240macro_rules! impl_super {
241 ($from: ty, $to: ty, $($generics: tt)*) => {
242 impl<'a, P: IPtrOwned + 'a + Sized, $($generics)*> IntoSuperTrait<Dyn<'a, P, $to>> for Dyn<'a, P, $from>
243 {
244 fn into_super(this: Self) -> Dyn<'a, P, $to> {
245 let ptr = &this as *const _;
246 core::mem::forget(this);
247 unsafe { core::ptr::read(ptr as *const _) }
248 }
249 }
250 impl<'a, $($generics)*> IntoSuperTrait<DynRef<'a, $to>> for DynRef<'a, $from>
251 {
252 fn into_super(this: Self) -> DynRef<'a, $to> {
253 let ptr = &this as *const _;
254 unsafe { core::ptr::read(ptr as *const _) }
255 }
256 }
257 };
258}
259impl_super!(VTable<Head, Tail>, Tail, Head, Tail: HasDropVt + 'static);
260impl_super!(VtSend<Vt>, Vt, Vt: HasDropVt + 'static);
261impl_super!(VtSync<Vt>, Vt, Vt: HasDropVt + 'static);
262impl_super!(VtSync<VtSend<Vt>>, Vt, Vt: HasDropVt + 'static);
263impl_super!(VtSend<VtSync<Vt>>, Vt, Vt: HasDropVt + 'static);
264impl_super!(VtSync<VtSend<Vt>>, VtSync<Vt>, Vt: HasDropVt + 'static);
265impl_super!(VtSend<VtSync<Vt>>, VtSend<Vt>, Vt: HasDropVt + 'static);
266impl_super!(VtSend<VTable<Head, Tail>>, Tail, Head, Tail: HasDropVt + 'static);
267impl_super!(VtSync<VTable<Head, Tail>>, Tail, Head, Tail: HasDropVt + 'static);
268impl_super!(VtSync<VtSend<VTable<Head, Tail>>>, Tail, Head, Tail: HasDropVt + 'static);
269impl_super!(VtSend<VtSync<VTable<Head, Tail>>>, Tail, Head, Tail: HasDropVt + 'static);
270impl_super!(VtSend<VTable<Head, Tail>>, VtSend<Tail>, Head, Tail: HasDropVt + 'static);
271impl_super!(VtSync<VTable<Head, Tail>>, VtSync<Tail>, Head, Tail: HasDropVt + 'static);
272impl_super!(VtSync<VtSend<VTable<Head, Tail>>>, VtSync<VtSend<Tail>>, Head, Tail: HasDropVt + 'static);
273impl_super!(VtSend<VtSync<VTable<Head, Tail>>>, VtSend<VtSync<Tail>>, Head, Tail: HasDropVt + 'static);
274
275impl<'a, P: IPtrOwned + IPtrClone, Vt: HasDropVt + 'a> Clone for Dyn<'a, P, Vt> {
276 fn clone(&self) -> Self {
277 Self {
278 ptr: core::mem::ManuallyDrop::new(IPtrClone::clone(&self.ptr)),
279 vtable: self.vtable,
280 unsend: self.unsend,
281 }
282 }
283}
284impl<'a, P: IPtrOwned + IPtr, Vt: HasDropVt + 'a> Dyn<'a, P, Vt> {
285 #[allow(clippy::missing_const_for_fn)]
287 pub fn ptr(&self) -> &P {
288 &self.ptr
289 }
290 #[allow(clippy::missing_const_for_fn)]
292 pub fn ptr_mut(&mut self) -> &mut P {
293 &mut self.ptr
294 }
295 pub const fn vtable(&self) -> &'a Vt {
297 self.vtable
298 }
299 pub fn as_ref(&self) -> DynRef<'_, Vt> {
301 DynRef {
302 ptr: unsafe { self.ptr.as_ref() },
303 vtable: self.vtable,
304 unsend: core::marker::PhantomData,
305 }
306 }
307 pub fn as_mut(&mut self) -> Dyn<AnonymRefMut<'_>, Vt>
309 where
310 P: IPtrMut,
311 {
312 Dyn {
313 ptr: unsafe { core::mem::ManuallyDrop::new(self.ptr.as_mut()) },
314 vtable: self.vtable,
315 unsend: core::marker::PhantomData,
316 }
317 }
318 pub fn try_as_mut(&mut self) -> Option<Dyn<AnonymRefMut<'_>, Vt>>
320 where
321 P: IPtrTryAsMut,
322 {
323 Some(Dyn {
324 ptr: unsafe { core::mem::ManuallyDrop::new(self.ptr.try_as_mut()?) },
325 vtable: self.vtable,
326 unsend: core::marker::PhantomData,
327 })
328 }
329
330 pub fn into_super<Super>(self) -> Super
335 where
336 Self: IntoSuperTrait<Super>,
337 {
338 IntoSuperTrait::into_super(self)
339 }
340
341 pub unsafe fn downcast_ref<T>(&self) -> Option<&T>
362 where
363 Vt: PartialEq + Copy + IConstConstructor<'a, T>,
364 {
365 (self.vtable == Vt::vtable()).then(|| unsafe { self.ptr.as_ref().cast::<T>().as_ref() })
366 }
367 pub fn stable_downcast_ref<T: crate::IStable, Path>(&self) -> Option<&T>
369 where
370 Vt: TransitiveDeref<crate::vtable::StabbyVtableAny<'a>, Path> + IConstConstructor<'a, T>,
371 {
372 (self.id() == T::ID && self.report() == T::REPORT)
373 .then(|| unsafe { self.ptr.as_ref().cast::<T>().as_ref() })
374 }
375 pub unsafe fn downcast_mut<T>(&mut self) -> Option<&mut T>
396 where
397 Vt: PartialEq + Copy + IConstConstructor<'a, T>,
398 P: IPtrMut,
399 {
400 (self.vtable == Vt::vtable()).then(|| unsafe { self.ptr.as_mut().cast::<T>().as_mut() })
401 }
402 pub fn stable_downcast_mut<T: crate::IStable, Path>(&mut self) -> Option<&mut T>
404 where
405 Vt: TransitiveDeref<crate::vtable::StabbyVtableAny<'a>, Path> + IConstConstructor<'a, T>,
406 P: IPtrMut,
407 {
408 (self.id() == T::ID && self.report() == T::REPORT)
409 .then(|| unsafe { self.ptr.as_mut().cast::<T>().as_mut() })
410 }
411}
412
413impl<
414 'a,
415 Vt: HasDropVt + Copy + IConstConstructor<'static, P::Target> + 'static,
416 P: IntoDyn + 'a,
417 > From<P> for Dyn<'a, P::Anonymized, Vt>
418where
419 P::Anonymized: IPtrOwned,
420{
421 fn from(value: P) -> Self {
422 Self {
423 ptr: core::mem::ManuallyDrop::new(value.anonimize()),
424 vtable: Vt::vtable(),
425 unsend: core::marker::PhantomData,
426 }
427 }
428}
429
430impl<P: IPtrOwned, Vt: HasDropVt> Drop for Dyn<'_, P, Vt> {
431 fn drop(&mut self) {
432 P::drop(&mut self.ptr, *unsafe {
433 self.vtable.drop_vt().drop.as_ref_unchecked()
434 })
435 }
436}
437
438impl<'a, T, Vt: Copy + IConstConstructor<'a, T>> From<&'a T> for DynRef<'a, Vt> {
439 fn from(value: &'a T) -> Self {
440 DynRef {
441 ptr: value.into(),
442 vtable: Vt::vtable(),
443 unsend: core::marker::PhantomData,
444 }
445 }
446}
447
448unsafe impl<Vt: HasSendVt> Send for DynRef<'_, Vt> {}
450unsafe impl<Vt: HasSyncVt> Sync for DynRef<'_, Vt> {}
452
453unsafe impl<P: IPtrOwned + Send, Vt: HasSendVt + HasDropVt> Send for Dyn<'_, P, Vt> {}
455unsafe impl<P: IPtrOwned + Sync, Vt: HasSyncVt + HasDropVt> Sync for Dyn<'_, P, Vt> {}