• 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 // 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