#[cfg(test)]
mod tests {
use std::rc::Rc;
use std::cell::RefCell;
use {CppDeletable, Deleter, CppBox};
struct Struct1 {
value: Rc<RefCell<i32>>,
}
unsafe extern "C" fn struct1_delete(this_ptr: *mut Struct1) {
(*this_ptr).value.borrow_mut().clone_from(&mut 42);
}
impl CppDeletable for Struct1 {
fn deleter() -> Deleter<Self> {
struct1_delete
}
}
#[test]
fn test_drop_calls_deleter() {
let value1 = Rc::new(RefCell::new(10));
let mut object1 = Struct1 {
value: value1.clone()
};
assert!(value1.borrow().clone() == 10);
unsafe {
CppBox::new(&mut object1 as *mut _);
}
assert!(value1.borrow().clone() == 42);
}
}
pub type Deleter<T> = unsafe extern "C" fn(this_ptr: *mut T);
pub trait CppDeletable : Sized {
fn deleter() -> Deleter<Self>;
}
pub struct CppBox<T> {
ptr: *mut T,
deleter: Deleter<T>,
}
impl<T> CppBox<T> {
pub fn as_ptr(&self) -> *const T {
self.ptr
}
pub fn as_mut_ptr(&self) -> *mut T {
self.ptr
}
pub fn unbox(self) -> *mut T {
self.ptr
}
}
impl<T: CppDeletable> CppBox<T> {
pub unsafe fn new(ptr: *mut T) -> CppBox<T> {
CppBox {
ptr: ptr,
deleter: CppDeletable::deleter()
}
}
}
impl<T> AsRef<T> for CppBox<T> {
fn as_ref(&self) -> &T {
unsafe {
&*self.ptr
}
}
}
impl<T> AsMut<T> for CppBox<T> {
fn as_mut(&mut self) -> &mut T {
unsafe {
&mut *self.ptr
}
}
}
impl<T> std::ops::Deref for CppBox<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe {
&*self.ptr
}
}
}
impl<T> std::ops::DerefMut for CppBox<T> {
fn deref_mut(&mut self) -> &mut T {
unsafe {
&mut *self.ptr
}
}
}
impl<T> Drop for CppBox<T> {
fn drop(&mut self) {
if !self.ptr.is_null() {
unsafe {
(self.deleter)(self.ptr);
}
}
}
}
pub struct AsStruct;
pub struct AsBox;