mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2024-11-26 03:21:03 +00:00
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
|
||||
// except according to those terms.
|
||||
|
||||
use caps_features::*;
|
||||
use miniobject::*;
|
||||
use std::fmt;
|
||||
use std::ptr;
|
||||
use std::str;
|
||||
use structure::*;
|
||||
|
||||
|
@ -68,12 +70,27 @@ impl GstRc<CapsRef> {
|
|||
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!();
|
||||
unsafe {
|
||||
from_glib_full(ffi::gst_caps_merge_structure(
|
||||
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;
|
||||
}
|
||||
|
||||
Some(StructureRef::from_glib_borrow(
|
||||
structure as *const ffi::GstStructure,
|
||||
))
|
||||
Some(StructureRef::from_glib_borrow(structure))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,9 +165,41 @@ impl CapsRef {
|
|||
return None;
|
||||
}
|
||||
|
||||
Some(StructureRef::from_glib_borrow_mut(
|
||||
structure as *mut ffi::GstStructure,
|
||||
))
|
||||
Some(StructureRef::from_glib_borrow_mut(structure))
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
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 {
|
||||
skip_assert_initialized!();
|
||||
unsafe {
|
||||
|
@ -268,7 +347,7 @@ impl glib::types::StaticType for CapsRef {
|
|||
}
|
||||
|
||||
macro_rules! define_iter(
|
||||
($name:ident, $typ:ty, $styp:ty) => {
|
||||
($name:ident, $typ:ty, $styp:ty, $get_item:expr) => {
|
||||
pub struct $name<'a> {
|
||||
caps: $typ,
|
||||
idx: u32,
|
||||
|
@ -297,15 +376,13 @@ macro_rules! define_iter(
|
|||
}
|
||||
|
||||
unsafe {
|
||||
let structure = ffi::gst_caps_get_structure(self.caps.as_ptr(), self.idx);
|
||||
if structure.is_null() {
|
||||
let item = $get_item(self.caps, self.idx);
|
||||
if item.is_none() {
|
||||
return None;
|
||||
}
|
||||
|
||||
self.idx += 1;
|
||||
Some(StructureRef::from_glib_borrow_mut(
|
||||
structure as *mut ffi::GstStructure,
|
||||
))
|
||||
item
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -329,14 +406,7 @@ macro_rules! define_iter(
|
|||
self.n_structures -= 1;
|
||||
|
||||
unsafe {
|
||||
let structure = ffi::gst_caps_get_structure(self.caps.as_ptr(), self.n_structures);
|
||||
if structure.is_null() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(StructureRef::from_glib_borrow_mut(
|
||||
structure as *mut ffi::GstStructure,
|
||||
))
|
||||
$get_item(self.caps, self.n_structures)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -345,8 +415,70 @@ macro_rules! define_iter(
|
|||
}
|
||||
);
|
||||
|
||||
define_iter!(Iter, &'a CapsRef, &'a StructureRef);
|
||||
define_iter!(IterMut, &'a mut CapsRef, &'a mut StructureRef);
|
||||
define_iter!(
|
||||
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 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
|
@ -379,25 +511,47 @@ impl ToOwned for CapsRef {
|
|||
unsafe impl Sync for CapsRef {}
|
||||
unsafe impl Send for CapsRef {}
|
||||
|
||||
pub struct Builder {
|
||||
pub struct Builder<'a> {
|
||||
s: ::Structure,
|
||||
features: Option<&'a [&'a str]>,
|
||||
any_features: bool,
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
fn new(name: &str) -> Self {
|
||||
impl<'a> Builder<'a> {
|
||||
fn new<'b>(name: &'b str) -> Builder<'a> {
|
||||
Builder {
|
||||
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
|
||||
}
|
||||
|
||||
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 {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -412,7 +566,7 @@ mod tests {
|
|||
fn test_simple() {
|
||||
::init().unwrap();
|
||||
|
||||
let caps = Caps::new_simple(
|
||||
let mut caps = Caps::new_simple(
|
||||
"foo/bar",
|
||||
&[
|
||||
("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 >"
|
||||
);
|
||||
|
||||
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 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()
|
||||
);
|
||||
}
|
||||
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(),
|
||||
"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 Caps;
|
||||
use CapsFeatures;
|
||||
use CapsFeaturesRef;
|
||||
use CapsRef;
|
||||
use Structure;
|
||||
use StructureRef;
|
||||
|
@ -36,15 +38,12 @@ const CAPS_VARIANT_NAMES: &[&str] = &[
|
|||
&CAPS_VARIANT_SOME_STR,
|
||||
];
|
||||
|
||||
// `CapsFeature` is not available in `gstreamer-rs` yet
|
||||
struct CapsItemSe<'a>(&'a StructureRef);
|
||||
struct CapsItemSe<'a>(&'a StructureRef, Option<&'a CapsFeaturesRef>);
|
||||
impl<'a> Serialize for CapsItemSe<'a> {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut tup = serializer.serialize_tuple(2)?;
|
||||
tup.serialize_element(self.0)?;
|
||||
// `CapsFeature` is not available in `gstreamer-rs` yet
|
||||
// Fake the type for now and use `None` as a value
|
||||
tup.serialize_element::<Option<Structure>>(&None)?;
|
||||
tup.serialize_element(&self.1)?;
|
||||
tup.end()
|
||||
}
|
||||
}
|
||||
|
@ -52,12 +51,19 @@ impl<'a> Serialize for CapsItemSe<'a> {
|
|||
struct CapsForIterSe<'a>(&'a CapsRef);
|
||||
impl<'a> Serialize for CapsForIterSe<'a> {
|
||||
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;
|
||||
if size > 0 {
|
||||
let mut seq = serializer.serialize_seq(Some(size))?;
|
||||
for structure in iter {
|
||||
seq.serialize_element(&CapsItemSe(structure))?;
|
||||
for (structure, features) in iter {
|
||||
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()
|
||||
} else {
|
||||
|
@ -98,13 +104,7 @@ impl Serialize for Caps {
|
|||
}
|
||||
}
|
||||
|
||||
// `CapsFeature` is not available in `gstreamer-rs` yet
|
||||
struct CapsItemDe(Structure);
|
||||
impl From<CapsItemDe> for Structure {
|
||||
fn from(caps_item: CapsItemDe) -> Structure {
|
||||
caps_item.0
|
||||
}
|
||||
}
|
||||
struct CapsItemDe(Structure, Option<CapsFeatures>);
|
||||
|
||||
struct CapsItemVisitor;
|
||||
impl<'de> Visitor<'de> for CapsItemVisitor {
|
||||
|
@ -118,20 +118,13 @@ impl<'de> Visitor<'de> for CapsItemVisitor {
|
|||
let structure = seq
|
||||
.next_element::<Structure>()?
|
||||
.ok_or(de::Error::custom("Expected a `Structure` for `Caps` item"))?;
|
||||
// `CapsFeature` is not available in `gstreamer-rs` yet
|
||||
// Fake the type for now and expect `None` as a value
|
||||
let feature_option = seq
|
||||
.next_element::<Option<Structure>>()?
|
||||
.ok_or(de::Error::custom(
|
||||
"Expected an `Option<CapsFeature>` for `Caps` item",
|
||||
))?;
|
||||
if feature_option.is_some() {
|
||||
Err(de::Error::custom(
|
||||
"Found a value for `CapsFeature`, expected `None` (not implemented yet)",
|
||||
))
|
||||
} else {
|
||||
Ok(CapsItemDe(structure))
|
||||
}
|
||||
let features_option =
|
||||
seq.next_element::<Option<CapsFeatures>>()?
|
||||
.ok_or(de::Error::custom(
|
||||
"Expected an `Option<CapsFeature>` for `Caps` item",
|
||||
))?;
|
||||
|
||||
Ok(CapsItemDe(structure, features_option))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,7 +149,7 @@ impl<'de> Visitor<'de> for CapsSomeVisitor {
|
|||
{
|
||||
let caps = caps.get_mut().unwrap();
|
||||
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))
|
||||
|
@ -238,6 +231,7 @@ mod tests {
|
|||
|
||||
use Array;
|
||||
use Caps;
|
||||
use CapsFeatures;
|
||||
use Fraction;
|
||||
|
||||
#[test]
|
||||
|
@ -274,6 +268,71 @@ mod tests {
|
|||
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 res = ron::ser::to_string_pretty(&caps_any, pretty_config.clone());
|
||||
assert_eq!(Ok("Any".to_owned()), res);
|
||||
|
@ -328,6 +387,74 @@ mod tests {
|
|||
],
|
||||
).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]
|
||||
|
@ -354,5 +481,29 @@ mod tests {
|
|||
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]))
|
||||
.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};
|
||||
#[cfg(feature = "ser_de")]
|
||||
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 use tags::{Tag, TagList, TagListRef};
|
||||
|
|
Loading…
Reference in a new issue