blob: 3a5fc6692e5e2dd0c113eba24f7c19b7fc2939d9 [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};
10use core::ptr;
David Tolnay7db73692019-10-20 14:51:12 -040011
12/// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
13#[repr(C)]
14pub struct UniquePtr<T>
15where
16 T: UniquePtrTarget,
17{
18 repr: *mut c_void,
19 ty: PhantomData<T>,
20}
21
22impl<T> UniquePtr<T>
23where
24 T: UniquePtrTarget,
25{
26 /// Makes a new UniquePtr wrapping a null pointer.
27 ///
28 /// Matches the behavior of default-constructing a std::unique\_ptr.
29 pub fn null() -> Self {
30 UniquePtr {
31 repr: T::__null(),
32 ty: PhantomData,
33 }
34 }
35
36 /// Allocates memory on the heap and makes a UniquePtr pointing to it.
Adrian Taylor9f7ff2e2020-10-12 17:29:25 -070037 pub fn new(value: T) -> Self
38 where
David Tolnayca0f9da2020-10-16 13:16:17 -070039 T: ExternType<Kind = Trivial>,
40 {
David Tolnay7db73692019-10-20 14:51:12 -040041 UniquePtr {
42 repr: T::__new(value),
43 ty: PhantomData,
44 }
45 }
46
47 /// Checks whether the UniquePtr does not own an object.
48 ///
49 /// This is the opposite of [std::unique_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_bool).
50 pub fn is_null(&self) -> bool {
51 let ptr = unsafe { T::__get(self.repr) };
52 ptr.is_null()
53 }
54
55 /// Returns a reference to the object owned by this UniquePtr if any,
56 /// otherwise None.
57 pub fn as_ref(&self) -> Option<&T> {
58 unsafe { T::__get(self.repr).as_ref() }
59 }
60
David Tolnay1a61b162020-04-09 23:20:05 -070061 /// Returns a mutable reference to the object owned by this UniquePtr if
62 /// any, otherwise None.
63 pub fn as_mut(&mut self) -> Option<&mut T> {
64 unsafe { (T::__get(self.repr) as *mut T).as_mut() }
65 }
66
David Tolnay7db73692019-10-20 14:51:12 -040067 /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
68 ///
69 /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release).
70 pub fn into_raw(self) -> *mut T {
71 let ptr = unsafe { T::__release(self.repr) };
72 mem::forget(self);
73 ptr
74 }
75
76 /// Constructs a UniquePtr retaking ownership of a pointer previously
77 /// obtained from `into_raw`.
78 ///
79 /// # Safety
80 ///
81 /// This function is unsafe because improper use may lead to memory
82 /// problems. For example a double-free may occur if the function is called
83 /// twice on the same raw pointer.
84 pub unsafe fn from_raw(raw: *mut T) -> Self {
85 UniquePtr {
86 repr: T::__raw(raw),
87 ty: PhantomData,
88 }
89 }
90}
91
92unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
93unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {}
94
95impl<T> Drop for UniquePtr<T>
96where
97 T: UniquePtrTarget,
98{
99 fn drop(&mut self) {
100 unsafe { T::__drop(self.repr) }
101 }
102}
103
David Tolnayd20032a2020-04-09 23:21:53 -0700104impl<T> Deref for UniquePtr<T>
105where
106 T: UniquePtrTarget,
107{
108 type Target = T;
109
110 fn deref(&self) -> &Self::Target {
111 match self.as_ref() {
112 Some(target) => target,
David Tolnay9f318a12020-04-09 23:44:02 -0700113 None => panic!("called deref on a null UniquePtr<{}>", T::__NAME),
David Tolnayd20032a2020-04-09 23:21:53 -0700114 }
115 }
116}
117
118impl<T> DerefMut for UniquePtr<T>
119where
120 T: UniquePtrTarget,
121{
122 fn deref_mut(&mut self) -> &mut Self::Target {
123 match self.as_mut() {
124 Some(target) => target,
David Tolnay9f318a12020-04-09 23:44:02 -0700125 None => panic!("called deref_mut on a null UniquePtr<{}>", T::__NAME),
David Tolnayd20032a2020-04-09 23:21:53 -0700126 }
127 }
128}
129
David Tolnay7db73692019-10-20 14:51:12 -0400130impl<T> Debug for UniquePtr<T>
131where
132 T: Debug + UniquePtrTarget,
133{
134 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
135 match self.as_ref() {
136 None => formatter.write_str("nullptr"),
137 Some(value) => Debug::fmt(value, formatter),
138 }
139 }
140}
141
142impl<T> Display for UniquePtr<T>
143where
144 T: Display + UniquePtrTarget,
145{
146 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
147 match self.as_ref() {
148 None => formatter.write_str("nullptr"),
149 Some(value) => Display::fmt(value, formatter),
150 }
151 }
152}
153
154// Methods are private; not intended to be implemented outside of cxxbridge
155// codebase.
156pub unsafe trait UniquePtrTarget {
157 #[doc(hidden)]
David Tolnay3b40b6f2020-04-24 17:58:24 -0700158 const __NAME: &'static dyn Display;
David Tolnayad266772020-04-09 23:42:29 -0700159 #[doc(hidden)]
David Tolnay7db73692019-10-20 14:51:12 -0400160 fn __null() -> *mut c_void;
161 #[doc(hidden)]
David Tolnay53838912020-04-09 20:56:44 -0700162 fn __new(value: Self) -> *mut c_void
163 where
164 Self: Sized,
165 {
166 // Opaque C types do not get this method because they can never exist by
167 // value on the Rust side of the bridge.
168 let _ = value;
169 unreachable!()
170 }
David Tolnay7db73692019-10-20 14:51:12 -0400171 #[doc(hidden)]
172 unsafe fn __raw(raw: *mut Self) -> *mut c_void;
173 #[doc(hidden)]
174 unsafe fn __get(repr: *mut c_void) -> *const Self;
175 #[doc(hidden)]
176 unsafe fn __release(repr: *mut c_void) -> *mut Self;
177 #[doc(hidden)]
178 unsafe fn __drop(repr: *mut c_void);
179}
180
181extern "C" {
David Tolnay8f16ae72020-10-08 18:21:13 -0700182 #[link_name = "cxxbridge05$unique_ptr$std$string$null"]
David Tolnay7db73692019-10-20 14:51:12 -0400183 fn unique_ptr_std_string_null(this: *mut *mut c_void);
David Tolnay8f16ae72020-10-08 18:21:13 -0700184 #[link_name = "cxxbridge05$unique_ptr$std$string$raw"]
David Tolnay7db73692019-10-20 14:51:12 -0400185 fn unique_ptr_std_string_raw(this: *mut *mut c_void, raw: *mut CxxString);
David Tolnay8f16ae72020-10-08 18:21:13 -0700186 #[link_name = "cxxbridge05$unique_ptr$std$string$get"]
David Tolnay7db73692019-10-20 14:51:12 -0400187 fn unique_ptr_std_string_get(this: *const *mut c_void) -> *const CxxString;
David Tolnay8f16ae72020-10-08 18:21:13 -0700188 #[link_name = "cxxbridge05$unique_ptr$std$string$release"]
David Tolnay7db73692019-10-20 14:51:12 -0400189 fn unique_ptr_std_string_release(this: *mut *mut c_void) -> *mut CxxString;
David Tolnay8f16ae72020-10-08 18:21:13 -0700190 #[link_name = "cxxbridge05$unique_ptr$std$string$drop"]
David Tolnay7db73692019-10-20 14:51:12 -0400191 fn unique_ptr_std_string_drop(this: *mut *mut c_void);
192}
193
194unsafe impl UniquePtrTarget for CxxString {
David Tolnay3b40b6f2020-04-24 17:58:24 -0700195 const __NAME: &'static dyn Display = &"CxxString";
David Tolnay7db73692019-10-20 14:51:12 -0400196 fn __null() -> *mut c_void {
197 let mut repr = ptr::null_mut::<c_void>();
David Tolnay2c4b35f2020-10-04 21:22:30 -0700198 unsafe {
199 unique_ptr_std_string_null(&mut repr);
200 }
David Tolnay7db73692019-10-20 14:51:12 -0400201 repr
202 }
David Tolnay7db73692019-10-20 14:51:12 -0400203 unsafe fn __raw(raw: *mut Self) -> *mut c_void {
204 let mut repr = ptr::null_mut::<c_void>();
205 unique_ptr_std_string_raw(&mut repr, raw);
206 repr
207 }
208 unsafe fn __get(repr: *mut c_void) -> *const Self {
209 unique_ptr_std_string_get(&repr)
210 }
211 unsafe fn __release(mut repr: *mut c_void) -> *mut Self {
212 unique_ptr_std_string_release(&mut repr)
213 }
214 unsafe fn __drop(mut repr: *mut c_void) {
215 unique_ptr_std_string_drop(&mut repr);
216 }
217}
David Tolnay3b40b6f2020-04-24 17:58:24 -0700218
219unsafe impl<T> UniquePtrTarget for CxxVector<T>
220where
221 T: VectorElement + 'static,
222{
223 const __NAME: &'static dyn Display = &cxx_vector::TypeName::<T>::new();
224 fn __null() -> *mut c_void {
225 T::__unique_ptr_null()
226 }
227 unsafe fn __raw(raw: *mut Self) -> *mut c_void {
228 T::__unique_ptr_raw(raw)
229 }
230 unsafe fn __get(repr: *mut c_void) -> *const Self {
231 T::__unique_ptr_get(repr)
232 }
233 unsafe fn __release(repr: *mut c_void) -> *mut Self {
234 T::__unique_ptr_release(repr)
235 }
236 unsafe fn __drop(repr: *mut c_void) {
237 T::__unique_ptr_drop(repr);
238 }
239}