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