pub trait GstWrapper { type GstType: glib::prelude::ObjectType; fn from_gst(gst: Self::GstType) -> Self; // fn into_gst(self) -> Self::GstType; fn as_gst_ref(&self) -> &Self::GstType; fn from_gst_ref(gst: &Self::GstType) -> &Self; } #[macro_export] macro_rules! wrap_gst { ($name:ident) => { $crate::wrap_gst!($name, gstreamer::$name); }; ($name:ident, $inner:ty) => { $crate::wrap_gst!(core $name, $inner); $crate::wrap_gst!($name, $inner, into_inner); }; ($name:ident, $inner:ty, skip_inner) => { $crate::wrap_gst!(core $name, $inner); }; (core $name:ident, $inner:ty) => { #[derive(Debug, Clone)] #[repr(transparent)] pub struct $name { pub(crate) inner: $inner, } // impl From<$name> for $inner { // fn from(wrapper: $name) -> Self { // wrapper.into_inner() // } // } impl $name { pub fn into_inner(self) -> $inner { self.inner.clone() } } impl $crate::wrapper::GstWrapper for $name { type GstType = $inner; fn from_gst(gst: Self::GstType) -> Self { Self { inner: gst } } // fn into_gst(self) -> Self::GstType { // self.inner.clone() // } fn as_gst_ref(&self) -> &Self::GstType { &self.inner } fn from_gst_ref(gst: &Self::GstType) -> &Self { unsafe { &*(gst as *const Self::GstType as *const Self) } } } impl ChildOf<$name> for $name { fn upcast_ref(&self) -> &$name { self } } }; ($name:ident, $inner:ty, into_inner) => { impl From<$inner> for $name { fn from(inner: $inner) -> Self { Self { inner } } } }; } /// A trait for types that can be upcasted to type T. pub trait ChildOf { fn upcast_ref(&self) -> &T; } #[macro_export] macro_rules! parent_child { ($parent:ty, $child:ty) => { impl ChildOf<$parent> for $child where $child: GstWrapper, $parent: GstWrapper, { fn upcast_ref(&self) -> &$parent { let upcasted = self.inner.upcast_ref::<<$parent as GstWrapper>::GstType>(); unsafe { &*(upcasted as *const <$parent as GstWrapper>::GstType as *const $parent) } } } }; ($parent:ty, $child:ty, downcast) => { impl ChildOf<$parent> for $child where $child: GstWrapper, $parent: GstWrapper, { fn upcast_ref(&self) -> &$parent { let downcasted = self .inner .downcast_ref::<<$parent as GstWrapper>::GstType>() .expect( format!( "BUG: Failed to downcast GStreamer type from child {} to parent {}", stringify!($child), stringify!($parent) ) .as_str(), ); unsafe { &*(downcasted as *const <$parent as GstWrapper>::GstType as *const $parent) } } } }; // ($parent:ty, $child:ty, deref) => { // $crate::parent_child!($parent, $child); // $crate::parent_child!($parent, $child, __deref); // }; // // ($parent:ty, $child:ty, downcast, deref) => { // $crate::parent_child!($parent, $child, downcast); // $crate::parent_child!($parent, $child, __deref); // }; // ($parent:ty, $child:ty, deref, downcast) => { // $crate::parent_child!($parent, $child, downcast); // $crate::parent_child!($parent, $child, __deref); // }; // // ($parent:ty, $child:ty, __deref) => { // impl core::ops::Deref for $child // where // $child: GstWrapper, // $parent: GstWrapper, // { // type Target = $parent; // // fn deref(&self) -> &Self::Target { // self.upcast_ref() // } // } // }; }