summaryrefslogtreecommitdiffstats
path: root/vendor/array_tool/src/iter.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/array_tool/src/iter.rs')
-rw-r--r--vendor/array_tool/src/iter.rs166
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)
+ }
+}