1 use crate::cxx_vector::{CxxVector, VectorElement}; 2 use crate::fmt::display; 3 use crate::kind::Trivial; 4 use crate::string::CxxString; 5 use crate::ExternType; 6 use core::ffi::c_void; 7 use core::fmt::{self, Debug, Display}; 8 use core::marker::PhantomData; 9 use core::mem::{self, MaybeUninit}; 10 use core::ops::{Deref, DerefMut}; 11 use core::pin::Pin; 12 13 /// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`. 14 #[repr(C)] 15 pub struct UniquePtr<T> 16 where 17 T: UniquePtrTarget, 18 { 19 repr: MaybeUninit<*mut c_void>, 20 ty: PhantomData<T>, 21 } 22 23 impl<T> UniquePtr<T> 24 where 25 T: UniquePtrTarget, 26 { 27 /// Makes a new UniquePtr wrapping a null pointer. 28 /// 29 /// Matches the behavior of default-constructing a std::unique\_ptr. null() -> Self30 pub fn null() -> Self { 31 UniquePtr { 32 repr: T::__null(), 33 ty: PhantomData, 34 } 35 } 36 37 /// Allocates memory on the heap and makes a UniquePtr pointing to it. new(value: T) -> Self where T: ExternType<Kind = Trivial>,38 pub fn new(value: T) -> Self 39 where 40 T: ExternType<Kind = Trivial>, 41 { 42 UniquePtr { 43 repr: T::__new(value), 44 ty: PhantomData, 45 } 46 } 47 48 /// Checks whether the UniquePtr does not own an object. 49 /// 50 /// This is the opposite of [std::unique_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_bool). is_null(&self) -> bool51 pub fn is_null(&self) -> bool { 52 let ptr = unsafe { T::__get(self.repr) }; 53 ptr.is_null() 54 } 55 56 /// Returns a reference to the object owned by this UniquePtr if any, 57 /// otherwise None. as_ref(&self) -> Option<&T>58 pub fn as_ref(&self) -> Option<&T> { 59 unsafe { T::__get(self.repr).as_ref() } 60 } 61 62 /// Returns a mutable pinned reference to the object owned by this UniquePtr 63 /// if any, otherwise None. as_mut(&mut self) -> Option<Pin<&mut T>>64 pub fn as_mut(&mut self) -> Option<Pin<&mut T>> { 65 unsafe { 66 let mut_reference = (T::__get(self.repr) as *mut T).as_mut()?; 67 Some(Pin::new_unchecked(mut_reference)) 68 } 69 } 70 71 /// Returns a mutable pinned reference to the object owned by this 72 /// UniquePtr. 73 /// 74 /// # Panics 75 /// 76 /// Panics if the UniquePtr holds a null pointer. pin_mut(&mut self) -> Pin<&mut T>77 pub fn pin_mut(&mut self) -> Pin<&mut T> { 78 match self.as_mut() { 79 Some(target) => target, 80 None => panic!( 81 "called pin_mut on a null UniquePtr<{}>", 82 display(T::__typename), 83 ), 84 } 85 } 86 87 /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T. 88 /// 89 /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release). into_raw(self) -> *mut T90 pub fn into_raw(self) -> *mut T { 91 let ptr = unsafe { T::__release(self.repr) }; 92 mem::forget(self); 93 ptr 94 } 95 96 /// Constructs a UniquePtr retaking ownership of a pointer previously 97 /// obtained from `into_raw`. 98 /// 99 /// # Safety 100 /// 101 /// This function is unsafe because improper use may lead to memory 102 /// problems. For example a double-free may occur if the function is called 103 /// twice on the same raw pointer. from_raw(raw: *mut T) -> Self104 pub unsafe fn from_raw(raw: *mut T) -> Self { 105 UniquePtr { 106 repr: unsafe { T::__raw(raw) }, 107 ty: PhantomData, 108 } 109 } 110 } 111 112 unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {} 113 unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {} 114 115 // UniquePtr is not a self-referential type and is safe to move out of a Pin, 116 // regardless whether the pointer's target is Unpin. 117 impl<T> Unpin for UniquePtr<T> where T: UniquePtrTarget {} 118 119 impl<T> Drop for UniquePtr<T> 120 where 121 T: UniquePtrTarget, 122 { drop(&mut self)123 fn drop(&mut self) { 124 unsafe { T::__drop(self.repr) } 125 } 126 } 127 128 impl<T> Deref for UniquePtr<T> 129 where 130 T: UniquePtrTarget, 131 { 132 type Target = T; 133 deref(&self) -> &Self::Target134 fn deref(&self) -> &Self::Target { 135 match self.as_ref() { 136 Some(target) => target, 137 None => panic!( 138 "called deref on a null UniquePtr<{}>", 139 display(T::__typename), 140 ), 141 } 142 } 143 } 144 145 impl<T> DerefMut for UniquePtr<T> 146 where 147 T: UniquePtrTarget + Unpin, 148 { deref_mut(&mut self) -> &mut Self::Target149 fn deref_mut(&mut self) -> &mut Self::Target { 150 match self.as_mut() { 151 Some(target) => Pin::into_inner(target), 152 None => panic!( 153 "called deref_mut on a null UniquePtr<{}>", 154 display(T::__typename), 155 ), 156 } 157 } 158 } 159 160 impl<T> Debug for UniquePtr<T> 161 where 162 T: Debug + UniquePtrTarget, 163 { fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result164 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 165 match self.as_ref() { 166 None => formatter.write_str("nullptr"), 167 Some(value) => Debug::fmt(value, formatter), 168 } 169 } 170 } 171 172 impl<T> Display for UniquePtr<T> 173 where 174 T: Display + UniquePtrTarget, 175 { fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result176 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 177 match self.as_ref() { 178 None => formatter.write_str("nullptr"), 179 Some(value) => Display::fmt(value, formatter), 180 } 181 } 182 } 183 184 /// Trait bound for types which may be used as the `T` inside of a 185 /// `UniquePtr<T>` in generic code. 186 /// 187 /// This trait has no publicly callable or implementable methods. Implementing 188 /// it outside of the CXX codebase is not supported. 189 /// 190 /// # Example 191 /// 192 /// A bound `T: UniquePtrTarget` may be necessary when manipulating 193 /// [`UniquePtr`] in generic code. 194 /// 195 /// ``` 196 /// use cxx::memory::{UniquePtr, UniquePtrTarget}; 197 /// use std::fmt::Display; 198 /// 199 /// pub fn take_generic_ptr<T>(ptr: UniquePtr<T>) 200 /// where 201 /// T: UniquePtrTarget + Display, 202 /// { 203 /// println!("the unique_ptr points to: {}", *ptr); 204 /// } 205 /// ``` 206 /// 207 /// Writing the same generic function without a `UniquePtrTarget` trait bound 208 /// would not compile. 209 pub unsafe trait UniquePtrTarget { 210 #[doc(hidden)] __typename(f: &mut fmt::Formatter) -> fmt::Result211 fn __typename(f: &mut fmt::Formatter) -> fmt::Result; 212 #[doc(hidden)] __null() -> MaybeUninit<*mut c_void>213 fn __null() -> MaybeUninit<*mut c_void>; 214 #[doc(hidden)] __new(value: Self) -> MaybeUninit<*mut c_void> where Self: Sized,215 fn __new(value: Self) -> MaybeUninit<*mut c_void> 216 where 217 Self: Sized, 218 { 219 // Opaque C types do not get this method because they can never exist by 220 // value on the Rust side of the bridge. 221 let _ = value; 222 unreachable!() 223 } 224 #[doc(hidden)] __raw(raw: *mut Self) -> MaybeUninit<*mut c_void>225 unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void>; 226 #[doc(hidden)] __get(repr: MaybeUninit<*mut c_void>) -> *const Self227 unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self; 228 #[doc(hidden)] __release(repr: MaybeUninit<*mut c_void>) -> *mut Self229 unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self; 230 #[doc(hidden)] __drop(repr: MaybeUninit<*mut c_void>)231 unsafe fn __drop(repr: MaybeUninit<*mut c_void>); 232 } 233 234 extern "C" { 235 #[link_name = "cxxbridge1$unique_ptr$std$string$null"] unique_ptr_std_string_null(this: *mut MaybeUninit<*mut c_void>)236 fn unique_ptr_std_string_null(this: *mut MaybeUninit<*mut c_void>); 237 #[link_name = "cxxbridge1$unique_ptr$std$string$raw"] unique_ptr_std_string_raw(this: *mut MaybeUninit<*mut c_void>, raw: *mut CxxString)238 fn unique_ptr_std_string_raw(this: *mut MaybeUninit<*mut c_void>, raw: *mut CxxString); 239 #[link_name = "cxxbridge1$unique_ptr$std$string$get"] unique_ptr_std_string_get(this: *const MaybeUninit<*mut c_void>) -> *const CxxString240 fn unique_ptr_std_string_get(this: *const MaybeUninit<*mut c_void>) -> *const CxxString; 241 #[link_name = "cxxbridge1$unique_ptr$std$string$release"] unique_ptr_std_string_release(this: *mut MaybeUninit<*mut c_void>) -> *mut CxxString242 fn unique_ptr_std_string_release(this: *mut MaybeUninit<*mut c_void>) -> *mut CxxString; 243 #[link_name = "cxxbridge1$unique_ptr$std$string$drop"] unique_ptr_std_string_drop(this: *mut MaybeUninit<*mut c_void>)244 fn unique_ptr_std_string_drop(this: *mut MaybeUninit<*mut c_void>); 245 } 246 247 unsafe impl UniquePtrTarget for CxxString { __typename(f: &mut fmt::Formatter) -> fmt::Result248 fn __typename(f: &mut fmt::Formatter) -> fmt::Result { 249 f.write_str("CxxString") 250 } __null() -> MaybeUninit<*mut c_void>251 fn __null() -> MaybeUninit<*mut c_void> { 252 let mut repr = MaybeUninit::uninit(); 253 unsafe { 254 unique_ptr_std_string_null(&mut repr); 255 } 256 repr 257 } __raw(raw: *mut Self) -> MaybeUninit<*mut c_void>258 unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> { 259 let mut repr = MaybeUninit::uninit(); 260 unsafe { unique_ptr_std_string_raw(&mut repr, raw) } 261 repr 262 } __get(repr: MaybeUninit<*mut c_void>) -> *const Self263 unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self { 264 unsafe { unique_ptr_std_string_get(&repr) } 265 } __release(mut repr: MaybeUninit<*mut c_void>) -> *mut Self266 unsafe fn __release(mut repr: MaybeUninit<*mut c_void>) -> *mut Self { 267 unsafe { unique_ptr_std_string_release(&mut repr) } 268 } __drop(mut repr: MaybeUninit<*mut c_void>)269 unsafe fn __drop(mut repr: MaybeUninit<*mut c_void>) { 270 unsafe { unique_ptr_std_string_drop(&mut repr) } 271 } 272 } 273 274 unsafe impl<T> UniquePtrTarget for CxxVector<T> 275 where 276 T: VectorElement, 277 { __typename(f: &mut fmt::Formatter) -> fmt::Result278 fn __typename(f: &mut fmt::Formatter) -> fmt::Result { 279 write!(f, "CxxVector<{}>", display(T::__typename)) 280 } __null() -> MaybeUninit<*mut c_void>281 fn __null() -> MaybeUninit<*mut c_void> { 282 T::__unique_ptr_null() 283 } __raw(raw: *mut Self) -> MaybeUninit<*mut c_void>284 unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> { 285 unsafe { T::__unique_ptr_raw(raw) } 286 } __get(repr: MaybeUninit<*mut c_void>) -> *const Self287 unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self { 288 unsafe { T::__unique_ptr_get(repr) } 289 } __release(repr: MaybeUninit<*mut c_void>) -> *mut Self290 unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self { 291 unsafe { T::__unique_ptr_release(repr) } 292 } __drop(repr: MaybeUninit<*mut c_void>)293 unsafe fn __drop(repr: MaybeUninit<*mut c_void>) { 294 unsafe { T::__unique_ptr_drop(repr) } 295 } 296 } 297