blob: 2a731d794a3f5643a6bbab1f89b7ec58755fdf36 [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};
David Tolnay3384c142020-09-14 00:26:47 -04003use core::ffi::c_void;
4use core::fmt::{self, Debug, Display};
5use core::marker::PhantomData;
6use core::mem;
7use core::ops::{Deref, DerefMut};
8use core::ptr;
David Tolnay7db73692019-10-20 14:51:12 -04009
10/// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
11#[repr(C)]
12pub struct UniquePtr<T>
13where
14 T: UniquePtrTarget,
15{
16 repr: *mut c_void,
17 ty: PhantomData<T>,
18}
19
20impl<T> UniquePtr<T>
21where
22 T: UniquePtrTarget,
23{
24 /// Makes a new UniquePtr wrapping a null pointer.
25 ///
26 /// Matches the behavior of default-constructing a std::unique\_ptr.
27 pub fn null() -> Self {
28 UniquePtr {
29 repr: T::__null(),
30 ty: PhantomData,
31 }
32 }
33
34 /// Allocates memory on the heap and makes a UniquePtr pointing to it.
35 pub fn new(value: T) -> Self {
36 UniquePtr {
37 repr: T::__new(value),
38 ty: PhantomData,
39 }
40 }
41
42 /// Checks whether the UniquePtr does not own an object.
43 ///
44 /// This is the opposite of [std::unique_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_bool).
45 pub fn is_null(&self) -> bool {
46 let ptr = unsafe { T::__get(self.repr) };
47 ptr.is_null()
48 }
49
50 /// Returns a reference to the object owned by this UniquePtr if any,
51 /// otherwise None.
52 pub fn as_ref(&self) -> Option<&T> {
53 unsafe { T::__get(self.repr).as_ref() }
54 }
55
David Tolnay1a61b162020-04-09 23:20:05 -070056 /// Returns a mutable reference to the object owned by this UniquePtr if
57 /// any, otherwise None.
58 pub fn as_mut(&mut self) -> Option<&mut T> {
59 unsafe { (T::__get(self.repr) as *mut T).as_mut() }
60 }
61
David Tolnay7db73692019-10-20 14:51:12 -040062 /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
63 ///
64 /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release).
65 pub fn into_raw(self) -> *mut T {
66 let ptr = unsafe { T::__release(self.repr) };
67 mem::forget(self);
68 ptr
69 }
70
71 /// Constructs a UniquePtr retaking ownership of a pointer previously
72 /// obtained from `into_raw`.
73 ///
74 /// # Safety
75 ///
76 /// This function is unsafe because improper use may lead to memory
77 /// problems. For example a double-free may occur if the function is called
78 /// twice on the same raw pointer.
79 pub unsafe fn from_raw(raw: *mut T) -> Self {
80 UniquePtr {
81 repr: T::__raw(raw),
82 ty: PhantomData,
83 }
84 }
85}
86
87unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
88unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {}
89
90impl<T> Drop for UniquePtr<T>
91where
92 T: UniquePtrTarget,
93{
94 fn drop(&mut self) {
95 unsafe { T::__drop(self.repr) }
96 }
97}
98
David Tolnayd20032a2020-04-09 23:21:53 -070099impl<T> Deref for UniquePtr<T>
100where
101 T: UniquePtrTarget,
102{
103 type Target = T;
104
105 fn deref(&self) -> &Self::Target {
106 match self.as_ref() {
107 Some(target) => target,
David Tolnay9f318a12020-04-09 23:44:02 -0700108 None => panic!("called deref on a null UniquePtr<{}>", T::__NAME),
David Tolnayd20032a2020-04-09 23:21:53 -0700109 }
110 }
111}
112
113impl<T> DerefMut for UniquePtr<T>
114where
115 T: UniquePtrTarget,
116{
117 fn deref_mut(&mut self) -> &mut Self::Target {
118 match self.as_mut() {
119 Some(target) => target,
David Tolnay9f318a12020-04-09 23:44:02 -0700120 None => panic!("called deref_mut on a null UniquePtr<{}>", T::__NAME),
David Tolnayd20032a2020-04-09 23:21:53 -0700121 }
122 }
123}
124
David Tolnay7db73692019-10-20 14:51:12 -0400125impl<T> Debug for UniquePtr<T>
126where
127 T: Debug + UniquePtrTarget,
128{
129 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
130 match self.as_ref() {
131 None => formatter.write_str("nullptr"),
132 Some(value) => Debug::fmt(value, formatter),
133 }
134 }
135}
136
137impl<T> Display for UniquePtr<T>
138where
139 T: Display + UniquePtrTarget,
140{
141 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
142 match self.as_ref() {
143 None => formatter.write_str("nullptr"),
144 Some(value) => Display::fmt(value, formatter),
145 }
146 }
147}
148
149// Methods are private; not intended to be implemented outside of cxxbridge
150// codebase.
151pub unsafe trait UniquePtrTarget {
152 #[doc(hidden)]
David Tolnay3b40b6f2020-04-24 17:58:24 -0700153 const __NAME: &'static dyn Display;
David Tolnayad266772020-04-09 23:42:29 -0700154 #[doc(hidden)]
David Tolnay7db73692019-10-20 14:51:12 -0400155 fn __null() -> *mut c_void;
156 #[doc(hidden)]
David Tolnay53838912020-04-09 20:56:44 -0700157 fn __new(value: Self) -> *mut c_void
158 where
159 Self: Sized,
160 {
161 // Opaque C types do not get this method because they can never exist by
162 // value on the Rust side of the bridge.
163 let _ = value;
164 unreachable!()
165 }
David Tolnay7db73692019-10-20 14:51:12 -0400166 #[doc(hidden)]
167 unsafe fn __raw(raw: *mut Self) -> *mut c_void;
168 #[doc(hidden)]
169 unsafe fn __get(repr: *mut c_void) -> *const Self;
170 #[doc(hidden)]
171 unsafe fn __release(repr: *mut c_void) -> *mut Self;
172 #[doc(hidden)]
173 unsafe fn __drop(repr: *mut c_void);
174}
175
176extern "C" {
David Tolnay591dcb62020-09-01 23:00:38 -0700177 #[link_name = "cxxbridge04$unique_ptr$std$string$null"]
David Tolnay7db73692019-10-20 14:51:12 -0400178 fn unique_ptr_std_string_null(this: *mut *mut c_void);
David Tolnay591dcb62020-09-01 23:00:38 -0700179 #[link_name = "cxxbridge04$unique_ptr$std$string$raw"]
David Tolnay7db73692019-10-20 14:51:12 -0400180 fn unique_ptr_std_string_raw(this: *mut *mut c_void, raw: *mut CxxString);
David Tolnay591dcb62020-09-01 23:00:38 -0700181 #[link_name = "cxxbridge04$unique_ptr$std$string$get"]
David Tolnay7db73692019-10-20 14:51:12 -0400182 fn unique_ptr_std_string_get(this: *const *mut c_void) -> *const CxxString;
David Tolnay591dcb62020-09-01 23:00:38 -0700183 #[link_name = "cxxbridge04$unique_ptr$std$string$release"]
David Tolnay7db73692019-10-20 14:51:12 -0400184 fn unique_ptr_std_string_release(this: *mut *mut c_void) -> *mut CxxString;
David Tolnay591dcb62020-09-01 23:00:38 -0700185 #[link_name = "cxxbridge04$unique_ptr$std$string$drop"]
David Tolnay7db73692019-10-20 14:51:12 -0400186 fn unique_ptr_std_string_drop(this: *mut *mut c_void);
187}
188
189unsafe impl UniquePtrTarget for CxxString {
David Tolnay3b40b6f2020-04-24 17:58:24 -0700190 const __NAME: &'static dyn Display = &"CxxString";
David Tolnay7db73692019-10-20 14:51:12 -0400191 fn __null() -> *mut c_void {
192 let mut repr = ptr::null_mut::<c_void>();
193 unsafe { unique_ptr_std_string_null(&mut repr) }
194 repr
195 }
David Tolnay7db73692019-10-20 14:51:12 -0400196 unsafe fn __raw(raw: *mut Self) -> *mut c_void {
197 let mut repr = ptr::null_mut::<c_void>();
198 unique_ptr_std_string_raw(&mut repr, raw);
199 repr
200 }
201 unsafe fn __get(repr: *mut c_void) -> *const Self {
202 unique_ptr_std_string_get(&repr)
203 }
204 unsafe fn __release(mut repr: *mut c_void) -> *mut Self {
205 unique_ptr_std_string_release(&mut repr)
206 }
207 unsafe fn __drop(mut repr: *mut c_void) {
208 unique_ptr_std_string_drop(&mut repr);
209 }
210}
David Tolnay3b40b6f2020-04-24 17:58:24 -0700211
212unsafe impl<T> UniquePtrTarget for CxxVector<T>
213where
214 T: VectorElement + 'static,
215{
216 const __NAME: &'static dyn Display = &cxx_vector::TypeName::<T>::new();
217 fn __null() -> *mut c_void {
218 T::__unique_ptr_null()
219 }
220 unsafe fn __raw(raw: *mut Self) -> *mut c_void {
221 T::__unique_ptr_raw(raw)
222 }
223 unsafe fn __get(repr: *mut c_void) -> *const Self {
224 T::__unique_ptr_get(repr)
225 }
226 unsafe fn __release(repr: *mut c_void) -> *mut Self {
227 T::__unique_ptr_release(repr)
228 }
229 unsafe fn __drop(repr: *mut c_void) {
230 T::__unique_ptr_drop(repr);
231 }
232}