cpp_core/ptr.rs
1use crate::ops::{Begin, BeginMut, End, EndMut, Increment, Indirection};
2use crate::vector_ops::{Data, DataMut, Size};
3use crate::{
4 cpp_iter, CppBox, CppDeletable, CppIterator, DynamicCast, Ref, StaticDowncast, StaticUpcast,
5};
6use std::ops::Deref;
7use std::{fmt, slice};
8
9/// A pointer to a C++ object (similar to a C++ pointer).
10///
11/// A `Ptr` may or may not be owned. If you actually own the object, it's recommended to
12/// convert it to `CppBox` using `to_box` method.
13///
14/// Note that unlike Rust references, `Ptr` can be freely copied,
15/// producing multiple pointers to the same object, which is usually necessary
16/// to do when working with C++ libraries.
17///
18/// `Ptr` implements operator traits and delegates them
19/// to the corresponding C++ operators.
20/// This means that you can use `&ptr + value` to access the object's `operator+`.
21///
22/// `Ptr` implements `Deref`, allowing to call the object's methods
23/// directly. In addition, methods of the object's first base class are also directly available
24/// thanks to nested `Deref` implementations.
25///
26/// `Ptr` can contain a null pointer. `Deref` will panic if attempted to dereference
27/// a null pointer.
28///
29/// If the object provides an iterator interface through `begin()` and `end()` functions,
30/// `Ptr` will implement `IntoIterator`, so you can iterate on it directly.
31///
32/// ### Safety
33///
34/// It's not possible to automatically track the ownership of objects possibly managed by C++
35/// libraries. The user must ensure that the object is alive while `Ptr` exists. Note that
36/// with `Ptr`, it's possible to call unsafe C++ code without using any more unsafe Rust code,
37/// for example, by using operator traits, so care should be taken when exposing
38/// `Ptr` in a safe interface.
39///
40/// Null pointers must not be dereferenced.
41pub struct Ptr<T>(*mut T);
42
43/// Creates another pointer to the same object.
44impl<T> Clone for Ptr<T> {
45 fn clone(&self) -> Self {
46 Ptr(self.0)
47 }
48}
49
50/// Creates another pointer to the same object.
51impl<T> Copy for Ptr<T> {}
52
53impl<T> fmt::Debug for Ptr<T> {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 write!(f, "Ptr({:?})", self.0)
56 }
57}
58
59impl<T> Ptr<T> {
60 /// Creates a `Ptr` from a raw pointer.
61 ///
62 /// ### Safety
63 ///
64 /// See type level documentation.
65 pub unsafe fn from_raw(ptr: *const T) -> Self {
66 Ptr(ptr as *mut T)
67 }
68
69 /// Creates a null pointer.
70 ///
71 /// Note that accessing the content of a null `Ptr` through `Deref`
72 /// will result in a panic.
73 ///
74 /// Note that you can also use `NullPtr` to specify a null pointer to a function accepting
75 /// `impl CastInto<Ptr<_>>`. Unlike `Ptr`, `NullPtr` is not a generic type, so it will
76 /// not cause type inference issues.
77 ///
78 /// ### Safety
79 ///
80 /// Null pointers must not be dereferenced. See type level documentation.
81 pub unsafe fn null() -> Self {
82 Ptr(std::ptr::null_mut())
83 }
84
85 /// Returns the content as a raw const pointer.
86 pub fn as_mut_raw_ptr(self) -> *mut T {
87 self.0 as *mut T
88 }
89
90 /// Returns the content as a raw const pointer.
91 pub fn as_raw_ptr(self) -> *const T {
92 self.0
93 }
94
95 /// Returns the content as a const `Ref`. Returns `None` if `self` is a null pointer.
96 ///
97 /// ### Safety
98 ///
99 /// The operation is safe as long as `self` is valid or null. See type level documentation.
100 pub unsafe fn as_ref(self) -> Option<Ref<T>> {
101 Ref::from_raw(self.0)
102 }
103
104 /// Returns a reference to the value. Returns `None` if the pointer is null.
105 ///
106 /// ### Safety
107 ///
108 /// `self` must be valid.
109 /// The content must not be read or modified through other ways while the returned reference
110 /// exists.See type level documentation.
111 pub unsafe fn as_raw_ref<'a>(self) -> Option<&'a T> {
112 self.as_ref().map(|r| r.as_raw_ref())
113 }
114
115 /// Returns a mutable reference to the value. Returns `None` if the pointer is null.
116 ///
117 /// ### Safety
118 ///
119 /// `self` must be valid.
120 /// The content must not be read or modified through other ways while the returned reference
121 /// exists.See type level documentation.
122 pub unsafe fn as_mut_raw_ref<'a>(self) -> Option<&'a mut T> {
123 self.as_ref().map(|r| r.as_mut_raw_ref())
124 }
125
126 /// Returns true if the pointer is null.
127 pub fn is_null(self) -> bool {
128 self.0.is_null()
129 }
130
131 /// Converts the pointer to the base class type `U`.
132 ///
133 /// ### Safety
134 ///
135 /// This operation is safe as long as `self` is valid or null.
136 pub unsafe fn static_upcast<U>(self) -> Ptr<U>
137 where
138 T: StaticUpcast<U>,
139 {
140 StaticUpcast::static_upcast(self)
141 }
142
143 /// Converts the pointer to the derived class type `U`.
144 ///
145 /// It's recommended to use `dynamic_cast` instead because it performs a checked conversion.
146 ///
147 /// ### Safety
148 ///
149 /// This operation is safe as long as `self` is valid and it's type is `U` or inherits from `U`,
150 /// of if `self` is a null pointer.
151 pub unsafe fn static_downcast<U>(self) -> Ptr<U>
152 where
153 T: StaticDowncast<U>,
154 {
155 StaticDowncast::static_downcast(self)
156 }
157
158 /// Converts the pointer to the derived class type `U`. Returns `None` if the object's type
159 /// is not `U` and doesn't inherit `U`.
160 ///
161 /// ### Safety
162 ///
163 /// This operation is safe as long as `self` is valid or null.
164 pub unsafe fn dynamic_cast<U>(self) -> Ptr<U>
165 where
166 T: DynamicCast<U>,
167 {
168 DynamicCast::dynamic_cast(self)
169 }
170}
171
172impl<V, T> Ptr<V>
173where
174 V: Data<Output = *const T> + Size,
175{
176 /// Returns the content of the object as a slice, based on `data()` and `size()` methods.
177 ///
178 /// # Safety
179 ///
180 /// The caller must make sure `self` contains a valid pointer. The content must
181 /// not be read or modified through other ways while the returned slice exists.
182 /// This function
183 /// may invoke arbitrary foreign code, so no safety guarantees can be made.
184 pub unsafe fn as_slice<'a>(self) -> &'a [T] {
185 let ptr = self.data();
186 let size = self.size();
187 slice::from_raw_parts(ptr, size)
188 }
189}
190
191impl<V, T> Ptr<V>
192where
193 V: DataMut<Output = *mut T> + Size,
194{
195 /// Returns the content of the vector as a mutable slice,
196 /// based on `data()` and `size()` methods.
197 ///
198 /// # Safety
199 ///
200 /// The caller must make sure `self` contains a valid pointer. The content must
201 /// not be read or modified through other ways while the returned slice exists.
202 /// This function
203 /// may invoke arbitrary foreign code, so no safety guarantees can be made.
204 pub unsafe fn as_mut_slice<'a>(self) -> &'a mut [T] {
205 let ptr = self.data_mut();
206 let size = self.size();
207 slice::from_raw_parts_mut(ptr, size)
208 }
209}
210
211impl<T, T1, T2> Ptr<T>
212where
213 T: Begin<Output = CppBox<T1>> + End<Output = CppBox<T2>>,
214 T1: CppDeletable + PartialEq<Ref<T2>> + Increment + Indirection,
215 T2: CppDeletable,
216{
217 /// Returns an iterator over the content of the object,
218 /// based on `begin()` and `end()` methods.
219 ///
220 /// # Safety
221 ///
222 /// The caller must make sure `self` contains a valid pointer. The content must
223 /// not be read or modified through other ways while the returned slice exists.
224 /// This function
225 /// may invoke arbitrary foreign code, so no safety guarantees can be made.
226 pub unsafe fn iter(self) -> CppIterator<T1, T2> {
227 cpp_iter(self.begin(), self.end())
228 }
229}
230
231impl<T, T1, T2> Ptr<T>
232where
233 T: BeginMut<Output = CppBox<T1>> + EndMut<Output = CppBox<T2>>,
234 T1: CppDeletable + PartialEq<Ref<T2>> + Increment + Indirection,
235 T2: CppDeletable,
236{
237 /// Returns a mutable iterator over the content of the object,
238 /// based on `begin()` and `end()` methods.
239 ///
240 /// # Safety
241 ///
242 /// The caller must make sure `self` contains a valid pointer. The content must
243 /// not be read or modified through other ways while the returned slice exists.
244 /// This function
245 /// may invoke arbitrary foreign code, so no safety guarantees can be made.
246 pub unsafe fn iter_mut(self) -> CppIterator<T1, T2> {
247 cpp_iter(self.begin_mut(), self.end_mut())
248 }
249}
250
251/// Allows to call member functions of `T` and its base classes directly on the pointer.
252///
253/// Panics if the pointer is null.
254impl<T> Deref for Ptr<T> {
255 type Target = T;
256
257 fn deref(&self) -> &T {
258 if self.0.is_null() {
259 panic!("attempted to deref a null Ptr<T>");
260 }
261 unsafe { &(*self.0) }
262 }
263}
264
265impl<T: CppDeletable> Ptr<T> {
266 /// Converts this pointer to a `CppBox`. Returns `None` if `self`
267 /// is a null pointer.
268 ///
269 /// Use this function to take ownership of the object. This is
270 /// the same as `CppBox::new`.
271 ///
272 /// # Safety
273 ///
274 /// See type level documentation. See also `CppBox::new` documentation.
275 pub unsafe fn to_box(self) -> Option<CppBox<T>> {
276 CppBox::new(self)
277 }
278}
279
280/// A null pointer.
281///
282/// `NullPtr` implements `CastInto<Ptr<T>>`, so it can be
283/// passed as argument to functions accepting pointers. It's possible to use `Ptr::null()`
284/// as well, but that would require a type annotation.
285pub struct NullPtr;
286
287#[test]
288fn ptr_deref() {
289 let i = 42;
290 unsafe {
291 let ptr: Ptr<i32> = Ptr::from_raw(&i);
292 assert_eq!(*ptr, 42);
293 }
294}