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}