[go: up one dir, main page]

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