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