use gtype::GType;
use types::gpointer;
use util::{box_free, box_from_pointer, box_into_pointer};
use gobject as ffi;
use std::ffi::CString;
use std::mem;
pub trait BoxedType {
fn get_type() -> GType;
unsafe fn from_ptr(ptr: gpointer) -> Self;
unsafe fn into_ptr(self) -> gpointer;
}
pub fn type_of<T>() -> GType where T: BoxedType
{
<T as BoxedType>::get_type()
}
unsafe extern "C" fn box_copy<T>(raw: gpointer) -> gpointer
where T: Clone
{
let boxed: Box<T> = box_from_pointer(raw);
let copy: Box<T> = boxed.clone();
mem::forget(boxed);
box_into_pointer(copy)
}
unsafe fn into_boxed_copy_func(callback: unsafe extern "C" fn(gpointer) -> gpointer)
-> ffi::GBoxedCopyFunc
{
mem::transmute(callback)
}
unsafe fn into_boxed_free_func(callback: unsafe extern "C" fn(gpointer))
-> ffi::GBoxedFreeFunc
{
mem::transmute(callback)
}
pub fn register_box_type<T>(name: &str) -> GType
where T: Clone + Send + 'static
{
let c_name = CString::new(name).unwrap();
let raw = unsafe {
ffi::g_boxed_type_register_static(c_name.as_ptr(),
into_boxed_copy_func(box_copy::<T>),
into_boxed_free_func(box_free::<T>))
};
assert!(raw != 0, "failed to register type \"{}\"", name);
unsafe { GType::from_raw(raw) }
}
pub unsafe trait BoxRegistered : Clone + Send {
fn box_type() -> GType;
}
impl<T> BoxedType for Box<T> where T: BoxRegistered {
fn get_type() -> GType {
<T as BoxRegistered>::box_type()
}
unsafe fn from_ptr(raw: gpointer) -> Box<T> {
box_from_pointer(raw)
}
unsafe fn into_ptr(self) -> gpointer {
box_into_pointer(self)
}
}