1use crate::shared_ptr::{SharedPtr, SharedPtrTarget};
2use crate::string::CxxString;
3use core::ffi::c_void;
4use core::fmt::{self, Debug};
5use core::marker::PhantomData;
6use core::mem::MaybeUninit;
7use core::ptr;
8
9#[repr(C)]
16pub struct WeakPtr<T>
17where
18 T: WeakPtrTarget,
19{
20 repr: [MaybeUninit<*mut c_void>; 2],
21 ty: PhantomData<T>,
22}
23
24impl<T> WeakPtr<T>
25where
26 T: WeakPtrTarget,
27{
28 pub fn null() -> Self {
32 let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit();
33 let new = weak_ptr.as_mut_ptr().cast();
34 unsafe {
35 T::__null(new);
36 weak_ptr.assume_init()
37 }
38 }
39
40 pub fn upgrade(&self) -> SharedPtr<T>
45 where
46 T: SharedPtrTarget,
47 {
48 let this = ptr::from_ref::<Self>(self).cast::<c_void>();
49 let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit();
50 let new = shared_ptr.as_mut_ptr().cast();
51 unsafe {
52 T::__upgrade(this, new);
53 shared_ptr.assume_init()
54 }
55 }
56}
57
58unsafe impl<T> Send for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {}
59unsafe impl<T> Sync for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {}
60
61impl<T> Clone for WeakPtr<T>
62where
63 T: WeakPtrTarget,
64{
65 fn clone(&self) -> Self {
66 let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit();
67 let new = weak_ptr.as_mut_ptr().cast();
68 let this = ptr::from_ref::<Self>(self).cast::<c_void>();
69 unsafe {
70 T::__clone(this, new);
71 weak_ptr.assume_init()
72 }
73 }
74}
75
76impl<T> Drop for WeakPtr<T>
77where
78 T: WeakPtrTarget,
79{
80 fn drop(&mut self) {
81 let this = ptr::from_mut::<Self>(self).cast::<c_void>();
82 unsafe { T::__drop(this) }
83 }
84}
85
86impl<T> Debug for WeakPtr<T>
87where
88 T: Debug + WeakPtrTarget + SharedPtrTarget,
89{
90 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
91 Debug::fmt(&self.upgrade(), formatter)
92 }
93}
94
95pub unsafe trait WeakPtrTarget {
101 #[doc(hidden)]
102 fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
103 #[doc(hidden)]
104 unsafe fn __null(new: *mut c_void);
105 #[doc(hidden)]
106 unsafe fn __clone(this: *const c_void, new: *mut c_void);
107 #[doc(hidden)]
108 unsafe fn __downgrade(shared: *const c_void, new: *mut c_void);
109 #[doc(hidden)]
110 unsafe fn __upgrade(weak: *const c_void, shared: *mut c_void);
111 #[doc(hidden)]
112 unsafe fn __drop(this: *mut c_void);
113}
114
115macro_rules! impl_weak_ptr_target {
116 ($segment:expr, $name:expr, $ty:ty) => {
117 unsafe impl WeakPtrTarget for $ty {
118 fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
119 f.write_str($name)
120 }
121 unsafe fn __null(new: *mut c_void) {
122 extern "C" {
123 #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$null")]
124 fn __null(new: *mut c_void);
125 }
126 unsafe { __null(new) }
127 }
128 unsafe fn __clone(this: *const c_void, new: *mut c_void) {
129 extern "C" {
130 #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$clone")]
131 fn __clone(this: *const c_void, new: *mut c_void);
132 }
133 unsafe { __clone(this, new) }
134 }
135 unsafe fn __downgrade(shared: *const c_void, weak: *mut c_void) {
136 extern "C" {
137 #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$downgrade")]
138 fn __downgrade(shared: *const c_void, weak: *mut c_void);
139 }
140 unsafe { __downgrade(shared, weak) }
141 }
142 unsafe fn __upgrade(weak: *const c_void, shared: *mut c_void) {
143 extern "C" {
144 #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$upgrade")]
145 fn __upgrade(weak: *const c_void, shared: *mut c_void);
146 }
147 unsafe { __upgrade(weak, shared) }
148 }
149 unsafe fn __drop(this: *mut c_void) {
150 extern "C" {
151 #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$drop")]
152 fn __drop(this: *mut c_void);
153 }
154 unsafe { __drop(this) }
155 }
156 }
157 };
158}
159
160macro_rules! impl_weak_ptr_target_for_primitive {
161 ($ty:ident) => {
162 impl_weak_ptr_target!(stringify!($ty), stringify!($ty), $ty);
163 };
164}
165
166impl_weak_ptr_target_for_primitive!(bool);
167impl_weak_ptr_target_for_primitive!(u8);
168impl_weak_ptr_target_for_primitive!(u16);
169impl_weak_ptr_target_for_primitive!(u32);
170impl_weak_ptr_target_for_primitive!(u64);
171impl_weak_ptr_target_for_primitive!(usize);
172impl_weak_ptr_target_for_primitive!(i8);
173impl_weak_ptr_target_for_primitive!(i16);
174impl_weak_ptr_target_for_primitive!(i32);
175impl_weak_ptr_target_for_primitive!(i64);
176impl_weak_ptr_target_for_primitive!(isize);
177impl_weak_ptr_target_for_primitive!(f32);
178impl_weak_ptr_target_for_primitive!(f64);
179
180impl_weak_ptr_target!("string", "CxxString", CxxString);