forked from mirrors/gstreamer-rs
Implement std::iter::Iterator<Item=Result<glib::Value, IteratorError> for gst::Iterator
This commit is contained in:
parent
8306e5cf72
commit
f7bce553cd
5 changed files with 92 additions and 118 deletions
|
@ -55,7 +55,6 @@ generate = [
|
||||||
"Gst.SegmentFlags",
|
"Gst.SegmentFlags",
|
||||||
"Gst.PadMode",
|
"Gst.PadMode",
|
||||||
"Gst.SchedulingFlags",
|
"Gst.SchedulingFlags",
|
||||||
"Gst.IteratorResult",
|
|
||||||
"Gst.ChildProxy",
|
"Gst.ChildProxy",
|
||||||
"Gst.Preset",
|
"Gst.Preset",
|
||||||
"Gst.TagSetter",
|
"Gst.TagSetter",
|
||||||
|
|
|
@ -836,69 +836,6 @@ impl SetValue for Format {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
|
||||||
pub enum IteratorResult {
|
|
||||||
Done,
|
|
||||||
Ok,
|
|
||||||
Resync,
|
|
||||||
Error,
|
|
||||||
#[doc(hidden)]
|
|
||||||
__Unknown(i32),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
impl ToGlib for IteratorResult {
|
|
||||||
type GlibType = ffi::GstIteratorResult;
|
|
||||||
|
|
||||||
fn to_glib(&self) -> ffi::GstIteratorResult {
|
|
||||||
match *self {
|
|
||||||
IteratorResult::Done => ffi::GST_ITERATOR_DONE,
|
|
||||||
IteratorResult::Ok => ffi::GST_ITERATOR_OK,
|
|
||||||
IteratorResult::Resync => ffi::GST_ITERATOR_RESYNC,
|
|
||||||
IteratorResult::Error => ffi::GST_ITERATOR_ERROR,
|
|
||||||
IteratorResult::__Unknown(value) => unsafe{std::mem::transmute(value)}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
impl FromGlib<ffi::GstIteratorResult> for IteratorResult {
|
|
||||||
fn from_glib(value: ffi::GstIteratorResult) -> Self {
|
|
||||||
skip_assert_initialized!();
|
|
||||||
match value as i32 {
|
|
||||||
0 => IteratorResult::Done,
|
|
||||||
1 => IteratorResult::Ok,
|
|
||||||
2 => IteratorResult::Resync,
|
|
||||||
3 => IteratorResult::Error,
|
|
||||||
value => IteratorResult::__Unknown(value),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl StaticType for IteratorResult {
|
|
||||||
fn static_type() -> Type {
|
|
||||||
unsafe { from_glib(ffi::gst_iterator_result_get_type()) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> FromValueOptional<'a> for IteratorResult {
|
|
||||||
unsafe fn from_value_optional(value: &Value) -> Option<Self> {
|
|
||||||
Some(FromValue::from_value(value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> FromValue<'a> for IteratorResult {
|
|
||||||
unsafe fn from_value(value: &Value) -> Self {
|
|
||||||
from_glib(std::mem::transmute::<i32, ffi::GstIteratorResult>(gobject_ffi::g_value_get_enum(value.to_glib_none().0)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SetValue for IteratorResult {
|
|
||||||
unsafe fn set_value(value: &mut Value, this: &Self) {
|
|
||||||
gobject_ffi::g_value_set_enum(value.to_glib_none_mut().0, this.to_glib() as i32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||||
pub enum LibraryError {
|
pub enum LibraryError {
|
||||||
Failed,
|
Failed,
|
||||||
|
|
|
@ -108,7 +108,6 @@ pub use self::enums::DebugLevel;
|
||||||
pub use self::enums::EventType;
|
pub use self::enums::EventType;
|
||||||
pub use self::enums::FlowReturn;
|
pub use self::enums::FlowReturn;
|
||||||
pub use self::enums::Format;
|
pub use self::enums::Format;
|
||||||
pub use self::enums::IteratorResult;
|
|
||||||
pub use self::enums::LibraryError;
|
pub use self::enums::LibraryError;
|
||||||
pub use self::enums::PadDirection;
|
pub use self::enums::PadDirection;
|
||||||
pub use self::enums::PadLinkReturn;
|
pub use self::enums::PadLinkReturn;
|
||||||
|
|
|
@ -10,9 +10,15 @@ use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use glib;
|
use glib;
|
||||||
use glib::Value;
|
use glib::Value;
|
||||||
use IteratorResult;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
use std::iter::Iterator as StdIterator;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||||
|
pub enum IteratorError {
|
||||||
|
Resync,
|
||||||
|
Error,
|
||||||
|
}
|
||||||
|
|
||||||
glib_wrapper! {
|
glib_wrapper! {
|
||||||
pub struct Iterator(Boxed<ffi::GstIterator>);
|
pub struct Iterator(Boxed<ffi::GstIterator>);
|
||||||
|
@ -25,22 +31,6 @@ glib_wrapper! {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator {
|
impl Iterator {
|
||||||
#[cfg_attr(feature = "cargo-clippy", allow(should_implement_trait))]
|
|
||||||
pub fn next(&mut self) -> Result<Value, IteratorResult> {
|
|
||||||
unsafe {
|
|
||||||
let mut value = Value::uninitialized();
|
|
||||||
let res = from_glib(ffi::gst_iterator_next(
|
|
||||||
self.to_glib_none_mut().0,
|
|
||||||
value.to_glib_none_mut().0,
|
|
||||||
));
|
|
||||||
if res == IteratorResult::Ok {
|
|
||||||
Ok(value)
|
|
||||||
} else {
|
|
||||||
Err(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resync(&mut self) {
|
pub fn resync(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi::gst_iterator_resync(self.to_glib_none_mut().0);
|
ffi::gst_iterator_resync(self.to_glib_none_mut().0);
|
||||||
|
@ -74,7 +64,7 @@ impl Iterator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find<F>(&mut self, func: F) -> Option<glib::Value>
|
pub fn find_simple<F>(&mut self, func: F) -> Option<glib::Value>
|
||||||
where
|
where
|
||||||
F: FnMut(&glib::Value) -> bool,
|
F: FnMut(&glib::Value) -> bool,
|
||||||
{
|
{
|
||||||
|
@ -99,7 +89,7 @@ impl Iterator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn foreach<F>(&mut self, func: F) -> IteratorResult
|
pub fn foreach<F>(&mut self, func: F) -> Result<(), IteratorError>
|
||||||
where
|
where
|
||||||
F: FnMut(&glib::Value),
|
F: FnMut(&glib::Value),
|
||||||
{
|
{
|
||||||
|
@ -108,15 +98,21 @@ impl Iterator {
|
||||||
let func_obj: &mut (FnMut(&glib::Value)) = &mut func;
|
let func_obj: &mut (FnMut(&glib::Value)) = &mut func;
|
||||||
let func_ptr = &func_obj as *const &mut (FnMut(&glib::Value)) as gpointer;
|
let func_ptr = &func_obj as *const &mut (FnMut(&glib::Value)) as gpointer;
|
||||||
|
|
||||||
from_glib(ffi::gst_iterator_foreach(
|
let res = ffi::gst_iterator_foreach(
|
||||||
self.to_glib_none_mut().0,
|
self.to_glib_none_mut().0,
|
||||||
Some(foreach_trampoline),
|
Some(foreach_trampoline),
|
||||||
func_ptr,
|
func_ptr,
|
||||||
))
|
);
|
||||||
|
|
||||||
|
match res {
|
||||||
|
ffi::GST_ITERATOR_OK | ffi::GST_ITERATOR_DONE => Ok(()),
|
||||||
|
ffi::GST_ITERATOR_RESYNC => Err(IteratorError::Resync),
|
||||||
|
ffi::GST_ITERATOR_ERROR => Err(IteratorError::Error),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fold<F, T>(&mut self, init: T, func: F) -> Result<T, IteratorResult>
|
pub fn fold_with_early_exit<F, T>(&mut self, init: T, func: F) -> Result<T, IteratorError>
|
||||||
where
|
where
|
||||||
F: FnMut(T, &glib::Value) -> Result<T, T>,
|
F: FnMut(T, &glib::Value) -> Result<T, T>,
|
||||||
{
|
{
|
||||||
|
@ -134,18 +130,19 @@ impl Iterator {
|
||||||
&mut accum as *mut _ as gpointer,
|
&mut accum as *mut _ as gpointer,
|
||||||
);
|
);
|
||||||
|
|
||||||
let res = from_glib(ffi::gst_iterator_fold(
|
let res = ffi::gst_iterator_fold(
|
||||||
self.to_glib_none_mut().0,
|
self.to_glib_none_mut().0,
|
||||||
Some(fold_trampoline::<T>),
|
Some(fold_trampoline::<T>),
|
||||||
ret.to_glib_none_mut().0,
|
ret.to_glib_none_mut().0,
|
||||||
func_ptr,
|
func_ptr,
|
||||||
));
|
);
|
||||||
|
|
||||||
gobject_ffi::g_value_unset(ret.to_glib_none_mut().0);
|
gobject_ffi::g_value_unset(ret.to_glib_none_mut().0);
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
IteratorResult::Ok | IteratorResult::Done => Ok(accum.unwrap()),
|
ffi::GST_ITERATOR_OK | ffi::GST_ITERATOR_DONE => Ok(accum.unwrap()),
|
||||||
_ => Err(res),
|
ffi::GST_ITERATOR_RESYNC => Err(IteratorError::Resync),
|
||||||
|
ffi::GST_ITERATOR_ERROR => Err(IteratorError::Error),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,6 +179,23 @@ impl Iterator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl StdIterator for Iterator {
|
||||||
|
type Item = Result<Value, IteratorError>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Result<Value, IteratorError>> {
|
||||||
|
unsafe {
|
||||||
|
let mut value = Value::uninitialized();
|
||||||
|
let res = ffi::gst_iterator_next(self.to_glib_none_mut().0, value.to_glib_none_mut().0);
|
||||||
|
match res {
|
||||||
|
ffi::GST_ITERATOR_OK => Some(Ok(value)),
|
||||||
|
ffi::GST_ITERATOR_DONE => None,
|
||||||
|
ffi::GST_ITERATOR_RESYNC => Some(Err(IteratorError::Resync)),
|
||||||
|
ffi::GST_ITERATOR_ERROR => Some(Err(IteratorError::Error)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct RsIterator<I: IteratorImpl> {
|
struct RsIterator<I: IteratorImpl> {
|
||||||
iter: ffi::GstIterator,
|
iter: ffi::GstIterator,
|
||||||
|
@ -190,7 +204,7 @@ struct RsIterator<I: IteratorImpl> {
|
||||||
|
|
||||||
pub trait IteratorImpl: Clone + Send + 'static {
|
pub trait IteratorImpl: Clone + Send + 'static {
|
||||||
fn item_type() -> glib::Type;
|
fn item_type() -> glib::Type;
|
||||||
fn next(&mut self) -> Result<glib::Value, IteratorResult>;
|
fn next(&mut self) -> Option<Result<glib::Value, IteratorError>>;
|
||||||
fn resync(&mut self);
|
fn resync(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,15 +232,16 @@ unsafe extern "C" fn rs_iterator_next<I: IteratorImpl>(
|
||||||
callback_guard!();
|
callback_guard!();
|
||||||
let it = it as *mut RsIterator<I>;
|
let it = it as *mut RsIterator<I>;
|
||||||
match (*it).imp.as_mut().map(|imp| imp.next()).unwrap() {
|
match (*it).imp.as_mut().map(|imp| imp.next()).unwrap() {
|
||||||
Ok(value) => {
|
Some(Ok(value)) => {
|
||||||
ptr::write(result, ptr::read(value.to_glib_none().0));
|
ptr::write(result, ptr::read(value.to_glib_none().0));
|
||||||
mem::forget(value);
|
mem::forget(value);
|
||||||
ffi::GST_ITERATOR_OK
|
ffi::GST_ITERATOR_OK
|
||||||
}
|
}
|
||||||
Err(res) => {
|
None => ffi::GST_ITERATOR_DONE,
|
||||||
assert_ne!(res, IteratorResult::Ok);
|
Some(Err(res)) => match res {
|
||||||
res.to_glib()
|
IteratorError::Resync => ffi::GST_ITERATOR_RESYNC,
|
||||||
}
|
IteratorError::Error => ffi::GST_ITERATOR_ERROR,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,14 +272,14 @@ impl<T: glib::StaticType + glib::value::ToValue + Clone + Send + 'static> Iterat
|
||||||
T::static_type()
|
T::static_type()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next(&mut self) -> Result<glib::Value, IteratorResult> {
|
fn next(&mut self) -> Option<Result<glib::Value, IteratorError>> {
|
||||||
if self.pos < self.items.len() {
|
if self.pos < self.items.len() {
|
||||||
let res = Ok(self.items[self.pos].clone().to_value());
|
let res = Ok(self.items[self.pos].clone().to_value());
|
||||||
self.pos += 1;
|
self.pos += 1;
|
||||||
return res;
|
return Some(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(IteratorResult::Done)
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resync(&mut self) {
|
fn resync(&mut self) {
|
||||||
|
@ -401,14 +416,26 @@ mod tests {
|
||||||
|
|
||||||
let vec = vec![1i32, 2, 3];
|
let vec = vec![1i32, 2, 3];
|
||||||
let mut it = Iterator::from_vec(vec);
|
let mut it = Iterator::from_vec(vec);
|
||||||
|
let val = it.next().unwrap();
|
||||||
|
assert_eq!(val.unwrap().get::<i32>().unwrap(), 1);
|
||||||
|
let val = it.next().unwrap();
|
||||||
|
assert_eq!(val.unwrap().get::<i32>().unwrap(), 2);
|
||||||
|
let val = it.next().unwrap();
|
||||||
|
assert_eq!(val.unwrap().get::<i32>().unwrap(), 3);
|
||||||
|
assert!(it.next().is_none());
|
||||||
|
|
||||||
let val = it.next().unwrap();
|
let vec = vec![1i32, 2, 3];
|
||||||
assert_eq!(val.get::<i32>().unwrap(), 1);
|
let it = Iterator::from_vec(vec);
|
||||||
let val = it.next().unwrap();
|
let vals: Vec<_> = it.map(|v| v.unwrap().get::<i32>().unwrap()).collect();
|
||||||
assert_eq!(val.get::<i32>().unwrap(), 2);
|
assert_eq!(vals, [1, 2, 3]);
|
||||||
let val = it.next().unwrap();
|
|
||||||
assert_eq!(val.get::<i32>().unwrap(), 3);
|
let vec = vec![1i32, 2, 3];
|
||||||
assert_eq!(it.next().unwrap_err(), IteratorResult::Done);
|
let it = Iterator::from_vec(vec);
|
||||||
|
let mut vals = Vec::new();
|
||||||
|
for v in it {
|
||||||
|
vals.push(v.unwrap().get::<i32>().unwrap());
|
||||||
|
}
|
||||||
|
assert_eq!(vals, [1, 2, 3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -416,22 +443,25 @@ mod tests {
|
||||||
::init().unwrap();
|
::init().unwrap();
|
||||||
|
|
||||||
let vec = vec![1i32, 2, 3];
|
let vec = vec![1i32, 2, 3];
|
||||||
let mut it = Iterator::from_vec(vec).filter(|val| val.get::<i32>().unwrap() % 2 == 1);
|
let it = Iterator::from_vec(vec).filter(|val| val.get::<i32>().unwrap() % 2 == 1);
|
||||||
|
let vals: Vec<_> = it.map(|v| v.unwrap().get::<i32>().unwrap()).collect();
|
||||||
let val = it.next().unwrap();
|
assert_eq!(vals, [1, 3]);
|
||||||
assert_eq!(val.get::<i32>().unwrap(), 1);
|
|
||||||
let val = it.next().unwrap();
|
|
||||||
assert_eq!(val.get::<i32>().unwrap(), 3);
|
|
||||||
assert_eq!(it.next().unwrap_err(), IteratorResult::Done);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_find() {
|
fn test_find() {
|
||||||
::init().unwrap();
|
::init().unwrap();
|
||||||
|
|
||||||
|
// Our find
|
||||||
let vec = vec![1i32, 2, 3];
|
let vec = vec![1i32, 2, 3];
|
||||||
let val = Iterator::from_vec(vec).find(|val| val.get::<i32>().unwrap() == 2);
|
let val = Iterator::from_vec(vec).find_simple(|val| val.get::<i32>().unwrap() == 2);
|
||||||
assert_eq!(val.unwrap().get::<i32>().unwrap(), 2);
|
assert_eq!(val.unwrap().get::<i32>().unwrap(), 2);
|
||||||
|
|
||||||
|
// Find from std::iter::Iterator
|
||||||
|
let vec = vec![1i32, 2, 3];
|
||||||
|
let val =
|
||||||
|
Iterator::from_vec(vec).find(|val| val.as_ref().unwrap().get::<i32>().unwrap() == 2);
|
||||||
|
assert_eq!(val.unwrap().unwrap().get::<i32>().unwrap(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -441,7 +471,7 @@ mod tests {
|
||||||
let vec = vec![1i32, 2, 3];
|
let vec = vec![1i32, 2, 3];
|
||||||
let mut sum = 0;
|
let mut sum = 0;
|
||||||
let res = Iterator::from_vec(vec).foreach(|val| sum += val.get::<i32>().unwrap());
|
let res = Iterator::from_vec(vec).foreach(|val| sum += val.get::<i32>().unwrap());
|
||||||
assert_eq!(res, IteratorResult::Done);
|
assert_eq!(res, Ok(()));
|
||||||
assert_eq!(sum, 6);
|
assert_eq!(sum, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,11 +479,20 @@ mod tests {
|
||||||
fn test_fold() {
|
fn test_fold() {
|
||||||
::init().unwrap();
|
::init().unwrap();
|
||||||
|
|
||||||
|
// Our fold
|
||||||
let vec = vec![1i32, 2, 3];
|
let vec = vec![1i32, 2, 3];
|
||||||
let res = Iterator::from_vec(vec).fold(0, |mut sum, val| {
|
let res = Iterator::from_vec(vec).fold_with_early_exit(0, |mut sum, val| {
|
||||||
sum += val.get::<i32>().unwrap();
|
sum += val.get::<i32>().unwrap();
|
||||||
Ok(sum)
|
Ok(sum)
|
||||||
});
|
});
|
||||||
assert_eq!(res.unwrap(), 6);
|
assert_eq!(res.unwrap(), 6);
|
||||||
|
|
||||||
|
// Fold from std::iter::Iterator
|
||||||
|
let vec = vec![1i32, 2, 3];
|
||||||
|
let res = Iterator::from_vec(vec).fold(0, |mut sum, val| {
|
||||||
|
sum += val.unwrap().get::<i32>().unwrap();
|
||||||
|
sum
|
||||||
|
});
|
||||||
|
assert_eq!(res, 6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,7 +104,7 @@ pub use pad::{PadExtManual, PadProbeData, PadProbeId, PadProbeInfo, PAD_PROBE_ID
|
||||||
pub use gobject::GObjectExtManualGst;
|
pub use gobject::GObjectExtManualGst;
|
||||||
pub use child_proxy::ChildProxyExtManual;
|
pub use child_proxy::ChildProxyExtManual;
|
||||||
pub use tag_setter::TagSetterExtManual;
|
pub use tag_setter::TagSetterExtManual;
|
||||||
pub use self::iterator::Iterator;
|
pub use self::iterator::{Iterator, IteratorError};
|
||||||
pub use device_provider::DeviceProviderExtManual;
|
pub use device_provider::DeviceProviderExtManual;
|
||||||
pub use parse_context::ParseContext;
|
pub use parse_context::ParseContext;
|
||||||
#[cfg(feature = "futures")]
|
#[cfg(feature = "futures")]
|
||||||
|
|
Loading…
Reference in a new issue