blob: 1603881e702e5b3dc4a5f32ec918bd9db826ec2d [file] [log] [blame]
David Tolnayac5af502021-03-25 00:29:06 -04001use crate::fmt::display;
Adrian Taylor9f7ff2e2020-10-12 17:29:25 -07002use crate::kind::Trivial;
David Tolnaybac25822020-12-12 23:13:51 -08003use crate::string::CxxString;
David Tolnayac5af502021-03-25 00:29:06 -04004use crate::vector::{CxxVector, VectorElement};
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;
9use core::mem;
David Tolnay300ef4a2020-11-19 20:26:34 -080010use core::ops::{Deref, DerefMut};
David Tolnaya4170652020-11-15 17:00:59 -080011use core::pin::Pin;
David Tolnay3384c142020-09-14 00:26:47 -040012use core::ptr;
David Tolnay7db73692019-10-20 14:51:12 -040013
14/// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
15#[repr(C)]
16pub struct UniquePtr<T>
17where
18 T: UniquePtrTarget,
19{
20 repr: *mut c_void,
21 ty: PhantomData<T>,
22}
23
24impl<T> UniquePtr<T>
25where
26 T: UniquePtrTarget,
27{
28 /// Makes a new UniquePtr wrapping a null pointer.
29 ///
30 /// Matches the behavior of default-constructing a std::unique\_ptr.
31 pub fn null() -> Self {
32 UniquePtr {
33 repr: T::__null(),
34 ty: PhantomData,
35 }
36 }
37
38 /// Allocates memory on the heap and makes a UniquePtr pointing to it.
Adrian Taylor9f7ff2e2020-10-12 17:29:25 -070039 pub fn new(value: T) -> Self
40 where
David Tolnayca0f9da2020-10-16 13:16:17 -070041 T: ExternType<Kind = Trivial>,
42 {
David Tolnay7db73692019-10-20 14:51:12 -040043 UniquePtr {
44 repr: T::__new(value),
45 ty: PhantomData,
46 }
47 }
48
49 /// Checks whether the UniquePtr does not own an object.
50 ///
51 /// This is the opposite of [std::unique_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_bool).
52 pub fn is_null(&self) -> bool {
53 let ptr = unsafe { T::__get(self.repr) };
54 ptr.is_null()
55 }
56
57 /// Returns a reference to the object owned by this UniquePtr if any,
58 /// otherwise None.
59 pub fn as_ref(&self) -> Option<&T> {
60 unsafe { T::__get(self.repr).as_ref() }
61 }
62
David Tolnay6fdeeeb2020-11-16 22:34:50 -080063 /// Returns a mutable pinned reference to the object owned by this UniquePtr
64 /// if any, otherwise None.
65 pub fn as_mut(&mut self) -> Option<Pin<&mut T>> {
66 unsafe {
67 let mut_reference = (T::__get(self.repr) as *mut T).as_mut()?;
68 Some(Pin::new_unchecked(mut_reference))
69 }
David Tolnay1a61b162020-04-09 23:20:05 -070070 }
71
David Tolnay09a30862020-11-22 12:01:57 -080072 /// Returns a mutable pinned reference to the object owned by this
73 /// UniquePtr.
74 ///
75 /// # Panics
76 ///
77 /// Panics if the UniquePtr holds a null pointer.
78 pub fn pin_mut(&mut self) -> Pin<&mut T> {
79 match self.as_mut() {
80 Some(target) => target,
David Tolnayac5af502021-03-25 00:29:06 -040081 None => panic!(
82 "called pin_mut on a null UniquePtr<{}>",
83 display(T::__typename),
84 ),
David Tolnay09a30862020-11-22 12:01:57 -080085 }
86 }
87
David Tolnay7db73692019-10-20 14:51:12 -040088 /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
89 ///
90 /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release).
91 pub fn into_raw(self) -> *mut T {
92 let ptr = unsafe { T::__release(self.repr) };
93 mem::forget(self);
94 ptr
95 }
96
97 /// Constructs a UniquePtr retaking ownership of a pointer previously
98 /// obtained from `into_raw`.
99 ///
100 /// # Safety
101 ///
102 /// This function is unsafe because improper use may lead to memory
103 /// problems. For example a double-free may occur if the function is called
104 /// twice on the same raw pointer.
105 pub unsafe fn from_raw(raw: *mut T) -> Self {
106 UniquePtr {
107 repr: T::__raw(raw),
108 ty: PhantomData,
109 }
110 }
111}
112
113unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
114unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {}
115
116impl<T> Drop for UniquePtr<T>
117where
118 T: UniquePtrTarget,
119{
120 fn drop(&mut self) {
121 unsafe { T::__drop(self.repr) }
122 }
123}
124
David Tolnayd20032a2020-04-09 23:21:53 -0700125impl<T> Deref for UniquePtr<T>
126where
127 T: UniquePtrTarget,
128{
129 type Target = T;
130
131 fn deref(&self) -> &Self::Target {
132 match self.as_ref() {
133 Some(target) => target,
David Tolnayac5af502021-03-25 00:29:06 -0400134 None => panic!(
135 "called deref on a null UniquePtr<{}>",
136 display(T::__typename),
137 ),
David Tolnayd20032a2020-04-09 23:21:53 -0700138 }
139 }
140}
141
David Tolnay300ef4a2020-11-19 20:26:34 -0800142impl<T> DerefMut for UniquePtr<T>
143where
144 T: UniquePtrTarget + Unpin,
145{
146 fn deref_mut(&mut self) -> &mut Self::Target {
147 match self.as_mut() {
148 Some(target) => Pin::into_inner(target),
David Tolnayac5af502021-03-25 00:29:06 -0400149 None => panic!(
150 "called deref_mut on a null UniquePtr<{}>",
151 display(T::__typename),
152 ),
David Tolnay300ef4a2020-11-19 20:26:34 -0800153 }
154 }
155}
156
David Tolnay7db73692019-10-20 14:51:12 -0400157impl<T> Debug for UniquePtr<T>
158where
159 T: Debug + UniquePtrTarget,
160{
161 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
162 match self.as_ref() {
163 None => formatter.write_str("nullptr"),
164 Some(value) => Debug::fmt(value, formatter),
165 }
166 }
167}
168
169impl<T> Display for UniquePtr<T>
170where
171 T: Display + UniquePtrTarget,
172{
173 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
174 match self.as_ref() {
175 None => formatter.write_str("nullptr"),
176 Some(value) => Display::fmt(value, formatter),
177 }
178 }
179}
180
181// Methods are private; not intended to be implemented outside of cxxbridge
182// codebase.
183pub unsafe trait UniquePtrTarget {
184 #[doc(hidden)]
David Tolnayac5af502021-03-25 00:29:06 -0400185 fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
David Tolnayad266772020-04-09 23:42:29 -0700186 #[doc(hidden)]
David Tolnay7db73692019-10-20 14:51:12 -0400187 fn __null() -> *mut c_void;
188 #[doc(hidden)]
David Tolnay53838912020-04-09 20:56:44 -0700189 fn __new(value: Self) -> *mut c_void
190 where
191 Self: Sized,
192 {
193 // Opaque C types do not get this method because they can never exist by
194 // value on the Rust side of the bridge.
195 let _ = value;
196 unreachable!()
197 }
David Tolnay7db73692019-10-20 14:51:12 -0400198 #[doc(hidden)]
199 unsafe fn __raw(raw: *mut Self) -> *mut c_void;
200 #[doc(hidden)]
201 unsafe fn __get(repr: *mut c_void) -> *const Self;
202 #[doc(hidden)]
203 unsafe fn __release(repr: *mut c_void) -> *mut Self;
204 #[doc(hidden)]
205 unsafe fn __drop(repr: *mut c_void);
206}
207
208extern "C" {
David Tolnay0f0162f2020-11-16 23:43:37 -0800209 #[link_name = "cxxbridge1$unique_ptr$std$string$null"]
David Tolnay7db73692019-10-20 14:51:12 -0400210 fn unique_ptr_std_string_null(this: *mut *mut c_void);
David Tolnay0f0162f2020-11-16 23:43:37 -0800211 #[link_name = "cxxbridge1$unique_ptr$std$string$raw"]
David Tolnay7db73692019-10-20 14:51:12 -0400212 fn unique_ptr_std_string_raw(this: *mut *mut c_void, raw: *mut CxxString);
David Tolnay0f0162f2020-11-16 23:43:37 -0800213 #[link_name = "cxxbridge1$unique_ptr$std$string$get"]
David Tolnay7db73692019-10-20 14:51:12 -0400214 fn unique_ptr_std_string_get(this: *const *mut c_void) -> *const CxxString;
David Tolnay0f0162f2020-11-16 23:43:37 -0800215 #[link_name = "cxxbridge1$unique_ptr$std$string$release"]
David Tolnay7db73692019-10-20 14:51:12 -0400216 fn unique_ptr_std_string_release(this: *mut *mut c_void) -> *mut CxxString;
David Tolnay0f0162f2020-11-16 23:43:37 -0800217 #[link_name = "cxxbridge1$unique_ptr$std$string$drop"]
David Tolnay7db73692019-10-20 14:51:12 -0400218 fn unique_ptr_std_string_drop(this: *mut *mut c_void);
219}
220
221unsafe impl UniquePtrTarget for CxxString {
David Tolnayac5af502021-03-25 00:29:06 -0400222 fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
223 f.write_str("CxxString")
224 }
David Tolnay7db73692019-10-20 14:51:12 -0400225 fn __null() -> *mut c_void {
226 let mut repr = ptr::null_mut::<c_void>();
David Tolnay2c4b35f2020-10-04 21:22:30 -0700227 unsafe {
228 unique_ptr_std_string_null(&mut repr);
229 }
David Tolnay7db73692019-10-20 14:51:12 -0400230 repr
231 }
David Tolnay7db73692019-10-20 14:51:12 -0400232 unsafe fn __raw(raw: *mut Self) -> *mut c_void {
233 let mut repr = ptr::null_mut::<c_void>();
234 unique_ptr_std_string_raw(&mut repr, raw);
235 repr
236 }
237 unsafe fn __get(repr: *mut c_void) -> *const Self {
238 unique_ptr_std_string_get(&repr)
239 }
240 unsafe fn __release(mut repr: *mut c_void) -> *mut Self {
241 unique_ptr_std_string_release(&mut repr)
242 }
243 unsafe fn __drop(mut repr: *mut c_void) {
244 unique_ptr_std_string_drop(&mut repr);
245 }
246}
David Tolnay3b40b6f2020-04-24 17:58:24 -0700247
248unsafe impl<T> UniquePtrTarget for CxxVector<T>
249where
250 T: VectorElement + 'static,
251{
David Tolnayac5af502021-03-25 00:29:06 -0400252 fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
253 write!(f, "CxxVector<{}>", display(T::__typename))
254 }
David Tolnay3b40b6f2020-04-24 17:58:24 -0700255 fn __null() -> *mut c_void {
256 T::__unique_ptr_null()
257 }
258 unsafe fn __raw(raw: *mut Self) -> *mut c_void {
259 T::__unique_ptr_raw(raw)
260 }
261 unsafe fn __get(repr: *mut c_void) -> *const Self {
262 T::__unique_ptr_get(repr)
263 }
264 unsafe fn __release(repr: *mut c_void) -> *mut Self {
265 T::__unique_ptr_release(repr)
266 }
267 unsafe fn __drop(repr: *mut c_void) {
268 T::__unique_ptr_drop(repr);
269 }
270}