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}