Trait abi_stable::pointer_trait::OwnedPointer

source ·
pub unsafe trait OwnedPointer:
    Sized
    + AsMutPtr
    + GetPointerKind {
    // Required methods
    unsafe fn get_move_ptr(
        this: &mut ManuallyDrop<Self>,
    ) -> MovePtr<'_, Self::PtrTarget>;
    unsafe fn drop_allocation(this: &mut ManuallyDrop<Self>);

    // Provided methods
    fn with_move_ptr<F, R>(this: ManuallyDrop<Self>, func: F) -> R
       where F: FnOnce(MovePtr<'_, Self::PtrTarget>) -> R { ... }
    fn in_move_ptr<F, R>(self, func: F) -> R
       where F: FnOnce(MovePtr<'_, Self::PtrTarget>) -> R { ... }
}
Expand description

For owned pointers, allows extracting their contents separate from deallocating them.

§Safety

Implementors must:

  • Implement this trait such that get_move_ptr can be called before drop_allocation.

  • Not override with_move_ptr

  • Not override in_move_ptr

§Example

Implementing this trait for a Box-like type.

use abi_stable::{
    pointer_trait::{
        CallReferentDrop, PK_SmartPointer,
        GetPointerKind, AsPtr, AsMutPtr, OwnedPointer,
    },
    sabi_types::MovePtr,
    std_types::RString,
    StableAbi,
};

use std::{
    alloc::{self, Layout},
    marker::PhantomData,
    mem::ManuallyDrop,
};


fn main(){
    let this = BoxLike::new(RString::from("12345"));
     
    let string: RString = this.in_move_ptr(|x: MovePtr<'_, RString>|{
        MovePtr::into_inner(x)
    });

    assert_eq!(string, "12345");
}


#[repr(C)]
#[derive(StableAbi)]
pub struct BoxLike<T> {
    ptr: *mut T,
     
    dropper: unsafe extern "C" fn(*mut T, CallReferentDrop),

    _marker: PhantomData<T>,
}


impl<T> BoxLike<T>{
    pub fn new(value:T)->Self{
        let box_ = Box::new(value);
         
        Self{
            ptr: Box::into_raw(box_),
            dropper: destroy_box::<T>,
            _marker:PhantomData,
        }
    }
}

unsafe impl<T> GetPointerKind for BoxLike<T> {
    type PtrTarget = T;
    type Kind = PK_SmartPointer;
}

unsafe impl<T> AsPtr for BoxLike<T> {
    fn as_ptr(&self) -> *const T {
        self.ptr
    }
}

unsafe impl<T> AsMutPtr for BoxLike<T> {
    fn as_mut_ptr(&mut self) -> *mut T {
        self.ptr
    }
}

unsafe impl<T> OwnedPointer for BoxLike<T> {
    unsafe fn get_move_ptr(this: &mut ManuallyDrop<Self>) -> MovePtr<'_,Self::PtrTarget>{
        MovePtr::from_raw(this.ptr)
    }
     
    unsafe fn drop_allocation(this: &mut ManuallyDrop<Self>) {
        unsafe{
            (this.dropper)(this.ptr, CallReferentDrop::No)
        }
    }
}

impl<T> Drop for BoxLike<T>{
    fn drop(&mut self){
        unsafe{
            (self.dropper)(self.ptr, CallReferentDrop::Yes)
        }
    }
}

unsafe extern "C" fn destroy_box<T>(v: *mut T, call_drop: CallReferentDrop) {
    abi_stable::extern_fn_panic_handling! {
        let mut box_ = Box::from_raw(v as *mut ManuallyDrop<T>);
        if call_drop == CallReferentDrop::Yes {
            ManuallyDrop::drop(&mut *box_);
        }
        drop(box_);
    }
}

Required Methods§

source

unsafe fn get_move_ptr( this: &mut ManuallyDrop<Self>, ) -> MovePtr<'_, Self::PtrTarget>

Gets a move pointer to the contents of this pointer.

§Safety

This function logically moves the owned contents out of this pointer, the only safe thing that can be done with the pointer afterwads is to call OwnedPointer::drop_allocation.

§Example
use abi_stable::{
    pointer_trait::OwnedPointer,
    sabi_types::MovePtr,
    std_types::{RBox, RVec},
    rvec, StableAbi,
};

use std::mem::ManuallyDrop;

let mut this = ManuallyDrop::new(RBox::new(rvec![3, 5, 8]));

// safety:
// this is only called once,
// and the `RVec` is never accessed again through the `RBox`.
let moveptr: MovePtr<'_, RVec<u8>> = unsafe { OwnedPointer::get_move_ptr(&mut this) };

let vector: RVec<u8> = MovePtr::into_inner(moveptr);

// safety: this is only called once, after all uses of `this`
unsafe{ OwnedPointer::drop_allocation(&mut this); }

assert_eq!(vector[..], [3, 5, 8]);
source

unsafe fn drop_allocation(this: &mut ManuallyDrop<Self>)

Deallocates the pointer without dropping its owned contents.

Note that if Self::get_move_ptr has not been called this will leak the values owned by the referent of the pointer.

§Safety

This method must only be called once, since it’ll deallocate whatever memory this pointer owns.

§Example

get_move_ptr has an example that uses both that function and this one.

Provided Methods§

source

fn with_move_ptr<F, R>(this: ManuallyDrop<Self>, func: F) -> R
where F: FnOnce(MovePtr<'_, Self::PtrTarget>) -> R,

Runs a callback with the contents of this pointer, and then deallocates it.

The pointer is deallocated even in the case that func panics

§Example
use abi_stable::{
    pointer_trait::OwnedPointer,
    sabi_types::MovePtr,
    std_types::{RBox, RCow, RCowSlice},
};

use std::mem::ManuallyDrop;

let this = ManuallyDrop::new(RBox::new(RCow::from_slice(&[13, 21, 34])));

let cow: RCowSlice<'static, u8> = OwnedPointer::with_move_ptr(this, |moveptr|{
    MovePtr::into_inner(moveptr)
});

assert_eq!(cow[..], [13, 21, 34]);
source

fn in_move_ptr<F, R>(self, func: F) -> R
where F: FnOnce(MovePtr<'_, Self::PtrTarget>) -> R,

Runs a callback with the contents of this pointer, and then deallocates it.

The pointer is deallocated even in the case that func panics

§Example
use abi_stable::{
    pointer_trait::OwnedPointer,
    sabi_types::MovePtr,
    std_types::RBox,
};

let this = RBox::new(Foo(41));

let cow: Foo = this.in_move_ptr(|moveptr| MovePtr::into_inner(moveptr) );

assert_eq!(cow, Foo(41));


#[derive(Debug, PartialEq)]
struct Foo(u32);

Object Safety§

This trait is not object safe.

Implementors§

source§

impl<T> OwnedPointer for RBox<T>

source§

impl<T, Inline> OwnedPointer for RSmallBox<T, Inline>