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;
6#[cfg(feature = "std")]
7use alloc::string::String;
8#[cfg(feature = "std")]
9use alloc::vec::Vec;
10use core::ffi::c_void;
11use core::fmt::{self, Debug, Display};
12use core::marker::PhantomData;
13use core::mem::{self, MaybeUninit};
14use core::ops::{Deref, DerefMut};
15use core::pin::Pin;
16#[cfg(feature = "std")]
17use std::io::{self, IoSlice, Read, Write};
18
19/// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
20#[repr(C)]
21pub struct UniquePtr<T>
22where
23    T: UniquePtrTarget,
24{
25    repr: MaybeUninit<*mut c_void>,
26    ty: PhantomData<T>,
27}
28
29impl<T> UniquePtr<T>
30where
31    T: UniquePtrTarget,
32{
33    /// Makes a new UniquePtr wrapping a null pointer.
34    ///
35    /// Matches the behavior of default-constructing a std::unique\_ptr.
36    pub fn null() -> Self {
37        UniquePtr {
38            repr: T::__null(),
39            ty: PhantomData,
40        }
41    }
42
43    /// Allocates memory on the heap and makes a UniquePtr pointing to it.
44    pub fn new(value: T) -> Self
45    where
46        T: ExternType<Kind = Trivial>,
47    {
48        UniquePtr {
49            repr: T::__new(value),
50            ty: PhantomData,
51        }
52    }
53
54    /// Checks whether the UniquePtr does not own an object.
55    ///
56    /// This is the opposite of [std::unique_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_bool).
57    pub fn is_null(&self) -> bool {
58        let ptr = unsafe { T::__get(self.repr) };
59        ptr.is_null()
60    }
61
62    /// Returns a reference to the object owned by this UniquePtr if any,
63    /// otherwise None.
64    pub fn as_ref(&self) -> Option<&T> {
65        unsafe { T::__get(self.repr).as_ref() }
66    }
67
68    /// Returns a mutable pinned reference to the object owned by this UniquePtr
69    /// if any, otherwise None.
70    pub fn as_mut(&mut self) -> Option<Pin<&mut T>> {
71        unsafe {
72            let mut_reference = (T::__get(self.repr) as *mut T).as_mut()?;
73            Some(Pin::new_unchecked(mut_reference))
74        }
75    }
76
77    /// Returns a mutable pinned reference to the object owned by this
78    /// UniquePtr.
79    ///
80    /// # Panics
81    ///
82    /// Panics if the UniquePtr holds a null pointer.
83    pub fn pin_mut(&mut self) -> Pin<&mut T> {
84        match self.as_mut() {
85            Some(target) => target,
86            None => panic!(
87                "called pin_mut on a null UniquePtr<{}>",
88                display(T::__typename),
89            ),
90        }
91    }
92
93    /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
94    ///
95    /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release).
96    pub fn into_raw(self) -> *mut T {
97        let ptr = unsafe { T::__release(self.repr) };
98        mem::forget(self);
99        ptr
100    }
101
102    /// Constructs a UniquePtr retaking ownership of a pointer previously
103    /// obtained from `into_raw`.
104    ///
105    /// # Safety
106    ///
107    /// This function is unsafe because improper use may lead to memory
108    /// problems. For example a double-free may occur if the function is called
109    /// twice on the same raw pointer.
110    pub unsafe fn from_raw(raw: *mut T) -> Self {
111        UniquePtr {
112            repr: unsafe { T::__raw(raw) },
113            ty: PhantomData,
114        }
115    }
116}
117
118unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
119unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {}
120
121// UniquePtr is not a self-referential type and is safe to move out of a Pin,
122// regardless whether the pointer's target is Unpin.
123impl<T> Unpin for UniquePtr<T> where T: UniquePtrTarget {}
124
125impl<T> Drop for UniquePtr<T>
126where
127    T: UniquePtrTarget,
128{
129    fn drop(&mut self) {
130        unsafe { T::__drop(self.repr) }
131    }
132}
133
134impl<T> Deref for UniquePtr<T>
135where
136    T: UniquePtrTarget,
137{
138    type Target = T;
139
140    fn deref(&self) -> &Self::Target {
141        match self.as_ref() {
142            Some(target) => target,
143            None => panic!(
144                "called deref on a null UniquePtr<{}>",
145                display(T::__typename),
146            ),
147        }
148    }
149}
150
151impl<T> DerefMut for UniquePtr<T>
152where
153    T: UniquePtrTarget + Unpin,
154{
155    fn deref_mut(&mut self) -> &mut Self::Target {
156        match self.as_mut() {
157            Some(target) => Pin::into_inner(target),
158            None => panic!(
159                "called deref_mut on a null UniquePtr<{}>",
160                display(T::__typename),
161            ),
162        }
163    }
164}
165
166impl<T> Debug for UniquePtr<T>
167where
168    T: Debug + UniquePtrTarget,
169{
170    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
171        match self.as_ref() {
172            None => formatter.write_str("nullptr"),
173            Some(value) => Debug::fmt(value, formatter),
174        }
175    }
176}
177
178impl<T> Display for UniquePtr<T>
179where
180    T: Display + UniquePtrTarget,
181{
182    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
183        match self.as_ref() {
184            None => formatter.write_str("nullptr"),
185            Some(value) => Display::fmt(value, formatter),
186        }
187    }
188}
189
190/// Forwarding `Read` trait implementation in a manner similar to `Box<T>`.
191///
192/// Note that the implementation will panic for null `UniquePtr<T>`.
193#[cfg(feature = "std")]
194impl<T> Read for UniquePtr<T>
195where
196    for<'a> Pin<&'a mut T>: Read,
197    T: UniquePtrTarget,
198{
199    #[inline]
200    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
201        self.pin_mut().read(buf)
202    }
203
204    #[inline]
205    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
206        self.pin_mut().read_to_end(buf)
207    }
208
209    #[inline]
210    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
211        self.pin_mut().read_to_string(buf)
212    }
213
214    #[inline]
215    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
216        self.pin_mut().read_exact(buf)
217    }
218
219    // TODO: Foward other `Read` trait methods when they get stabilized (e.g.
220    // `read_buf` and/or `is_read_vectored`).
221}
222
223/// Forwarding `Write` trait implementation in a manner similar to `Box<T>`.
224///
225/// Note that the implementation will panic for null `UniquePtr<T>`.
226#[cfg(feature = "std")]
227impl<T> Write for UniquePtr<T>
228where
229    for<'a> Pin<&'a mut T>: Write,
230    T: UniquePtrTarget,
231{
232    #[inline]
233    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
234        self.pin_mut().write(buf)
235    }
236
237    #[inline]
238    fn write_vectored(&mut self, bufs: &[IoSlice]) -> io::Result<usize> {
239        self.pin_mut().write_vectored(bufs)
240    }
241
242    #[inline]
243    fn flush(&mut self) -> io::Result<()> {
244        self.pin_mut().flush()
245    }
246
247    #[inline]
248    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
249        self.pin_mut().write_all(buf)
250    }
251
252    #[inline]
253    fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
254        self.pin_mut().write_fmt(fmt)
255    }
256
257    // TODO: Foward other `Write` trait methods when they get stabilized (e.g.
258    // `write_all_vectored` and/or `is_write_vectored`).
259}
260
261/// Trait bound for types which may be used as the `T` inside of a
262/// `UniquePtr<T>` in generic code.
263///
264/// This trait has no publicly callable or implementable methods. Implementing
265/// it outside of the CXX codebase is not supported.
266///
267/// # Example
268///
269/// A bound `T: UniquePtrTarget` may be necessary when manipulating
270/// [`UniquePtr`] in generic code.
271///
272/// ```
273/// use cxx::memory::{UniquePtr, UniquePtrTarget};
274/// use std::fmt::Display;
275///
276/// pub fn take_generic_ptr<T>(ptr: UniquePtr<T>)
277/// where
278///     T: UniquePtrTarget + Display,
279/// {
280///     println!("the unique_ptr points to: {}", *ptr);
281/// }
282/// ```
283///
284/// Writing the same generic function without a `UniquePtrTarget` trait bound
285/// would not compile.
286pub unsafe trait UniquePtrTarget {
287    #[doc(hidden)]
288    fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
289    #[doc(hidden)]
290    fn __null() -> MaybeUninit<*mut c_void>;
291    #[doc(hidden)]
292    fn __new(value: Self) -> MaybeUninit<*mut c_void>
293    where
294        Self: Sized,
295    {
296        // Opaque C types do not get this method because they can never exist by
297        // value on the Rust side of the bridge.
298        let _ = value;
299        unreachable!()
300    }
301    #[doc(hidden)]
302    unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void>;
303    #[doc(hidden)]
304    unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self;
305    #[doc(hidden)]
306    unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self;
307    #[doc(hidden)]
308    unsafe fn __drop(repr: MaybeUninit<*mut c_void>);
309}
310
311extern "C" {
312    #[link_name = "cxxbridge1$unique_ptr$std$string$null"]
313    fn unique_ptr_std_string_null(this: *mut MaybeUninit<*mut c_void>);
314    #[link_name = "cxxbridge1$unique_ptr$std$string$raw"]
315    fn unique_ptr_std_string_raw(this: *mut MaybeUninit<*mut c_void>, raw: *mut CxxString);
316    #[link_name = "cxxbridge1$unique_ptr$std$string$get"]
317    fn unique_ptr_std_string_get(this: *const MaybeUninit<*mut c_void>) -> *const CxxString;
318    #[link_name = "cxxbridge1$unique_ptr$std$string$release"]
319    fn unique_ptr_std_string_release(this: *mut MaybeUninit<*mut c_void>) -> *mut CxxString;
320    #[link_name = "cxxbridge1$unique_ptr$std$string$drop"]
321    fn unique_ptr_std_string_drop(this: *mut MaybeUninit<*mut c_void>);
322}
323
324unsafe impl UniquePtrTarget for CxxString {
325    fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
326        f.write_str("CxxString")
327    }
328    fn __null() -> MaybeUninit<*mut c_void> {
329        let mut repr = MaybeUninit::uninit();
330        unsafe {
331            unique_ptr_std_string_null(&mut repr);
332        }
333        repr
334    }
335    unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> {
336        let mut repr = MaybeUninit::uninit();
337        unsafe { unique_ptr_std_string_raw(&mut repr, raw) }
338        repr
339    }
340    unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self {
341        unsafe { unique_ptr_std_string_get(&repr) }
342    }
343    unsafe fn __release(mut repr: MaybeUninit<*mut c_void>) -> *mut Self {
344        unsafe { unique_ptr_std_string_release(&mut repr) }
345    }
346    unsafe fn __drop(mut repr: MaybeUninit<*mut c_void>) {
347        unsafe { unique_ptr_std_string_drop(&mut repr) }
348    }
349}
350
351unsafe impl<T> UniquePtrTarget for CxxVector<T>
352where
353    T: VectorElement,
354{
355    fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
356        write!(f, "CxxVector<{}>", display(T::__typename))
357    }
358    fn __null() -> MaybeUninit<*mut c_void> {
359        T::__unique_ptr_null()
360    }
361    unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> {
362        unsafe { T::__unique_ptr_raw(raw) }
363    }
364    unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self {
365        unsafe { T::__unique_ptr_get(repr) }
366    }
367    unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self {
368        unsafe { T::__unique_ptr_release(repr) }
369    }
370    unsafe fn __drop(repr: MaybeUninit<*mut c_void>) {
371        unsafe { T::__unique_ptr_drop(repr) }
372    }
373}