aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Tolnay <dtolnay@gmail.com>2020-12-28 17:09:48 -0800
committerDavid Tolnay <dtolnay@gmail.com>2020-12-28 17:41:20 -0800
commit215e77fbec91468f294ea372f7c5524ed890de65 (patch)
tree73fdfa32580be49721a028616cb6961ec90b09f2 /src
parentcd1430c5ef65932a24c7fd2fd478db16a8cb19e1 (diff)
downloadcxx-215e77fbec91468f294ea372f7c5524ed890de65.tar.gz
Add Rust std::weak_ptr binding
Diffstat (limited to 'src')
-rw-r--r--src/cxx.cc15
-rw-r--r--src/lib.rs4
-rw-r--r--src/weak_ptr.rs130
3 files changed, 148 insertions, 1 deletions
diff --git a/src/cxx.cc b/src/cxx.cc
index b15dcaa3..e573b446 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -508,6 +508,21 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
void cxxbridge1$std$shared_ptr$##RUST_TYPE##$drop( \
const std::shared_ptr<CXX_TYPE> *self) noexcept { \
self->~shared_ptr(); \
+ } \
+ static_assert(sizeof(std::weak_ptr<CXX_TYPE>) == 2 * sizeof(void *), ""); \
+ static_assert(alignof(std::weak_ptr<CXX_TYPE>) == alignof(void *), ""); \
+ void cxxbridge1$std$weak_ptr$##RUST_TYPE##$null( \
+ std::weak_ptr<CXX_TYPE> *ptr) noexcept { \
+ new (ptr) std::weak_ptr<CXX_TYPE>(); \
+ } \
+ void cxxbridge1$std$weak_ptr$##RUST_TYPE##$clone( \
+ const std::weak_ptr<CXX_TYPE> &self, \
+ std::weak_ptr<CXX_TYPE> *ptr) noexcept { \
+ new (ptr) std::weak_ptr<CXX_TYPE>(self); \
+ } \
+ void cxxbridge1$std$weak_ptr$##RUST_TYPE##$drop( \
+ const std::weak_ptr<CXX_TYPE> *self) noexcept { \
+ self->~weak_ptr(); \
}
// Usize and isize are the same type as one of the below.
diff --git a/src/lib.rs b/src/lib.rs
index ff723c31..76453ea6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -360,7 +360,6 @@
//! <tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
//! <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
//! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
-//! <tr><td><sup><i>tbd</i></sup></td><td>std::weak_ptr&lt;T&gt;</td></tr>
//! </table>
#![no_std]
@@ -411,6 +410,7 @@ mod unique_ptr;
mod unwind;
#[path = "cxx_vector.rs"]
pub mod vector;
+mod weak_ptr;
pub use crate::exception::Exception;
pub use crate::extern_type::{kind, ExternType};
@@ -419,6 +419,7 @@ pub use crate::string::CxxString;
pub use crate::unique_ptr::UniquePtr;
#[doc(inline)]
pub use crate::vector::CxxVector;
+pub use crate::weak_ptr::WeakPtr;
pub use cxxbridge_macro::bridge;
/// For use in impls of the `ExternType` trait. See [`ExternType`].
@@ -457,6 +458,7 @@ pub mod private {
pub use crate::unique_ptr::UniquePtrTarget;
pub use crate::unwind::catch_unwind;
pub use crate::vector::VectorElement;
+ pub use crate::weak_ptr::WeakPtrTarget;
}
mod actually_private {
diff --git a/src/weak_ptr.rs b/src/weak_ptr.rs
new file mode 100644
index 00000000..d73ee8fe
--- /dev/null
+++ b/src/weak_ptr.rs
@@ -0,0 +1,130 @@
+use crate::string::CxxString;
+use core::ffi::c_void;
+use core::fmt::Display;
+use core::marker::PhantomData;
+use core::mem::MaybeUninit;
+
+/// Binding to C++ `std::weak_ptr<T>`.
+#[repr(C)]
+pub struct WeakPtr<T>
+where
+ T: WeakPtrTarget,
+{
+ repr: [*mut c_void; 2],
+ ty: PhantomData<T>,
+}
+
+impl<T> WeakPtr<T>
+where
+ T: WeakPtrTarget,
+{
+ /// Makes a new WeakPtr wrapping a null pointer.
+ ///
+ /// Matches the behavior of default-constructing a std::weak\_ptr.
+ pub fn null() -> Self {
+ let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit();
+ let new = weak_ptr.as_mut_ptr().cast();
+ unsafe {
+ T::__null(new);
+ weak_ptr.assume_init()
+ }
+ }
+}
+
+unsafe impl<T> Send for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {}
+unsafe impl<T> Sync for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {}
+
+impl<T> Clone for WeakPtr<T>
+where
+ T: WeakPtrTarget,
+{
+ fn clone(&self) -> Self {
+ let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit();
+ let new = weak_ptr.as_mut_ptr().cast();
+ let this = self as *const Self as *mut c_void;
+ unsafe {
+ T::__clone(this, new);
+ weak_ptr.assume_init()
+ }
+ }
+}
+
+impl<T> Drop for WeakPtr<T>
+where
+ T: WeakPtrTarget,
+{
+ fn drop(&mut self) {
+ let this = self as *mut Self as *mut c_void;
+ unsafe { T::__drop(this) }
+ }
+}
+
+// Methods are private; not intended to be implemented outside of cxxbridge
+// codebase.
+pub unsafe trait WeakPtrTarget {
+ #[doc(hidden)]
+ const __NAME: &'static dyn Display;
+ #[doc(hidden)]
+ unsafe fn __null(new: *mut c_void);
+ #[doc(hidden)]
+ unsafe fn __clone(this: *const c_void, new: *mut c_void);
+ #[doc(hidden)]
+ unsafe fn __drop(this: *mut c_void);
+}
+
+macro_rules! impl_weak_ptr_target {
+ ($segment:expr, $name:expr, $ty:ty) => {
+ unsafe impl WeakPtrTarget for $ty {
+ const __NAME: &'static dyn Display = &$name;
+ unsafe fn __null(new: *mut c_void) {
+ extern "C" {
+ attr! {
+ #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$null")]
+ fn __null(new: *mut c_void);
+ }
+ }
+ __null(new);
+ }
+ unsafe fn __clone(this: *const c_void, new: *mut c_void) {
+ extern "C" {
+ attr! {
+ #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$clone")]
+ fn __clone(this: *const c_void, new: *mut c_void);
+ }
+ }
+ __clone(this, new);
+ }
+ unsafe fn __drop(this: *mut c_void) {
+ extern "C" {
+ attr! {
+ #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$drop")]
+ fn __drop(this: *mut c_void);
+ }
+ }
+ __drop(this);
+ }
+ }
+ };
+}
+
+macro_rules! impl_weak_ptr_target_for_primitive {
+ ($ty:ident) => {
+ impl_weak_ptr_target!(stringify!($ty), stringify!($ty), $ty);
+ };
+}
+
+impl_weak_ptr_target_for_primitive!(bool);
+impl_weak_ptr_target_for_primitive!(u8);
+impl_weak_ptr_target_for_primitive!(u16);
+impl_weak_ptr_target_for_primitive!(u32);
+impl_weak_ptr_target_for_primitive!(u64);
+impl_weak_ptr_target_for_primitive!(usize);
+impl_weak_ptr_target_for_primitive!(i8);
+impl_weak_ptr_target_for_primitive!(i16);
+impl_weak_ptr_target_for_primitive!(i32);
+impl_weak_ptr_target_for_primitive!(i64);
+impl_weak_ptr_target_for_primitive!(isize);
+impl_weak_ptr_target_for_primitive!(f32);
+impl_weak_ptr_target_for_primitive!(f64);
+
+impl_weak_ptr_target!("string", "CxxString", CxxString);