• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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