blob: ab8b9ef5c9f60b26101471fd87d26996fcb0e60d [file] [log] [blame]
David Tolnay7db73692019-10-20 14:51:12 -04001use crate::cxx_string::CxxString;
2use std::ffi::c_void;
3use std::fmt::{self, Debug, Display};
4use std::marker::PhantomData;
David Tolnay25b8c8f2020-04-09 21:11:36 -07005use std::mem;
David Tolnayd20032a2020-04-09 23:21:53 -07006use std::ops::{Deref, DerefMut};
David Tolnay7db73692019-10-20 14:51:12 -04007use std::ptr;
8
9/// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
10#[repr(C)]
11pub struct UniquePtr<T>
12where
13 T: UniquePtrTarget,
14{
15 repr: *mut c_void,
16 ty: PhantomData<T>,
17}
18
19impl<T> UniquePtr<T>
20where
21 T: UniquePtrTarget,
22{
23 /// Makes a new UniquePtr wrapping a null pointer.
24 ///
25 /// Matches the behavior of default-constructing a std::unique\_ptr.
26 pub fn null() -> Self {
27 UniquePtr {
28 repr: T::__null(),
29 ty: PhantomData,
30 }
31 }
32
33 /// Allocates memory on the heap and makes a UniquePtr pointing to it.
34 pub fn new(value: T) -> Self {
35 UniquePtr {
36 repr: T::__new(value),
37 ty: PhantomData,
38 }
39 }
40
41 /// Checks whether the UniquePtr does not own an object.
42 ///
43 /// This is the opposite of [std::unique_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_bool).
44 pub fn is_null(&self) -> bool {
45 let ptr = unsafe { T::__get(self.repr) };
46 ptr.is_null()
47 }
48
49 /// Returns a reference to the object owned by this UniquePtr if any,
50 /// otherwise None.
51 pub fn as_ref(&self) -> Option<&T> {
52 unsafe { T::__get(self.repr).as_ref() }
53 }
54
David Tolnay1a61b162020-04-09 23:20:05 -070055 /// Returns a mutable reference to the object owned by this UniquePtr if
56 /// any, otherwise None.
57 pub fn as_mut(&mut self) -> Option<&mut T> {
58 unsafe { (T::__get(self.repr) as *mut T).as_mut() }
59 }
60
David Tolnay7db73692019-10-20 14:51:12 -040061 /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
62 ///
63 /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release).
64 pub fn into_raw(self) -> *mut T {
65 let ptr = unsafe { T::__release(self.repr) };
66 mem::forget(self);
67 ptr
68 }
69
70 /// Constructs a UniquePtr retaking ownership of a pointer previously
71 /// obtained from `into_raw`.
72 ///
73 /// # Safety
74 ///
75 /// This function is unsafe because improper use may lead to memory
76 /// problems. For example a double-free may occur if the function is called
77 /// twice on the same raw pointer.
78 pub unsafe fn from_raw(raw: *mut T) -> Self {
79 UniquePtr {
80 repr: T::__raw(raw),
81 ty: PhantomData,
82 }
83 }
84}
85
86unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
87unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {}
88
89impl<T> Drop for UniquePtr<T>
90where
91 T: UniquePtrTarget,
92{
93 fn drop(&mut self) {
94 unsafe { T::__drop(self.repr) }
95 }
96}
97
David Tolnayd20032a2020-04-09 23:21:53 -070098impl<T> Deref for UniquePtr<T>
99where
100 T: UniquePtrTarget,
101{
102 type Target = T;
103
104 fn deref(&self) -> &Self::Target {
105 match self.as_ref() {
106 Some(target) => target,
107 None => panic!("called deref on a null UniquePtr"),
108 }
109 }
110}
111
112impl<T> DerefMut for UniquePtr<T>
113where
114 T: UniquePtrTarget,
115{
116 fn deref_mut(&mut self) -> &mut Self::Target {
117 match self.as_mut() {
118 Some(target) => target,
119 None => panic!("called deref_mut on a null UniquePtr"),
120 }
121 }
122}
123
David Tolnay7db73692019-10-20 14:51:12 -0400124impl<T> Debug for UniquePtr<T>
125where
126 T: Debug + UniquePtrTarget,
127{
128 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
129 match self.as_ref() {
130 None => formatter.write_str("nullptr"),
131 Some(value) => Debug::fmt(value, formatter),
132 }
133 }
134}
135
136impl<T> Display for UniquePtr<T>
137where
138 T: Display + UniquePtrTarget,
139{
140 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
141 match self.as_ref() {
142 None => formatter.write_str("nullptr"),
143 Some(value) => Display::fmt(value, formatter),
144 }
145 }
146}
147
148// Methods are private; not intended to be implemented outside of cxxbridge
149// codebase.
150pub unsafe trait UniquePtrTarget {
151 #[doc(hidden)]
David Tolnayad266772020-04-09 23:42:29 -0700152 const __NAME: &'static str;
153 #[doc(hidden)]
David Tolnay7db73692019-10-20 14:51:12 -0400154 fn __null() -> *mut c_void;
155 #[doc(hidden)]
David Tolnay53838912020-04-09 20:56:44 -0700156 fn __new(value: Self) -> *mut c_void
157 where
158 Self: Sized,
159 {
160 // Opaque C types do not get this method because they can never exist by
161 // value on the Rust side of the bridge.
162 let _ = value;
163 unreachable!()
164 }
David Tolnay7db73692019-10-20 14:51:12 -0400165 #[doc(hidden)]
166 unsafe fn __raw(raw: *mut Self) -> *mut c_void;
167 #[doc(hidden)]
168 unsafe fn __get(repr: *mut c_void) -> *const Self;
169 #[doc(hidden)]
170 unsafe fn __release(repr: *mut c_void) -> *mut Self;
171 #[doc(hidden)]
172 unsafe fn __drop(repr: *mut c_void);
173}
174
175extern "C" {
David Tolnay8c730492020-03-13 01:29:06 -0700176 #[link_name = "cxxbridge02$unique_ptr$std$string$null"]
David Tolnay7db73692019-10-20 14:51:12 -0400177 fn unique_ptr_std_string_null(this: *mut *mut c_void);
David Tolnay8c730492020-03-13 01:29:06 -0700178 #[link_name = "cxxbridge02$unique_ptr$std$string$raw"]
David Tolnay7db73692019-10-20 14:51:12 -0400179 fn unique_ptr_std_string_raw(this: *mut *mut c_void, raw: *mut CxxString);
David Tolnay8c730492020-03-13 01:29:06 -0700180 #[link_name = "cxxbridge02$unique_ptr$std$string$get"]
David Tolnay7db73692019-10-20 14:51:12 -0400181 fn unique_ptr_std_string_get(this: *const *mut c_void) -> *const CxxString;
David Tolnay8c730492020-03-13 01:29:06 -0700182 #[link_name = "cxxbridge02$unique_ptr$std$string$release"]
David Tolnay7db73692019-10-20 14:51:12 -0400183 fn unique_ptr_std_string_release(this: *mut *mut c_void) -> *mut CxxString;
David Tolnay8c730492020-03-13 01:29:06 -0700184 #[link_name = "cxxbridge02$unique_ptr$std$string$drop"]
David Tolnay7db73692019-10-20 14:51:12 -0400185 fn unique_ptr_std_string_drop(this: *mut *mut c_void);
186}
187
188unsafe impl UniquePtrTarget for CxxString {
David Tolnayad266772020-04-09 23:42:29 -0700189 const __NAME: &'static str = "CxxString";
David Tolnay7db73692019-10-20 14:51:12 -0400190 fn __null() -> *mut c_void {
191 let mut repr = ptr::null_mut::<c_void>();
192 unsafe { unique_ptr_std_string_null(&mut repr) }
193 repr
194 }
David Tolnay7db73692019-10-20 14:51:12 -0400195 unsafe fn __raw(raw: *mut Self) -> *mut c_void {
196 let mut repr = ptr::null_mut::<c_void>();
197 unique_ptr_std_string_raw(&mut repr, raw);
198 repr
199 }
200 unsafe fn __get(repr: *mut c_void) -> *const Self {
201 unique_ptr_std_string_get(&repr)
202 }
203 unsafe fn __release(mut repr: *mut c_void) -> *mut Self {
204 unique_ptr_std_string_release(&mut repr)
205 }
206 unsafe fn __drop(mut repr: *mut c_void) {
207 unique_ptr_std_string_drop(&mut repr);
208 }
209}