abi_stable/std_types/
boxed.rs

1//! Contains the ffi-safe equivalent of `std::boxed::Box`.
2
3use std::{
4    borrow::{Borrow, BorrowMut},
5    error::Error as StdError,
6    future::Future,
7    hash::Hasher,
8    io::{self, BufRead, IoSlice, IoSliceMut, Read, Seek, Write},
9    iter::FusedIterator,
10    marker::{PhantomData, Unpin},
11    mem::ManuallyDrop,
12    ops::DerefMut,
13    pin::Pin,
14    ptr::{self, NonNull},
15    task::{Context, Poll},
16};
17
18#[allow(unused_imports)]
19use core_extensions::SelfOps;
20
21use crate::{
22    marker_type::NonOwningPhantom,
23    pointer_trait::{
24        AsMutPtr, AsPtr, CallReferentDrop, CanTransmuteElement, Deallocate, GetPointerKind,
25        OwnedPointer, PK_SmartPointer,
26    },
27    prefix_type::WithMetadata,
28    sabi_types::MovePtr,
29    std_types::utypeid::{new_utypeid, UTypeId},
30    traits::IntoReprRust,
31};
32
33// #[cfg(test)]
34#[cfg(all(test, not(feature = "only_new_tests")))]
35mod test;
36
37mod private {
38    use super::*;
39
40    /// Ffi-safe equivalent of `std::box::Box`.
41    ///
42    /// # Example
43    ///
44    /// Declaring a recursive datatype.
45    ///
46    /// ```
47    /// use abi_stable::{
48    ///     std_types::{RBox, RString},
49    ///     StableAbi,
50    /// };
51    ///
52    /// #[repr(u8)]
53    /// #[derive(StableAbi)]
54    /// enum Command {
55    ///     SendProduct {
56    ///         id: u64,
57    ///     },
58    ///     GoProtest {
59    ///         cause: RString,
60    ///         place: RString,
61    ///     },
62    ///     SendComplaint {
63    ///         cause: RString,
64    ///         website: RString,
65    ///     },
66    ///     WithMetadata {
67    ///         command: RBox<Command>,
68    ///         metadata: RString,
69    ///     },
70    /// }
71    ///
72    /// ```
73    ///
74    #[repr(C)]
75    #[derive(StableAbi)]
76    pub struct RBox<T> {
77        data: NonNull<T>,
78        vtable: BoxVtable_Ref<T>,
79        _marker: PhantomData<T>,
80    }
81
82    impl<T> RBox<T> {
83        /// Constucts an `RBox<T>` from a value.
84        ///
85        /// # Example
86        ///
87        /// ```
88        /// use abi_stable::std_types::RBox;
89        ///
90        /// let baux = RBox::new(100);
91        /// assert_eq!(*baux, 100);
92        ///
93        /// ```
94        pub fn new(value: T) -> Self {
95            Box::new(value).piped(RBox::from_box)
96        }
97
98        /// Constructs a `Pin<RBox<T>>`.
99        ///
100        pub fn pin(value: T) -> Pin<RBox<T>> {
101            RBox::new(value).into_pin()
102        }
103
104        /// Converts a `Box<T>` to an `RBox<T>`, reusing its heap allocation.
105        ///
106        /// # Example
107        ///
108        /// ```
109        /// use abi_stable::std_types::RBox;
110        ///
111        /// let baux = Box::new(200);
112        /// let baux = RBox::from_box(baux);
113        /// assert_eq!(*baux, 200);
114        ///
115        /// ```
116        pub fn from_box(p: Box<T>) -> RBox<T> {
117            RBox {
118                data: unsafe { NonNull::new_unchecked(Box::into_raw(p)) },
119                vtable: VTableGetter::<T>::LIB_VTABLE,
120                _marker: PhantomData,
121            }
122        }
123
124        /// Constructs a `Box<T>` from a `MovePtr<'_, T>`.
125        ///
126        /// # Example
127        ///
128        /// ```
129        /// use std::mem::ManuallyDrop;
130        ///
131        /// use abi_stable::{
132        ///     pointer_trait::OwnedPointer,
133        ///     sabi_types::RSmallBox,
134        ///     std_types::RBox,
135        /// };
136        ///
137        /// let b = RSmallBox::<_, [u8; 1]>::new(77u8);
138        /// let rbox: RBox<_> = b.in_move_ptr(|x| RBox::from_move_ptr(x));
139        ///
140        /// assert_eq!(*rbox, 77);
141        ///
142        /// ```
143        pub fn from_move_ptr(p: MovePtr<'_, T>) -> RBox<T> {
144            MovePtr::into_rbox(p)
145        }
146
147        #[inline(always)]
148        pub(super) const fn data(&self) -> *mut T {
149            self.data.as_ptr()
150        }
151        #[inline(always)]
152        pub(super) fn data_mut(&mut self) -> *mut T {
153            self.data.as_ptr()
154        }
155
156        #[inline(always)]
157        pub(super) const fn vtable(&self) -> BoxVtable_Ref<T> {
158            self.vtable
159        }
160
161        #[allow(dead_code)]
162        #[cfg(test)]
163        pub(super) fn set_vtable_for_testing(&mut self) {
164            self.vtable = VTableGetter::<T>::LIB_VTABLE_FOR_TESTING;
165        }
166    }
167
168    unsafe impl<T> AsPtr for RBox<T> {
169        #[inline(always)]
170        fn as_ptr(&self) -> *const T {
171            self.data.as_ptr()
172        }
173    }
174    unsafe impl<T> AsMutPtr for RBox<T> {
175        #[inline(always)]
176        fn as_mut_ptr(&mut self) -> *mut T {
177            self.data.as_ptr()
178        }
179    }
180}
181
182pub use self::private::RBox;
183
184unsafe impl<T> GetPointerKind for RBox<T> {
185    type Kind = PK_SmartPointer;
186
187    type PtrTarget = T;
188}
189
190unsafe impl<T, O> CanTransmuteElement<O> for RBox<T> {
191    type TransmutedPtr = RBox<O>;
192
193    unsafe fn transmute_element_(self) -> Self::TransmutedPtr {
194        unsafe { core_extensions::utils::transmute_ignore_size(self) }
195    }
196}
197
198impl<T> RBox<T> {
199    /// Converts this `RBox<T>` into a `Box<T>`
200    ///
201    /// # Allocation
202    ///
203    /// If this is invoked outside of the dynamic library/binary that created the `RBox<T>`,
204    /// it will allocate a new `Box<T>` and move the data into it.
205    ///
206    /// # Example
207    ///
208    /// ```
209    /// use abi_stable::std_types::RBox;
210    ///
211    /// let baux: RBox<u32> = RBox::new(200);
212    /// let baux: Box<u32> = RBox::into_box(baux);
213    /// assert_eq!(*baux, 200);
214    ///
215    /// ```
216    pub fn into_box(this: Self) -> Box<T> {
217        let this = ManuallyDrop::new(this);
218
219        unsafe {
220            let this_vtable = this.vtable();
221            let other_vtable = VTableGetter::LIB_VTABLE;
222            if ::std::ptr::eq(this_vtable.0.to_raw_ptr(), other_vtable.0.to_raw_ptr())
223                || this_vtable.type_id()() == other_vtable.type_id()()
224            {
225                Box::from_raw(this.data())
226            } else {
227                let ret = Box::new(this.data().read());
228                // Just deallocating the Box<_>. without dropping the inner value
229                (this.vtable().destructor())(
230                    this.data() as *mut (),
231                    CallReferentDrop::No,
232                    Deallocate::Yes,
233                );
234                ret
235            }
236        }
237    }
238
239    /// Unwraps this `Box<T>` into the value it owns on the heap.
240    ///
241    /// # Example
242    ///
243    /// ```
244    /// use abi_stable::std_types::RBox;
245    ///
246    /// let baux: RBox<u32> = RBox::new(200);
247    /// let baux: u32 = RBox::into_inner(baux);
248    /// assert_eq!(baux, 200);
249    ///
250    /// ```
251    pub fn into_inner(this: Self) -> T {
252        unsafe {
253            let value = this.data().read();
254            Self::drop_allocation(&mut ManuallyDrop::new(this));
255            value
256        }
257    }
258
259    /// Wraps this `RBox` in a `Pin`
260    ///
261    pub fn into_pin(self) -> Pin<RBox<T>> {
262        // safety: this is the same as what Box does.
263        unsafe { Pin::new_unchecked(self) }
264    }
265}
266
267impl<T> DerefMut for RBox<T> {
268    fn deref_mut(&mut self) -> &mut Self::Target {
269        unsafe { &mut *self.data() }
270    }
271}
272
273/////////////////////////////////////////////////////////////////
274
275unsafe impl<T> OwnedPointer for RBox<T> {
276    #[inline]
277    unsafe fn get_move_ptr(this: &mut ManuallyDrop<Self>) -> MovePtr<'_, T> {
278        unsafe { MovePtr::from_raw(this.data_mut()) }
279    }
280
281    #[inline]
282    unsafe fn drop_allocation(this: &mut ManuallyDrop<Self>) {
283        let data: *mut T = this.data();
284        unsafe {
285            (this.vtable().destructor())(data as *mut (), CallReferentDrop::No, Deallocate::Yes);
286        }
287    }
288}
289
290/////////////////////////////////////////////////////////////////
291
292impl<T> Borrow<T> for RBox<T> {
293    fn borrow(&self) -> &T {
294        self
295    }
296}
297
298impl<T> BorrowMut<T> for RBox<T> {
299    fn borrow_mut(&mut self) -> &mut T {
300        self
301    }
302}
303
304impl<T> AsRef<T> for RBox<T> {
305    fn as_ref(&self) -> &T {
306        self
307    }
308}
309
310impl<T> AsMut<T> for RBox<T> {
311    fn as_mut(&mut self) -> &mut T {
312        self
313    }
314}
315
316/////////////////////////////////////////////////////////////////
317
318impl_from_rust_repr! {
319    impl[T] From<Box<T>> for RBox<T> {
320        fn(this){
321            RBox::from_box(this)
322        }
323    }
324}
325
326impl<T> From<RBox<T>> for Pin<RBox<T>> {
327    fn from(boxed: RBox<T>) -> Pin<RBox<T>> {
328        boxed.into_pin()
329    }
330}
331
332/////////////////////////////////////////////////////////////////
333
334impl<T> IntoReprRust for RBox<T> {
335    type ReprRust = Box<T>;
336
337    fn into_rust(self) -> Self::ReprRust {
338        Self::into_box(self)
339    }
340}
341
342/////////////////////////////////////////////////////////////////
343
344impl<T> Default for RBox<T>
345where
346    T: Default,
347{
348    fn default() -> Self {
349        Self::new(T::default())
350    }
351}
352
353impl<T> Clone for RBox<T>
354where
355    T: Clone,
356{
357    fn clone(&self) -> Self {
358        (**self).clone().piped(Box::new).into()
359    }
360}
361
362shared_impls! {pointer
363    mod = box_impls
364    new_type = RBox[][T],
365    original_type = Box,
366}
367
368unsafe impl<T: Send> Send for RBox<T> {}
369unsafe impl<T: Sync> Sync for RBox<T> {}
370impl<T> Unpin for RBox<T> {}
371
372///////////////////////////////////////////////////////////////
373
374impl<I> Iterator for RBox<I>
375where
376    I: Iterator,
377{
378    type Item = I::Item;
379    fn next(&mut self) -> Option<I::Item> {
380        (**self).next()
381    }
382    fn size_hint(&self) -> (usize, Option<usize>) {
383        (**self).size_hint()
384    }
385    fn nth(&mut self, n: usize) -> Option<I::Item> {
386        (**self).nth(n)
387    }
388    fn last(self) -> Option<I::Item> {
389        RBox::into_inner(self).last()
390    }
391}
392
393impl<I> DoubleEndedIterator for RBox<I>
394where
395    I: DoubleEndedIterator,
396{
397    fn next_back(&mut self) -> Option<I::Item> {
398        (**self).next_back()
399    }
400    fn nth_back(&mut self, n: usize) -> Option<I::Item> {
401        (**self).nth_back(n)
402    }
403}
404
405impl<I> ExactSizeIterator for RBox<I>
406where
407    I: ExactSizeIterator,
408{
409    fn len(&self) -> usize {
410        (**self).len()
411    }
412}
413
414impl<I> FusedIterator for RBox<I> where I: FusedIterator {}
415
416///////////////////////////////////////////////////////////////
417
418impl<F> Future for RBox<F>
419where
420    F: Future + Unpin,
421{
422    type Output = F::Output;
423
424    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
425        F::poll(Pin::new(&mut *self), cx)
426    }
427}
428
429///////////////////////////////////////////////////////////////
430
431impl<T> StdError for RBox<T>
432where
433    T: StdError,
434{
435    #[allow(deprecated, deprecated_in_future)]
436    fn description(&self) -> &str {
437        StdError::description(&**self)
438    }
439
440    #[allow(deprecated)]
441    fn cause(&self) -> Option<&dyn StdError> {
442        StdError::cause(&**self)
443    }
444
445    fn source(&self) -> Option<&(dyn StdError + 'static)> {
446        StdError::source(&**self)
447    }
448}
449
450///////////////////////////////////////////////////////////////
451
452impl<T> Read for RBox<T>
453where
454    T: Read,
455{
456    #[inline]
457    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
458        (**self).read(buf)
459    }
460
461    #[inline]
462    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
463        (**self).read_vectored(bufs)
464    }
465
466    #[inline]
467    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
468        (**self).read_to_end(buf)
469    }
470
471    #[inline]
472    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
473        (**self).read_to_string(buf)
474    }
475
476    #[inline]
477    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
478        (**self).read_exact(buf)
479    }
480}
481
482impl<T> Write for RBox<T>
483where
484    T: Write,
485{
486    #[inline]
487    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
488        (**self).write(buf)
489    }
490
491    #[inline]
492    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
493        (**self).write_vectored(bufs)
494    }
495
496    #[inline]
497    fn flush(&mut self) -> io::Result<()> {
498        (**self).flush()
499    }
500
501    #[inline]
502    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
503        (**self).write_all(buf)
504    }
505
506    #[inline]
507    fn write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> io::Result<()> {
508        (**self).write_fmt(fmt)
509    }
510}
511
512impl<T> Seek for RBox<T>
513where
514    T: Seek,
515{
516    #[inline]
517    fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
518        (**self).seek(pos)
519    }
520}
521
522impl<T> BufRead for RBox<T>
523where
524    T: BufRead,
525{
526    #[inline]
527    fn fill_buf(&mut self) -> io::Result<&[u8]> {
528        (**self).fill_buf()
529    }
530
531    #[inline]
532    fn consume(&mut self, amt: usize) {
533        (**self).consume(amt)
534    }
535
536    #[inline]
537    fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
538        (**self).read_until(byte, buf)
539    }
540
541    #[inline]
542    fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
543        (**self).read_line(buf)
544    }
545}
546
547///////////////////////////////////////////////////////////////
548
549impl<T> Hasher for RBox<T>
550where
551    T: Hasher,
552{
553    fn finish(&self) -> u64 {
554        (**self).finish()
555    }
556    fn write(&mut self, bytes: &[u8]) {
557        (**self).write(bytes)
558    }
559    fn write_u8(&mut self, i: u8) {
560        (**self).write_u8(i)
561    }
562    fn write_u16(&mut self, i: u16) {
563        (**self).write_u16(i)
564    }
565    fn write_u32(&mut self, i: u32) {
566        (**self).write_u32(i)
567    }
568    fn write_u64(&mut self, i: u64) {
569        (**self).write_u64(i)
570    }
571    fn write_u128(&mut self, i: u128) {
572        (**self).write_u128(i)
573    }
574    fn write_usize(&mut self, i: usize) {
575        (**self).write_usize(i)
576    }
577    fn write_i8(&mut self, i: i8) {
578        (**self).write_i8(i)
579    }
580    fn write_i16(&mut self, i: i16) {
581        (**self).write_i16(i)
582    }
583    fn write_i32(&mut self, i: i32) {
584        (**self).write_i32(i)
585    }
586    fn write_i64(&mut self, i: i64) {
587        (**self).write_i64(i)
588    }
589    fn write_i128(&mut self, i: i128) {
590        (**self).write_i128(i)
591    }
592    fn write_isize(&mut self, i: isize) {
593        (**self).write_isize(i)
594    }
595}
596
597///////////////////////////////////////////////////////////////
598
599impl<T> Drop for RBox<T> {
600    fn drop(&mut self) {
601        unsafe {
602            let data = self.data();
603            let dstr = RBox::vtable(self).destructor();
604            dstr(data as *mut (), CallReferentDrop::Yes, Deallocate::Yes);
605        }
606    }
607}
608
609///////////////////////////////////////////////////////////////
610
611#[derive(StableAbi)]
612#[repr(C)]
613#[sabi(kind(Prefix))]
614#[sabi(missing_field(panic))]
615pub(crate) struct BoxVtable<T> {
616    type_id: extern "C" fn() -> UTypeId,
617    #[sabi(last_prefix_field)]
618    destructor: unsafe extern "C" fn(*mut (), CallReferentDrop, Deallocate),
619    _marker: NonOwningPhantom<T>,
620}
621
622struct VTableGetter<'a, T>(&'a T);
623
624impl<'a, T: 'a> VTableGetter<'a, T> {
625    const DEFAULT_VTABLE: BoxVtable<T> = BoxVtable {
626        type_id: new_utypeid::<RBox<()>>,
627        destructor: destroy_box::<T>,
628        _marker: NonOwningPhantom::NEW,
629    };
630
631    staticref! {
632        const WM_DEFAULT: WithMetadata<BoxVtable<T>> = WithMetadata::new(Self::DEFAULT_VTABLE);
633    }
634
635    // The VTABLE for this type in this executable/library
636    const LIB_VTABLE: BoxVtable_Ref<T> = BoxVtable_Ref(Self::WM_DEFAULT.as_prefix());
637
638    #[cfg(test)]
639    staticref! {
640        const WM_FOR_TESTING: WithMetadata<BoxVtable<T>> =
641            WithMetadata::new(
642                BoxVtable {
643                    type_id: new_utypeid::<RBox<i32>>,
644                    ..Self::DEFAULT_VTABLE
645                },
646            )
647    }
648
649    #[allow(dead_code)]
650    #[cfg(test)]
651    const LIB_VTABLE_FOR_TESTING: BoxVtable_Ref<T> =
652        BoxVtable_Ref(Self::WM_FOR_TESTING.as_prefix());
653}
654
655unsafe extern "C" fn destroy_box<T>(
656    ptr: *mut (),
657    call_drop: CallReferentDrop,
658    dealloc: Deallocate,
659) {
660    extern_fn_panic_handling! {no_early_return;
661        let ptr = ptr as *mut T;
662        if let CallReferentDrop::Yes = call_drop {
663            unsafe { ptr::drop_in_place(ptr); }
664        }
665        if let Deallocate::Yes = dealloc {
666            unsafe { drop(Box::from_raw(ptr as *mut ManuallyDrop<T>)); }
667        }
668    }
669}
670
671/////////////////////////////////////////////////////////////////