use std::marker::PhantomData;
use std::ptr;
use translate::*;
use types::{self, Type, StaticType};
use gobject_ffi;
#[allow(raw_pointer_derive)]
#[derive(Debug, PartialEq, Eq)]
pub struct Ref(*mut gobject_ffi::GObject);
impl Ref {
#[inline]
fn add_ref(&self) { unsafe { gobject_ffi::g_object_ref_sink(self.0 as *mut _); } }
#[inline]
fn unref(&self) { unsafe { gobject_ffi::g_object_unref(self.0 as *mut _); } }
#[inline]
pub fn from_glib_none(ptr: *mut gobject_ffi::GObject) -> Ref {
let r = Ref(ptr);
r.add_ref();
r
}
#[inline]
pub fn from_glib_full(ptr: *mut gobject_ffi::GObject) -> Ref {
Ref(ptr)
}
#[inline]
pub fn to_glib_none(&self) -> *mut gobject_ffi::GObject {
self.0
}
#[inline]
pub fn to_glib_full(&self) -> *mut gobject_ffi::GObject {
self.add_ref();
self.0
}
}
impl Clone for Ref {
#[inline]
fn clone(&self) -> Ref {
self.add_ref();
Ref(self.0)
}
}
impl Drop for Ref {
#[inline]
fn drop(&mut self) {
self.unref();
}
}
pub struct VirtualRef<'a, T> (&'a Ref, PhantomData<T>);
impl<'a, T> VirtualRef<'a, T> {
#[inline]
fn new(r: &'a Ref) -> VirtualRef<'a, T> { VirtualRef(r, PhantomData) }
}
impl<'a, T> ToGlibPtr<'a, *mut T> for VirtualRef<'a, T> {
type Storage = &'a Ref;
#[inline]
fn to_glib_none(&self) -> Stash<'a, *mut T, VirtualRef<'a, T>> {
Stash(self.0.to_glib_none() as *mut _, self.0)
}
#[inline]
fn to_glib_full(&self) -> *mut T {
self.0.to_glib_full() as *mut _
}
}
impl<'a, T> ToGlibPtr<'a, *mut T> for Option<&'a VirtualRef<'a, T>> {
type Storage = Option<&'a Ref>;
#[inline]
fn to_glib_none(&self) -> Stash<'a, *mut T, Option<&'a VirtualRef<'a, T>>> {
if let Some(ref s) = *self {
Stash(s.0.to_glib_none() as *mut _, Some(s.0))
}
else {
Stash(ptr::null_mut(), None)
}
}
#[inline]
fn to_glib_full(&self) -> *mut T {
self.as_ref().map_or(ptr::null_mut(), |s| s.0.to_glib_full() as *mut _)
}
}
pub trait Wrapper: StaticType {
type GlibType;
unsafe fn wrap(r: Ref) -> Self;
fn as_ref(&self) -> &Ref;
fn unwrap(self) -> Ref;
}
impl<'a, T, W: Wrapper<GlibType = T>> ToGlibPtr<'a, *mut T> for &'a W {
type Storage = &'a Ref;
#[inline]
fn to_glib_none(&self) -> Stash<'a, *mut T, &'a W> {
Stash(self.as_ref().to_glib_none() as *mut _, self.as_ref())
}
#[inline]
fn to_glib_full(&self) -> *mut T {
self.as_ref().to_glib_full() as *mut _
}
}
impl <T: Wrapper> FromGlibPtr<*mut <T as Wrapper>::GlibType> for T {
#[inline]
unsafe fn from_glib_none(ptr: *mut <T as Wrapper>::GlibType) -> Self {
assert!(!ptr.is_null());
debug_assert!(types::instance_of::<T>(ptr as *const _));
T::wrap(Ref::from_glib_none(ptr as *mut _))
}
#[inline]
unsafe fn from_glib_full(ptr: *mut <T as Wrapper>::GlibType) -> Self {
assert!(!ptr.is_null());
debug_assert!(types::instance_of::<T>(ptr as *const _));
T::wrap(Ref::from_glib_full(ptr as *mut _))
}
}
pub unsafe trait Upcast<T: Wrapper>: Wrapper {
#[inline]
fn upcast(&self) -> VirtualRef<<T as Wrapper>::GlibType> {
debug_assert!(types::instance_of::<T>(self.as_ref().to_glib_none() as *const _));
VirtualRef::<<T as Wrapper>::GlibType>::new(self.as_ref())
}
}
unsafe impl<T: Wrapper> Upcast<T> for T { }
pub trait Downcast<T> {
fn downcast(self) -> Result<T, Self>
where Self: Sized;
fn downcast_unchecked(self) -> T;
}
impl <Super, Sub> Downcast<Sub> for Super
where Super: Wrapper, Sub: Wrapper + Upcast<Super> {
#[inline]
fn downcast(self) -> Result<Sub, Super> {
if types::instance_of::<Sub>(self.as_ref().to_glib_none() as *const _) {
unsafe { Ok(Sub::wrap(self.unwrap())) }
}
else {
Err(self)
}
}
#[inline]
fn downcast_unchecked(self) -> Sub {
assert!(types::instance_of::<Sub>(self.as_ref().to_glib_none() as *const _));
unsafe { Sub::wrap(self.unwrap()) }
}
}
#[derive(Clone)]
pub struct Object(Ref);
impl Wrapper for Object {
type GlibType = gobject_ffi::GObject;
#[inline]
unsafe fn wrap(r: Ref) -> Object { Object(r) }
#[inline]
fn as_ref(&self) -> &Ref { &self.0 }
#[inline]
fn unwrap(self) -> Ref { self.0 }
}
impl StaticType for Object {
#[inline]
fn static_type() -> Type { Type::BaseObject }
}
pub trait ObjectExt {
}
impl<T: Upcast<Object>> ObjectExt for T {
}
#[derive(Debug)]
pub struct GenericObject<T>(Ref, PhantomData<T>);
impl<T> Wrapper for GenericObject<T> where GenericObject<T>: StaticType {
type GlibType = T;
#[inline]
unsafe fn wrap(r: Ref) -> GenericObject<T> { GenericObject(r, PhantomData) }
#[inline]
fn as_ref(&self) -> &Ref { &self.0 }
#[inline]
fn unwrap(self) -> Ref { self.0 }
}
impl<T> Clone for GenericObject<T> {
#[inline]
fn clone(&self) -> GenericObject<T> {
GenericObject(self.0.clone(), PhantomData)
}
}
unsafe impl<T> Upcast<Object> for GenericObject<T> where GenericObject<T>: StaticType { }