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 impl<T> Drop for UniquePtr<T> 116 where 117 T: UniquePtrTarget, 118 { drop(&mut self)119 fn drop(&mut self) { 120 unsafe { T::__drop(self.repr) } 121 } 122 } 123 124 impl<T> Deref for UniquePtr<T> 125 where 126 T: UniquePtrTarget, 127 { 128 type Target = T; 129 deref(&self) -> &Self::Target130 fn deref(&self) -> &Self::Target { 131 match self.as_ref() { 132 Some(target) => target, 133 None => panic!( 134 "called deref on a null UniquePtr<{}>", 135 display(T::__typename), 136 ), 137 } 138 } 139 } 140 141 impl<T> DerefMut for UniquePtr<T> 142 where 143 T: UniquePtrTarget + Unpin, 144 { deref_mut(&mut self) -> &mut Self::Target145 fn deref_mut(&mut self) -> &mut Self::Target { 146 match self.as_mut() { 147 Some(target) => Pin::into_inner(target), 148 None => panic!( 149 "called deref_mut on a null UniquePtr<{}>", 150 display(T::__typename), 151 ), 152 } 153 } 154 } 155 156 impl<T> Debug for UniquePtr<T> 157 where 158 T: Debug + UniquePtrTarget, 159 { fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result160 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 161 match self.as_ref() { 162 None => formatter.write_str("nullptr"), 163 Some(value) => Debug::fmt(value, formatter), 164 } 165 } 166 } 167 168 impl<T> Display for UniquePtr<T> 169 where 170 T: Display + UniquePtrTarget, 171 { fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result172 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 173 match self.as_ref() { 174 None => formatter.write_str("nullptr"), 175 Some(value) => Display::fmt(value, formatter), 176 } 177 } 178 } 179 180 /// Trait bound for types which may be used as the `T` inside of a 181 /// `UniquePtr<T>` in generic code. 182 /// 183 /// This trait has no publicly callable or implementable methods. Implementing 184 /// it outside of the CXX codebase is not supported. 185 /// 186 /// # Example 187 /// 188 /// A bound `T: UniquePtrTarget` may be necessary when manipulating 189 /// [`UniquePtr`] in generic code. 190 /// 191 /// ``` 192 /// use cxx::memory::{UniquePtr, UniquePtrTarget}; 193 /// use std::fmt::Display; 194 /// 195 /// pub fn take_generic_ptr<T>(ptr: UniquePtr<T>) 196 /// where 197 /// T: UniquePtrTarget + Display, 198 /// { 199 /// println!("the unique_ptr points to: {}", *ptr); 200 /// } 201 /// ``` 202 /// 203 /// Writing the same generic function without a `UniquePtrTarget` trait bound 204 /// would not compile. 205 pub unsafe trait UniquePtrTarget { 206 #[doc(hidden)] __typename(f: &mut fmt::Formatter) -> fmt::Result207 fn __typename(f: &mut fmt::Formatter) -> fmt::Result; 208 #[doc(hidden)] __null() -> MaybeUninit<*mut c_void>209 fn __null() -> MaybeUninit<*mut c_void>; 210 #[doc(hidden)] __new(value: Self) -> MaybeUninit<*mut c_void> where Self: Sized,211 fn __new(value: Self) -> MaybeUninit<*mut c_void> 212 where 213 Self: Sized, 214 { 215 // Opaque C types do not get this method because they can never exist by 216 // value on the Rust side of the bridge. 217 let _ = value; 218 unreachable!() 219 } 220 #[doc(hidden)] __raw(raw: *mut Self) -> MaybeUninit<*mut c_void>221 unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void>; 222 #[doc(hidden)] __get(repr: MaybeUninit<*mut c_void>) -> *const Self223 unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self; 224 #[doc(hidden)] __release(repr: MaybeUninit<*mut c_void>) -> *mut Self225 unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self; 226 #[doc(hidden)] __drop(repr: MaybeUninit<*mut c_void>)227 unsafe fn __drop(repr: MaybeUninit<*mut c_void>); 228 } 229 230 extern "C" { 231 #[link_name = "cxxbridge1$unique_ptr$std$string$null"] unique_ptr_std_string_null(this: *mut MaybeUninit<*mut c_void>)232 fn unique_ptr_std_string_null(this: *mut MaybeUninit<*mut c_void>); 233 #[link_name = "cxxbridge1$unique_ptr$std$string$raw"] unique_ptr_std_string_raw(this: *mut MaybeUninit<*mut c_void>, raw: *mut CxxString)234 fn unique_ptr_std_string_raw(this: *mut MaybeUninit<*mut c_void>, raw: *mut CxxString); 235 #[link_name = "cxxbridge1$unique_ptr$std$string$get"] unique_ptr_std_string_get(this: *const MaybeUninit<*mut c_void>) -> *const CxxString236 fn unique_ptr_std_string_get(this: *const MaybeUninit<*mut c_void>) -> *const CxxString; 237 #[link_name = "cxxbridge1$unique_ptr$std$string$release"] unique_ptr_std_string_release(this: *mut MaybeUninit<*mut c_void>) -> *mut CxxString238 fn unique_ptr_std_string_release(this: *mut MaybeUninit<*mut c_void>) -> *mut CxxString; 239 #[link_name = "cxxbridge1$unique_ptr$std$string$drop"] unique_ptr_std_string_drop(this: *mut MaybeUninit<*mut c_void>)240 fn unique_ptr_std_string_drop(this: *mut MaybeUninit<*mut c_void>); 241 } 242 243 unsafe impl UniquePtrTarget for CxxString { 244 #[doc(hidden)] __typename(f: &mut fmt::Formatter) -> fmt::Result245 fn __typename(f: &mut fmt::Formatter) -> fmt::Result { 246 f.write_str("CxxString") 247 } 248 #[doc(hidden)] __null() -> MaybeUninit<*mut c_void>249 fn __null() -> MaybeUninit<*mut c_void> { 250 let mut repr = MaybeUninit::uninit(); 251 unsafe { 252 unique_ptr_std_string_null(&mut repr); 253 } 254 repr 255 } 256 #[doc(hidden)] __raw(raw: *mut Self) -> MaybeUninit<*mut c_void>257 unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> { 258 let mut repr = MaybeUninit::uninit(); 259 unsafe { unique_ptr_std_string_raw(&mut repr, raw) } 260 repr 261 } 262 #[doc(hidden)] __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 } 266 #[doc(hidden)] __release(mut repr: MaybeUninit<*mut c_void>) -> *mut Self267 unsafe fn __release(mut repr: MaybeUninit<*mut c_void>) -> *mut Self { 268 unsafe { unique_ptr_std_string_release(&mut repr) } 269 } 270 #[doc(hidden)] __drop(mut repr: MaybeUninit<*mut c_void>)271 unsafe fn __drop(mut repr: MaybeUninit<*mut c_void>) { 272 unsafe { unique_ptr_std_string_drop(&mut repr) } 273 } 274 } 275 276 unsafe impl<T> UniquePtrTarget for CxxVector<T> 277 where 278 T: VectorElement, 279 { 280 #[doc(hidden)] __typename(f: &mut fmt::Formatter) -> fmt::Result281 fn __typename(f: &mut fmt::Formatter) -> fmt::Result { 282 write!(f, "CxxVector<{}>", display(T::__typename)) 283 } 284 #[doc(hidden)] __null() -> MaybeUninit<*mut c_void>285 fn __null() -> MaybeUninit<*mut c_void> { 286 T::__unique_ptr_null() 287 } 288 #[doc(hidden)] __raw(raw: *mut Self) -> MaybeUninit<*mut c_void>289 unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> { 290 unsafe { T::__unique_ptr_raw(raw) } 291 } 292 #[doc(hidden)] __get(repr: MaybeUninit<*mut c_void>) -> *const Self293 unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self { 294 unsafe { T::__unique_ptr_get(repr) } 295 } 296 #[doc(hidden)] __release(repr: MaybeUninit<*mut c_void>) -> *mut Self297 unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self { 298 unsafe { T::__unique_ptr_release(repr) } 299 } 300 #[doc(hidden)] __drop(repr: MaybeUninit<*mut c_void>)301 unsafe fn __drop(repr: MaybeUninit<*mut c_void>) { 302 unsafe { T::__unique_ptr_drop(repr) } 303 } 304 } 305