wrapped2d 0.3.1

Rust binding for Box2D
macro_rules! _from_ffi {
    { $wrap:ident <= $wrapped:ty } => {
        impl FromFFI<$wrapped> for $wrap {
            unsafe fn from_ffi(ptr: *mut $wrapped) -> $wrap {
                assert!(!ptr.is_null());
                $wrap {
                    ptr: ptr,
                }
            }
        }
    }
}

macro_rules! wrap {
    { $wrapped:ty => custom $wrap:ident } => {
        impl Wrapped<$wrapped> for $wrap {
            unsafe fn ptr(&self) -> *const $wrapped {
                self.ptr as *const $wrapped
            }

            unsafe fn mut_ptr(&mut self) -> *mut $wrapped {
                self.ptr
            }
        }
    };

    { $wrapped:ty => $(#[$attr:meta])* pub $wrap:ident } => {
        $(#[$attr])*
        pub struct $wrap {
            ptr: *mut $wrapped,
        }

        wrap! { $wrapped => custom $wrap }
        _from_ffi! { $wrap <= $wrapped }
    };

    { $wrapped:ty => $(#[$attr:meta])* $wrap:ident } => {
        $(#[$attr])*
        struct $wrap {
            ptr: *mut $wrapped,
        }

        wrap! { $wrapped => custom $wrap }
        _from_ffi! { $wrap <= $wrapped }
    };

    {
        base $base:ty => custom $wrap:ident
        < $as_base:path
    } => {
        impl WrappedBase<$base> for $wrap {
            unsafe fn base_ptr(&self) -> *const $base {
                $as_base(self.ptr) as *const $base
            }

            unsafe fn mut_base_ptr(&mut self) -> *mut $base {
                $as_base(self.ptr)
            }
        }
    };

    {
        $base:ty: $wrapped:ty => custom $wrap:ident
        < $as_base:path
        > $base_as:path
    } => {
        wrap! { $wrapped => custom $wrap }
        wrap! {
            base $base => custom $wrap
            < $as_base
        }
    };

    {
        $base:ty: $wrapped:ty => pub $wrap:ident
        < $as_base:path
        > $base_as:path
    } => {
        wrap! { $wrapped => pub $wrap }
        wrap! {
            base $base => custom $wrap
            < $as_base
        }

        impl FromFFI<$base> for $wrap {
            unsafe fn from_ffi(ptr: *mut $base) -> $wrap {
                assert!(!ptr.is_null());
                $wrap {
                    ptr: $base_as(ptr),
                }
            }
        }
    };
}

use std::mem;
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};

#[doc(hidden)]
pub trait Wrapped<T> {
    unsafe fn ptr(&self) -> *const T;
    unsafe fn mut_ptr(&mut self) -> *mut T;
}

#[doc(hidden)]
pub trait WrappedBase<B> {
    unsafe fn base_ptr(&self) -> *const B;
    unsafe fn mut_base_ptr(&mut self) -> *mut B;
}

#[doc(hidden)]
pub trait FromFFI<T> {
    unsafe fn from_ffi(ptr: *mut T) -> Self where Self: Sized;
}

pub struct WrappedRefMut<'a, T> {
    object: Option<T>,
    phantom: PhantomData<&'a ()>,
}

impl<'a, T> WrappedRefMut<'a, T> {
    #[doc(hidden)]
    pub unsafe fn new(t: T) -> WrappedRefMut<'a, T> {
        WrappedRefMut {
            object: Some(t),
            phantom: PhantomData,
        }
    }
}

impl<'a, T> Deref for WrappedRefMut<'a, T> {
    type Target = T;

    fn deref<'b>(&'b self) -> &'b T {
        self.object.as_ref().unwrap()
    }
}

impl<'a, T> DerefMut for WrappedRefMut<'a, T> {
    fn deref_mut<'b>(&'b mut self) -> &'b mut T {
        self.object.as_mut().unwrap()
    }
}

impl<'a, T> Drop for WrappedRefMut<'a, T> {
    fn drop(&mut self) {
        mem::forget(self.object.take())
    }
}

pub struct WrappedRef<'a, T> {
    object: Option<T>,
    phantom: PhantomData<&'a ()>,
}

impl<'a, T> WrappedRef<'a, T> {
    #[doc(hidden)]
    pub unsafe fn new(t: T) -> WrappedRef<'a, T> {
        WrappedRef {
            object: Some(t),
            phantom: PhantomData,
        }
    }
}

impl<'a, T> Deref for WrappedRef<'a, T> {
    type Target = T;

    fn deref<'b>(&'b self) -> &'b T {
        self.object.as_ref().unwrap()
    }
}

impl<'a, T> Drop for WrappedRef<'a, T> {
    fn drop(&mut self) {
        mem::forget(self.object.take())
    }
}