pub unsafe trait IsA<T>: 'static {}
pub unsafe trait Implements<I> {}
pub unsafe trait RawWrapper: Sized {
type Ffi;
fn as_raw(&self) -> *mut Self::Ffi;
unsafe fn from_raw_full(ptr: *mut Self::Ffi) -> Option<Self>;
unsafe fn from_raw_none(ptr: *mut Self::Ffi) -> Option<Self>;
fn static_type() -> glib::types::Type;
}
pub trait Cast: Sized {
fn upcast<T>(self) -> T
where
Self: IsA<T>,
T: RawWrapper,
Self: RawWrapper,
{
unsafe {
let ptr = self.as_raw() as *mut T::Ffi;
std::mem::forget(self);
T::from_raw_full(ptr).expect("non-null instance during upcast")
}
}
fn upcast_ref<T>(&self) -> &T
where
Self: AsRef<T>,
{
self.as_ref()
}
fn downcast<T>(self) -> Result<T, Self>
where
Self: RawWrapper,
T: RawWrapper + IsA<Self>,
{
if self.is::<T>() {
unsafe {
let ptr = self.as_raw() as *mut T::Ffi;
std::mem::forget(self);
Ok(T::from_raw_full(ptr).expect("non-null instance during downcast"))
}
} else {
Err(self)
}
}
fn is<T>(&self) -> bool
where
Self: RawWrapper,
T: RawWrapper,
{
unsafe {
let instance = self.as_raw() as *mut gobject_sys::GTypeInstance;
if instance.is_null() {
return false;
}
let want = glib::translate::IntoGlib::into_glib(T::static_type());
gobject_sys::g_type_check_instance_is_a(instance, want) != glib_sys::GFALSE
}
}
}
impl<W: RawWrapper> Cast for W {}
pub(crate) unsafe fn opt_string(ptr: *const std::os::raw::c_char) -> Option<String> {
if ptr.is_null() {
None
} else {
Some(std::ffi::CStr::from_ptr(ptr).to_string_lossy().into_owned())
}
}
pub(crate) unsafe fn take_string(ptr: *mut std::os::raw::c_char) -> Option<String> {
if ptr.is_null() {
return None;
}
let s = std::ffi::CStr::from_ptr(ptr).to_string_lossy().into_owned();
glib_sys::g_free(ptr as glib_sys::gpointer);
Some(s)
}
#[doc(hidden)]
pub use ::std::ptr::NonNull as __NonNull;
#[macro_export]
#[doc(hidden)]
macro_rules! ffi_wrapper {
(
$(#[$meta:meta])*
pub struct $name:ident(ptr: *mut $ffi:path) {
root_ref: $root_ref:ident,
root_unref: $root_unref:ident,
get_type: $get_type:ident,
}
) => {
$(#[$meta])*
#[repr(transparent)]
pub struct $name($crate::object::__NonNull<$ffi>);
unsafe impl $crate::object::RawWrapper for $name {
type Ffi = $ffi;
#[inline]
fn as_raw(&self) -> *mut $ffi {
self.0.as_ptr()
}
unsafe fn from_raw_full(ptr: *mut $ffi) -> Option<Self> {
$crate::object::__NonNull::new(ptr).map(Self)
}
unsafe fn from_raw_none(ptr: *mut $ffi) -> Option<Self> {
let nn = $crate::object::__NonNull::new(ptr)?;
ffi::$root_ref(ptr as ffi::gpointer);
Some(Self(nn))
}
fn static_type() -> glib::types::Type {
unsafe { glib::translate::from_glib(ffi::$get_type()) }
}
}
impl Clone for $name {
fn clone(&self) -> Self {
unsafe {
ffi::$root_ref(self.0.as_ptr() as ffi::gpointer);
Self(self.0)
}
}
}
impl Drop for $name {
fn drop(&mut self) {
unsafe { ffi::$root_unref(self.0.as_ptr() as ffi::gpointer) }
}
}
impl ::std::fmt::Debug for $name {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
f.debug_tuple(stringify!($name))
.field(&self.0.as_ptr())
.finish()
}
}
};
}