blob: d9ac4429fc3594136248116c704a777b2934a42e [file] [log] [blame]
David Tolnayc2c1e3b2021-03-25 00:53:32 -04001use crate::cxx_vector::{CxxVector, VectorElement};
David Tolnayac5af502021-03-25 00:29:06 -04002use crate::fmt::display;
Adrian Taylor9f7ff2e2020-10-12 17:29:25 -07003use crate::kind::Trivial;
David Tolnaybac25822020-12-12 23:13:51 -08004use crate::string::CxxString;
David Tolnayca0f9da2020-10-16 13:16:17 -07005use crate::ExternType;
David Tolnay3384c142020-09-14 00:26:47 -04006use core::ffi::c_void;
7use core::fmt::{self, Debug, Display};
8use core::marker::PhantomData;
David Tolnay46cff542021-05-02 10:59:57 -07009use core::mem::{self, MaybeUninit};
David Tolnay300ef4a2020-11-19 20:26:34 -080010use core::ops::{Deref, DerefMut};
David Tolnaya4170652020-11-15 17:00:59 -080011use core::pin::Pin;
David Tolnay7db73692019-10-20 14:51:12 -040012
13/// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
14#[repr(C)]
15pub struct UniquePtr<T>
16where
17 T: UniquePtrTarget,
18{
David Tolnay46cff542021-05-02 10:59:57 -070019 repr: MaybeUninit<*mut c_void>,
David Tolnay7db73692019-10-20 14:51:12 -040020 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.
Adrian Taylor9f7ff2e2020-10-12 17:29:25 -070038 pub fn new(value: T) -> Self
39 where
David Tolnayca0f9da2020-10-16 13:16:17 -070040 T: ExternType<Kind = Trivial>,
41 {
David Tolnay7db73692019-10-20 14:51:12 -040042 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
David Tolnay6fdeeeb2020-11-16 22:34:50 -080062 /// 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 }
David Tolnay1a61b162020-04-09 23:20:05 -070069 }
70
David Tolnay09a30862020-11-22 12:01:57 -080071 /// 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,
David Tolnayac5af502021-03-25 00:29:06 -040080 None => panic!(
81 "called pin_mut on a null UniquePtr<{}>",
82 display(T::__typename),
83 ),
David Tolnay09a30862020-11-22 12:01:57 -080084 }
85 }
86
David Tolnay7db73692019-10-20 14:51:12 -040087 /// 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: 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
115impl<T> Drop for UniquePtr<T>
116where
117 T: UniquePtrTarget,
118{
119 fn drop(&mut self) {
120 unsafe { T::__drop(self.repr) }
121 }
122}
123
David Tolnayd20032a2020-04-09 23:21:53 -0700124impl<T> Deref for UniquePtr<T>
125where
126 T: UniquePtrTarget,
127{
128 type Target = T;
129
130 fn deref(&self) -> &Self::Target {
131 match self.as_ref() {
132 Some(target) => target,
David Tolnayac5af502021-03-25 00:29:06 -0400133 None => panic!(
134 "called deref on a null UniquePtr<{}>",
135 display(T::__typename),
136 ),
David Tolnayd20032a2020-04-09 23:21:53 -0700137 }
138 }
139}
140
David Tolnay300ef4a2020-11-19 20:26:34 -0800141impl<T> DerefMut for UniquePtr<T>
142where
143 T: UniquePtrTarget + Unpin,
144{
145 fn deref_mut(&mut self) -> &mut Self::Target {
146 match self.as_mut() {
147 Some(target) => Pin::into_inner(target),
David Tolnayac5af502021-03-25 00:29:06 -0400148 None => panic!(
149 "called deref_mut on a null UniquePtr<{}>",
150 display(T::__typename),
151 ),
David Tolnay300ef4a2020-11-19 20:26:34 -0800152 }
153 }
154}
155
David Tolnay7db73692019-10-20 14:51:12 -0400156impl<T> Debug for UniquePtr<T>
157where
158 T: Debug + UniquePtrTarget,
159{
160 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
161 match self.as_ref() {
162 None => formatter.write_str("nullptr"),
163 Some(value) => Debug::fmt(value, formatter),
164 }
165 }
166}
167
168impl<T> Display for UniquePtr<T>
169where
170 T: Display + UniquePtrTarget,
171{
172 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
173 match self.as_ref() {
174 None => formatter.write_str("nullptr"),
175 Some(value) => Display::fmt(value, formatter),
176 }
177 }
178}
179
David Tolnaycccf0682021-03-25 02:04:03 -0400180/// Trait bound for types which may be used as the `T` inside of a
181/// `UniquePtr<T>` in generic code.
182///
183/// This trait has no publicly callable or implementable methods. Implementing
184/// it outside of the CXX codebase is not supported.
185///
186/// # Example
187///
188/// A bound `T: UniquePtrTarget` may be necessary when manipulating
189/// [`UniquePtr`] in generic code.
190///
191/// ```
192/// use cxx::memory::{UniquePtr, UniquePtrTarget};
193/// use std::fmt::Display;
194///
195/// pub fn take_generic_ptr<T>(ptr: UniquePtr<T>)
196/// where
197/// T: UniquePtrTarget + Display,
198/// {
199/// println!("the unique_ptr points to: {}", *ptr);
200/// }
201/// ```
202///
203/// Writing the same generic function without a `UniquePtrTarget` trait bound
204/// would not compile.
David Tolnay7db73692019-10-20 14:51:12 -0400205pub unsafe trait UniquePtrTarget {
206 #[doc(hidden)]
David Tolnayac5af502021-03-25 00:29:06 -0400207 fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
David Tolnayad266772020-04-09 23:42:29 -0700208 #[doc(hidden)]
David Tolnay46cff542021-05-02 10:59:57 -0700209 fn __null() -> MaybeUninit<*mut c_void>;
David Tolnay7db73692019-10-20 14:51:12 -0400210 #[doc(hidden)]
David Tolnay46cff542021-05-02 10:59:57 -0700211 fn __new(value: Self) -> MaybeUninit<*mut c_void>
David Tolnay53838912020-04-09 20:56:44 -0700212 where
213 Self: Sized,
214 {
215 // Opaque C types do not get this method because they can never exist by
216 // value on the Rust side of the bridge.
217 let _ = value;
218 unreachable!()
219 }
David Tolnay7db73692019-10-20 14:51:12 -0400220 #[doc(hidden)]
David Tolnay46cff542021-05-02 10:59:57 -0700221 unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void>;
David Tolnay7db73692019-10-20 14:51:12 -0400222 #[doc(hidden)]
David Tolnay46cff542021-05-02 10:59:57 -0700223 unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self;
David Tolnay7db73692019-10-20 14:51:12 -0400224 #[doc(hidden)]
David Tolnay46cff542021-05-02 10:59:57 -0700225 unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self;
David Tolnay7db73692019-10-20 14:51:12 -0400226 #[doc(hidden)]
David Tolnay46cff542021-05-02 10:59:57 -0700227 unsafe fn __drop(repr: MaybeUninit<*mut c_void>);
David Tolnay7db73692019-10-20 14:51:12 -0400228}
229
230extern "C" {
David Tolnay0f0162f2020-11-16 23:43:37 -0800231 #[link_name = "cxxbridge1$unique_ptr$std$string$null"]
David Tolnay46cff542021-05-02 10:59:57 -0700232 fn unique_ptr_std_string_null(this: *mut MaybeUninit<*mut c_void>);
David Tolnay0f0162f2020-11-16 23:43:37 -0800233 #[link_name = "cxxbridge1$unique_ptr$std$string$raw"]
David Tolnay46cff542021-05-02 10:59:57 -0700234 fn unique_ptr_std_string_raw(this: *mut MaybeUninit<*mut c_void>, raw: *mut CxxString);
David Tolnay0f0162f2020-11-16 23:43:37 -0800235 #[link_name = "cxxbridge1$unique_ptr$std$string$get"]
David Tolnay46cff542021-05-02 10:59:57 -0700236 fn unique_ptr_std_string_get(this: *const MaybeUninit<*mut c_void>) -> *const CxxString;
David Tolnay0f0162f2020-11-16 23:43:37 -0800237 #[link_name = "cxxbridge1$unique_ptr$std$string$release"]
David Tolnay46cff542021-05-02 10:59:57 -0700238 fn unique_ptr_std_string_release(this: *mut MaybeUninit<*mut c_void>) -> *mut CxxString;
David Tolnay0f0162f2020-11-16 23:43:37 -0800239 #[link_name = "cxxbridge1$unique_ptr$std$string$drop"]
David Tolnay46cff542021-05-02 10:59:57 -0700240 fn unique_ptr_std_string_drop(this: *mut MaybeUninit<*mut c_void>);
David Tolnay7db73692019-10-20 14:51:12 -0400241}
242
243unsafe impl UniquePtrTarget for CxxString {
David Tolnayb99359b2021-03-25 02:05:20 -0400244 #[doc(hidden)]
David Tolnayac5af502021-03-25 00:29:06 -0400245 fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
246 f.write_str("CxxString")
247 }
David Tolnayb99359b2021-03-25 02:05:20 -0400248 #[doc(hidden)]
David Tolnay46cff542021-05-02 10:59:57 -0700249 fn __null() -> MaybeUninit<*mut c_void> {
250 let mut repr = MaybeUninit::uninit();
David Tolnay2c4b35f2020-10-04 21:22:30 -0700251 unsafe {
252 unique_ptr_std_string_null(&mut repr);
253 }
David Tolnay7db73692019-10-20 14:51:12 -0400254 repr
255 }
David Tolnayb99359b2021-03-25 02:05:20 -0400256 #[doc(hidden)]
David Tolnay46cff542021-05-02 10:59:57 -0700257 unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> {
258 let mut repr = MaybeUninit::uninit();
David Tolnay7db73692019-10-20 14:51:12 -0400259 unique_ptr_std_string_raw(&mut repr, raw);
260 repr
261 }
David Tolnayb99359b2021-03-25 02:05:20 -0400262 #[doc(hidden)]
David Tolnay46cff542021-05-02 10:59:57 -0700263 unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self {
David Tolnay7db73692019-10-20 14:51:12 -0400264 unique_ptr_std_string_get(&repr)
265 }
David Tolnayb99359b2021-03-25 02:05:20 -0400266 #[doc(hidden)]
David Tolnay46cff542021-05-02 10:59:57 -0700267 unsafe fn __release(mut repr: MaybeUninit<*mut c_void>) -> *mut Self {
David Tolnay7db73692019-10-20 14:51:12 -0400268 unique_ptr_std_string_release(&mut repr)
269 }
David Tolnayb99359b2021-03-25 02:05:20 -0400270 #[doc(hidden)]
David Tolnay46cff542021-05-02 10:59:57 -0700271 unsafe fn __drop(mut repr: MaybeUninit<*mut c_void>) {
David Tolnay7db73692019-10-20 14:51:12 -0400272 unique_ptr_std_string_drop(&mut repr);
273 }
274}
David Tolnay3b40b6f2020-04-24 17:58:24 -0700275
276unsafe impl<T> UniquePtrTarget for CxxVector<T>
277where
David Tolnay3def5222021-03-25 00:31:39 -0400278 T: VectorElement,
David Tolnay3b40b6f2020-04-24 17:58:24 -0700279{
David Tolnayb99359b2021-03-25 02:05:20 -0400280 #[doc(hidden)]
David Tolnayac5af502021-03-25 00:29:06 -0400281 fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
282 write!(f, "CxxVector<{}>", display(T::__typename))
283 }
David Tolnayb99359b2021-03-25 02:05:20 -0400284 #[doc(hidden)]
David Tolnay46cff542021-05-02 10:59:57 -0700285 fn __null() -> MaybeUninit<*mut c_void> {
David Tolnay3b40b6f2020-04-24 17:58:24 -0700286 T::__unique_ptr_null()
287 }
David Tolnayb99359b2021-03-25 02:05:20 -0400288 #[doc(hidden)]
David Tolnay46cff542021-05-02 10:59:57 -0700289 unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> {
David Tolnay3b40b6f2020-04-24 17:58:24 -0700290 T::__unique_ptr_raw(raw)
291 }
David Tolnayb99359b2021-03-25 02:05:20 -0400292 #[doc(hidden)]
David Tolnay46cff542021-05-02 10:59:57 -0700293 unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self {
David Tolnay3b40b6f2020-04-24 17:58:24 -0700294 T::__unique_ptr_get(repr)
295 }
David Tolnayb99359b2021-03-25 02:05:20 -0400296 #[doc(hidden)]
David Tolnay46cff542021-05-02 10:59:57 -0700297 unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self {
David Tolnay3b40b6f2020-04-24 17:58:24 -0700298 T::__unique_ptr_release(repr)
299 }
David Tolnayb99359b2021-03-25 02:05:20 -0400300 #[doc(hidden)]
David Tolnay46cff542021-05-02 10:59:57 -0700301 unsafe fn __drop(repr: MaybeUninit<*mut c_void>) {
David Tolnay3b40b6f2020-04-24 17:58:24 -0700302 T::__unique_ptr_drop(repr);
303 }
304}