blob: c8c5a67cd150592100e00902457009431e95b749 [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 Tolnay7db73692019-10-20 14:51:12 -04006use std::ptr;
7
8/// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
9#[repr(C)]
10pub struct UniquePtr<T>
11where
12 T: UniquePtrTarget,
13{
14 repr: *mut c_void,
15 ty: PhantomData<T>,
16}
17
18impl<T> UniquePtr<T>
19where
20 T: UniquePtrTarget,
21{
22 /// Makes a new UniquePtr wrapping a null pointer.
23 ///
24 /// Matches the behavior of default-constructing a std::unique\_ptr.
25 pub fn null() -> Self {
26 UniquePtr {
27 repr: T::__null(),
28 ty: PhantomData,
29 }
30 }
31
32 /// Allocates memory on the heap and makes a UniquePtr pointing to it.
33 pub fn new(value: T) -> Self {
34 UniquePtr {
35 repr: T::__new(value),
36 ty: PhantomData,
37 }
38 }
39
40 /// Checks whether the UniquePtr does not own an object.
41 ///
42 /// This is the opposite of [std::unique_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_bool).
43 pub fn is_null(&self) -> bool {
44 let ptr = unsafe { T::__get(self.repr) };
45 ptr.is_null()
46 }
47
48 /// Returns a reference to the object owned by this UniquePtr if any,
49 /// otherwise None.
50 pub fn as_ref(&self) -> Option<&T> {
51 unsafe { T::__get(self.repr).as_ref() }
52 }
53
David Tolnay1a61b162020-04-09 23:20:05 -070054 /// Returns a mutable reference to the object owned by this UniquePtr if
55 /// any, otherwise None.
56 pub fn as_mut(&mut self) -> Option<&mut T> {
57 unsafe { (T::__get(self.repr) as *mut T).as_mut() }
58 }
59
David Tolnay7db73692019-10-20 14:51:12 -040060 /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
61 ///
62 /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release).
63 pub fn into_raw(self) -> *mut T {
64 let ptr = unsafe { T::__release(self.repr) };
65 mem::forget(self);
66 ptr
67 }
68
69 /// Constructs a UniquePtr retaking ownership of a pointer previously
70 /// obtained from `into_raw`.
71 ///
72 /// # Safety
73 ///
74 /// This function is unsafe because improper use may lead to memory
75 /// problems. For example a double-free may occur if the function is called
76 /// twice on the same raw pointer.
77 pub unsafe fn from_raw(raw: *mut T) -> Self {
78 UniquePtr {
79 repr: T::__raw(raw),
80 ty: PhantomData,
81 }
82 }
83}
84
85unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
86unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {}
87
88impl<T> Drop for UniquePtr<T>
89where
90 T: UniquePtrTarget,
91{
92 fn drop(&mut self) {
93 unsafe { T::__drop(self.repr) }
94 }
95}
96
97impl<T> Debug for UniquePtr<T>
98where
99 T: Debug + UniquePtrTarget,
100{
101 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
102 match self.as_ref() {
103 None => formatter.write_str("nullptr"),
104 Some(value) => Debug::fmt(value, formatter),
105 }
106 }
107}
108
109impl<T> Display for UniquePtr<T>
110where
111 T: Display + UniquePtrTarget,
112{
113 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
114 match self.as_ref() {
115 None => formatter.write_str("nullptr"),
116 Some(value) => Display::fmt(value, formatter),
117 }
118 }
119}
120
121// Methods are private; not intended to be implemented outside of cxxbridge
122// codebase.
123pub unsafe trait UniquePtrTarget {
124 #[doc(hidden)]
David Tolnayad266772020-04-09 23:42:29 -0700125 const __NAME: &'static str;
126 #[doc(hidden)]
David Tolnay7db73692019-10-20 14:51:12 -0400127 fn __null() -> *mut c_void;
128 #[doc(hidden)]
David Tolnay53838912020-04-09 20:56:44 -0700129 fn __new(value: Self) -> *mut c_void
130 where
131 Self: Sized,
132 {
133 // Opaque C types do not get this method because they can never exist by
134 // value on the Rust side of the bridge.
135 let _ = value;
136 unreachable!()
137 }
David Tolnay7db73692019-10-20 14:51:12 -0400138 #[doc(hidden)]
139 unsafe fn __raw(raw: *mut Self) -> *mut c_void;
140 #[doc(hidden)]
141 unsafe fn __get(repr: *mut c_void) -> *const Self;
142 #[doc(hidden)]
143 unsafe fn __release(repr: *mut c_void) -> *mut Self;
144 #[doc(hidden)]
145 unsafe fn __drop(repr: *mut c_void);
146}
147
148extern "C" {
David Tolnay8c730492020-03-13 01:29:06 -0700149 #[link_name = "cxxbridge02$unique_ptr$std$string$null"]
David Tolnay7db73692019-10-20 14:51:12 -0400150 fn unique_ptr_std_string_null(this: *mut *mut c_void);
David Tolnay8c730492020-03-13 01:29:06 -0700151 #[link_name = "cxxbridge02$unique_ptr$std$string$raw"]
David Tolnay7db73692019-10-20 14:51:12 -0400152 fn unique_ptr_std_string_raw(this: *mut *mut c_void, raw: *mut CxxString);
David Tolnay8c730492020-03-13 01:29:06 -0700153 #[link_name = "cxxbridge02$unique_ptr$std$string$get"]
David Tolnay7db73692019-10-20 14:51:12 -0400154 fn unique_ptr_std_string_get(this: *const *mut c_void) -> *const CxxString;
David Tolnay8c730492020-03-13 01:29:06 -0700155 #[link_name = "cxxbridge02$unique_ptr$std$string$release"]
David Tolnay7db73692019-10-20 14:51:12 -0400156 fn unique_ptr_std_string_release(this: *mut *mut c_void) -> *mut CxxString;
David Tolnay8c730492020-03-13 01:29:06 -0700157 #[link_name = "cxxbridge02$unique_ptr$std$string$drop"]
David Tolnay7db73692019-10-20 14:51:12 -0400158 fn unique_ptr_std_string_drop(this: *mut *mut c_void);
159}
160
161unsafe impl UniquePtrTarget for CxxString {
David Tolnayad266772020-04-09 23:42:29 -0700162 const __NAME: &'static str = "CxxString";
David Tolnay7db73692019-10-20 14:51:12 -0400163 fn __null() -> *mut c_void {
164 let mut repr = ptr::null_mut::<c_void>();
165 unsafe { unique_ptr_std_string_null(&mut repr) }
166 repr
167 }
David Tolnay7db73692019-10-20 14:51:12 -0400168 unsafe fn __raw(raw: *mut Self) -> *mut c_void {
169 let mut repr = ptr::null_mut::<c_void>();
170 unique_ptr_std_string_raw(&mut repr, raw);
171 repr
172 }
173 unsafe fn __get(repr: *mut c_void) -> *const Self {
174 unique_ptr_std_string_get(&repr)
175 }
176 unsafe fn __release(mut repr: *mut c_void) -> *mut Self {
177 unique_ptr_std_string_release(&mut repr)
178 }
179 unsafe fn __drop(mut repr: *mut c_void) {
180 unique_ptr_std_string_drop(&mut repr);
181 }
182}