cxx/
shared_ptr.rs
1use crate::fmt::display;
2use crate::kind::Trivial;
3use crate::string::CxxString;
4use crate::weak_ptr::{WeakPtr, WeakPtrTarget};
5use crate::ExternType;
6use core::ffi::c_void;
7use core::fmt::{self, Debug, Display};
8use core::marker::PhantomData;
9use core::mem::MaybeUninit;
10use core::ops::Deref;
11
12#[repr(C)]
14pub struct SharedPtr<T>
15where
16 T: SharedPtrTarget,
17{
18 repr: [MaybeUninit<*mut c_void>; 2],
19 ty: PhantomData<T>,
20}
21
22impl<T> SharedPtr<T>
23where
24 T: SharedPtrTarget,
25{
26 pub fn null() -> Self {
30 let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit();
31 let new = shared_ptr.as_mut_ptr().cast();
32 unsafe {
33 T::__null(new);
34 shared_ptr.assume_init()
35 }
36 }
37
38 pub fn new(value: T) -> Self
40 where
41 T: ExternType<Kind = Trivial>,
42 {
43 let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit();
44 let new = shared_ptr.as_mut_ptr().cast();
45 unsafe {
46 T::__new(value, new);
47 shared_ptr.assume_init()
48 }
49 }
50
51 pub fn is_null(&self) -> bool {
55 let this = self as *const Self as *const c_void;
56 let ptr = unsafe { T::__get(this) };
57 ptr.is_null()
58 }
59
60 pub fn as_ref(&self) -> Option<&T> {
63 let this = self as *const Self as *const c_void;
64 unsafe { T::__get(this).as_ref() }
65 }
66
67 pub fn downgrade(self: &SharedPtr<T>) -> WeakPtr<T>
73 where
74 T: WeakPtrTarget,
75 {
76 let this = self as *const Self as *const c_void;
77 let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit();
78 let new = weak_ptr.as_mut_ptr().cast();
79 unsafe {
80 T::__downgrade(this, new);
81 weak_ptr.assume_init()
82 }
83 }
84}
85
86unsafe impl<T> Send for SharedPtr<T> where T: Send + Sync + SharedPtrTarget {}
87unsafe impl<T> Sync for SharedPtr<T> where T: Send + Sync + SharedPtrTarget {}
88
89impl<T> Clone for SharedPtr<T>
90where
91 T: SharedPtrTarget,
92{
93 fn clone(&self) -> Self {
94 let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit();
95 let new = shared_ptr.as_mut_ptr().cast();
96 let this = self as *const Self as *mut c_void;
97 unsafe {
98 T::__clone(this, new);
99 shared_ptr.assume_init()
100 }
101 }
102}
103
104impl<T> Unpin for SharedPtr<T> where T: SharedPtrTarget {}
107
108impl<T> Drop for SharedPtr<T>
109where
110 T: SharedPtrTarget,
111{
112 fn drop(&mut self) {
113 let this = self as *mut Self as *mut c_void;
114 unsafe { T::__drop(this) }
115 }
116}
117
118impl<T> Deref for SharedPtr<T>
119where
120 T: SharedPtrTarget,
121{
122 type Target = T;
123
124 fn deref(&self) -> &Self::Target {
125 match self.as_ref() {
126 Some(target) => target,
127 None => panic!(
128 "called deref on a null SharedPtr<{}>",
129 display(T::__typename),
130 ),
131 }
132 }
133}
134
135impl<T> Debug for SharedPtr<T>
136where
137 T: Debug + SharedPtrTarget,
138{
139 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
140 match self.as_ref() {
141 None => formatter.write_str("nullptr"),
142 Some(value) => Debug::fmt(value, formatter),
143 }
144 }
145}
146
147impl<T> Display for SharedPtr<T>
148where
149 T: Display + SharedPtrTarget,
150{
151 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
152 match self.as_ref() {
153 None => formatter.write_str("nullptr"),
154 Some(value) => Display::fmt(value, formatter),
155 }
156 }
157}
158
159pub unsafe trait SharedPtrTarget {
185 #[doc(hidden)]
186 fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
187 #[doc(hidden)]
188 unsafe fn __null(new: *mut c_void);
189 #[doc(hidden)]
190 unsafe fn __new(value: Self, new: *mut c_void)
191 where
192 Self: Sized,
193 {
194 let _ = value;
197 let _ = new;
198 unreachable!()
199 }
200 #[doc(hidden)]
201 unsafe fn __clone(this: *const c_void, new: *mut c_void);
202 #[doc(hidden)]
203 unsafe fn __get(this: *const c_void) -> *const Self;
204 #[doc(hidden)]
205 unsafe fn __drop(this: *mut c_void);
206}
207
208macro_rules! impl_shared_ptr_target {
209 ($segment:expr, $name:expr, $ty:ty) => {
210 unsafe impl SharedPtrTarget for $ty {
211 fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
212 f.write_str($name)
213 }
214 unsafe fn __null(new: *mut c_void) {
215 extern "C" {
216 #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$null")]
217 fn __null(new: *mut c_void);
218 }
219 unsafe { __null(new) }
220 }
221 unsafe fn __new(value: Self, new: *mut c_void) {
222 extern "C" {
223 #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$uninit")]
224 fn __uninit(new: *mut c_void) -> *mut c_void;
225 }
226 unsafe { __uninit(new).cast::<$ty>().write(value) }
227 }
228 unsafe fn __clone(this: *const c_void, new: *mut c_void) {
229 extern "C" {
230 #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$clone")]
231 fn __clone(this: *const c_void, new: *mut c_void);
232 }
233 unsafe { __clone(this, new) }
234 }
235 unsafe fn __get(this: *const c_void) -> *const Self {
236 extern "C" {
237 #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$get")]
238 fn __get(this: *const c_void) -> *const c_void;
239 }
240 unsafe { __get(this) }.cast()
241 }
242 unsafe fn __drop(this: *mut c_void) {
243 extern "C" {
244 #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$drop")]
245 fn __drop(this: *mut c_void);
246 }
247 unsafe { __drop(this) }
248 }
249 }
250 };
251}
252
253macro_rules! impl_shared_ptr_target_for_primitive {
254 ($ty:ident) => {
255 impl_shared_ptr_target!(stringify!($ty), stringify!($ty), $ty);
256 };
257}
258
259impl_shared_ptr_target_for_primitive!(bool);
260impl_shared_ptr_target_for_primitive!(u8);
261impl_shared_ptr_target_for_primitive!(u16);
262impl_shared_ptr_target_for_primitive!(u32);
263impl_shared_ptr_target_for_primitive!(u64);
264impl_shared_ptr_target_for_primitive!(usize);
265impl_shared_ptr_target_for_primitive!(i8);
266impl_shared_ptr_target_for_primitive!(i16);
267impl_shared_ptr_target_for_primitive!(i32);
268impl_shared_ptr_target_for_primitive!(i64);
269impl_shared_ptr_target_for_primitive!(isize);
270impl_shared_ptr_target_for_primitive!(f32);
271impl_shared_ptr_target_for_primitive!(f64);
272
273impl_shared_ptr_target!("string", "CxxString", CxxString);