From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/array_tool/src/iter.rs | 166 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 vendor/array_tool/src/iter.rs (limited to 'vendor/array_tool/src/iter.rs') diff --git a/vendor/array_tool/src/iter.rs b/vendor/array_tool/src/iter.rs new file mode 100644 index 000000000..a176d5c79 --- /dev/null +++ b/vendor/array_tool/src/iter.rs @@ -0,0 +1,166 @@ +use std::cmp; +use std::iter::IntoIterator; + +#[doc(hidden)] +#[derive(Clone, Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct ZipOption { + a: A, + b: B, + // index and len are only used by the specialized version of zip + index: usize, + len: usize, +} + +/// Zips to iterators together to the longest length +/// via Option<(Option, Option)> +pub trait ZipOpt { + /// Zip to iterators to longest length via Option<(Option, Option)> results. + /// # Example + /// ``` + /// use array_tool::iter::ZipOpt; + /// + /// let a = vec!["a","b","c", "d"]; + /// let b = vec!["c","d"]; + /// let mut x = a.iter().zip_option(b.iter()); + /// + /// assert_eq!(x.next(), Some((Some(&"a"), Some(&"c")))); + /// assert_eq!(x.next(), Some((Some(&"b"), Some(&"d")))); + /// assert_eq!(x.next(), Some((Some(&"c"), None))); + /// assert_eq!(x.next(), Some((Some(&"d"), None))); + /// assert_eq!(x.next(), None); + /// ``` + /// + /// # Output + /// ```text + /// vec![ "a", "b", "c", "d" ] + /// ``` + fn zip_option(self, other: U) -> ZipOption + where Self: Sized, U: IntoIterator; +} + +impl ZipOpt for I { + #[inline] + fn zip_option(self, other: U) -> ZipOption + where Self: Sized, U: IntoIterator { + + ZipOption::new(self, other.into_iter()) + } +} + +impl Iterator for ZipOption where A: Iterator, B: Iterator { + type Item = (Option, Option); + + #[inline] + fn next(&mut self) -> Option { + ZipImpl::next(self) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + ZipImpl::size_hint(self) + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + ZipImpl::nth(self, n) + } +} + +#[doc(hidden)] +impl DoubleEndedIterator for ZipOption where +A: DoubleEndedIterator + ExactSizeIterator, +B: DoubleEndedIterator + ExactSizeIterator, +{ + #[inline] + fn next_back(&mut self) -> Option<(Option, Option)> { + ZipImpl::next_back(self) + } +} + +#[doc(hidden)] +trait ZipImpl { + type Item; + fn new(a: A, b: B) -> Self; + fn next(&mut self) -> Option; + fn size_hint(&self) -> (usize, Option); + fn nth(&mut self, n: usize) -> Option; + fn super_nth(&mut self, mut n: usize) -> Option { + while let Some(x) = self.next() { + if n == 0 { return Some(x) } + n -= 1; + } + None + } + fn next_back(&mut self) -> Option + where A: DoubleEndedIterator + ExactSizeIterator, + B: DoubleEndedIterator + ExactSizeIterator; +} + +#[doc(hidden)] +impl ZipImpl for ZipOption + where A: Iterator, B: Iterator { + type Item = (Option, Option); + fn new(a: A, b: B) -> Self { + ZipOption { + a, + b, + index: 0, // unused + len: 0, // unused + } + } + + #[inline] + fn next(&mut self) -> Option<(Option, Option)> { + let first = self.a.next(); + let second = self.b.next(); + + if first.is_some() || second.is_some() { + Some((first, second)) + } else { + None + } + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.super_nth(n) + } + + #[inline] + fn next_back(&mut self) -> Option<(Option, Option)> + where A: DoubleEndedIterator + ExactSizeIterator, + B: DoubleEndedIterator + ExactSizeIterator { + let a_sz = self.a.len(); + let b_sz = self.b.len(); + if a_sz != b_sz { + // Adjust a, b to equal length + if a_sz > b_sz { + for _ in 0..a_sz - b_sz { self.a.next_back(); } + } else { + for _ in 0..b_sz - a_sz { self.b.next_back(); } + } + } + match (self.a.next_back(), self.b.next_back()) { + (None, None) => None, + (f,s) => Some((f, s)), + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let (a_lower, a_upper) = self.a.size_hint(); + let (b_lower, b_upper) = self.b.size_hint(); + + let lower = cmp::min(a_lower, b_lower); + + let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) => Some(cmp::max(x,y)), + (Some(x), None) => Some(x), + (None, Some(y)) => Some(y), + (None, None) => None + }; + + (lower, upper) + } +} -- cgit v1.2.3