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