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 beforedrop_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§
sourceunsafe fn get_move_ptr(
this: &mut ManuallyDrop<Self>,
) -> MovePtr<'_, Self::PtrTarget>
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]);
sourceunsafe fn drop_allocation(this: &mut ManuallyDrop<Self>)
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§
sourcefn with_move_ptr<F, R>(this: ManuallyDrop<Self>, func: F) -> R
fn with_move_ptr<F, R>(this: ManuallyDrop<Self>, func: F) -> 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]);
sourcefn in_move_ptr<F, R>(self, func: F) -> R
fn in_move_ptr<F, R>(self, func: F) -> 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);