diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /vendor/array_tool/src/iter.rs | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/array_tool/src/iter.rs')
-rw-r--r-- | vendor/array_tool/src/iter.rs | 166 |
1 files changed, 166 insertions, 0 deletions
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, B> { + 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<A>, Option<B>)> +pub trait ZipOpt { + /// Zip to iterators to longest length via Option<(Option<A>, Option<B>)> 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<U>(self, other: U) -> ZipOption<Self, U::IntoIter> + where Self: Sized, U: IntoIterator; +} + +impl<I: Iterator> ZipOpt for I { + #[inline] + fn zip_option<U>(self, other: U) -> ZipOption<Self, U::IntoIter> + where Self: Sized, U: IntoIterator { + + ZipOption::new(self, other.into_iter()) + } +} + +impl<A, B> Iterator for ZipOption<A, B> where A: Iterator, B: Iterator { + type Item = (Option<A::Item>, Option<B::Item>); + + #[inline] + fn next(&mut self) -> Option<Self::Item> { + ZipImpl::next(self) + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + ZipImpl::size_hint(self) + } + + #[inline] + fn nth(&mut self, n: usize) -> Option<Self::Item> { + ZipImpl::nth(self, n) + } +} + +#[doc(hidden)] +impl<A, B> DoubleEndedIterator for ZipOption<A, B> where +A: DoubleEndedIterator + ExactSizeIterator, +B: DoubleEndedIterator + ExactSizeIterator, +{ + #[inline] + fn next_back(&mut self) -> Option<(Option<A::Item>, Option<B::Item>)> { + ZipImpl::next_back(self) + } +} + +#[doc(hidden)] +trait ZipImpl<A, B> { + type Item; + fn new(a: A, b: B) -> Self; + fn next(&mut self) -> Option<Self::Item>; + fn size_hint(&self) -> (usize, Option<usize>); + fn nth(&mut self, n: usize) -> Option<Self::Item>; + fn super_nth(&mut self, mut n: usize) -> Option<Self::Item> { + while let Some(x) = self.next() { + if n == 0 { return Some(x) } + n -= 1; + } + None + } + fn next_back(&mut self) -> Option<Self::Item> + where A: DoubleEndedIterator + ExactSizeIterator, + B: DoubleEndedIterator + ExactSizeIterator; +} + +#[doc(hidden)] +impl<A, B> ZipImpl<A, B> for ZipOption<A, B> + where A: Iterator, B: Iterator { + type Item = (Option<A::Item>, Option<B::Item>); + fn new(a: A, b: B) -> Self { + ZipOption { + a, + b, + index: 0, // unused + len: 0, // unused + } + } + + #[inline] + fn next(&mut self) -> Option<(Option<A::Item>, Option<B::Item>)> { + 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::Item> { + self.super_nth(n) + } + + #[inline] + fn next_back(&mut self) -> Option<(Option<A::Item>, Option<B::Item>)> + 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<usize>) { + 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) + } +} |