From ae4dd88f3d51183c8a1deff21ef7b6697b0abb09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sat, 26 Nov 2022 13:56:53 +0200 Subject: [PATCH] Update for GLib `Into` changes Part-of: --- gstreamer-audio/src/audio_format_info.rs | 8 + gstreamer-audio/src/audio_info.rs | 8 + gstreamer-audio/src/caps.rs | 3 +- gstreamer-pbutils/src/element_properties.rs | 6 +- gstreamer-video/src/caps.rs | 3 +- gstreamer-video/src/video_info.rs | 15 ++ gstreamer-video/src/video_time_code.rs | 8 + .../src/video_time_code_interval.rs | 8 + gstreamer/src/caps.rs | 2 +- gstreamer/src/caps_features.rs | 14 ++ gstreamer/src/child_proxy.rs | 4 +- gstreamer/src/date_time_serde.rs | 7 + gstreamer/src/element_factory.rs | 4 +- gstreamer/src/enums.rs | 7 + gstreamer/src/format/clock_time.rs | 6 + gstreamer/src/gobject.rs | 2 +- gstreamer/src/iterator.rs | 19 +- gstreamer/src/memory.rs | 14 ++ gstreamer/src/miniobject.rs | 14 ++ gstreamer/src/segment.rs | 9 +- gstreamer/src/static_caps.rs | 7 + gstreamer/src/static_pad_template.rs | 7 + gstreamer/src/structure.rs | 24 ++- gstreamer/src/tags.rs | 15 +- gstreamer/src/value.rs | 194 ++++++++++++------ gstreamer/src/value_serde.rs | 138 ++++++++----- 26 files changed, 393 insertions(+), 153 deletions(-) diff --git a/gstreamer-audio/src/audio_format_info.rs b/gstreamer-audio/src/audio_format_info.rs index 43680adce..902905071 100644 --- a/gstreamer-audio/src/audio_format_info.rs +++ b/gstreamer-audio/src/audio_format_info.rs @@ -365,6 +365,14 @@ impl glib::value::ToValueOptional for AudioFormatInfo { } } +#[doc(hidden)] +impl From for glib::Value { + fn from(v: AudioFormatInfo) -> glib::Value { + skip_assert_initialized!(); + glib::value::ToValue::to_value(&v) + } +} + #[doc(hidden)] impl glib::translate::GlibPtrDefault for AudioFormatInfo { type GlibType = *mut ffi::GstAudioFormatInfo; diff --git a/gstreamer-audio/src/audio_info.rs b/gstreamer-audio/src/audio_info.rs index f29256d95..57cf26a19 100644 --- a/gstreamer-audio/src/audio_info.rs +++ b/gstreamer-audio/src/audio_info.rs @@ -361,6 +361,14 @@ impl glib::value::ToValue for AudioInfo { } } +#[doc(hidden)] +impl From for glib::Value { + fn from(v: AudioInfo) -> glib::Value { + skip_assert_initialized!(); + glib::value::ToValue::to_value(&v) + } +} + #[doc(hidden)] impl glib::value::ToValueOptional for AudioInfo { fn to_value_optional(s: Option<&Self>) -> glib::Value { diff --git a/gstreamer-audio/src/caps.rs b/gstreamer-audio/src/caps.rs index ea89603a1..a8c866b04 100644 --- a/gstreamer-audio/src/caps.rs +++ b/gstreamer-audio/src/caps.rs @@ -1,5 +1,4 @@ use crate::{AudioFormat, AudioLayout}; -use gst::prelude::*; use gst::Caps; use std::ops::Bound::*; use std::ops::RangeBounds; @@ -134,7 +133,7 @@ impl AudioCapsBuilder { } } - pub fn field(self, name: &str, value: V) -> Self { + pub fn field(self, name: &str, value: impl Into + Send) -> Self { Self { builder: self.builder.field(name, value), } diff --git a/gstreamer-pbutils/src/element_properties.rs b/gstreamer-pbutils/src/element_properties.rs index 82f01c0b3..bf4c68c53 100644 --- a/gstreamer-pbutils/src/element_properties.rs +++ b/gstreamer-pbutils/src/element_properties.rs @@ -136,7 +136,7 @@ pub struct ElementPropertiesGeneralBuilder { impl ElementPropertiesGeneralBuilder { pub fn field(mut self, property_name: &str, value: T) -> Self where - T: ToSendValue + Sync, + T: Into + Send, { self.structure.set(property_name, value); self @@ -167,7 +167,7 @@ impl ElementPropertiesMapBuilder { pub fn build(self) -> ElementProperties { ElementProperties( gst::Structure::builder("element-properties-map") - .field("map", gst::List::from(self.map)) + .field("map", gst::List::new(self.map)) .build(), ) } @@ -239,7 +239,7 @@ pub struct ElementPropertiesMapItemBuilder { impl ElementPropertiesMapItemBuilder { pub fn field(mut self, property_name: &str, value: T) -> Self where - T: ToSendValue + Sync, + T: Into + Send, { self.structure.set(property_name, value); self diff --git a/gstreamer-video/src/caps.rs b/gstreamer-video/src/caps.rs index 33edfffce..d23d57d0e 100644 --- a/gstreamer-video/src/caps.rs +++ b/gstreamer-video/src/caps.rs @@ -1,5 +1,4 @@ use crate::VideoFormat; -use gst::prelude::*; use gst::Caps; use std::ops::Bound::*; use std::ops::RangeBounds; @@ -176,7 +175,7 @@ impl VideoCapsBuilder { } } - pub fn field(self, name: &str, value: V) -> Self { + pub fn field(self, name: &str, value: impl Into + Send) -> Self { Self { builder: self.builder.field(name, value), } diff --git a/gstreamer-video/src/video_info.rs b/gstreamer-video/src/video_info.rs index cacebbaee..e1efa3815 100644 --- a/gstreamer-video/src/video_info.rs +++ b/gstreamer-video/src/video_info.rs @@ -83,6 +83,13 @@ impl ToValue for VideoColorRange { } } +impl From for glib::Value { + fn from(v: VideoColorRange) -> glib::Value { + skip_assert_initialized!(); + glib::value::ToValue::to_value(&v) + } +} + #[doc(alias = "GstVideoColorimetry")] #[derive(Copy, Clone)] pub struct VideoColorimetry(ffi::GstVideoColorimetry); @@ -892,6 +899,14 @@ impl glib::value::ToValueOptional for VideoInfo { } } +#[doc(hidden)] +impl From for glib::Value { + fn from(v: VideoInfo) -> glib::Value { + skip_assert_initialized!(); + glib::value::ToValue::to_value(&v) + } +} + #[doc(hidden)] impl glib::translate::Uninitialized for VideoInfo { unsafe fn uninitialized() -> Self { diff --git a/gstreamer-video/src/video_time_code.rs b/gstreamer-video/src/video_time_code.rs index 08d2c9f17..31c265668 100644 --- a/gstreamer-video/src/video_time_code.rs +++ b/gstreamer-video/src/video_time_code.rs @@ -485,6 +485,14 @@ macro_rules! generic_impl { value } } + + #[doc(hidden)] + impl From<$name> for glib::Value { + fn from(v: $name) -> glib::Value { + skip_assert_initialized!(); + glib::value::ToValue::to_value(&v) + } + } }; } diff --git a/gstreamer-video/src/video_time_code_interval.rs b/gstreamer-video/src/video_time_code_interval.rs index 0f88497ca..e0010da40 100644 --- a/gstreamer-video/src/video_time_code_interval.rs +++ b/gstreamer-video/src/video_time_code_interval.rs @@ -255,3 +255,11 @@ impl glib::value::ToValueOptional for VideoTimeCodeInterval { value } } + +#[doc(hidden)] +impl From for glib::Value { + fn from(v: VideoTimeCodeInterval) -> glib::Value { + skip_assert_initialized!(); + glib::value::ToValue::to_value(&v) + } +} diff --git a/gstreamer/src/caps.rs b/gstreamer/src/caps.rs index 022d73d2e..bfb0d6f71 100644 --- a/gstreamer/src/caps.rs +++ b/gstreamer/src/caps.rs @@ -953,7 +953,7 @@ impl Builder { } impl Builder { - pub fn field(mut self, name: &str, value: V) -> Self { + pub fn field(mut self, name: &str, value: impl Into + Send) -> Self { self.s.set(name, value); self } diff --git a/gstreamer/src/caps_features.rs b/gstreamer/src/caps_features.rs index 880028f6c..6d4a7f752 100644 --- a/gstreamer/src/caps_features.rs +++ b/gstreamer/src/caps_features.rs @@ -281,6 +281,20 @@ impl glib::value::ToValueOptional for CapsFeatures { } } +impl From for glib::Value { + fn from(v: CapsFeatures) -> glib::Value { + skip_assert_initialized!(); + let mut value = glib::Value::for_value_type::(); + unsafe { + glib::gobject_ffi::g_value_take_boxed( + value.to_glib_none_mut().0, + IntoGlibPtr::<*mut ffi::GstCapsFeatures>::into_glib_ptr(v) as *mut _, + ) + } + value + } +} + impl GlibPtrDefault for CapsFeatures { type GlibType = *mut ffi::GstCapsFeatures; } diff --git a/gstreamer/src/child_proxy.rs b/gstreamer/src/child_proxy.rs index 44c3c82e0..e1738b89a 100644 --- a/gstreamer/src/child_proxy.rs +++ b/gstreamer/src/child_proxy.rs @@ -17,7 +17,7 @@ pub trait ChildProxyExtManual: 'static { fn child_property_value(&self, name: &str) -> glib::Value; #[doc(alias = "gst_child_proxy_set")] - fn set_child_property(&self, name: &str, value: V); + fn set_child_property(&self, name: &str, value: impl Into); #[doc(alias = "gst_child_proxy_set_property")] fn set_child_property_from_value(&self, name: &str, value: &glib::Value); } @@ -54,7 +54,7 @@ impl> ChildProxyExtManual for O { } #[track_caller] - fn set_child_property(&self, name: &str, value: V) { + fn set_child_property(&self, name: &str, value: impl Into) { let (child, pspec) = self.lookup(name).unwrap(); child.set_property(pspec.name(), value) } diff --git a/gstreamer/src/date_time_serde.rs b/gstreamer/src/date_time_serde.rs index 5b8b8f4ac..2598c3b97 100644 --- a/gstreamer/src/date_time_serde.rs +++ b/gstreamer/src/date_time_serde.rs @@ -56,6 +56,13 @@ impl StaticType for Date { } } +impl From for glib::Value { + fn from(v: Date) -> glib::Value { + skip_assert_initialized!(); + v.0.into() + } +} + impl Serialize for Date { fn serialize(&self, serializer: S) -> Result { DateTimeVariants::YMD( diff --git a/gstreamer/src/element_factory.rs b/gstreamer/src/element_factory.rs index f34a15417..f546395db 100644 --- a/gstreamer/src/element_factory.rs +++ b/gstreamer/src/element_factory.rs @@ -251,12 +251,12 @@ impl<'a> ElementBuilder<'a> { // rustdoc-stripper-ignore-next /// Set property `name` to the given value `value`. - pub fn property(self, name: &'a str, value: T) -> Self { + pub fn property(self, name: &'a str, value: impl Into + 'a) -> Self { Self { name_or_factory: self.name_or_factory, properties: { let mut properties = self.properties; - properties.push((name, ValueOrStr::Value(value.to_value()))); + properties.push((name, ValueOrStr::Value(value.into()))); properties }, } diff --git a/gstreamer/src/enums.rs b/gstreamer/src/enums.rs index 447d76d7a..48194ba41 100644 --- a/gstreamer/src/enums.rs +++ b/gstreamer/src/enums.rs @@ -643,6 +643,13 @@ impl ToValue for MessageType { } } +impl From for glib::Value { + fn from(v: MessageType) -> glib::Value { + skip_assert_initialized!(); + ToValue::to_value(&v) + } +} + impl State { #[must_use] pub fn next(self, pending: Self) -> Self { diff --git a/gstreamer/src/format/clock_time.rs b/gstreamer/src/format/clock_time.rs index 86b4a59eb..cd065da2f 100644 --- a/gstreamer/src/format/clock_time.rs +++ b/gstreamer/src/format/clock_time.rs @@ -323,6 +323,12 @@ impl glib::value::ToValueOptional for ClockTime { } } +impl From for glib::Value { + fn from(v: ClockTime) -> glib::Value { + glib::value::ToValue::to_value(&v) + } +} + #[doc(hidden)] impl glib::StaticType for ClockTime { fn static_type() -> glib::Type { diff --git a/gstreamer/src/gobject.rs b/gstreamer/src/gobject.rs index be2645445..85dd04099 100644 --- a/gstreamer/src/gobject.rs +++ b/gstreamer/src/gobject.rs @@ -44,7 +44,7 @@ impl> GObjectExtManualGst for O { } }; - self.set_property_from_value(name, &value) + self.set_property(name, value) } } diff --git a/gstreamer/src/iterator.rs b/gstreamer/src/iterator.rs index 6f90dad9c..1605b9df3 100644 --- a/gstreamer/src/iterator.rs +++ b/gstreamer/src/iterator.rs @@ -206,10 +206,7 @@ where } } -impl IntoGlibPtr<*mut ffi::GstIterator> for Iterator -where - for<'a> T: FromValue<'a> + 'static, -{ +impl IntoGlibPtr<*mut ffi::GstIterator> for Iterator { unsafe fn into_glib_ptr(self) -> *mut ffi::GstIterator { let s = mem::ManuallyDrop::new(self); let it = s.to_glib_none().0; @@ -552,6 +549,20 @@ impl glib::value::ToValueOptional for Iterator { } } +impl From> for glib::Value { + fn from(v: Iterator) -> glib::Value { + skip_assert_initialized!(); + let mut value = glib::Value::for_value_type::>(); + unsafe { + glib::gobject_ffi::g_value_take_boxed( + value.to_glib_none_mut().0, + v.into_glib_ptr() as *mut _, + ) + } + value + } +} + #[doc(hidden)] impl glib::translate::GlibPtrDefault for Iterator { type GlibType = *mut ffi::GstIterator; diff --git a/gstreamer/src/memory.rs b/gstreamer/src/memory.rs index 714189ac1..aae275d0c 100644 --- a/gstreamer/src/memory.rs +++ b/gstreamer/src/memory.rs @@ -820,6 +820,20 @@ macro_rules! memory_object_wrapper { } } + impl From<$name> for $crate::glib::Value { + fn from(v: $name) -> $crate::glib::Value { + skip_assert_initialized!(); + let mut value = $crate::glib::Value::for_value_type::<$name>(); + unsafe { + $crate::glib::gobject_ffi::g_value_take_boxed( + $crate::glib::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0, + $crate::glib::translate::IntoGlibPtr::<*mut $ffi_name>::into_glib_ptr(v) as *mut _, + ) + } + value + } + } + unsafe impl<'a> $crate::glib::value::FromValue<'a> for &'a $ref_name { type Checker = $crate::memory::MemoryTypeValueTypeChecker<$name>; diff --git a/gstreamer/src/miniobject.rs b/gstreamer/src/miniobject.rs index 607b779f9..39e0f233f 100644 --- a/gstreamer/src/miniobject.rs +++ b/gstreamer/src/miniobject.rs @@ -531,6 +531,20 @@ macro_rules! mini_object_wrapper ( } } + impl From<$name> for $crate::glib::Value { + fn from(v: $name) -> $crate::glib::Value { + skip_assert_initialized!(); + let mut value = $crate::glib::Value::for_value_type::<$name>(); + unsafe { + $crate::glib::gobject_ffi::g_value_take_boxed( + $crate::glib::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0, + $crate::glib::translate::IntoGlibPtr::<*mut $ffi_name>::into_glib_ptr(v) as *mut _, + ) + } + value + } + } + unsafe impl<'a> $crate::glib::value::FromValue<'a> for &'a $ref_name { type Checker = $crate::glib::value::GenericValueTypeOrNoneChecker; diff --git a/gstreamer/src/segment.rs b/gstreamer/src/segment.rs index f0a8c0f76..40cf934ea 100644 --- a/gstreamer/src/segment.rs +++ b/gstreamer/src/segment.rs @@ -643,7 +643,14 @@ impl glib::value::ToValueOptional for FormattedSegme value } } -#[doc(hidden)] + +impl From> for glib::Value { + fn from(v: FormattedSegment) -> glib::Value { + skip_assert_initialized!(); + glib::value::ToValue::to_value(&v) + } +} + #[doc(hidden)] impl glib::translate::GlibPtrDefault for FormattedSegment { type GlibType = *mut ffi::GstSegment; diff --git a/gstreamer/src/static_caps.rs b/gstreamer/src/static_caps.rs index bc88e5915..44e378c0f 100644 --- a/gstreamer/src/static_caps.rs +++ b/gstreamer/src/static_caps.rs @@ -72,6 +72,13 @@ impl glib::value::ToValue for StaticCaps { } } +impl From for glib::Value { + fn from(v: StaticCaps) -> glib::Value { + skip_assert_initialized!(); + glib::value::ToValue::to_value(&v) + } +} + #[doc(hidden)] impl glib::value::ToValueOptional for StaticCaps { fn to_value_optional(s: Option<&Self>) -> glib::Value { diff --git a/gstreamer/src/static_pad_template.rs b/gstreamer/src/static_pad_template.rs index bc682ada8..b254a7c71 100644 --- a/gstreamer/src/static_pad_template.rs +++ b/gstreamer/src/static_pad_template.rs @@ -118,6 +118,13 @@ impl glib::value::ToValueOptional for StaticPadTemplate { } } +impl From for glib::Value { + fn from(v: StaticPadTemplate) -> glib::Value { + skip_assert_initialized!(); + glib::value::ToValue::to_value(&v) + } +} + #[doc(hidden)] impl glib::translate::GlibPtrDefault for StaticPadTemplate { type GlibType = *mut ffi::GstStaticPadTemplate; diff --git a/gstreamer/src/structure.rs b/gstreamer/src/structure.rs index 056101ce1..1f43a3022 100644 --- a/gstreamer/src/structure.rs +++ b/gstreamer/src/structure.rs @@ -349,6 +349,20 @@ impl glib::value::ToValueOptional for Structure { } } +impl From for glib::Value { + fn from(v: Structure) -> glib::Value { + skip_assert_initialized!(); + let mut value = glib::Value::for_value_type::(); + unsafe { + glib::gobject_ffi::g_value_take_boxed( + value.to_glib_none_mut().0, + glib::translate::IntoGlibPtr::<*mut ffi::GstStructure>::into_glib_ptr(v) as *mut _, + ) + } + value + } +} + impl GlibPtrDefault for Structure { type GlibType = *mut ffi::GstStructure; } @@ -457,8 +471,8 @@ impl StructureRef { } #[doc(alias = "gst_structure_set")] - pub fn set(&mut self, name: &str, value: T) { - let value = value.to_send_value(); + pub fn set(&mut self, name: &str, value: impl Into + Send) { + let value = unsafe { glib::SendValue::unsafe_from(value.into().into_raw()) }; self.set_value(name, value); } @@ -474,8 +488,8 @@ impl StructureRef { } #[doc(alias = "gst_structure_id_set")] - pub fn set_by_quark(&mut self, name: glib::Quark, value: T) { - let value = value.to_send_value(); + pub fn set_by_quark(&mut self, name: glib::Quark, value: impl Into + Send) { + let value = unsafe { glib::SendValue::unsafe_from(value.into().into_raw()) }; self.set_value_by_quark(name, value); } @@ -1035,7 +1049,7 @@ impl Builder { } } - pub fn field(mut self, name: &str, value: V) -> Self { + pub fn field(mut self, name: &str, value: impl Into + Send) -> Self { self.s.set(name, value); self } diff --git a/gstreamer/src/tags.rs b/gstreamer/src/tags.rs index cefbadec3..a3275418c 100644 --- a/gstreamer/src/tags.rs +++ b/gstreamer/src/tags.rs @@ -7,9 +7,7 @@ use std::mem; use once_cell::sync::Lazy; -use glib::translate::{ - from_glib, from_glib_full, FromGlibPtrFull, IntoGlib, ToGlibPtr, ToGlibPtrMut, -}; +use glib::translate::*; use glib::value::{FromValue, SendValue, ToSendValue, Value}; use glib::StaticType; @@ -376,14 +374,13 @@ impl TagListRef { } #[doc(alias = "gst_tag_list_add")] - pub fn add_generic( + pub fn add_generic( &mut self, tag_name: &str, - value: T, + value: impl ToSendValue, mode: TagMergeMode, ) -> Result<(), TagError> { - let v = value.to_send_value(); - self.add_value(tag_name, &v, mode) + self.add_value(tag_name, &value.to_send_value(), mode) } #[doc(alias = "gst_tag_list_add_value")] @@ -1107,8 +1104,6 @@ pub fn merge_use_first(src: &Value) -> Value { assert_eq!(src.type_(), crate::List::static_type()); unsafe { - use glib::translate::Uninitialized; - let mut res = Value::uninitialized(); ffi::gst_tag_merge_use_first(res.to_glib_none_mut().0, src.to_glib_none().0); res @@ -1121,8 +1116,6 @@ pub fn merge_strings_with_comma(src: &Value) -> Value { assert_eq!(src.type_(), crate::List::static_type()); unsafe { - use glib::translate::Uninitialized; - let mut res = Value::uninitialized(); ffi::gst_tag_merge_strings_with_comma(res.to_glib_none_mut().0, src.to_glib_none().0); res diff --git a/gstreamer/src/value.rs b/gstreamer/src/value.rs index 01d20f41d..736e3b07d 100644 --- a/gstreamer/src/value.rs +++ b/gstreamer/src/value.rs @@ -6,8 +6,7 @@ use std::fmt; use std::ops; use std::slice; -use glib::translate::{from_glib, FromGlibPtrFull, ToGlibPtr, ToGlibPtrMut, Uninitialized}; -use glib::value::ToSendValue; +use glib::translate::*; use glib::StaticType; #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] @@ -281,6 +280,13 @@ impl glib::value::ToValue for Fraction { } } +impl From for glib::Value { + fn from(v: Fraction) -> glib::Value { + skip_assert_initialized!(); + glib::value::ToValue::to_value(&v) + } +} + #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct IntRange { @@ -423,6 +429,13 @@ impl glib::value::ToValue for IntRange { } } +impl From> for glib::Value { + fn from(v: IntRange) -> glib::Value { + skip_assert_initialized!(); + glib::value::ToValue::to_value(&v) + } +} + impl glib::types::StaticType for IntRange { fn static_type() -> glib::types::Type { unsafe { from_glib(ffi::gst_int64_range_get_type()) } @@ -465,6 +478,13 @@ impl glib::value::ToValue for IntRange { } } +impl From> for glib::Value { + fn from(v: IntRange) -> glib::Value { + skip_assert_initialized!(); + glib::value::ToValue::to_value(&v) + } +} + #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FractionRange { @@ -548,6 +568,13 @@ impl glib::value::ToValue for FractionRange { } } +impl From for glib::Value { + fn from(v: FractionRange) -> glib::Value { + skip_assert_initialized!(); + glib::value::ToValue::to_value(&v) + } +} + #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Bitmask(pub u64); @@ -646,27 +673,56 @@ impl glib::value::ToValue for Bitmask { } } -#[derive(Clone, Debug)] -pub struct Array(Vec); +impl From for glib::Value { + fn from(v: Bitmask) -> glib::Value { + skip_assert_initialized!(); + glib::value::ToValue::to_value(&v) + } +} + +#[derive(Clone)] +pub struct Array(glib::SendValue); unsafe impl Send for Array {} unsafe impl Sync for Array {} +impl fmt::Debug for Array { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Array").field(&self.as_slice()).finish() + } +} + impl Array { - pub fn new(values: impl IntoIterator) -> Self { + pub fn new(values: impl IntoIterator + Send>) -> Self { assert_initialized_main_thread!(); - Self(values.into_iter().map(|v| v.to_send_value()).collect()) + unsafe { + let mut value = glib::Value::for_value_type::(); + for v in values.into_iter() { + let mut v = v.into().into_raw(); + ffi::gst_value_array_append_and_take_value(value.to_glib_none_mut().0, &mut v); + } + + Self(glib::SendValue::unsafe_from(value.into_raw())) + } } pub fn from_values(values: impl IntoIterator) -> Self { assert_initialized_main_thread!(); - Self(values.into_iter().collect()) + Self::new(values) } pub fn as_slice(&self) -> &[glib::SendValue] { - self.0.as_slice() + unsafe { + let arr = (*self.0.as_ptr()).data[0].v_pointer as *const glib::ffi::GArray; + if arr.is_null() || (*arr).len == 0 { + &[] + } else { + #[allow(clippy::cast_ptr_alignment)] + slice::from_raw_parts((*arr).data as *const glib::SendValue, (*arr).len as usize) + } + } } } @@ -691,14 +747,6 @@ impl std::iter::FromIterator for Array { } } -impl From> for Array { - fn from(values: Vec) -> Self { - assert_initialized_main_thread!(); - - Self(values) - } -} - impl glib::value::ValueType for Array { type Type = Self; } @@ -708,29 +756,13 @@ unsafe impl<'a> glib::value::FromValue<'a> for Array { unsafe fn from_value(value: &'a glib::Value) -> Self { skip_assert_initialized!(); - let arr = (*value.to_glib_none().0).data[0].v_pointer as *const glib::ffi::GArray; - if arr.is_null() || (*arr).len == 0 { - Self(Vec::new()) - } else { - #[allow(clippy::cast_ptr_alignment)] - Self::from_values( - slice::from_raw_parts((*arr).data as *const glib::SendValue, (*arr).len as usize) - .iter() - .cloned(), - ) - } + Self(glib::SendValue::unsafe_from(value.clone().into_raw())) } } impl glib::value::ToValue for Array { fn to_value(&self) -> glib::Value { - let mut value = glib::Value::for_value_type::(); - unsafe { - for v in self.as_slice() { - ffi::gst_value_array_append_value(value.to_glib_none_mut().0, v.to_glib_none().0); - } - } - value + self.0.clone().into() } fn value_type(&self) -> glib::Type { @@ -738,6 +770,13 @@ impl glib::value::ToValue for Array { } } +impl From for glib::Value { + fn from(v: Array) -> glib::Value { + skip_assert_initialized!(); + v.0.into() + } +} + impl glib::types::StaticType for Array { fn static_type() -> glib::types::Type { unsafe { from_glib(ffi::gst_value_array_get_type()) } @@ -781,7 +820,7 @@ unsafe impl<'a> glib::value::FromValue<'a> for ArrayRef<'a> { unsafe fn from_value(value: &'a glib::Value) -> Self { skip_assert_initialized!(); - let arr = (*value.to_glib_none().0).data[0].v_pointer as *const glib::ffi::GArray; + let arr = (*value.as_ptr()).data[0].v_pointer as *const glib::ffi::GArray; if arr.is_null() || (*arr).len == 0 { Self(&[]) } else { @@ -810,33 +849,62 @@ impl<'a> glib::value::ToValue for ArrayRef<'a> { } } +impl<'a> From> for glib::Value { + fn from(v: ArrayRef<'a>) -> glib::Value { + skip_assert_initialized!(); + glib::value::ToValue::to_value(&v) + } +} + impl<'a> glib::types::StaticType for ArrayRef<'a> { fn static_type() -> glib::types::Type { unsafe { from_glib(ffi::gst_value_array_get_type()) } } } -#[derive(Clone, Debug)] -pub struct List(Vec); +#[derive(Clone)] +pub struct List(glib::SendValue); unsafe impl Send for List {} unsafe impl Sync for List {} +impl fmt::Debug for List { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("List").field(&self.as_slice()).finish() + } +} + impl List { - pub fn new(values: impl IntoIterator) -> Self { + pub fn new(values: impl IntoIterator + Send>) -> Self { assert_initialized_main_thread!(); - Self(values.into_iter().map(|v| v.to_send_value()).collect()) + unsafe { + let mut value = glib::Value::for_value_type::(); + for v in values.into_iter() { + let mut v = v.into().into_raw(); + ffi::gst_value_list_append_and_take_value(value.to_glib_none_mut().0, &mut v); + } + + Self(glib::SendValue::unsafe_from(value.into_raw())) + } } pub fn from_values(values: impl IntoIterator) -> Self { assert_initialized_main_thread!(); - Self(values.into_iter().collect()) + Self::new(values) } pub fn as_slice(&self) -> &[glib::SendValue] { - self.0.as_slice() + unsafe { + let arr = (*self.0.as_ptr()).data[0].v_pointer as *const glib::ffi::GArray; + if arr.is_null() || (*arr).len == 0 { + &[] + } else { + #[allow(clippy::cast_ptr_alignment)] + slice::from_raw_parts((*arr).data as *const glib::SendValue, (*arr).len as usize) + } + } } } @@ -861,14 +929,6 @@ impl std::iter::FromIterator for List { } } -impl From> for List { - fn from(values: Vec) -> Self { - assert_initialized_main_thread!(); - - Self(values) - } -} - impl glib::value::ValueType for List { type Type = Self; } @@ -878,29 +938,13 @@ unsafe impl<'a> glib::value::FromValue<'a> for List { unsafe fn from_value(value: &'a glib::Value) -> Self { skip_assert_initialized!(); - let arr = (*value.to_glib_none().0).data[0].v_pointer as *const glib::ffi::GArray; - if arr.is_null() || (*arr).len == 0 { - Self(Vec::new()) - } else { - #[allow(clippy::cast_ptr_alignment)] - Self::from_values( - slice::from_raw_parts((*arr).data as *const glib::SendValue, (*arr).len as usize) - .iter() - .cloned(), - ) - } + Self(glib::SendValue::unsafe_from(value.clone().into_raw())) } } impl glib::value::ToValue for List { fn to_value(&self) -> glib::Value { - let mut value = glib::Value::for_value_type::(); - unsafe { - for v in self.as_slice() { - ffi::gst_value_list_append_value(value.to_glib_none_mut().0, v.to_glib_none().0); - } - } - value + self.0.clone().into() } fn value_type(&self) -> glib::Type { @@ -908,6 +952,13 @@ impl glib::value::ToValue for List { } } +impl From for glib::Value { + fn from(v: List) -> glib::Value { + skip_assert_initialized!(); + v.0.into() + } +} + impl glib::types::StaticType for List { fn static_type() -> glib::types::Type { unsafe { from_glib(ffi::gst_value_list_get_type()) } @@ -951,7 +1002,7 @@ unsafe impl<'a> glib::value::FromValue<'a> for ListRef<'a> { unsafe fn from_value(value: &'a glib::Value) -> Self { skip_assert_initialized!(); - let arr = (*value.to_glib_none().0).data[0].v_pointer as *const glib::ffi::GArray; + let arr = (*value.as_ptr()).data[0].v_pointer as *const glib::ffi::GArray; if arr.is_null() || (*arr).len == 0 { Self(&[]) } else { @@ -980,6 +1031,13 @@ impl<'a> glib::value::ToValue for ListRef<'a> { } } +impl<'a> From> for glib::Value { + fn from(v: ListRef<'a>) -> glib::Value { + skip_assert_initialized!(); + glib::value::ToValue::to_value(&v) + } +} + impl<'a> glib::types::StaticType for ListRef<'a> { fn static_type() -> glib::types::Type { unsafe { from_glib(ffi::gst_value_list_get_type()) } diff --git a/gstreamer/src/value_serde.rs b/gstreamer/src/value_serde.rs index c4f17a83b..bbe686111 100644 --- a/gstreamer/src/value_serde.rs +++ b/gstreamer/src/value_serde.rs @@ -17,6 +17,7 @@ use once_cell::sync::Lazy; use crate::Buffer; use crate::DateTime; +use crate::List; use crate::Sample; use crate::Structure; @@ -106,7 +107,7 @@ macro_rules! ser_value ( } else if *INT_RANGE_I64_OTHER_TYPE_ID == type_id { ser_some_value!($value, IntRange, $ser_closure) } else if *LIST_OTHER_TYPE_ID == type_id { - ser_some_value!($value, List, $ser_closure) + ser_some_value!($value, crate::List, $ser_closure) } else if *SAMPLE_OTHER_TYPE_ID == type_id { ser_opt_value!($value, Sample, $ser_closure) } else if *BUFFER_OTHER_TYPE_ID == type_id { @@ -523,48 +524,61 @@ mod tests { fn test_deserialize_collections() { crate::init().unwrap(); - // Array + // Array of fractions let array_ron = r#"[ ("Fraction", (1, 3)), ("Fraction", (1, 2)), + ]"#; + let array: Array = ron::de::from_str(array_ron).unwrap(); + let slice = array.as_slice(); + assert_eq!(2, slice.len()); + + let fraction = slice[0].get::().expect("slice[0]"); + assert_eq!(fraction.0.numer(), &1); + assert_eq!(fraction.0.denom(), &3); + + let fraction = slice[1].get::().expect("slice[1]"); + assert_eq!(fraction.0.numer(), &1); + assert_eq!(fraction.0.denom(), &2); + + // Array of strings + let array_ron = r#"[ ("String", Some("test str")), ("String", None), + ]"#; + let array: Array = ron::de::from_str(array_ron).unwrap(); + let slice = array.as_slice(); + assert_eq!(2, slice.len()); + assert_eq!( + "test str".to_owned(), + slice[0].get::().expect("slice[0]") + ); + + assert!(slice[1] + .get::>() + .expect("slice[1]") + .is_none()); + + // Array of dates + let array_ron = r#"[ ("Date", Some(YMD(2019, 8, 19))), ("Date", None), ]"#; let array: Array = ron::de::from_str(array_ron).unwrap(); let slice = array.as_slice(); - assert_eq!(6, slice.len()); - - let fraction = slice[0].get::().expect("slice[0]"); - assert_eq!(fraction.0.numer(), &1); - assert_eq!(fraction.0.denom(), &3); - - let fraction = slice[1].get::().expect("slice[1]"); - assert_eq!(fraction.0.numer(), &1); - assert_eq!(fraction.0.denom(), &2); - - assert_eq!( - "test str".to_owned(), - slice[2].get::().expect("slice[2]") - ); - - assert!(slice[3] - .get::>() - .expect("slice[3]") - .is_none()); - + assert_eq!(2, slice.len()); assert_eq!( Date::from_dmy(19, DateMonth::August, 2019).unwrap(), - slice[4].get::().expect("slice[4]") + slice[0].get::().expect("slice[0]") ); - assert!(slice[5].get::>().expect("slice[5]").is_none()); + assert!(slice[1].get::>().expect("slice[1]").is_none()); - let array_json = r#"[["Fraction",[1,3]],["Fraction",[1,2]],["String","test str"],["String",null],["Date",{"YMD":[2019,8,19]}],["Date",null]]"#; + // Array of fractions + let array_json = r#"[["Fraction",[1,3]],["Fraction",[1,2]]]"#; let array: Array = serde_json::from_str(array_json).unwrap(); let slice = array.as_slice(); - assert_eq!(6, slice.len()); + assert_eq!(2, slice.len()); let fraction = slice[0].get::().expect("slice[0]"); assert_eq!(fraction.0.numer(), &1); @@ -574,57 +588,79 @@ mod tests { assert_eq!(fraction.0.numer(), &1); assert_eq!(fraction.0.denom(), &2); + // Array of strings + let array_json = r#"[["String","test str"],["String",null]]"#; + let array: Array = serde_json::from_str(array_json).unwrap(); + let slice = array.as_slice(); + assert_eq!(2, slice.len()); assert_eq!( "test str".to_owned(), - slice[2].get::().expect("slice[2]") + slice[0].get::().expect("slice[0]") ); - assert!(slice[3] + assert!(slice[1] .get::>() - .expect("slice[3]") + .expect("slice[1]") .is_none()); + // Array of dates + let array_json = r#"[["Date",{"YMD":[2019,8,19]}],["Date",null]]"#; + let array: Array = serde_json::from_str(array_json).unwrap(); + let slice = array.as_slice(); + assert_eq!(2, slice.len()); assert_eq!( Date::from_dmy(19, DateMonth::August, 2019).unwrap(), - slice[4].get::().expect("slice[4]") + slice[0].get::().expect("slice[0]") ); - assert!(slice[5].get::>().expect("slice[5]").is_none()); + assert!(slice[1].get::>().expect("slice[1]").is_none()); - // List + // List of fractions let list_ron = r#"[ ("Fraction", (1, 2)), + ]"#; + let list: List = ron::de::from_str(list_ron).unwrap(); + let slice = list.as_slice(); + assert_eq!(1, slice.len()); + + let fraction = slice[0].get::().expect("slice[0]"); + assert_eq!(fraction.0.numer(), &1); + assert_eq!(fraction.0.denom(), &2); + + // List of strings + let list_ron = r#"[ ("String", Some("test str")), ("String", None), + ]"#; + let list: List = ron::de::from_str(list_ron).unwrap(); + let slice = list.as_slice(); + assert_eq!(2, slice.len()); + assert_eq!( + "test str".to_owned(), + slice[0].get::().expect("slice[0]") + ); + + assert!(slice[1] + .get::>() + .expect("slice[1]") + .is_none()); + + // List of date times + let list_ron = r#"[ ("DateTime", Some(YMDhmsTz(2019, 8, 19, 13, 34, 42, 2))), ("DateTime", None), ]"#; let list: List = ron::de::from_str(list_ron).unwrap(); let slice = list.as_slice(); - assert_eq!(5, slice.len()); - - let fraction = slice[0].get::().expect("slice[0]"); - assert_eq!(fraction.0.numer(), &1); - assert_eq!(fraction.0.denom(), &2); - - assert_eq!( - "test str".to_owned(), - slice[1].get::().expect("slice[1]") - ); - - assert!(slice[2] - .get::>() - .expect("slice[2]") - .is_none()); - + assert_eq!(2, slice.len()); assert_eq!( DateTime::new(2f32, 2019, 8, 19, 13, 34, 42f64).unwrap(), - slice[3].get::().expect("slice[3]") + slice[0].get::().expect("slice[0]") ); - assert!(slice[4] + assert!(slice[1] .get::>() - .expect("slice[4]") + .expect("slice[1]") .is_none()); }