From 3a0bcd0b9e341d7a62effb1af09a1d329c79b345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 23 Mar 2025 12:16:39 +0200 Subject: [PATCH] bufferpool: Change BufferPoolConfig::options() to return an iterator Avoids unnecessary allocations for the Vec. Part-of: --- gstreamer/src/buffer_pool.rs | 32 ++++++----- gstreamer/src/utils.rs | 103 +++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 15 deletions(-) diff --git a/gstreamer/src/buffer_pool.rs b/gstreamer/src/buffer_pool.rs index 853a72ff8..47069734c 100644 --- a/gstreamer/src/buffer_pool.rs +++ b/gstreamer/src/buffer_pool.rs @@ -128,20 +128,8 @@ impl BufferPoolConfigRef { #[doc(alias = "get_options")] #[doc(alias = "gst_buffer_pool_config_n_options")] #[doc(alias = "gst_buffer_pool_config_get_option")] - pub fn options(&self) -> Vec { - unsafe { - let n = ffi::gst_buffer_pool_config_n_options(self.0.as_mut_ptr()) as usize; - let mut options = Vec::with_capacity(n); - - for i in 0..n { - options.push(from_glib_none(ffi::gst_buffer_pool_config_get_option( - self.0.as_mut_ptr(), - i as u32, - ))); - } - - options - } + pub fn options(&self) -> OptionsIter<'_> { + OptionsIter::new(self) } #[doc(alias = "gst_buffer_pool_config_set_params")] @@ -247,9 +235,23 @@ impl BufferPoolConfigRef { ) } } - // TODO: options iterator } +crate::utils::define_fixed_size_iter!( + OptionsIter, + &'a BufferPoolConfigRef, + &'a glib::GStr, + |collection: &BufferPoolConfigRef| unsafe { + ffi::gst_buffer_pool_config_n_options(collection.as_mut_ptr()) as usize + }, + |collection: &BufferPoolConfigRef, idx: usize| unsafe { + glib::GStr::from_ptr(ffi::gst_buffer_pool_config_get_option( + collection.as_mut_ptr(), + idx as u32, + )) + } +); + #[derive(Debug, Copy, Clone)] #[doc(alias = "GstBufferPoolAcquireParams")] pub struct BufferPoolAcquireParams(ffi::GstBufferPoolAcquireParams); diff --git a/gstreamer/src/utils.rs b/gstreamer/src/utils.rs index f929c25c2..60e01e47b 100644 --- a/gstreamer/src/utils.rs +++ b/gstreamer/src/utils.rs @@ -78,3 +78,106 @@ where } } } + +macro_rules! define_fixed_size_iter( + ($name:ident, $typ:ty, $ityp:ty, $get_len:expr, $get_item:expr) => { + #[derive(Debug)] + pub struct $name<'a> { + pub(crate) collection: $typ, + idx: usize, + size: usize, + } + + impl<'a> $name<'a> { + #[inline] + fn new(collection: $typ) -> $name<'a> { + skip_assert_initialized!(); + let size = $get_len(collection) as usize; + $name { + collection, + idx: 0, + size, + } + } + } + + impl<'a> Iterator for $name<'a> { + type Item = $ityp; + + #[inline] + fn next(&mut self) -> Option { + if self.idx >= self.size { + return None; + } + + let item = $get_item(self.collection, self.idx); + self.idx += 1; + + Some(item) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let remaining = self.size - self.idx; + + (remaining, Some(remaining)) + } + + #[inline] + fn count(self) -> usize { + self.size - self.idx + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + let (end, overflow) = self.idx.overflowing_add(n); + if end >= self.size || overflow { + self.idx = self.size; + None + } else { + self.idx = end + 1; + Some($get_item(self.collection, end)) + } + } + + #[inline] + fn last(self) -> Option { + if self.idx == self.size { + None + } else { + Some($get_item(self.collection, self.size - 1)) + } + } + } + + impl DoubleEndedIterator for $name<'_> { + #[inline] + fn next_back(&mut self) -> Option { + if self.idx == self.size { + return None; + } + + self.size -= 1; + Some($get_item(self.collection, self.size)) + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.size.overflowing_sub(n); + if end <= self.idx || overflow { + self.idx = self.size; + None + } else { + self.size = end - 1; + Some($get_item(self.collection, self.size)) + } + } + } + + impl ExactSizeIterator for $name<'_> {} + + impl std::iter::FusedIterator for $name<'_> {} + } +); + +pub(crate) use define_fixed_size_iter;