blob: 283c2f151d6e38ac5652b52dd8efb7fdab0ede32 [file] [log] [blame]
David Tolnay7db73692019-10-20 14:51:12 -04001use crate::cxx_string::CxxString;
David Tolnay3b40b6f2020-04-24 17:58:24 -07002use crate::cxx_vector::{self, CxxVector, VectorElement};
Adrian Taylor9f7ff2e2020-10-12 17:29:25 -07003use crate::kind::Trivial;
David Tolnayca0f9da2020-10-16 13:16:17 -07004use crate::ExternType;
David Tolnay3384c142020-09-14 00:26:47 -04005use core::ffi::c_void;
6use core::fmt::{self, Debug, Display};
7use core::marker::PhantomData;
8use core::mem;
9use core::ops::{Deref, DerefMut};
David Tolnaya4170652020-11-15 17:00:59 -080010use core::pin::Pin;
David Tolnay3384c142020-09-14 00:26:47 -040011use core::ptr;
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{
19 repr: *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.
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 Tolnay1a61b162020-04-09 23:20:05 -070062 /// Returns a mutable reference to the object owned by this UniquePtr if
63 /// any, otherwise None.
64 pub fn as_mut(&mut self) -> Option<&mut T> {
65 unsafe { (T::__get(self.repr) as *mut T).as_mut() }
66 }
67
David Tolnay7db73692019-10-20 14:51:12 -040068 /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
69 ///
70 /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release).
71 pub fn into_raw(self) -> *mut T {
72 let ptr = unsafe { T::__release(self.repr) };
73 mem::forget(self);
74 ptr
75 }
76
77 /// Constructs a UniquePtr retaking ownership of a pointer previously
78 /// obtained from `into_raw`.
79 ///
80 /// # Safety
81 ///
82 /// This function is unsafe because improper use may lead to memory
83 /// problems. For example a double-free may occur if the function is called
84 /// twice on the same raw pointer.
85 pub unsafe fn from_raw(raw: *mut T) -> Self {
86 UniquePtr {
87 repr: T::__raw(raw),
88 ty: PhantomData,
89 }
90 }
David Tolnaya4170652020-11-15 17:00:59 -080091
92 #[doc(hidden)]
93 pub unsafe fn __pin_into_raw(ptr: Pin<UniquePtr<T>>) -> *mut T {
94 Self::into_raw(Pin::into_inner_unchecked(ptr))
95 }
96
97 #[doc(hidden)]
98 pub unsafe fn __pin_from_raw(raw: *mut T) -> Pin<Self> {
99 Pin::new_unchecked(Self::from_raw(raw))
100 }
David Tolnay7db73692019-10-20 14:51:12 -0400101}
102
103unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
104unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {}
105
106impl<T> Drop for UniquePtr<T>
107where
108 T: UniquePtrTarget,
109{
110 fn drop(&mut self) {
111 unsafe { T::__drop(self.repr) }
112 }
113}
114
David Tolnayd20032a2020-04-09 23:21:53 -0700115impl<T> Deref for UniquePtr<T>
116where
117 T: UniquePtrTarget,
118{
119 type Target = T;
120
121 fn deref(&self) -> &Self::Target {
122 match self.as_ref() {
123 Some(target) => target,
David Tolnay9f318a12020-04-09 23:44:02 -0700124 None => panic!("called deref on a null UniquePtr<{}>", T::__NAME),
David Tolnayd20032a2020-04-09 23:21:53 -0700125 }
126 }
127}
128
129impl<T> DerefMut for UniquePtr<T>
130where
131 T: UniquePtrTarget,
132{
133 fn deref_mut(&mut self) -> &mut Self::Target {
134 match self.as_mut() {
135 Some(target) => target,
David Tolnay9f318a12020-04-09 23:44:02 -0700136 None => panic!("called deref_mut on a null UniquePtr<{}>", T::__NAME),
David Tolnayd20032a2020-04-09 23:21:53 -0700137 }
138 }
139}
140
David Tolnay7db73692019-10-20 14:51:12 -0400141impl<T> Debug for UniquePtr<T>
142where
143 T: Debug + UniquePtrTarget,
144{
145 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
146 match self.as_ref() {
147 None => formatter.write_str("nullptr"),
148 Some(value) => Debug::fmt(value, formatter),
149 }
150 }
151}
152
153impl<T> Display for UniquePtr<T>
154where
155 T: Display + UniquePtrTarget,
156{
157 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
158 match self.as_ref() {
159 None => formatter.write_str("nullptr"),
160 Some(value) => Display::fmt(value, formatter),
161 }
162 }
163}
164
165// Methods are private; not intended to be implemented outside of cxxbridge
166// codebase.
167pub unsafe trait UniquePtrTarget {
168 #[doc(hidden)]
David Tolnay3b40b6f2020-04-24 17:58:24 -0700169 const __NAME: &'static dyn Display;
David Tolnayad266772020-04-09 23:42:29 -0700170 #[doc(hidden)]
David Tolnay7db73692019-10-20 14:51:12 -0400171 fn __null() -> *mut c_void;
172 #[doc(hidden)]
David Tolnay53838912020-04-09 20:56:44 -0700173 fn __new(value: Self) -> *mut c_void
174 where
175 Self: Sized,
176 {
177 // Opaque C types do not get this method because they can never exist by
178 // value on the Rust side of the bridge.
179 let _ = value;
180 unreachable!()
181 }
David Tolnay7db73692019-10-20 14:51:12 -0400182 #[doc(hidden)]
183 unsafe fn __raw(raw: *mut Self) -> *mut c_void;
184 #[doc(hidden)]
185 unsafe fn __get(repr: *mut c_void) -> *const Self;
186 #[doc(hidden)]
187 unsafe fn __release(repr: *mut c_void) -> *mut Self;
188 #[doc(hidden)]
189 unsafe fn __drop(repr: *mut c_void);
190}
191
192extern "C" {
David Tolnay8f16ae72020-10-08 18:21:13 -0700193 #[link_name = "cxxbridge05$unique_ptr$std$string$null"]
David Tolnay7db73692019-10-20 14:51:12 -0400194 fn unique_ptr_std_string_null(this: *mut *mut c_void);
David Tolnay8f16ae72020-10-08 18:21:13 -0700195 #[link_name = "cxxbridge05$unique_ptr$std$string$raw"]
David Tolnay7db73692019-10-20 14:51:12 -0400196 fn unique_ptr_std_string_raw(this: *mut *mut c_void, raw: *mut CxxString);
David Tolnay8f16ae72020-10-08 18:21:13 -0700197 #[link_name = "cxxbridge05$unique_ptr$std$string$get"]
David Tolnay7db73692019-10-20 14:51:12 -0400198 fn unique_ptr_std_string_get(this: *const *mut c_void) -> *const CxxString;
David Tolnay8f16ae72020-10-08 18:21:13 -0700199 #[link_name = "cxxbridge05$unique_ptr$std$string$release"]
David Tolnay7db73692019-10-20 14:51:12 -0400200 fn unique_ptr_std_string_release(this: *mut *mut c_void) -> *mut CxxString;
David Tolnay8f16ae72020-10-08 18:21:13 -0700201 #[link_name = "cxxbridge05$unique_ptr$std$string$drop"]
David Tolnay7db73692019-10-20 14:51:12 -0400202 fn unique_ptr_std_string_drop(this: *mut *mut c_void);
203}
204
205unsafe impl UniquePtrTarget for CxxString {
David Tolnay3b40b6f2020-04-24 17:58:24 -0700206 const __NAME: &'static dyn Display = &"CxxString";
David Tolnay7db73692019-10-20 14:51:12 -0400207 fn __null() -> *mut c_void {
208 let mut repr = ptr::null_mut::<c_void>();
David Tolnay2c4b35f2020-10-04 21:22:30 -0700209 unsafe {
210 unique_ptr_std_string_null(&mut repr);
211 }
David Tolnay7db73692019-10-20 14:51:12 -0400212 repr
213 }
David Tolnay7db73692019-10-20 14:51:12 -0400214 unsafe fn __raw(raw: *mut Self) -> *mut c_void {
215 let mut repr = ptr::null_mut::<c_void>();
216 unique_ptr_std_string_raw(&mut repr, raw);
217 repr
218 }
219 unsafe fn __get(repr: *mut c_void) -> *const Self {
220 unique_ptr_std_string_get(&repr)
221 }
222 unsafe fn __release(mut repr: *mut c_void) -> *mut Self {
223 unique_ptr_std_string_release(&mut repr)
224 }
225 unsafe fn __drop(mut repr: *mut c_void) {
226 unique_ptr_std_string_drop(&mut repr);
227 }
228}
David Tolnay3b40b6f2020-04-24 17:58:24 -0700229
230unsafe impl<T> UniquePtrTarget for CxxVector<T>
231where
232 T: VectorElement + 'static,
233{
234 const __NAME: &'static dyn Display = &cxx_vector::TypeName::<T>::new();
235 fn __null() -> *mut c_void {
236 T::__unique_ptr_null()
237 }
238 unsafe fn __raw(raw: *mut Self) -> *mut c_void {
239 T::__unique_ptr_raw(raw)
240 }
241 unsafe fn __get(repr: *mut c_void) -> *const Self {
242 T::__unique_ptr_get(repr)
243 }
244 unsafe fn __release(repr: *mut c_void) -> *mut Self {
245 T::__unique_ptr_release(repr)
246 }
247 unsafe fn __drop(repr: *mut c_void) {
248 T::__unique_ptr_drop(repr);
249 }
250}