133d722a9Sopenharmony_ciuse crate::shared_ptr::{SharedPtr, SharedPtrTarget};
233d722a9Sopenharmony_ciuse crate::string::CxxString;
333d722a9Sopenharmony_ciuse core::ffi::c_void;
433d722a9Sopenharmony_ciuse core::fmt::{self, Debug};
533d722a9Sopenharmony_ciuse core::marker::PhantomData;
633d722a9Sopenharmony_ciuse core::mem::MaybeUninit;
733d722a9Sopenharmony_ci
833d722a9Sopenharmony_ci/// Binding to C++ `std::weak_ptr<T>`.
933d722a9Sopenharmony_ci///
1033d722a9Sopenharmony_ci/// The typical way to construct a WeakPtr from Rust is by [downgrading] from a
1133d722a9Sopenharmony_ci/// SharedPtr.
1233d722a9Sopenharmony_ci///
1333d722a9Sopenharmony_ci/// [downgrading]: crate::SharedPtr::downgrade
1433d722a9Sopenharmony_ci#[repr(C)]
1533d722a9Sopenharmony_cipub struct WeakPtr<T>
1633d722a9Sopenharmony_ciwhere
1733d722a9Sopenharmony_ci    T: WeakPtrTarget,
1833d722a9Sopenharmony_ci{
1933d722a9Sopenharmony_ci    repr: [MaybeUninit<*mut c_void>; 2],
2033d722a9Sopenharmony_ci    ty: PhantomData<T>,
2133d722a9Sopenharmony_ci}
2233d722a9Sopenharmony_ci
2333d722a9Sopenharmony_ciimpl<T> WeakPtr<T>
2433d722a9Sopenharmony_ciwhere
2533d722a9Sopenharmony_ci    T: WeakPtrTarget,
2633d722a9Sopenharmony_ci{
2733d722a9Sopenharmony_ci    /// Makes a new WeakPtr wrapping a null pointer.
2833d722a9Sopenharmony_ci    ///
2933d722a9Sopenharmony_ci    /// Matches the behavior of default-constructing a std::weak\_ptr.
3033d722a9Sopenharmony_ci    pub fn null() -> Self {
3133d722a9Sopenharmony_ci        let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit();
3233d722a9Sopenharmony_ci        let new = weak_ptr.as_mut_ptr().cast();
3333d722a9Sopenharmony_ci        unsafe {
3433d722a9Sopenharmony_ci            T::__null(new);
3533d722a9Sopenharmony_ci            weak_ptr.assume_init()
3633d722a9Sopenharmony_ci        }
3733d722a9Sopenharmony_ci    }
3833d722a9Sopenharmony_ci
3933d722a9Sopenharmony_ci    /// Upgrades a non-owning reference into an owning reference if possible,
4033d722a9Sopenharmony_ci    /// otherwise to a null reference.
4133d722a9Sopenharmony_ci    ///
4233d722a9Sopenharmony_ci    /// Matches the behavior of [std::weak_ptr\<T\>::lock](https://en.cppreference.com/w/cpp/memory/weak_ptr/lock).
4333d722a9Sopenharmony_ci    pub fn upgrade(&self) -> SharedPtr<T>
4433d722a9Sopenharmony_ci    where
4533d722a9Sopenharmony_ci        T: SharedPtrTarget,
4633d722a9Sopenharmony_ci    {
4733d722a9Sopenharmony_ci        let this = self as *const Self as *const c_void;
4833d722a9Sopenharmony_ci        let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit();
4933d722a9Sopenharmony_ci        let new = shared_ptr.as_mut_ptr().cast();
5033d722a9Sopenharmony_ci        unsafe {
5133d722a9Sopenharmony_ci            T::__upgrade(this, new);
5233d722a9Sopenharmony_ci            shared_ptr.assume_init()
5333d722a9Sopenharmony_ci        }
5433d722a9Sopenharmony_ci    }
5533d722a9Sopenharmony_ci}
5633d722a9Sopenharmony_ci
5733d722a9Sopenharmony_ciunsafe impl<T> Send for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {}
5833d722a9Sopenharmony_ciunsafe impl<T> Sync for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {}
5933d722a9Sopenharmony_ci
6033d722a9Sopenharmony_ciimpl<T> Clone for WeakPtr<T>
6133d722a9Sopenharmony_ciwhere
6233d722a9Sopenharmony_ci    T: WeakPtrTarget,
6333d722a9Sopenharmony_ci{
6433d722a9Sopenharmony_ci    fn clone(&self) -> Self {
6533d722a9Sopenharmony_ci        let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit();
6633d722a9Sopenharmony_ci        let new = weak_ptr.as_mut_ptr().cast();
6733d722a9Sopenharmony_ci        let this = self as *const Self as *mut c_void;
6833d722a9Sopenharmony_ci        unsafe {
6933d722a9Sopenharmony_ci            T::__clone(this, new);
7033d722a9Sopenharmony_ci            weak_ptr.assume_init()
7133d722a9Sopenharmony_ci        }
7233d722a9Sopenharmony_ci    }
7333d722a9Sopenharmony_ci}
7433d722a9Sopenharmony_ci
7533d722a9Sopenharmony_ciimpl<T> Drop for WeakPtr<T>
7633d722a9Sopenharmony_ciwhere
7733d722a9Sopenharmony_ci    T: WeakPtrTarget,
7833d722a9Sopenharmony_ci{
7933d722a9Sopenharmony_ci    fn drop(&mut self) {
8033d722a9Sopenharmony_ci        let this = self as *mut Self as *mut c_void;
8133d722a9Sopenharmony_ci        unsafe { T::__drop(this) }
8233d722a9Sopenharmony_ci    }
8333d722a9Sopenharmony_ci}
8433d722a9Sopenharmony_ci
8533d722a9Sopenharmony_ciimpl<T> Debug for WeakPtr<T>
8633d722a9Sopenharmony_ciwhere
8733d722a9Sopenharmony_ci    T: Debug + WeakPtrTarget + SharedPtrTarget,
8833d722a9Sopenharmony_ci{
8933d722a9Sopenharmony_ci    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
9033d722a9Sopenharmony_ci        Debug::fmt(&self.upgrade(), formatter)
9133d722a9Sopenharmony_ci    }
9233d722a9Sopenharmony_ci}
9333d722a9Sopenharmony_ci
9433d722a9Sopenharmony_ci/// Trait bound for types which may be used as the `T` inside of a `WeakPtr<T>`
9533d722a9Sopenharmony_ci/// in generic code.
9633d722a9Sopenharmony_ci///
9733d722a9Sopenharmony_ci/// This trait has no publicly callable or implementable methods. Implementing
9833d722a9Sopenharmony_ci/// it outside of the CXX codebase is not supported.
9933d722a9Sopenharmony_cipub unsafe trait WeakPtrTarget {
10033d722a9Sopenharmony_ci    #[doc(hidden)]
10133d722a9Sopenharmony_ci    fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
10233d722a9Sopenharmony_ci    #[doc(hidden)]
10333d722a9Sopenharmony_ci    unsafe fn __null(new: *mut c_void);
10433d722a9Sopenharmony_ci    #[doc(hidden)]
10533d722a9Sopenharmony_ci    unsafe fn __clone(this: *const c_void, new: *mut c_void);
10633d722a9Sopenharmony_ci    #[doc(hidden)]
10733d722a9Sopenharmony_ci    unsafe fn __downgrade(shared: *const c_void, new: *mut c_void);
10833d722a9Sopenharmony_ci    #[doc(hidden)]
10933d722a9Sopenharmony_ci    unsafe fn __upgrade(weak: *const c_void, shared: *mut c_void);
11033d722a9Sopenharmony_ci    #[doc(hidden)]
11133d722a9Sopenharmony_ci    unsafe fn __drop(this: *mut c_void);
11233d722a9Sopenharmony_ci}
11333d722a9Sopenharmony_ci
11433d722a9Sopenharmony_cimacro_rules! impl_weak_ptr_target {
11533d722a9Sopenharmony_ci    ($segment:expr, $name:expr, $ty:ty) => {
11633d722a9Sopenharmony_ci        unsafe impl WeakPtrTarget for $ty {
11733d722a9Sopenharmony_ci            fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
11833d722a9Sopenharmony_ci                f.write_str($name)
11933d722a9Sopenharmony_ci            }
12033d722a9Sopenharmony_ci            unsafe fn __null(new: *mut c_void) {
12133d722a9Sopenharmony_ci                extern "C" {
12233d722a9Sopenharmony_ci                    attr! {
12333d722a9Sopenharmony_ci                        #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$null")]
12433d722a9Sopenharmony_ci                        fn __null(new: *mut c_void);
12533d722a9Sopenharmony_ci                    }
12633d722a9Sopenharmony_ci                }
12733d722a9Sopenharmony_ci                unsafe { __null(new) }
12833d722a9Sopenharmony_ci            }
12933d722a9Sopenharmony_ci            unsafe fn __clone(this: *const c_void, new: *mut c_void) {
13033d722a9Sopenharmony_ci                extern "C" {
13133d722a9Sopenharmony_ci                    attr! {
13233d722a9Sopenharmony_ci                        #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$clone")]
13333d722a9Sopenharmony_ci                        fn __clone(this: *const c_void, new: *mut c_void);
13433d722a9Sopenharmony_ci                    }
13533d722a9Sopenharmony_ci                }
13633d722a9Sopenharmony_ci                unsafe { __clone(this, new) }
13733d722a9Sopenharmony_ci            }
13833d722a9Sopenharmony_ci            unsafe fn __downgrade(shared: *const c_void, weak: *mut c_void) {
13933d722a9Sopenharmony_ci                extern "C" {
14033d722a9Sopenharmony_ci                    attr! {
14133d722a9Sopenharmony_ci                        #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$downgrade")]
14233d722a9Sopenharmony_ci                        fn __downgrade(shared: *const c_void, weak: *mut c_void);
14333d722a9Sopenharmony_ci                    }
14433d722a9Sopenharmony_ci                }
14533d722a9Sopenharmony_ci                unsafe { __downgrade(shared, weak) }
14633d722a9Sopenharmony_ci            }
14733d722a9Sopenharmony_ci            unsafe fn __upgrade(weak: *const c_void, shared: *mut c_void) {
14833d722a9Sopenharmony_ci                extern "C" {
14933d722a9Sopenharmony_ci                    attr! {
15033d722a9Sopenharmony_ci                        #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$upgrade")]
15133d722a9Sopenharmony_ci                        fn __upgrade(weak: *const c_void, shared: *mut c_void);
15233d722a9Sopenharmony_ci                    }
15333d722a9Sopenharmony_ci                }
15433d722a9Sopenharmony_ci                unsafe { __upgrade(weak, shared) }
15533d722a9Sopenharmony_ci            }
15633d722a9Sopenharmony_ci            unsafe fn __drop(this: *mut c_void) {
15733d722a9Sopenharmony_ci                extern "C" {
15833d722a9Sopenharmony_ci                    attr! {
15933d722a9Sopenharmony_ci                        #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$drop")]
16033d722a9Sopenharmony_ci                        fn __drop(this: *mut c_void);
16133d722a9Sopenharmony_ci                    }
16233d722a9Sopenharmony_ci                }
16333d722a9Sopenharmony_ci                unsafe { __drop(this) }
16433d722a9Sopenharmony_ci            }
16533d722a9Sopenharmony_ci        }
16633d722a9Sopenharmony_ci    };
16733d722a9Sopenharmony_ci}
16833d722a9Sopenharmony_ci
16933d722a9Sopenharmony_cimacro_rules! impl_weak_ptr_target_for_primitive {
17033d722a9Sopenharmony_ci    ($ty:ident) => {
17133d722a9Sopenharmony_ci        impl_weak_ptr_target!(stringify!($ty), stringify!($ty), $ty);
17233d722a9Sopenharmony_ci    };
17333d722a9Sopenharmony_ci}
17433d722a9Sopenharmony_ci
17533d722a9Sopenharmony_ciimpl_weak_ptr_target_for_primitive!(bool);
17633d722a9Sopenharmony_ciimpl_weak_ptr_target_for_primitive!(u8);
17733d722a9Sopenharmony_ciimpl_weak_ptr_target_for_primitive!(u16);
17833d722a9Sopenharmony_ciimpl_weak_ptr_target_for_primitive!(u32);
17933d722a9Sopenharmony_ciimpl_weak_ptr_target_for_primitive!(u64);
18033d722a9Sopenharmony_ciimpl_weak_ptr_target_for_primitive!(usize);
18133d722a9Sopenharmony_ciimpl_weak_ptr_target_for_primitive!(i8);
18233d722a9Sopenharmony_ciimpl_weak_ptr_target_for_primitive!(i16);
18333d722a9Sopenharmony_ciimpl_weak_ptr_target_for_primitive!(i32);
18433d722a9Sopenharmony_ciimpl_weak_ptr_target_for_primitive!(i64);
18533d722a9Sopenharmony_ciimpl_weak_ptr_target_for_primitive!(isize);
18633d722a9Sopenharmony_ciimpl_weak_ptr_target_for_primitive!(f32);
18733d722a9Sopenharmony_ciimpl_weak_ptr_target_for_primitive!(f64);
18833d722a9Sopenharmony_ci
18933d722a9Sopenharmony_ciimpl_weak_ptr_target!("string", "CxxString", CxxString);
190