blob: d73ee8fe8577b75886e9d86e0515c94cc9d00dc8 [file] [log] [blame]
David Tolnay215e77f2020-12-28 17:09:48 -08001use crate::string::CxxString;
2use core::ffi::c_void;
3use core::fmt::Display;
4use core::marker::PhantomData;
5use core::mem::MaybeUninit;
6
7/// Binding to C++ `std::weak_ptr<T>`.
8#[repr(C)]
9pub struct WeakPtr<T>
10where
11 T: WeakPtrTarget,
12{
13 repr: [*mut c_void; 2],
14 ty: PhantomData<T>,
15}
16
17impl<T> WeakPtr<T>
18where
19 T: WeakPtrTarget,
20{
21 /// Makes a new WeakPtr wrapping a null pointer.
22 ///
23 /// Matches the behavior of default-constructing a std::weak\_ptr.
24 pub fn null() -> Self {
25 let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit();
26 let new = weak_ptr.as_mut_ptr().cast();
27 unsafe {
28 T::__null(new);
29 weak_ptr.assume_init()
30 }
31 }
32}
33
34unsafe impl<T> Send for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {}
35unsafe impl<T> Sync for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {}
36
37impl<T> Clone for WeakPtr<T>
38where
39 T: WeakPtrTarget,
40{
41 fn clone(&self) -> Self {
42 let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit();
43 let new = weak_ptr.as_mut_ptr().cast();
44 let this = self as *const Self as *mut c_void;
45 unsafe {
46 T::__clone(this, new);
47 weak_ptr.assume_init()
48 }
49 }
50}
51
52impl<T> Drop for WeakPtr<T>
53where
54 T: WeakPtrTarget,
55{
56 fn drop(&mut self) {
57 let this = self as *mut Self as *mut c_void;
58 unsafe { T::__drop(this) }
59 }
60}
61
62// Methods are private; not intended to be implemented outside of cxxbridge
63// codebase.
64pub unsafe trait WeakPtrTarget {
65 #[doc(hidden)]
66 const __NAME: &'static dyn Display;
67 #[doc(hidden)]
68 unsafe fn __null(new: *mut c_void);
69 #[doc(hidden)]
70 unsafe fn __clone(this: *const c_void, new: *mut c_void);
71 #[doc(hidden)]
72 unsafe fn __drop(this: *mut c_void);
73}
74
75macro_rules! impl_weak_ptr_target {
76 ($segment:expr, $name:expr, $ty:ty) => {
77 unsafe impl WeakPtrTarget for $ty {
78 const __NAME: &'static dyn Display = &$name;
79 unsafe fn __null(new: *mut c_void) {
80 extern "C" {
81 attr! {
82 #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$null")]
83 fn __null(new: *mut c_void);
84 }
85 }
86 __null(new);
87 }
88 unsafe fn __clone(this: *const c_void, new: *mut c_void) {
89 extern "C" {
90 attr! {
91 #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$clone")]
92 fn __clone(this: *const c_void, new: *mut c_void);
93 }
94 }
95 __clone(this, new);
96 }
97 unsafe fn __drop(this: *mut c_void) {
98 extern "C" {
99 attr! {
100 #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$drop")]
101 fn __drop(this: *mut c_void);
102 }
103 }
104 __drop(this);
105 }
106 }
107 };
108}
109
110macro_rules! impl_weak_ptr_target_for_primitive {
111 ($ty:ident) => {
112 impl_weak_ptr_target!(stringify!($ty), stringify!($ty), $ty);
113 };
114}
115
116impl_weak_ptr_target_for_primitive!(bool);
117impl_weak_ptr_target_for_primitive!(u8);
118impl_weak_ptr_target_for_primitive!(u16);
119impl_weak_ptr_target_for_primitive!(u32);
120impl_weak_ptr_target_for_primitive!(u64);
121impl_weak_ptr_target_for_primitive!(usize);
122impl_weak_ptr_target_for_primitive!(i8);
123impl_weak_ptr_target_for_primitive!(i16);
124impl_weak_ptr_target_for_primitive!(i32);
125impl_weak_ptr_target_for_primitive!(i64);
126impl_weak_ptr_target_for_primitive!(isize);
127impl_weak_ptr_target_for_primitive!(f32);
128impl_weak_ptr_target_for_primitive!(f64);
129
130impl_weak_ptr_target!("string", "CxxString", CxxString);