From 7086a754bea4de14e970318eafdbb90c260d6855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 27 May 2020 13:07:32 +0300 Subject: [PATCH] Add various glib::Value trait impls for borrowed versions of types For SDPMessageRef, StructureRef and CapsFeatureRef this involves the conversion from and to a glib::Value. Specifically this means that e.g. a StructureRef can be retrieved from a glib::Value via borrowing, i.e. without creating a copy of the structure first. For all mini objects only retrieval from a glib::Value is implemented as the other direction would allow to get multiple immutable references from a mutable reference without borrowing, which is not allowed and would make it possible to observe a mini object changing while having an immutable reference to it. --- gstreamer-sdp/src/sdp_message.rs | 39 +++++++++++++++++++++++ gstreamer/src/caps_features.rs | 54 ++++++++++++++++++++++++++------ gstreamer/src/miniobject.rs | 16 ++++++++++ gstreamer/src/structure.rs | 54 ++++++++++++++++++++++++++------ 4 files changed, 143 insertions(+), 20 deletions(-) diff --git a/gstreamer-sdp/src/sdp_message.rs b/gstreamer-sdp/src/sdp_message.rs index 8720229ef..a92b3961e 100644 --- a/gstreamer-sdp/src/sdp_message.rs +++ b/gstreamer-sdp/src/sdp_message.rs @@ -928,6 +928,45 @@ impl ToOwned for SDPMessageRef { } } +impl glib::types::StaticType for SDPMessageRef { + fn static_type() -> glib::types::Type { + unsafe { from_glib(gst_sdp_sys::gst_sdp_message_get_type()) } + } +} + +impl<'a> glib::value::FromValueOptional<'a> for &'a SDPMessageRef { + unsafe fn from_value_optional(v: &'a glib::Value) -> Option { + let ptr = gobject_sys::g_value_get_boxed(v.to_glib_none().0); + if ptr.is_null() { + None + } else { + Some(&*(ptr as *const SDPMessageRef)) + } + } +} + +impl glib::value::SetValue for SDPMessageRef { + unsafe fn set_value(v: &mut glib::Value, s: &Self) { + gobject_sys::g_value_set_boxed( + v.to_glib_none_mut().0, + s as *const SDPMessageRef as glib_sys::gpointer, + ); + } +} + +impl glib::value::SetValueOptional for SDPMessageRef { + unsafe fn set_value_optional(v: &mut glib::Value, s: Option<&Self>) { + if let Some(s) = s { + gobject_sys::g_value_set_boxed( + v.to_glib_none_mut().0, + s as *const SDPMessageRef as glib_sys::gpointer, + ); + } else { + gobject_sys::g_value_set_boxed(v.to_glib_none_mut().0, ptr::null_mut()); + } + } +} + macro_rules! define_iter( ($name:ident, $typ:ty, $get_item:expr, $get_len:expr) => { #[derive(Debug)] diff --git a/gstreamer/src/caps_features.rs b/gstreamer/src/caps_features.rs index d57a2a98f..5348b4424 100644 --- a/gstreamer/src/caps_features.rs +++ b/gstreamer/src/caps_features.rs @@ -19,8 +19,8 @@ use once_cell::sync::Lazy; use glib; use glib::translate::{ - from_glib, from_glib_full, from_glib_none, FromGlibPtrFull, FromGlibPtrNone, GlibPtrDefault, - Stash, StashMut, ToGlibPtr, ToGlibPtrMut, + from_glib, from_glib_full, FromGlibPtrFull, FromGlibPtrNone, GlibPtrDefault, Stash, StashMut, + ToGlibPtr, ToGlibPtrMut, }; use glib_sys::gpointer; use gobject_sys; @@ -247,24 +247,23 @@ impl FromGlibPtrFull<*mut gst_sys::GstCapsFeatures> for CapsFeatures { impl<'a> glib::value::FromValueOptional<'a> for CapsFeatures { unsafe fn from_value_optional(v: &'a glib::Value) -> Option { - let ptr = gobject_sys::g_value_get_boxed(v.to_glib_none().0); - from_glib_none(ptr as *const gst_sys::GstCapsFeatures) + <&'a CapsFeaturesRef as glib::value::FromValueOptional<'a>>::from_value_optional(v) + .map(ToOwned::to_owned) } } impl glib::value::SetValue for CapsFeatures { unsafe fn set_value(v: &mut glib::Value, s: &Self) { - gobject_sys::g_value_set_boxed(v.to_glib_none_mut().0, s.0.as_ptr() as gpointer); + ::set_value(v, s.as_ref()) } } impl glib::value::SetValueOptional for CapsFeatures { unsafe fn set_value_optional(v: &mut glib::Value, s: Option<&Self>) { - if let Some(s) = s { - gobject_sys::g_value_set_boxed(v.to_glib_none_mut().0, s.as_ptr() as gpointer); - } else { - gobject_sys::g_value_set_boxed(v.to_glib_none_mut().0, ptr::null_mut()); - } + ::set_value_optional( + v, + s.map(|s| s.as_ref()), + ) } } @@ -359,6 +358,41 @@ impl CapsFeaturesRef { } } +impl glib::types::StaticType for CapsFeaturesRef { + fn static_type() -> glib::types::Type { + unsafe { from_glib(gst_sys::gst_structure_get_type()) } + } +} + +impl<'a> glib::value::FromValueOptional<'a> for &'a CapsFeaturesRef { + unsafe fn from_value_optional(v: &'a glib::Value) -> Option { + let ptr = gobject_sys::g_value_get_boxed(v.to_glib_none().0); + if ptr.is_null() { + None + } else { + Some(CapsFeaturesRef::from_glib_borrow( + ptr as *const gst_sys::GstCapsFeatures, + )) + } + } +} + +impl glib::value::SetValue for CapsFeaturesRef { + unsafe fn set_value(v: &mut glib::Value, s: &Self) { + gobject_sys::g_value_set_boxed(v.to_glib_none_mut().0, s.as_ptr() as gpointer); + } +} + +impl glib::value::SetValueOptional for CapsFeaturesRef { + unsafe fn set_value_optional(v: &mut glib::Value, s: Option<&Self>) { + if let Some(s) = s { + gobject_sys::g_value_set_boxed(v.to_glib_none_mut().0, s.as_ptr() as gpointer); + } else { + gobject_sys::g_value_set_boxed(v.to_glib_none_mut().0, ptr::null_mut()); + } + } +} + #[derive(Debug)] pub struct Iter<'a> { caps_features: &'a CapsFeaturesRef, diff --git a/gstreamer/src/miniobject.rs b/gstreamer/src/miniobject.rs index 638826e85..61594bfda 100644 --- a/gstreamer/src/miniobject.rs +++ b/gstreamer/src/miniobject.rs @@ -851,6 +851,22 @@ macro_rules! gst_define_mini_object_wrapper( } } + impl<'a> $crate::glib::value::FromValueOptional<'a> + for &'a $ref_name + { + unsafe fn from_value_optional(v: &'a glib::Value) -> Option { + let ptr = gobject_sys::g_value_get_boxed($crate::glib::translate::ToGlibPtr::to_glib_none(v).0); + if ptr.is_null() { + None + } else { + Some(&*(ptr as *const $ref_name)) + } + } + } + + // Can't have SetValue/SetValueOptional impls as otherwise one could use it to get + // immutable references from a mutable reference without borrowing via the value + impl ToOwned for $ref_name { type Owned = $name; diff --git a/gstreamer/src/structure.rs b/gstreamer/src/structure.rs index fe58cc665..a2f839f32 100644 --- a/gstreamer/src/structure.rs +++ b/gstreamer/src/structure.rs @@ -21,8 +21,8 @@ use Fraction; use glib; use glib::translate::{ - from_glib, from_glib_full, from_glib_none, FromGlibPtrFull, FromGlibPtrNone, GlibPtrDefault, - Stash, StashMut, ToGlib, ToGlibPtr, ToGlibPtrMut, + from_glib, from_glib_full, FromGlibPtrFull, FromGlibPtrNone, GlibPtrDefault, Stash, StashMut, + ToGlib, ToGlibPtr, ToGlibPtrMut, }; use glib::value::{FromValue, FromValueOptional, SendValue, ToSendValue}; use glib_sys::gpointer; @@ -309,24 +309,23 @@ impl FromGlibPtrFull<*mut gst_sys::GstStructure> for Structure { impl<'a> glib::value::FromValueOptional<'a> for Structure { unsafe fn from_value_optional(v: &'a glib::Value) -> Option { - let ptr = gobject_sys::g_value_get_boxed(v.to_glib_none().0); - from_glib_none(ptr as *const gst_sys::GstStructure) + <&'a StructureRef as glib::value::FromValueOptional<'a>>::from_value_optional(v) + .map(ToOwned::to_owned) } } impl glib::value::SetValue for Structure { unsafe fn set_value(v: &mut glib::Value, s: &Self) { - gobject_sys::g_value_set_boxed(v.to_glib_none_mut().0, s.0.as_ptr() as gpointer); + ::set_value(v, s.as_ref()) } } impl glib::value::SetValueOptional for Structure { unsafe fn set_value_optional(v: &mut glib::Value, s: Option<&Self>) { - if let Some(s) = s { - gobject_sys::g_value_set_boxed(v.to_glib_none_mut().0, s.as_ptr() as gpointer); - } else { - gobject_sys::g_value_set_boxed(v.to_glib_none_mut().0, ptr::null_mut()); - } + ::set_value_optional( + v, + s.map(|s| s.as_ref()), + ) } } @@ -599,6 +598,41 @@ impl PartialEq for StructureRef { impl Eq for StructureRef {} +impl glib::types::StaticType for StructureRef { + fn static_type() -> glib::types::Type { + unsafe { from_glib(gst_sys::gst_structure_get_type()) } + } +} + +impl<'a> glib::value::FromValueOptional<'a> for &'a StructureRef { + unsafe fn from_value_optional(v: &'a glib::Value) -> Option { + let ptr = gobject_sys::g_value_get_boxed(v.to_glib_none().0); + if ptr.is_null() { + None + } else { + Some(StructureRef::from_glib_borrow( + ptr as *const gst_sys::GstStructure, + )) + } + } +} + +impl glib::value::SetValue for StructureRef { + unsafe fn set_value(v: &mut glib::Value, s: &Self) { + gobject_sys::g_value_set_boxed(v.to_glib_none_mut().0, s.as_ptr() as gpointer); + } +} + +impl glib::value::SetValueOptional for StructureRef { + unsafe fn set_value_optional(v: &mut glib::Value, s: Option<&Self>) { + if let Some(s) = s { + gobject_sys::g_value_set_boxed(v.to_glib_none_mut().0, s.as_ptr() as gpointer); + } else { + gobject_sys::g_value_set_boxed(v.to_glib_none_mut().0, ptr::null_mut()); + } + } +} + #[derive(Debug)] pub struct FieldIterator<'a> { structure: &'a StructureRef,