abi_stable/sabi_types/move_ptr.rs
1//! Contains the `MovePtr<_>` type.
2
3use std::{
4 alloc::{self, Layout},
5 fmt::{self, Display},
6 marker::PhantomData,
7 mem::ManuallyDrop,
8 ops::{Deref, DerefMut},
9 ptr::{self, NonNull},
10};
11
12use crate::{sabi_types::RMut, std_types::RBox, traits::IntoInner};
13
14/// A move pointer, which allows moving the value from the reference,
15/// consuming it in the process.
16///
17/// If `MovePtr::into_inner` isn't called, this drops the referenced value when it's dropped
18///
19/// # Safety
20///
21/// This is unsafe to construct since the user must ensure that the
22/// original owner of the value never accesses it again.
23///
24/// # Motivation
25///
26/// `MovePtr` was created as a way to pass `self` by value to ffi-safe trait object methods,
27/// since one can't simply pass `self` by value(because the type is erased).
28///
29/// # Examples
30///
31/// ### Using OwnedPointer::in_move_ptr
32///
33/// This is how one can use MovePtr without `unsafe`.
34///
35/// This simply moves the contents of an `RBox<T>` into a `Box<T>`.
36///
37/// ```
38/// use abi_stable::{
39/// pointer_trait::OwnedPointer, sabi_types::MovePtr, std_types::RBox,
40/// };
41///
42/// fn move_rbox_to_box<T>(rbox: RBox<T>) -> Box<T> {
43/// rbox.in_move_ptr(|move_ptr| MovePtr::into_box(move_ptr))
44/// }
45///
46/// assert_eq!(move_rbox_to_box(RBox::new(99)), Box::new(99));
47///
48/// assert_eq!(move_rbox_to_box(RBox::new(())), Box::new(()));
49///
50/// assert_eq!(
51/// move_rbox_to_box(RBox::new(String::from("SHIT"))),
52/// Box::new(String::from("SHIT"))
53/// );
54///
55///
56/// ```
57///
58/// ### Using the (unsafe) `MovePtr::new`
59///
60/// This is (sort of) how `RBox<T>` implements moving the `T` it owns out of its allocation
61///
62/// This is basically what `OwnedPointer::{with_move_ptr,in_move_ptr}` do.
63///
64/// ```
65/// use abi_stable::{
66/// pointer_trait::{AsMutPtr, OwnedPointer},
67/// sabi_types::MovePtr,
68/// std_types::RBox,
69/// };
70///
71/// use std::mem::ManuallyDrop;
72///
73/// let rbox = RBox::new(0x100);
74///
75/// let second_rbox;
76///
77/// unsafe {
78/// let mut rbox = ManuallyDrop::new(rbox);
79///
80/// let move_ptr = unsafe { MovePtr::from_rmut(rbox.as_rmut()) };
81/// second_rbox = RBox::from_move_ptr(move_ptr);
82///
83/// OwnedPointer::drop_allocation(&mut rbox);
84/// }
85///
86/// assert_eq!(second_rbox, RBox::new(0x100));
87///
88///
89/// ```
90#[repr(transparent)]
91#[derive(StableAbi)]
92#[sabi(bound(T:'a))]
93pub struct MovePtr<'a, T> {
94 ptr: NonNull<T>,
95 _marker: PhantomData<crate::utils::MutRef<'a, T>>,
96}
97
98impl<'a, T> MovePtr<'a, T> {
99 /// Constructs this move pointer from a mutable reference,
100 /// moving the value out of the reference.
101 ///
102 /// # Safety
103 ///
104 /// Callers must ensure that the original owner of the value won't
105 /// access the moved-out value anymore.
106 ///
107 /// # Example
108 ///
109 /// ```
110 /// use abi_stable::sabi_types::MovePtr;
111 ///
112 /// use std::mem::ManuallyDrop;
113 ///
114 /// let mut manual = ManuallyDrop::new(String::from("hello"));
115 ///
116 /// let moveptr = unsafe { MovePtr::new(&mut *manual) };
117 ///
118 /// drop(moveptr); // moveptr drops the String here.
119 /// ```
120 #[inline]
121 pub unsafe fn new(ptr: &'a mut T) -> Self {
122 Self {
123 ptr: unsafe { NonNull::new_unchecked(ptr) },
124 _marker: PhantomData,
125 }
126 }
127
128 /// Constructs this move pointer from an `RMut`,
129 /// moving the value out of the reference.
130 ///
131 /// # Safety
132 ///
133 /// Callers must ensure that the original owner of the value won't
134 /// access the moved-out value anymore.
135 ///
136 /// # Example
137 ///
138 /// ```
139 /// use abi_stable::{
140 /// pointer_trait::AsMutPtr, sabi_types::MovePtr, std_types::RString,
141 /// utils::manuallydrop_as_rmut,
142 /// };
143 ///
144 /// use std::mem::ManuallyDrop;
145 ///
146 /// let mut mdrop = ManuallyDrop::new(RString::from("hello"));
147 ///
148 /// // safety: `mdrop` is never accessed again
149 /// let moveptr = unsafe { MovePtr::from_rmut(manuallydrop_as_rmut(&mut mdrop)) };
150 /// assert_eq!(*moveptr, "hello");
151 ///
152 /// let string: RString = MovePtr::into_inner(moveptr);
153 /// assert_eq!(string, "hello");
154 ///
155 /// ```
156 #[inline]
157 pub const unsafe fn from_rmut(ptr: RMut<'a, T>) -> Self {
158 Self {
159 ptr: unsafe { NonNull::new_unchecked(ptr.into_raw()) },
160 _marker: PhantomData,
161 }
162 }
163
164 /// Constructs this move pointer from a raw pointer,
165 /// moving the value out of it.
166 ///
167 /// # Safety
168 ///
169 /// Callers must ensure that the original owner of the value won't
170 /// access the moved-out value anymore.
171 ///
172 /// Because this takes a mutable pointer, the lifetime of this `MovePtr` is unbounded.
173 /// You must ensure that it's not used for longer than the lifetime of the
174 /// pointed-to value.
175 ///
176 /// # Example
177 ///
178 /// ```
179 /// use abi_stable::{
180 /// pointer_trait::AsMutPtr, rvec, sabi_types::MovePtr, std_types::RVec,
181 /// utils::manuallydrop_as_raw_mut,
182 /// };
183 ///
184 /// use std::mem::ManuallyDrop;
185 ///
186 /// let mut mdrop = ManuallyDrop::new(rvec![3, 5, 8]);
187 ///
188 /// // safety: `mdrop` is never accessed again
189 /// let moveptr = unsafe { MovePtr::from_raw(manuallydrop_as_raw_mut(&mut mdrop)) };
190 /// assert_eq!(moveptr[..], [3, 5, 8]);
191 ///
192 /// let vector: RVec<u8> = MovePtr::into_inner(moveptr);
193 /// assert_eq!(vector[..], [3, 5, 8]);
194 ///
195 /// ```
196 pub const unsafe fn from_raw(ptr: *mut T) -> Self {
197 Self {
198 ptr: unsafe { NonNull::new_unchecked(ptr) },
199 _marker: PhantomData,
200 }
201 }
202
203 /// Gets a raw pointer to the value being moved.
204 ///
205 /// # Example
206 ///
207 /// ```
208 /// use abi_stable::{
209 /// pointer_trait::OwnedPointer, sabi_types::MovePtr, std_types::RBox,
210 /// };
211 ///
212 /// let rbox = RBox::new(String::from("NOPE"));
213 /// let address_rbox = &*rbox as *const String as usize;
214 ///
215 /// rbox.in_move_ptr(|move_ptr| {
216 /// assert_eq!(address_rbox, MovePtr::as_ptr(&move_ptr) as usize);
217 /// });
218 ///
219 /// ```
220 #[inline(always)]
221 pub const fn as_ptr(this: &Self) -> *const T {
222 this.ptr.as_ptr()
223 }
224
225 /// Gets a raw pointer to the value being moved.
226 ///
227 /// # Example
228 ///
229 /// # Example
230 ///
231 /// ```
232 /// use abi_stable::{
233 /// pointer_trait::OwnedPointer, sabi_types::MovePtr, std_types::RBox,
234 /// };
235 ///
236 /// let rbox = RBox::new(String::from("NOPE"));
237 /// let address_rbox = &*rbox as *const String as usize;
238 ///
239 /// rbox.in_move_ptr(|mut move_ptr| {
240 /// assert_eq!(address_rbox, MovePtr::as_mut_ptr(&mut move_ptr) as usize);
241 /// });
242 ///
243 /// ```
244 #[inline(always)]
245 pub fn as_mut_ptr(this: &mut Self) -> *mut T {
246 this.ptr.as_ptr()
247 }
248
249 /// Converts this MovePtr into a raw pointer,
250 /// which must be moved from before the pointed to value is deallocated,
251 /// otherwise the value will be leaked.
252 ///
253 /// # Example
254 ///
255 /// ```
256 /// use abi_stable::{
257 /// pointer_trait::OwnedPointer, sabi_types::MovePtr, std_types::RBox,
258 /// };
259 ///
260 /// let rbox = RBox::new(String::from("NOPE"));
261 ///
262 /// let string =
263 /// rbox.in_move_ptr(|move_ptr| unsafe { MovePtr::into_raw(move_ptr).read() });
264 ///
265 /// assert_eq!(string, String::from("NOPE"));
266 ///
267 /// ```
268 #[inline]
269 pub const fn into_raw(this: Self) -> *mut T {
270 let ptr = this.ptr.as_ptr();
271 std::mem::forget(this);
272 ptr
273 }
274
275 /// Moves the value into a new `Box<T>`
276 ///
277 /// # Example
278 ///
279 /// ```
280 /// use abi_stable::{
281 /// pointer_trait::OwnedPointer, sabi_types::MovePtr, std_types::RBox,
282 /// };
283 ///
284 /// let rbox = RBox::new(String::from("WHAT!!!"));
285 ///
286 /// let boxed = rbox.in_move_ptr(|move_ptr| unsafe { MovePtr::into_box(move_ptr) });
287 ///
288 /// assert_eq!(boxed, Box::new(String::from("WHAT!!!")));
289 ///
290 /// ```
291 #[inline]
292 pub fn into_box(this: Self) -> Box<T> {
293 unsafe {
294 let raw = Self::into_raw(this);
295
296 if std::mem::size_of::<T>() == 0 {
297 Box::from_raw(raw)
298 } else {
299 let allocated = alloc::alloc(Layout::new::<T>()) as *mut T;
300
301 raw.copy_to_nonoverlapping(allocated, 1);
302
303 Box::from_raw(allocated)
304 }
305 }
306 }
307
308 /// Moves the value into a new `RBox<T>`
309 ///
310 /// # Example
311 ///
312 /// ```
313 /// use abi_stable::{
314 /// pointer_trait::OwnedPointer, sabi_types::MovePtr, std_types::RBox,
315 /// };
316 ///
317 /// let rbox = RBox::new(String::from("WHAT!!!"));
318 ///
319 /// let boxed = rbox.in_move_ptr(|move_ptr| unsafe { MovePtr::into_rbox(move_ptr) });
320 ///
321 /// assert_eq!(boxed, RBox::new(String::from("WHAT!!!")));
322 ///
323 /// ```
324 #[inline]
325 pub fn into_rbox(this: Self) -> RBox<T> {
326 Self::into_box(this).into()
327 }
328
329 /// Moves the value out of the reference
330 ///
331 /// # Example
332 ///
333 /// ```
334 /// use abi_stable::{
335 /// pointer_trait::OwnedPointer, sabi_types::MovePtr, std_types::RBox,
336 /// };
337 ///
338 /// let rbox = RBox::new(String::from("(The Wi)zard(of)oz"));
339 ///
340 /// let string = rbox.in_move_ptr(|ptr| MovePtr::into_inner(ptr));
341 ///
342 /// assert_eq!(string, String::from("(The Wi)zard(of)oz"));
343 ///
344 /// ```
345 #[inline]
346 pub fn into_inner(this: Self) -> T {
347 let this = ManuallyDrop::new(this);
348 unsafe { this.ptr.as_ptr().read() }
349 }
350
351 /// Transmute this `RMove<'a, T>` into a `RMove<'a, U>`.
352 ///
353 /// # Safety
354 ///
355 /// This has the safety requirements as
356 /// [`std::mem::transmute`](https://doc.rust-lang.org/std/mem/fn.transmute.html),
357 /// as well as requiring that this `MovePtr` is aligned for `U`.
358 ///
359 ///
360 /// # Example
361 ///
362 /// ```
363 /// use abi_stable::{
364 /// pointer_trait::OwnedPointer,
365 /// sabi_types::MovePtr,
366 /// std_types::{RBox, RString, RVec},
367 /// };
368 ///
369 /// let rbox = RBox::new(RString::from("hello"));
370 ///
371 /// let bytes = rbox.in_move_ptr(|ptr| unsafe {
372 /// MovePtr::into_inner(MovePtr::transmute::<RVec<u8>>(ptr))
373 /// });
374 ///
375 /// assert_eq!(bytes.as_slice(), b"hello");
376 ///
377 /// ```
378 #[inline]
379 pub const unsafe fn transmute<U>(this: Self) -> MovePtr<'a, U>
380 where
381 U: 'a,
382 {
383 unsafe { std::mem::transmute::<MovePtr<'a, T>, MovePtr<'a, U>>(this) }
384 }
385}
386
387shared_impls! {
388 mod=move_ptr_impls
389 new_type=MovePtr['a][T],
390 original_type=AAAA,
391}
392
393impl<'a, T> Display for MovePtr<'a, T>
394where
395 T: Display,
396{
397 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
398 Display::fmt(&**self, f)
399 }
400}
401
402impl<'a, T> Deref for MovePtr<'a, T> {
403 type Target = T;
404
405 fn deref(&self) -> &T {
406 unsafe { &*(self.ptr.as_ptr() as *const _) }
407 }
408}
409
410impl<'a, T> DerefMut for MovePtr<'a, T> {
411 fn deref_mut(&mut self) -> &mut T {
412 unsafe { &mut *self.ptr.as_ptr() }
413 }
414}
415
416impl<'a, T> IntoInner for MovePtr<'a, T> {
417 type Element = T;
418
419 fn into_inner_(self) -> T {
420 Self::into_inner(self)
421 }
422}
423
424impl<'a, T> Drop for MovePtr<'a, T> {
425 fn drop(&mut self) {
426 unsafe {
427 ptr::drop_in_place(self.ptr.as_ptr());
428 }
429 }
430}
431
432unsafe impl<'a, T: Send> Send for MovePtr<'a, T> {}
433
434unsafe impl<'a, T: Sync> Sync for MovePtr<'a, T> {}
435
436//#[cfg(test)]
437#[cfg(all(test, not(feature = "only_new_tests")))]
438mod test {
439 use super::*;
440
441 use std::sync::Arc;
442
443 #[test]
444 fn with_manuallydrop() {
445 let arc = Arc::new(10);
446 unsafe {
447 let mut cloned_arc = ManuallyDrop::new(arc.clone());
448
449 let move_ptr = MovePtr::new(&mut *cloned_arc);
450 assert_eq!(Arc::strong_count(&*move_ptr), 2);
451
452 let moved_arc = MovePtr::into_inner(move_ptr);
453 assert_eq!(Arc::strong_count(&moved_arc), 2);
454 }
455 assert_eq!(Arc::strong_count(&arc), 1);
456 unsafe {
457 let mut cloned_arc = ManuallyDrop::new(arc.clone());
458
459 let move_ptr = MovePtr::new(&mut *cloned_arc);
460 assert_eq!(Arc::strong_count(&*move_ptr), 2);
461 }
462 assert_eq!(Arc::strong_count(&arc), 1);
463 }
464
465 #[test]
466 fn take_mutable_reference() {
467 unsafe {
468 let mut val = 3u32;
469 let mut mutref = ManuallyDrop::new(&mut val);
470
471 let mut move_ptr = MovePtr::<&mut u32>::new(&mut *mutref);
472 assert_eq!(**move_ptr, 3);
473
474 **move_ptr += 2;
475 assert_eq!(**move_ptr, 5);
476
477 let moved_mut: &mut u32 = MovePtr::into_inner(move_ptr);
478 assert_eq!(*moved_mut, 5);
479 }
480 }
481}