cxx/
unique_ptr.rs

1use crate::cxx_vector::{CxxVector, VectorElement};
2use crate::fmt::display;
3use crate::kind::Trivial;
4use crate::string::CxxString;
5use crate::ExternType;
6use core::ffi::c_void;
7use core::fmt::{self, Debug, Display};
8use core::marker::PhantomData;
9use core::mem::{self, MaybeUninit};
10use core::ops::{Deref, DerefMut};
11use core::pin::Pin;
12
13/// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
14#[repr(C)]
15pub struct UniquePtr<T>
16where
17    T: UniquePtrTarget,
18{
19    repr: MaybeUninit<*mut c_void>,
20    ty: PhantomData<T>,
21}
22
23impl<T> UniquePtr<T>
24where
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.
30    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.
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).
51    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.
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.
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.
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).
90    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.
104    pub unsafe fn from_raw(raw: *mut T) -> Self {
105        UniquePtr {
106            repr: unsafe { T::__raw(raw) },
107            ty: PhantomData,
108        }
109    }
110}
111
112unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
113unsafe 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.
117impl<T> Unpin for UniquePtr<T> where T: UniquePtrTarget {}
118
119impl<T> Drop for UniquePtr<T>
120where
121    T: UniquePtrTarget,
122{
123    fn drop(&mut self) {
124        unsafe { T::__drop(self.repr) }
125    }
126}
127
128impl<T> Deref for UniquePtr<T>
129where
130    T: UniquePtrTarget,
131{
132    type Target = T;
133
134    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
145impl<T> DerefMut for UniquePtr<T>
146where
147    T: UniquePtrTarget + Unpin,
148{
149    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
160impl<T> Debug for UniquePtr<T>
161where
162    T: Debug + UniquePtrTarget,
163{
164    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
172impl<T> Display for UniquePtr<T>
173where
174    T: Display + UniquePtrTarget,
175{
176    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.
209pub unsafe trait UniquePtrTarget {
210    #[doc(hidden)]
211    fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
212    #[doc(hidden)]
213    fn __null() -> MaybeUninit<*mut c_void>;
214    #[doc(hidden)]
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)]
225    unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void>;
226    #[doc(hidden)]
227    unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self;
228    #[doc(hidden)]
229    unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self;
230    #[doc(hidden)]
231    unsafe fn __drop(repr: MaybeUninit<*mut c_void>);
232}
233
234extern "C" {
235    #[link_name = "cxxbridge1$unique_ptr$std$string$null"]
236    fn unique_ptr_std_string_null(this: *mut MaybeUninit<*mut c_void>);
237    #[link_name = "cxxbridge1$unique_ptr$std$string$raw"]
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"]
240    fn unique_ptr_std_string_get(this: *const MaybeUninit<*mut c_void>) -> *const CxxString;
241    #[link_name = "cxxbridge1$unique_ptr$std$string$release"]
242    fn unique_ptr_std_string_release(this: *mut MaybeUninit<*mut c_void>) -> *mut CxxString;
243    #[link_name = "cxxbridge1$unique_ptr$std$string$drop"]
244    fn unique_ptr_std_string_drop(this: *mut MaybeUninit<*mut c_void>);
245}
246
247unsafe impl UniquePtrTarget for CxxString {
248    fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
249        f.write_str("CxxString")
250    }
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    }
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    }
263    unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self {
264        unsafe { unique_ptr_std_string_get(&repr) }
265    }
266    unsafe fn __release(mut repr: MaybeUninit<*mut c_void>) -> *mut Self {
267        unsafe { unique_ptr_std_string_release(&mut repr) }
268    }
269    unsafe fn __drop(mut repr: MaybeUninit<*mut c_void>) {
270        unsafe { unique_ptr_std_string_drop(&mut repr) }
271    }
272}
273
274unsafe impl<T> UniquePtrTarget for CxxVector<T>
275where
276    T: VectorElement,
277{
278    fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
279        write!(f, "CxxVector<{}>", display(T::__typename))
280    }
281    fn __null() -> MaybeUninit<*mut c_void> {
282        T::__unique_ptr_null()
283    }
284    unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> {
285        unsafe { T::__unique_ptr_raw(raw) }
286    }
287    unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self {
288        unsafe { T::__unique_ptr_get(repr) }
289    }
290    unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self {
291        unsafe { T::__unique_ptr_release(repr) }
292    }
293    unsafe fn __drop(repr: MaybeUninit<*mut c_void>) {
294        unsafe { T::__unique_ptr_drop(repr) }
295    }
296}