forked from mirrors/gstreamer-rs
Add support for CapsFeatures
Fixes https://github.com/sdroege/gstreamer-rs/issues/13
This commit is contained in:
parent
857ed8609c
commit
564f9faf84
5 changed files with 1049 additions and 73 deletions
|
@ -6,8 +6,10 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
use caps_features::*;
|
||||||
use miniobject::*;
|
use miniobject::*;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::ptr;
|
||||||
use std::str;
|
use std::str;
|
||||||
use structure::*;
|
use structure::*;
|
||||||
|
|
||||||
|
@ -68,12 +70,27 @@ impl GstRc<CapsRef> {
|
||||||
unsafe { from_glib_full(ffi::gst_caps_merge(caps.into_ptr(), other.into_ptr())) }
|
unsafe { from_glib_full(ffi::gst_caps_merge(caps.into_ptr(), other.into_ptr())) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn merge_structure(caps: Self, other: Structure) -> Self {
|
pub fn merge_structure(caps: Self, structure: Structure) -> Self {
|
||||||
skip_assert_initialized!();
|
skip_assert_initialized!();
|
||||||
unsafe {
|
unsafe {
|
||||||
from_glib_full(ffi::gst_caps_merge_structure(
|
from_glib_full(ffi::gst_caps_merge_structure(
|
||||||
caps.into_ptr(),
|
caps.into_ptr(),
|
||||||
other.into_ptr(),
|
structure.into_ptr(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn merge_structure_full(
|
||||||
|
caps: Self,
|
||||||
|
structure: Structure,
|
||||||
|
features: Option<CapsFeatures>,
|
||||||
|
) -> Self {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
unsafe {
|
||||||
|
from_glib_full(ffi::gst_caps_merge_structure_full(
|
||||||
|
caps.into_ptr(),
|
||||||
|
structure.into_ptr(),
|
||||||
|
features.map(|f| f.into_ptr()).unwrap_or(ptr::null_mut()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,9 +150,7 @@ impl CapsRef {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(StructureRef::from_glib_borrow(
|
Some(StructureRef::from_glib_borrow(structure))
|
||||||
structure as *const ffi::GstStructure,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,9 +165,41 @@ impl CapsRef {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(StructureRef::from_glib_borrow_mut(
|
Some(StructureRef::from_glib_borrow_mut(structure))
|
||||||
structure as *mut ffi::GstStructure,
|
}
|
||||||
))
|
}
|
||||||
|
|
||||||
|
pub fn get_features(&self, idx: u32) -> Option<&CapsFeaturesRef> {
|
||||||
|
if idx >= self.get_size() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let features = ffi::gst_caps_get_features(self.as_ptr(), idx);
|
||||||
|
Some(CapsFeaturesRef::from_glib_borrow(features))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_mut_features(&mut self, idx: u32) -> Option<&mut CapsFeaturesRef> {
|
||||||
|
if idx >= self.get_size() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let features = ffi::gst_caps_get_features(self.as_ptr(), idx);
|
||||||
|
Some(CapsFeaturesRef::from_glib_borrow_mut(features))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_features(&mut self, idx: u32, features: Option<CapsFeatures>) {
|
||||||
|
assert!(idx < self.get_size());
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ffi::gst_caps_set_features(
|
||||||
|
self.as_mut_ptr(),
|
||||||
|
idx,
|
||||||
|
features.map(|f| f.into_ptr()).unwrap_or(ptr::null_mut()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,10 +215,28 @@ impl CapsRef {
|
||||||
IterMut::new(self)
|
IterMut::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn iter_with_features(&self) -> IterFeatures {
|
||||||
|
IterFeatures::new(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter_with_features_mut(&mut self) -> IterFeaturesMut {
|
||||||
|
IterFeaturesMut::new(self)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn append_structure(&mut self, structure: Structure) {
|
pub fn append_structure(&mut self, structure: Structure) {
|
||||||
unsafe { ffi::gst_caps_append_structure(self.as_mut_ptr(), structure.into_ptr()) }
|
unsafe { ffi::gst_caps_append_structure(self.as_mut_ptr(), structure.into_ptr()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn append_structure_full(&mut self, structure: Structure, features: Option<CapsFeatures>) {
|
||||||
|
unsafe {
|
||||||
|
ffi::gst_caps_append_structure_full(
|
||||||
|
self.as_mut_ptr(),
|
||||||
|
structure.into_ptr(),
|
||||||
|
features.map(|f| f.into_ptr()).unwrap_or(ptr::null_mut()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn remove_structure(&mut self, idx: u32) {
|
pub fn remove_structure(&mut self, idx: u32) {
|
||||||
unsafe { ffi::gst_caps_remove_structure(self.as_mut_ptr(), idx) }
|
unsafe { ffi::gst_caps_remove_structure(self.as_mut_ptr(), idx) }
|
||||||
}
|
}
|
||||||
|
@ -250,6 +315,20 @@ impl CapsRef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_subset_structure_full(
|
||||||
|
&self,
|
||||||
|
structure: &StructureRef,
|
||||||
|
features: Option<&CapsFeaturesRef>,
|
||||||
|
) -> bool {
|
||||||
|
unsafe {
|
||||||
|
from_glib(ffi::gst_caps_is_subset_structure_full(
|
||||||
|
self.as_ptr(),
|
||||||
|
structure.as_ptr(),
|
||||||
|
features.map(|f| f.as_ptr()).unwrap_or(ptr::null()),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn subtract(&self, other: &Self) -> Caps {
|
pub fn subtract(&self, other: &Self) -> Caps {
|
||||||
skip_assert_initialized!();
|
skip_assert_initialized!();
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -268,7 +347,7 @@ impl glib::types::StaticType for CapsRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! define_iter(
|
macro_rules! define_iter(
|
||||||
($name:ident, $typ:ty, $styp:ty) => {
|
($name:ident, $typ:ty, $styp:ty, $get_item:expr) => {
|
||||||
pub struct $name<'a> {
|
pub struct $name<'a> {
|
||||||
caps: $typ,
|
caps: $typ,
|
||||||
idx: u32,
|
idx: u32,
|
||||||
|
@ -297,15 +376,13 @@ macro_rules! define_iter(
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let structure = ffi::gst_caps_get_structure(self.caps.as_ptr(), self.idx);
|
let item = $get_item(self.caps, self.idx);
|
||||||
if structure.is_null() {
|
if item.is_none() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.idx += 1;
|
self.idx += 1;
|
||||||
Some(StructureRef::from_glib_borrow_mut(
|
item
|
||||||
structure as *mut ffi::GstStructure,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,14 +406,7 @@ macro_rules! define_iter(
|
||||||
self.n_structures -= 1;
|
self.n_structures -= 1;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let structure = ffi::gst_caps_get_structure(self.caps.as_ptr(), self.n_structures);
|
$get_item(self.caps, self.n_structures)
|
||||||
if structure.is_null() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(StructureRef::from_glib_borrow_mut(
|
|
||||||
structure as *mut ffi::GstStructure,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -345,8 +415,70 @@ macro_rules! define_iter(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
define_iter!(Iter, &'a CapsRef, &'a StructureRef);
|
define_iter!(
|
||||||
define_iter!(IterMut, &'a mut CapsRef, &'a mut StructureRef);
|
Iter,
|
||||||
|
&'a CapsRef,
|
||||||
|
&'a StructureRef,
|
||||||
|
|caps: &CapsRef, idx| {
|
||||||
|
let ptr = ffi::gst_caps_get_structure(caps.as_ptr(), idx);
|
||||||
|
if ptr.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(StructureRef::from_glib_borrow(
|
||||||
|
ptr as *const ffi::GstStructure,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
define_iter!(
|
||||||
|
IterMut,
|
||||||
|
&'a mut CapsRef,
|
||||||
|
&'a mut StructureRef,
|
||||||
|
|caps: &CapsRef, idx| {
|
||||||
|
let ptr = ffi::gst_caps_get_structure(caps.as_ptr(), idx);
|
||||||
|
if ptr.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(StructureRef::from_glib_borrow_mut(
|
||||||
|
ptr as *mut ffi::GstStructure,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
define_iter!(
|
||||||
|
IterFeatures,
|
||||||
|
&'a CapsRef,
|
||||||
|
(&'a StructureRef, &'a CapsFeaturesRef),
|
||||||
|
|caps: &CapsRef, idx| {
|
||||||
|
let ptr1 = ffi::gst_caps_get_structure(caps.as_ptr(), idx);
|
||||||
|
let ptr2 = ffi::gst_caps_get_features(caps.as_ptr(), idx);
|
||||||
|
if ptr1.is_null() || ptr2.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some((
|
||||||
|
StructureRef::from_glib_borrow(ptr1 as *const ffi::GstStructure),
|
||||||
|
CapsFeaturesRef::from_glib_borrow(ptr2 as *const ffi::GstCapsFeatures),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
define_iter!(
|
||||||
|
IterFeaturesMut,
|
||||||
|
&'a mut CapsRef,
|
||||||
|
(&'a mut StructureRef, &'a mut CapsFeaturesRef),
|
||||||
|
|caps: &CapsRef, idx| {
|
||||||
|
let ptr1 = ffi::gst_caps_get_structure(caps.as_ptr(), idx);
|
||||||
|
let ptr2 = ffi::gst_caps_get_features(caps.as_ptr(), idx);
|
||||||
|
if ptr1.is_null() || ptr2.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some((
|
||||||
|
StructureRef::from_glib_borrow_mut(ptr1 as *mut ffi::GstStructure),
|
||||||
|
CapsFeaturesRef::from_glib_borrow_mut(ptr2 as *mut ffi::GstCapsFeatures),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
impl fmt::Debug for CapsRef {
|
impl fmt::Debug for CapsRef {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
@ -379,25 +511,47 @@ impl ToOwned for CapsRef {
|
||||||
unsafe impl Sync for CapsRef {}
|
unsafe impl Sync for CapsRef {}
|
||||||
unsafe impl Send for CapsRef {}
|
unsafe impl Send for CapsRef {}
|
||||||
|
|
||||||
pub struct Builder {
|
pub struct Builder<'a> {
|
||||||
s: ::Structure,
|
s: ::Structure,
|
||||||
|
features: Option<&'a [&'a str]>,
|
||||||
|
any_features: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Builder {
|
impl<'a> Builder<'a> {
|
||||||
fn new(name: &str) -> Self {
|
fn new<'b>(name: &'b str) -> Builder<'a> {
|
||||||
Builder {
|
Builder {
|
||||||
s: ::Structure::new_empty(name),
|
s: ::Structure::new_empty(name),
|
||||||
|
features: None,
|
||||||
|
any_features: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn field<V: ToSendValue>(mut self, name: &str, value: &V) -> Self {
|
pub fn field<'b, V: ToSendValue>(mut self, name: &'b str, value: &'b V) -> Self {
|
||||||
self.s.set(name, value);
|
self.s.set(name, value);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn features(mut self, features: &'a [&'a str]) -> Self {
|
||||||
|
self.features = Some(features);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn any_features(mut self) -> Self {
|
||||||
|
self.any_features = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build(self) -> Caps {
|
pub fn build(self) -> Caps {
|
||||||
let mut caps = Caps::new_empty();
|
let mut caps = Caps::new_empty();
|
||||||
caps.get_mut().unwrap().append_structure(self.s);
|
let features = if self.any_features {
|
||||||
|
Some(CapsFeatures::new_any())
|
||||||
|
} else {
|
||||||
|
self.features.map(|f| CapsFeatures::new(f))
|
||||||
|
};
|
||||||
|
|
||||||
|
caps.get_mut()
|
||||||
|
.unwrap()
|
||||||
|
.append_structure_full(self.s, features);
|
||||||
caps
|
caps
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,7 +566,7 @@ mod tests {
|
||||||
fn test_simple() {
|
fn test_simple() {
|
||||||
::init().unwrap();
|
::init().unwrap();
|
||||||
|
|
||||||
let caps = Caps::new_simple(
|
let mut caps = Caps::new_simple(
|
||||||
"foo/bar",
|
"foo/bar",
|
||||||
&[
|
&[
|
||||||
("int", &12),
|
("int", &12),
|
||||||
|
@ -427,19 +581,36 @@ mod tests {
|
||||||
"foo/bar, int=(int)12, bool=(boolean)true, string=(string)bla, fraction=(fraction)1/2, array=(int)< 1, 2 >"
|
"foo/bar, int=(int)12, bool=(boolean)true, string=(string)bla, fraction=(fraction)1/2, array=(int)< 1, 2 >"
|
||||||
);
|
);
|
||||||
|
|
||||||
let s = caps.get_structure(0).unwrap();
|
{
|
||||||
assert_eq!(
|
let s = caps.get_structure(0).unwrap();
|
||||||
s,
|
assert_eq!(
|
||||||
Structure::new(
|
s,
|
||||||
"foo/bar",
|
Structure::new(
|
||||||
&[
|
"foo/bar",
|
||||||
("int", &12),
|
&[
|
||||||
("bool", &true),
|
("int", &12),
|
||||||
("string", &"bla"),
|
("bool", &true),
|
||||||
("fraction", &Fraction::new(1, 2)),
|
("string", &"bla"),
|
||||||
("array", &Array::new(&[&1, &2])),
|
("fraction", &Fraction::new(1, 2)),
|
||||||
],
|
("array", &Array::new(&[&1, &2])),
|
||||||
).as_ref()
|
],
|
||||||
|
).as_ref()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
assert!(
|
||||||
|
caps.get_features(0)
|
||||||
|
.unwrap()
|
||||||
|
.is_equal(::CAPS_FEATURES_MEMORY_SYSTEM_MEMORY.as_ref())
|
||||||
|
);
|
||||||
|
|
||||||
|
{
|
||||||
|
let caps = caps.get_mut().unwrap();
|
||||||
|
caps.set_features(0, Some(CapsFeatures::new(&["foo:bla"])));
|
||||||
|
}
|
||||||
|
assert!(
|
||||||
|
caps.get_features(0)
|
||||||
|
.unwrap()
|
||||||
|
.is_equal(CapsFeatures::new(&["foo:bla"]).as_ref())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,5 +629,17 @@ mod tests {
|
||||||
caps.to_string(),
|
caps.to_string(),
|
||||||
"foo/bar, int=(int)12, bool=(boolean)true, string=(string)bla, fraction=(fraction)1/2, array=(int)< 1, 2 >"
|
"foo/bar, int=(int)12, bool=(boolean)true, string=(string)bla, fraction=(fraction)1/2, array=(int)< 1, 2 >"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let caps = Caps::builder("foo/bar")
|
||||||
|
.field("int", &12)
|
||||||
|
.any_features()
|
||||||
|
.build();
|
||||||
|
assert_eq!(caps.to_string(), "foo/bar(ANY), int=(int)12");
|
||||||
|
|
||||||
|
let caps = Caps::builder("foo/bar")
|
||||||
|
.field("int", &12)
|
||||||
|
.features(&["foo:bla", "foo:baz"])
|
||||||
|
.build();
|
||||||
|
assert_eq!(caps.to_string(), "foo/bar(foo:bla, foo:baz), int=(int)12");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
472
gstreamer/src/caps_features.rs
Normal file
472
gstreamer/src/caps_features.rs
Normal file
|
@ -0,0 +1,472 @@
|
||||||
|
// Copyright (C) 2018 Sebastian Dröge <sebastian@centricular.com>
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
use std::borrow::{Borrow, BorrowMut, ToOwned};
|
||||||
|
use std::ffi::CStr;
|
||||||
|
use std::fmt;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::mem;
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
use std::ptr;
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
use ffi;
|
||||||
|
use glib;
|
||||||
|
use glib::translate::{
|
||||||
|
from_glib, from_glib_full, from_glib_none, FromGlibPtrFull, FromGlibPtrNone, GlibPtrDefault,
|
||||||
|
Stash, StashMut, ToGlibPtr, ToGlibPtrMut,
|
||||||
|
};
|
||||||
|
use glib_ffi::gpointer;
|
||||||
|
use gobject_ffi;
|
||||||
|
|
||||||
|
pub struct CapsFeatures(ptr::NonNull<CapsFeaturesRef>, PhantomData<CapsFeaturesRef>);
|
||||||
|
unsafe impl Send for CapsFeatures {}
|
||||||
|
unsafe impl Sync for CapsFeatures {}
|
||||||
|
|
||||||
|
impl CapsFeatures {
|
||||||
|
pub fn new(features: &[&str]) -> Self {
|
||||||
|
let mut f = Self::new_empty();
|
||||||
|
|
||||||
|
for feature in features {
|
||||||
|
f.add(feature);
|
||||||
|
}
|
||||||
|
|
||||||
|
f
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_empty() -> Self {
|
||||||
|
assert_initialized_main_thread!();
|
||||||
|
unsafe {
|
||||||
|
CapsFeatures(
|
||||||
|
ptr::NonNull::new_unchecked(
|
||||||
|
ffi::gst_caps_features_new_empty() as *mut CapsFeaturesRef
|
||||||
|
),
|
||||||
|
PhantomData,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_any() -> Self {
|
||||||
|
assert_initialized_main_thread!();
|
||||||
|
unsafe {
|
||||||
|
CapsFeatures(
|
||||||
|
ptr::NonNull::new_unchecked(
|
||||||
|
ffi::gst_caps_features_new_any() as *mut CapsFeaturesRef
|
||||||
|
),
|
||||||
|
PhantomData,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_string(value: &str) -> Option<Self> {
|
||||||
|
assert_initialized_main_thread!();
|
||||||
|
unsafe {
|
||||||
|
let ptr = ffi::gst_caps_features_from_string(value.to_glib_none().0);
|
||||||
|
if ptr.is_null() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(CapsFeatures(
|
||||||
|
ptr::NonNull::new_unchecked(ptr as *mut CapsFeaturesRef),
|
||||||
|
PhantomData,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn into_ptr(self) -> *mut ffi::GstCapsFeatures {
|
||||||
|
let ptr = self.0.as_ptr() as *mut CapsFeaturesRef as *mut ffi::GstCapsFeatures;
|
||||||
|
mem::forget(self);
|
||||||
|
|
||||||
|
ptr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for CapsFeatures {
|
||||||
|
type Target = CapsFeaturesRef;
|
||||||
|
|
||||||
|
fn deref(&self) -> &CapsFeaturesRef {
|
||||||
|
unsafe { self.0.as_ref() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for CapsFeatures {
|
||||||
|
fn deref_mut(&mut self) -> &mut CapsFeaturesRef {
|
||||||
|
unsafe { self.0.as_mut() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<CapsFeaturesRef> for CapsFeatures {
|
||||||
|
fn as_ref(&self) -> &CapsFeaturesRef {
|
||||||
|
self.deref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsMut<CapsFeaturesRef> for CapsFeatures {
|
||||||
|
fn as_mut(&mut self) -> &mut CapsFeaturesRef {
|
||||||
|
self.deref_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for CapsFeatures {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
unsafe {
|
||||||
|
let ptr = ffi::gst_caps_features_copy(&self.0.as_ref().0) as *mut CapsFeaturesRef;
|
||||||
|
assert!(!ptr.is_null());
|
||||||
|
CapsFeatures(ptr::NonNull::new_unchecked(ptr), PhantomData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for CapsFeatures {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe { ffi::gst_caps_features_free(&mut self.0.as_mut().0) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for CapsFeatures {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_tuple("CapsFeatures")
|
||||||
|
.field(&self.to_string())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for CapsFeatures {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
// Need to make sure to not call ToString::to_string() here, which
|
||||||
|
// we have because of the Display impl. We need CapsFeaturesRef::to_string()
|
||||||
|
f.write_str(&CapsFeaturesRef::to_string(self.as_ref()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl str::FromStr for CapsFeatures {
|
||||||
|
type Err = ();
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, ()> {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
CapsFeatures::from_string(s).ok_or(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Borrow<CapsFeaturesRef> for CapsFeatures {
|
||||||
|
fn borrow(&self) -> &CapsFeaturesRef {
|
||||||
|
unsafe { self.0.as_ref() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BorrowMut<CapsFeaturesRef> for CapsFeatures {
|
||||||
|
fn borrow_mut(&mut self) -> &mut CapsFeaturesRef {
|
||||||
|
unsafe { self.0.as_mut() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl glib::types::StaticType for CapsFeatures {
|
||||||
|
fn static_type() -> glib::types::Type {
|
||||||
|
unsafe { from_glib(ffi::gst_caps_features_get_type()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ToGlibPtr<'a, *const ffi::GstCapsFeatures> for CapsFeatures {
|
||||||
|
type Storage = &'a Self;
|
||||||
|
|
||||||
|
fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GstCapsFeatures, Self> {
|
||||||
|
unsafe { Stash(&self.0.as_ref().0, self) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_glib_full(&self) -> *const ffi::GstCapsFeatures {
|
||||||
|
unsafe { ffi::gst_caps_features_copy(&self.0.as_ref().0) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ToGlibPtr<'a, *mut ffi::GstCapsFeatures> for CapsFeatures {
|
||||||
|
type Storage = &'a Self;
|
||||||
|
|
||||||
|
fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::GstCapsFeatures, Self> {
|
||||||
|
unsafe { Stash(&self.0.as_ref().0 as *const _ as *mut _, self) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_glib_full(&self) -> *mut ffi::GstCapsFeatures {
|
||||||
|
unsafe { ffi::gst_caps_features_copy(&self.0.as_ref().0) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ToGlibPtrMut<'a, *mut ffi::GstCapsFeatures> for CapsFeatures {
|
||||||
|
type Storage = &'a mut Self;
|
||||||
|
|
||||||
|
fn to_glib_none_mut(&'a mut self) -> StashMut<*mut ffi::GstCapsFeatures, Self> {
|
||||||
|
unsafe { StashMut(&mut self.0.as_mut().0, self) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromGlibPtrNone<*const ffi::GstCapsFeatures> for CapsFeatures {
|
||||||
|
unsafe fn from_glib_none(ptr: *const ffi::GstCapsFeatures) -> Self {
|
||||||
|
assert!(!ptr.is_null());
|
||||||
|
let ptr = ffi::gst_caps_features_copy(ptr);
|
||||||
|
assert!(!ptr.is_null());
|
||||||
|
CapsFeatures(
|
||||||
|
ptr::NonNull::new_unchecked(ptr as *mut CapsFeaturesRef),
|
||||||
|
PhantomData,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromGlibPtrNone<*mut ffi::GstCapsFeatures> for CapsFeatures {
|
||||||
|
unsafe fn from_glib_none(ptr: *mut ffi::GstCapsFeatures) -> Self {
|
||||||
|
assert!(!ptr.is_null());
|
||||||
|
let ptr = ffi::gst_caps_features_copy(ptr);
|
||||||
|
assert!(!ptr.is_null());
|
||||||
|
CapsFeatures(
|
||||||
|
ptr::NonNull::new_unchecked(ptr as *mut CapsFeaturesRef),
|
||||||
|
PhantomData,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromGlibPtrFull<*const ffi::GstCapsFeatures> for CapsFeatures {
|
||||||
|
unsafe fn from_glib_full(ptr: *const ffi::GstCapsFeatures) -> Self {
|
||||||
|
assert!(!ptr.is_null());
|
||||||
|
CapsFeatures(
|
||||||
|
ptr::NonNull::new_unchecked(ptr as *mut CapsFeaturesRef),
|
||||||
|
PhantomData,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromGlibPtrFull<*mut ffi::GstCapsFeatures> for CapsFeatures {
|
||||||
|
unsafe fn from_glib_full(ptr: *mut ffi::GstCapsFeatures) -> Self {
|
||||||
|
assert!(!ptr.is_null());
|
||||||
|
CapsFeatures(
|
||||||
|
ptr::NonNull::new_unchecked(ptr as *mut CapsFeaturesRef),
|
||||||
|
PhantomData,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> glib::value::FromValueOptional<'a> for CapsFeatures {
|
||||||
|
unsafe fn from_value_optional(v: &'a glib::Value) -> Option<Self> {
|
||||||
|
let ptr = gobject_ffi::g_value_get_boxed(v.to_glib_none().0);
|
||||||
|
assert!(!ptr.is_null());
|
||||||
|
from_glib_none(ptr as *const ffi::GstCapsFeatures)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl glib::value::SetValue for CapsFeatures {
|
||||||
|
unsafe fn set_value(v: &mut glib::Value, s: &Self) {
|
||||||
|
gobject_ffi::g_value_set_boxed(v.to_glib_none_mut().0, s.0.as_ptr() as gpointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl glib::value::SetValueOptional for CapsFeatures {
|
||||||
|
unsafe fn set_value_optional(v: &mut glib::Value, s: Option<&Self>) {
|
||||||
|
if let Some(s) = s {
|
||||||
|
gobject_ffi::g_value_set_boxed(v.to_glib_none_mut().0, s.as_ptr() as gpointer);
|
||||||
|
} else {
|
||||||
|
gobject_ffi::g_value_set_boxed(v.to_glib_none_mut().0, ptr::null_mut());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GlibPtrDefault for CapsFeatures {
|
||||||
|
type GlibType = *mut ffi::GstCapsFeatures;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct CapsFeaturesRef(ffi::GstCapsFeatures);
|
||||||
|
|
||||||
|
impl CapsFeaturesRef {
|
||||||
|
pub unsafe fn from_glib_borrow<'a>(ptr: *const ffi::GstCapsFeatures) -> &'a CapsFeaturesRef {
|
||||||
|
assert!(!ptr.is_null());
|
||||||
|
|
||||||
|
&*(ptr as *mut CapsFeaturesRef)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn from_glib_borrow_mut<'a>(
|
||||||
|
ptr: *mut ffi::GstCapsFeatures,
|
||||||
|
) -> &'a mut CapsFeaturesRef {
|
||||||
|
assert!(!ptr.is_null());
|
||||||
|
|
||||||
|
&mut *(ptr as *mut CapsFeaturesRef)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn as_ptr(&self) -> *const ffi::GstCapsFeatures {
|
||||||
|
self as *const Self as *const ffi::GstCapsFeatures
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn as_mut_ptr(&self) -> *mut ffi::GstCapsFeatures {
|
||||||
|
self as *const Self as *mut ffi::GstCapsFeatures
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_string(&self) -> String {
|
||||||
|
unsafe { from_glib_full(ffi::gst_caps_features_to_string(self.as_ptr())) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.get_size() == 0 && !self.is_any()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_any(&self) -> bool {
|
||||||
|
unsafe { from_glib(ffi::gst_caps_features_is_any(self.as_ptr())) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn contains(&self, feature: &str) -> bool {
|
||||||
|
unsafe {
|
||||||
|
from_glib(ffi::gst_caps_features_contains(
|
||||||
|
self.as_ptr(),
|
||||||
|
feature.to_glib_none().0,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_size(&self) -> u32 {
|
||||||
|
unsafe { ffi::gst_caps_features_get_size(self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_nth(&self, idx: u32) -> Option<&str> {
|
||||||
|
if idx >= self.get_size() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let feature = ffi::gst_caps_features_get_nth(self.as_ptr(), idx);
|
||||||
|
if feature.is_null() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(CStr::from_ptr(feature).to_str().unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add(&mut self, feature: &str) {
|
||||||
|
unsafe { ffi::gst_caps_features_add(self.as_mut_ptr(), feature.to_glib_none().0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove(&mut self, feature: &str) {
|
||||||
|
unsafe { ffi::gst_caps_features_remove(self.as_mut_ptr(), feature.to_glib_none().0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self) -> Iter {
|
||||||
|
Iter::new(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is not an equivalence relation with regards to ANY. Everything is equal to ANY
|
||||||
|
pub fn is_equal(&self, other: &CapsFeaturesRef) -> bool {
|
||||||
|
unsafe {
|
||||||
|
from_glib(ffi::gst_caps_features_is_equal(
|
||||||
|
self.as_ptr(),
|
||||||
|
other.as_ptr(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Iter<'a> {
|
||||||
|
caps_features: &'a CapsFeaturesRef,
|
||||||
|
idx: u32,
|
||||||
|
n_features: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iter<'a> {
|
||||||
|
fn new(caps_features: &'a CapsFeaturesRef) -> Iter<'a> {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
let n_features = caps_features.get_size();
|
||||||
|
|
||||||
|
Iter {
|
||||||
|
caps_features,
|
||||||
|
idx: 0,
|
||||||
|
n_features,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for Iter<'a> {
|
||||||
|
type Item = &'a str;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.idx >= self.n_features {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let feature = ffi::gst_caps_features_get_nth(self.caps_features.as_ptr(), self.idx);
|
||||||
|
if feature.is_null() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.idx += 1;
|
||||||
|
|
||||||
|
Some(CStr::from_ptr(feature).to_str().unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
if self.idx == self.n_features {
|
||||||
|
return (0, Some(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
let remaining = (self.n_features - self.idx) as usize;
|
||||||
|
|
||||||
|
(remaining, Some(remaining))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> DoubleEndedIterator for Iter<'a> {
|
||||||
|
fn next_back(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.idx == self.n_features {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.n_features -= 1;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let feature =
|
||||||
|
ffi::gst_caps_features_get_nth(self.caps_features.as_ptr(), self.n_features);
|
||||||
|
if feature.is_null() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(CStr::from_ptr(feature).to_str().unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ExactSizeIterator for Iter<'a> {}
|
||||||
|
|
||||||
|
impl fmt::Debug for CapsFeaturesRef {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_tuple("CapsFeatures")
|
||||||
|
.field(&self.to_string())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for CapsFeaturesRef {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.write_str(&self.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToOwned for CapsFeaturesRef {
|
||||||
|
type Owned = CapsFeatures;
|
||||||
|
|
||||||
|
fn to_owned(&self) -> CapsFeatures {
|
||||||
|
unsafe { from_glib_full(ffi::gst_caps_features_copy(self.as_ptr() as *const _) as *mut _) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Sync for CapsFeaturesRef {}
|
||||||
|
unsafe impl Send for CapsFeaturesRef {}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref CAPS_FEATURE_MEMORY_SYSTEM_MEMORY: &'static str = unsafe {
|
||||||
|
CStr::from_ptr(ffi::GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY)
|
||||||
|
.to_str()
|
||||||
|
.unwrap()
|
||||||
|
};
|
||||||
|
pub static ref CAPS_FEATURES_MEMORY_SYSTEM_MEMORY: CapsFeatures =
|
||||||
|
CapsFeatures::new(&[*CAPS_FEATURE_MEMORY_SYSTEM_MEMORY]);
|
||||||
|
}
|
166
gstreamer/src/caps_features_serde.rs
Normal file
166
gstreamer/src/caps_features_serde.rs
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
// Copyright (C) 2018 Sebastian Dröge <sebastian@centricular.com>
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
use serde::de;
|
||||||
|
use serde::de::{Deserialize, Deserializer, EnumAccess, SeqAccess, VariantAccess, Visitor};
|
||||||
|
use serde::ser::{Serialize, SerializeSeq, Serializer};
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use CapsFeatures;
|
||||||
|
use CapsFeaturesRef;
|
||||||
|
|
||||||
|
enum CapsFeaturesVariantKinds {
|
||||||
|
Any,
|
||||||
|
Some,
|
||||||
|
}
|
||||||
|
|
||||||
|
const CAPS_FEATURES_VARIANT_ANY_ID: u32 = 0;
|
||||||
|
const CAPS_FEATURES_VARIANT_ANY_STR: &str = "Any";
|
||||||
|
const CAPS_FEATURES_VARIANT_SOME_ID: u32 = 1;
|
||||||
|
const CAPS_FEATURES_VARIANT_SOME_STR: &str = "Some";
|
||||||
|
|
||||||
|
const CAPS_FEATURES_VARIANT_NAMES: &[&str] = &[
|
||||||
|
&CAPS_FEATURES_VARIANT_ANY_STR,
|
||||||
|
&CAPS_FEATURES_VARIANT_SOME_STR,
|
||||||
|
];
|
||||||
|
|
||||||
|
struct CapsFeaturesForIterSe<'a>(&'a CapsFeaturesRef);
|
||||||
|
impl<'a> Serialize for CapsFeaturesForIterSe<'a> {
|
||||||
|
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||||
|
let iter = self.0.iter();
|
||||||
|
let size = iter.size_hint().0;
|
||||||
|
if size > 0 {
|
||||||
|
let mut seq = serializer.serialize_seq(Some(size))?;
|
||||||
|
for feature in iter {
|
||||||
|
seq.serialize_element(feature)?;
|
||||||
|
}
|
||||||
|
seq.end()
|
||||||
|
} else {
|
||||||
|
let seq = serializer.serialize_seq(None)?;
|
||||||
|
seq.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for CapsFeaturesRef {
|
||||||
|
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||||
|
if self.is_any() {
|
||||||
|
serializer.serialize_unit_variant(
|
||||||
|
stringify!(CapsFeatures),
|
||||||
|
CAPS_FEATURES_VARIANT_ANY_ID,
|
||||||
|
CAPS_FEATURES_VARIANT_ANY_STR,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
serializer.serialize_newtype_variant(
|
||||||
|
stringify!(CapsFeatures),
|
||||||
|
CAPS_FEATURES_VARIANT_SOME_ID,
|
||||||
|
CAPS_FEATURES_VARIANT_SOME_STR,
|
||||||
|
&CapsFeaturesForIterSe(&self),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for CapsFeatures {
|
||||||
|
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||||
|
self.as_ref().serialize(serializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CapsFeaturesSome(CapsFeatures);
|
||||||
|
|
||||||
|
struct CapsFeaturesSomeVisitor;
|
||||||
|
impl<'de> Visitor<'de> for CapsFeaturesSomeVisitor {
|
||||||
|
type Value = CapsFeaturesSome;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("a sequence of `&str`")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||||
|
let mut features = CapsFeatures::new_empty();
|
||||||
|
while let Some(feature) = seq.next_element::<String>()? {
|
||||||
|
features.add(feature.as_ref());
|
||||||
|
}
|
||||||
|
Ok(CapsFeaturesSome(features))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for CapsFeaturesSome {
|
||||||
|
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<CapsFeaturesSome, D::Error> {
|
||||||
|
deserializer.deserialize_seq(CapsFeaturesSomeVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CapsFeaturesVariantKindsVisitor;
|
||||||
|
impl<'de> Visitor<'de> for CapsFeaturesVariantKindsVisitor {
|
||||||
|
type Value = CapsFeaturesVariantKinds;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("a Caps variant kind (`Any` or `Some`)")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_u32<E: de::Error>(self, value: u32) -> Result<Self::Value, E> {
|
||||||
|
match value {
|
||||||
|
CAPS_FEATURES_VARIANT_ANY_ID => Ok(CapsFeaturesVariantKinds::Any),
|
||||||
|
CAPS_FEATURES_VARIANT_SOME_ID => Ok(CapsFeaturesVariantKinds::Some),
|
||||||
|
_ => Err(de::Error::invalid_value(
|
||||||
|
de::Unexpected::Unsigned(value as u64),
|
||||||
|
&self,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
|
||||||
|
match value {
|
||||||
|
CAPS_FEATURES_VARIANT_ANY_STR => Ok(CapsFeaturesVariantKinds::Any),
|
||||||
|
CAPS_FEATURES_VARIANT_SOME_STR => Ok(CapsFeaturesVariantKinds::Some),
|
||||||
|
_ => Err(de::Error::unknown_variant(
|
||||||
|
value,
|
||||||
|
CAPS_FEATURES_VARIANT_NAMES,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for CapsFeaturesVariantKinds {
|
||||||
|
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||||
|
deserializer.deserialize_identifier(CapsFeaturesVariantKindsVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CapsFeaturesVisitor;
|
||||||
|
impl<'de> Visitor<'de> for CapsFeaturesVisitor {
|
||||||
|
type Value = CapsFeatures;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("a CapsFeatures enum (`Any` or `Some()`)")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_enum<A: EnumAccess<'de>>(self, data: A) -> Result<Self::Value, A::Error> {
|
||||||
|
let res = match data.variant()? {
|
||||||
|
(CapsFeaturesVariantKinds::Any, _v) => CapsFeatures::new_any(),
|
||||||
|
(CapsFeaturesVariantKinds::Some, v) => v
|
||||||
|
.newtype_variant::<CapsFeaturesSome>()
|
||||||
|
.map(|caps_features_some| caps_features_some.0)?,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for CapsFeatures {
|
||||||
|
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||||
|
deserializer.deserialize_enum(
|
||||||
|
stringify!(Caps),
|
||||||
|
CAPS_FEATURES_VARIANT_NAMES,
|
||||||
|
CapsFeaturesVisitor,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,6 +13,8 @@ use serde::ser::{Serialize, SerializeSeq, SerializeTuple, Serializer};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use Caps;
|
use Caps;
|
||||||
|
use CapsFeatures;
|
||||||
|
use CapsFeaturesRef;
|
||||||
use CapsRef;
|
use CapsRef;
|
||||||
use Structure;
|
use Structure;
|
||||||
use StructureRef;
|
use StructureRef;
|
||||||
|
@ -36,15 +38,12 @@ const CAPS_VARIANT_NAMES: &[&str] = &[
|
||||||
&CAPS_VARIANT_SOME_STR,
|
&CAPS_VARIANT_SOME_STR,
|
||||||
];
|
];
|
||||||
|
|
||||||
// `CapsFeature` is not available in `gstreamer-rs` yet
|
struct CapsItemSe<'a>(&'a StructureRef, Option<&'a CapsFeaturesRef>);
|
||||||
struct CapsItemSe<'a>(&'a StructureRef);
|
|
||||||
impl<'a> Serialize for CapsItemSe<'a> {
|
impl<'a> Serialize for CapsItemSe<'a> {
|
||||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||||
let mut tup = serializer.serialize_tuple(2)?;
|
let mut tup = serializer.serialize_tuple(2)?;
|
||||||
tup.serialize_element(self.0)?;
|
tup.serialize_element(self.0)?;
|
||||||
// `CapsFeature` is not available in `gstreamer-rs` yet
|
tup.serialize_element(&self.1)?;
|
||||||
// Fake the type for now and use `None` as a value
|
|
||||||
tup.serialize_element::<Option<Structure>>(&None)?;
|
|
||||||
tup.end()
|
tup.end()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,12 +51,19 @@ impl<'a> Serialize for CapsItemSe<'a> {
|
||||||
struct CapsForIterSe<'a>(&'a CapsRef);
|
struct CapsForIterSe<'a>(&'a CapsRef);
|
||||||
impl<'a> Serialize for CapsForIterSe<'a> {
|
impl<'a> Serialize for CapsForIterSe<'a> {
|
||||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||||
let iter = self.0.iter();
|
let iter = self.0.iter_with_features();
|
||||||
let size = iter.size_hint().0;
|
let size = iter.size_hint().0;
|
||||||
if size > 0 {
|
if size > 0 {
|
||||||
let mut seq = serializer.serialize_seq(Some(size))?;
|
let mut seq = serializer.serialize_seq(Some(size))?;
|
||||||
for structure in iter {
|
for (structure, features) in iter {
|
||||||
seq.serialize_element(&CapsItemSe(structure))?;
|
let features = if !features.is_any() && features
|
||||||
|
.is_equal(::CAPS_FEATURES_MEMORY_SYSTEM_MEMORY.as_ref())
|
||||||
|
{
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(features)
|
||||||
|
};
|
||||||
|
seq.serialize_element(&CapsItemSe(structure, features))?;
|
||||||
}
|
}
|
||||||
seq.end()
|
seq.end()
|
||||||
} else {
|
} else {
|
||||||
|
@ -98,13 +104,7 @@ impl Serialize for Caps {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// `CapsFeature` is not available in `gstreamer-rs` yet
|
struct CapsItemDe(Structure, Option<CapsFeatures>);
|
||||||
struct CapsItemDe(Structure);
|
|
||||||
impl From<CapsItemDe> for Structure {
|
|
||||||
fn from(caps_item: CapsItemDe) -> Structure {
|
|
||||||
caps_item.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CapsItemVisitor;
|
struct CapsItemVisitor;
|
||||||
impl<'de> Visitor<'de> for CapsItemVisitor {
|
impl<'de> Visitor<'de> for CapsItemVisitor {
|
||||||
|
@ -118,20 +118,13 @@ impl<'de> Visitor<'de> for CapsItemVisitor {
|
||||||
let structure = seq
|
let structure = seq
|
||||||
.next_element::<Structure>()?
|
.next_element::<Structure>()?
|
||||||
.ok_or(de::Error::custom("Expected a `Structure` for `Caps` item"))?;
|
.ok_or(de::Error::custom("Expected a `Structure` for `Caps` item"))?;
|
||||||
// `CapsFeature` is not available in `gstreamer-rs` yet
|
let features_option =
|
||||||
// Fake the type for now and expect `None` as a value
|
seq.next_element::<Option<CapsFeatures>>()?
|
||||||
let feature_option = seq
|
.ok_or(de::Error::custom(
|
||||||
.next_element::<Option<Structure>>()?
|
"Expected an `Option<CapsFeature>` for `Caps` item",
|
||||||
.ok_or(de::Error::custom(
|
))?;
|
||||||
"Expected an `Option<CapsFeature>` for `Caps` item",
|
|
||||||
))?;
|
Ok(CapsItemDe(structure, features_option))
|
||||||
if feature_option.is_some() {
|
|
||||||
Err(de::Error::custom(
|
|
||||||
"Found a value for `CapsFeature`, expected `None` (not implemented yet)",
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
Ok(CapsItemDe(structure))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +149,7 @@ impl<'de> Visitor<'de> for CapsSomeVisitor {
|
||||||
{
|
{
|
||||||
let caps = caps.get_mut().unwrap();
|
let caps = caps.get_mut().unwrap();
|
||||||
while let Some(caps_item) = seq.next_element::<CapsItemDe>()? {
|
while let Some(caps_item) = seq.next_element::<CapsItemDe>()? {
|
||||||
caps.append_structure(caps_item.into());
|
caps.append_structure_full(caps_item.0, caps_item.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(CapsSome(caps))
|
Ok(CapsSome(caps))
|
||||||
|
@ -238,6 +231,7 @@ mod tests {
|
||||||
|
|
||||||
use Array;
|
use Array;
|
||||||
use Caps;
|
use Caps;
|
||||||
|
use CapsFeatures;
|
||||||
use Fraction;
|
use Fraction;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -274,6 +268,71 @@ mod tests {
|
||||||
res,
|
res,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let caps = Caps::builder("foo/bar")
|
||||||
|
.field("int", &12)
|
||||||
|
.field("bool", &true)
|
||||||
|
.field("string", &"bla")
|
||||||
|
.field("fraction", &Fraction::new(1, 2))
|
||||||
|
.field("array", &Array::new(&[&1, &2]))
|
||||||
|
.features(&["foo:bar", "foo:baz"])
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let mut pretty_config = ron::ser::PrettyConfig::default();
|
||||||
|
pretty_config.new_line = "".to_string();
|
||||||
|
|
||||||
|
let res = ron::ser::to_string_pretty(&caps, pretty_config.clone());
|
||||||
|
assert_eq!(
|
||||||
|
Ok(concat!(
|
||||||
|
"Some([",
|
||||||
|
" ((\"foo/bar\", [",
|
||||||
|
" (\"int\", \"i32\", 12),",
|
||||||
|
" (\"bool\", \"bool\", true),",
|
||||||
|
" (\"string\", \"String\", \"bla\"),",
|
||||||
|
" (\"fraction\", \"Fraction\", (1, 2)),",
|
||||||
|
" (\"array\", \"Array\", [",
|
||||||
|
" (\"i32\", 1),",
|
||||||
|
" (\"i32\", 2),",
|
||||||
|
" ]),",
|
||||||
|
" ]), Some(Some([",
|
||||||
|
" \"foo:bar\",",
|
||||||
|
" \"foo:baz\",",
|
||||||
|
" ]))),",
|
||||||
|
"])"
|
||||||
|
).to_owned()),
|
||||||
|
res,
|
||||||
|
);
|
||||||
|
|
||||||
|
let caps = Caps::builder("foo/bar")
|
||||||
|
.field("int", &12)
|
||||||
|
.field("bool", &true)
|
||||||
|
.field("string", &"bla")
|
||||||
|
.field("fraction", &Fraction::new(1, 2))
|
||||||
|
.field("array", &Array::new(&[&1, &2]))
|
||||||
|
.any_features()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let mut pretty_config = ron::ser::PrettyConfig::default();
|
||||||
|
pretty_config.new_line = "".to_string();
|
||||||
|
|
||||||
|
let res = ron::ser::to_string_pretty(&caps, pretty_config.clone());
|
||||||
|
assert_eq!(
|
||||||
|
Ok(concat!(
|
||||||
|
"Some([",
|
||||||
|
" ((\"foo/bar\", [",
|
||||||
|
" (\"int\", \"i32\", 12),",
|
||||||
|
" (\"bool\", \"bool\", true),",
|
||||||
|
" (\"string\", \"String\", \"bla\"),",
|
||||||
|
" (\"fraction\", \"Fraction\", (1, 2)),",
|
||||||
|
" (\"array\", \"Array\", [",
|
||||||
|
" (\"i32\", 1),",
|
||||||
|
" (\"i32\", 2),",
|
||||||
|
" ]),",
|
||||||
|
" ]), Some(Any)),",
|
||||||
|
"])"
|
||||||
|
).to_owned()),
|
||||||
|
res,
|
||||||
|
);
|
||||||
|
|
||||||
let caps_any = Caps::new_any();
|
let caps_any = Caps::new_any();
|
||||||
let res = ron::ser::to_string_pretty(&caps_any, pretty_config.clone());
|
let res = ron::ser::to_string_pretty(&caps_any, pretty_config.clone());
|
||||||
assert_eq!(Ok("Any".to_owned()), res);
|
assert_eq!(Ok("Any".to_owned()), res);
|
||||||
|
@ -328,6 +387,74 @@ mod tests {
|
||||||
],
|
],
|
||||||
).as_ref()
|
).as_ref()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let caps_ron = r#"
|
||||||
|
Some([
|
||||||
|
(
|
||||||
|
("foo/bar", [
|
||||||
|
("int", "i32", 12),
|
||||||
|
("bool", "bool", true),
|
||||||
|
("string", "String", "bla"),
|
||||||
|
("fraction", "Fraction", (1, 2)),
|
||||||
|
("array", "Array", [
|
||||||
|
("i32", 1),
|
||||||
|
("i32", 2),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
Some(Some(["foo:bar", "foo:baz"])),
|
||||||
|
),
|
||||||
|
])"#;
|
||||||
|
let caps: Caps = ron::de::from_str(caps_ron).unwrap();
|
||||||
|
let s = caps.get_structure(0).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
s,
|
||||||
|
Structure::new(
|
||||||
|
"foo/bar",
|
||||||
|
&[
|
||||||
|
("int", &12),
|
||||||
|
("bool", &true),
|
||||||
|
("string", &"bla"),
|
||||||
|
("fraction", &Fraction::new(1, 2)),
|
||||||
|
("array", &Array::new(&[&1, &2])),
|
||||||
|
],
|
||||||
|
).as_ref()
|
||||||
|
);
|
||||||
|
let f = caps.get_features(0).unwrap();
|
||||||
|
assert!(f.is_equal(CapsFeatures::new(&["foo:bar", "foo:baz"]).as_ref()));
|
||||||
|
|
||||||
|
let caps_ron = r#"
|
||||||
|
Some([
|
||||||
|
(
|
||||||
|
("foo/bar", [
|
||||||
|
("int", "i32", 12),
|
||||||
|
("bool", "bool", true),
|
||||||
|
("string", "String", "bla"),
|
||||||
|
("fraction", "Fraction", (1, 2)),
|
||||||
|
("array", "Array", [
|
||||||
|
("i32", 1),
|
||||||
|
("i32", 2),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
Some(Any),
|
||||||
|
),
|
||||||
|
])"#;
|
||||||
|
let caps: Caps = ron::de::from_str(caps_ron).unwrap();
|
||||||
|
let s = caps.get_structure(0).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
s,
|
||||||
|
Structure::new(
|
||||||
|
"foo/bar",
|
||||||
|
&[
|
||||||
|
("int", &12),
|
||||||
|
("bool", &true),
|
||||||
|
("string", &"bla"),
|
||||||
|
("fraction", &Fraction::new(1, 2)),
|
||||||
|
("array", &Array::new(&[&1, &2])),
|
||||||
|
],
|
||||||
|
).as_ref()
|
||||||
|
);
|
||||||
|
let f = caps.get_features(0).unwrap();
|
||||||
|
assert!(f.is_any());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -354,5 +481,29 @@ mod tests {
|
||||||
let caps_ser = ron::ser::to_string(&caps).unwrap();
|
let caps_ser = ron::ser::to_string(&caps).unwrap();
|
||||||
let caps_de: Caps = ron::de::from_str(caps_ser.as_str()).unwrap();
|
let caps_de: Caps = ron::de::from_str(caps_ser.as_str()).unwrap();
|
||||||
assert!(caps_de.is_strictly_equal(&caps));
|
assert!(caps_de.is_strictly_equal(&caps));
|
||||||
|
|
||||||
|
let caps = Caps::builder("foo/bar")
|
||||||
|
.field("int", &12)
|
||||||
|
.field("bool", &true)
|
||||||
|
.field("string", &"bla")
|
||||||
|
.field("fraction", &Fraction::new(1, 2))
|
||||||
|
.field("array", &Array::new(&[&1, &2]))
|
||||||
|
.features(&["foo:bar", "foo:baz"])
|
||||||
|
.build();
|
||||||
|
let caps_ser = ron::ser::to_string(&caps).unwrap();
|
||||||
|
let caps_de: Caps = ron::de::from_str(caps_ser.as_str()).unwrap();
|
||||||
|
assert!(caps_de.is_strictly_equal(&caps));
|
||||||
|
|
||||||
|
let caps = Caps::builder("foo/bar")
|
||||||
|
.field("int", &12)
|
||||||
|
.field("bool", &true)
|
||||||
|
.field("string", &"bla")
|
||||||
|
.field("fraction", &Fraction::new(1, 2))
|
||||||
|
.field("array", &Array::new(&[&1, &2]))
|
||||||
|
.any_features()
|
||||||
|
.build();
|
||||||
|
let caps_ser = ron::ser::to_string(&caps).unwrap();
|
||||||
|
let caps_de: Caps = ron::de::from_str(caps_ser.as_str()).unwrap();
|
||||||
|
assert!(caps_de.is_strictly_equal(&caps));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,6 +91,10 @@ pub mod caps;
|
||||||
pub use caps::{Caps, CapsRef};
|
pub use caps::{Caps, CapsRef};
|
||||||
#[cfg(feature = "ser_de")]
|
#[cfg(feature = "ser_de")]
|
||||||
mod caps_serde;
|
mod caps_serde;
|
||||||
|
mod caps_features;
|
||||||
|
pub use caps_features::{CapsFeatures, CapsFeaturesRef, CAPS_FEATURE_MEMORY_SYSTEM_MEMORY, CAPS_FEATURES_MEMORY_SYSTEM_MEMORY};
|
||||||
|
#[cfg(feature = "ser_de")]
|
||||||
|
mod caps_features_serde;
|
||||||
|
|
||||||
pub mod tags;
|
pub mod tags;
|
||||||
pub use tags::{Tag, TagList, TagListRef};
|
pub use tags::{Tag, TagList, TagListRef};
|
||||||
|
|
Loading…
Reference in a new issue