blob: 0f9fa8f26008a76f3f70cdd2b4e48f2b0af40061 [file] [log] [blame]
Adrian Taylor9f7ff2e2020-10-12 17:29:25 -07001use crate::kind::Trivial;
David Tolnaybac25822020-12-12 23:13:51 -08002use crate::string::CxxString;
3use crate::vector::{self, CxxVector, VectorElement};
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;
David Tolnay300ef4a2020-11-19 20:26:34 -08009use 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 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,
80 None => panic!("called pin_mut on a null UniquePtr<{}>", T::__NAME),
81 }
82 }
83
David Tolnay7db73692019-10-20 14:51:12 -040084 /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
85 ///
86 /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release).
87 pub fn into_raw(self) -> *mut T {
88 let ptr = unsafe { T::__release(self.repr) };
89 mem::forget(self);
90 ptr
91 }
92
93 /// Constructs a UniquePtr retaking ownership of a pointer previously
94 /// obtained from `into_raw`.
95 ///
96 /// # Safety
97 ///
98 /// This function is unsafe because improper use may lead to memory
99 /// problems. For example a double-free may occur if the function is called
100 /// twice on the same raw pointer.
101 pub unsafe fn from_raw(raw: *mut T) -> Self {
102 UniquePtr {
103 repr: T::__raw(raw),
104 ty: PhantomData,
105 }
106 }
107}
108
109unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
110unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {}
111
112impl<T> Drop for UniquePtr<T>
113where
114 T: UniquePtrTarget,
115{
116 fn drop(&mut self) {
117 unsafe { T::__drop(self.repr) }
118 }
119}
120
David Tolnayd20032a2020-04-09 23:21:53 -0700121impl<T> Deref for UniquePtr<T>
122where
123 T: UniquePtrTarget,
124{
125 type Target = T;
126
127 fn deref(&self) -> &Self::Target {
128 match self.as_ref() {
129 Some(target) => target,
David Tolnay9f318a12020-04-09 23:44:02 -0700130 None => panic!("called deref on a null UniquePtr<{}>", T::__NAME),
David Tolnayd20032a2020-04-09 23:21:53 -0700131 }
132 }
133}
134
David Tolnay300ef4a2020-11-19 20:26:34 -0800135impl<T> DerefMut for UniquePtr<T>
136where
137 T: UniquePtrTarget + Unpin,
138{
139 fn deref_mut(&mut self) -> &mut Self::Target {
140 match self.as_mut() {
141 Some(target) => Pin::into_inner(target),
142 None => panic!("called deref_mut on a null UniquePtr<{}>", T::__NAME),
143 }
144 }
145}
146
David Tolnay7db73692019-10-20 14:51:12 -0400147impl<T> Debug for UniquePtr<T>
148where
149 T: Debug + UniquePtrTarget,
150{
151 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
152 match self.as_ref() {
153 None => formatter.write_str("nullptr"),
154 Some(value) => Debug::fmt(value, formatter),
155 }
156 }
157}
158
159impl<T> Display for UniquePtr<T>
160where
161 T: Display + UniquePtrTarget,
162{
163 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
164 match self.as_ref() {
165 None => formatter.write_str("nullptr"),
166 Some(value) => Display::fmt(value, formatter),
167 }
168 }
169}
170
171// Methods are private; not intended to be implemented outside of cxxbridge
172// codebase.
173pub unsafe trait UniquePtrTarget {
174 #[doc(hidden)]
David Tolnay3b40b6f2020-04-24 17:58:24 -0700175 const __NAME: &'static dyn Display;
David Tolnayad266772020-04-09 23:42:29 -0700176 #[doc(hidden)]
David Tolnay7db73692019-10-20 14:51:12 -0400177 fn __null() -> *mut c_void;
178 #[doc(hidden)]
David Tolnay53838912020-04-09 20:56:44 -0700179 fn __new(value: Self) -> *mut c_void
180 where
181 Self: Sized,
182 {
183 // Opaque C types do not get this method because they can never exist by
184 // value on the Rust side of the bridge.
185 let _ = value;
186 unreachable!()
187 }
David Tolnay7db73692019-10-20 14:51:12 -0400188 #[doc(hidden)]
189 unsafe fn __raw(raw: *mut Self) -> *mut c_void;
190 #[doc(hidden)]
191 unsafe fn __get(repr: *mut c_void) -> *const Self;
192 #[doc(hidden)]
193 unsafe fn __release(repr: *mut c_void) -> *mut Self;
194 #[doc(hidden)]
195 unsafe fn __drop(repr: *mut c_void);
196}
197
198extern "C" {
David Tolnay0f0162f2020-11-16 23:43:37 -0800199 #[link_name = "cxxbridge1$unique_ptr$std$string$null"]
David Tolnay7db73692019-10-20 14:51:12 -0400200 fn unique_ptr_std_string_null(this: *mut *mut c_void);
David Tolnay0f0162f2020-11-16 23:43:37 -0800201 #[link_name = "cxxbridge1$unique_ptr$std$string$raw"]
David Tolnay7db73692019-10-20 14:51:12 -0400202 fn unique_ptr_std_string_raw(this: *mut *mut c_void, raw: *mut CxxString);
David Tolnay0f0162f2020-11-16 23:43:37 -0800203 #[link_name = "cxxbridge1$unique_ptr$std$string$get"]
David Tolnay7db73692019-10-20 14:51:12 -0400204 fn unique_ptr_std_string_get(this: *const *mut c_void) -> *const CxxString;
David Tolnay0f0162f2020-11-16 23:43:37 -0800205 #[link_name = "cxxbridge1$unique_ptr$std$string$release"]
David Tolnay7db73692019-10-20 14:51:12 -0400206 fn unique_ptr_std_string_release(this: *mut *mut c_void) -> *mut CxxString;
David Tolnay0f0162f2020-11-16 23:43:37 -0800207 #[link_name = "cxxbridge1$unique_ptr$std$string$drop"]
David Tolnay7db73692019-10-20 14:51:12 -0400208 fn unique_ptr_std_string_drop(this: *mut *mut c_void);
209}
210
211unsafe impl UniquePtrTarget for CxxString {
David Tolnay3b40b6f2020-04-24 17:58:24 -0700212 const __NAME: &'static dyn Display = &"CxxString";
David Tolnay7db73692019-10-20 14:51:12 -0400213 fn __null() -> *mut c_void {
214 let mut repr = ptr::null_mut::<c_void>();
David Tolnay2c4b35f2020-10-04 21:22:30 -0700215 unsafe {
216 unique_ptr_std_string_null(&mut repr);
217 }
David Tolnay7db73692019-10-20 14:51:12 -0400218 repr
219 }
David Tolnay7db73692019-10-20 14:51:12 -0400220 unsafe fn __raw(raw: *mut Self) -> *mut c_void {
221 let mut repr = ptr::null_mut::<c_void>();
222 unique_ptr_std_string_raw(&mut repr, raw);
223 repr
224 }
225 unsafe fn __get(repr: *mut c_void) -> *const Self {
226 unique_ptr_std_string_get(&repr)
227 }
228 unsafe fn __release(mut repr: *mut c_void) -> *mut Self {
229 unique_ptr_std_string_release(&mut repr)
230 }
231 unsafe fn __drop(mut repr: *mut c_void) {
232 unique_ptr_std_string_drop(&mut repr);
233 }
234}
David Tolnay3b40b6f2020-04-24 17:58:24 -0700235
236unsafe impl<T> UniquePtrTarget for CxxVector<T>
237where
238 T: VectorElement + 'static,
239{
David Tolnaybac25822020-12-12 23:13:51 -0800240 const __NAME: &'static dyn Display = &vector::TypeName::<T>::new();
David Tolnay3b40b6f2020-04-24 17:58:24 -0700241 fn __null() -> *mut c_void {
242 T::__unique_ptr_null()
243 }
244 unsafe fn __raw(raw: *mut Self) -> *mut c_void {
245 T::__unique_ptr_raw(raw)
246 }
247 unsafe fn __get(repr: *mut c_void) -> *const Self {
248 T::__unique_ptr_get(repr)
249 }
250 unsafe fn __release(repr: *mut c_void) -> *mut Self {
251 T::__unique_ptr_release(repr)
252 }
253 unsafe fn __drop(repr: *mut c_void) {
254 T::__unique_ptr_drop(repr);
255 }
256}