Files
jello/gst/src/wrapper.rs
2025-12-25 02:14:56 +05:30

146 lines
4.3 KiB
Rust

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<T> {
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()
// }
// }
// };
}