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