summaryrefslogtreecommitdiff
path: root/vendor/itertools/src/pad_tail.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/itertools/src/pad_tail.rs')
-rw-r--r--vendor/itertools/src/pad_tail.rs124
1 files changed, 124 insertions, 0 deletions
diff --git a/vendor/itertools/src/pad_tail.rs b/vendor/itertools/src/pad_tail.rs
new file mode 100644
index 00000000..5595b42b
--- /dev/null
+++ b/vendor/itertools/src/pad_tail.rs
@@ -0,0 +1,124 @@
+use crate::size_hint;
+use std::iter::{Fuse, FusedIterator};
+
+/// An iterator adaptor that pads a sequence to a minimum length by filling
+/// missing elements using a closure.
+///
+/// Iterator element type is `I::Item`.
+///
+/// See [`.pad_using()`](crate::Itertools::pad_using) for more information.
+#[derive(Clone)]
+#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+pub struct PadUsing<I, F> {
+ iter: Fuse<I>,
+ min: usize,
+ pos: usize,
+ filler: F,
+}
+
+impl<I, F> std::fmt::Debug for PadUsing<I, F>
+where
+ I: std::fmt::Debug,
+{
+ debug_fmt_fields!(PadUsing, iter, min, pos);
+}
+
+/// Create a new `PadUsing` iterator.
+pub fn pad_using<I, F>(iter: I, min: usize, filler: F) -> PadUsing<I, F>
+where
+ I: Iterator,
+ F: FnMut(usize) -> I::Item,
+{
+ PadUsing {
+ iter: iter.fuse(),
+ min,
+ pos: 0,
+ filler,
+ }
+}
+
+impl<I, F> Iterator for PadUsing<I, F>
+where
+ I: Iterator,
+ F: FnMut(usize) -> I::Item,
+{
+ type Item = I::Item;
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ match self.iter.next() {
+ None => {
+ if self.pos < self.min {
+ let e = Some((self.filler)(self.pos));
+ self.pos += 1;
+ e
+ } else {
+ None
+ }
+ }
+ e => {
+ self.pos += 1;
+ e
+ }
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let tail = self.min.saturating_sub(self.pos);
+ size_hint::max(self.iter.size_hint(), (tail, Some(tail)))
+ }
+
+ fn fold<B, G>(self, mut init: B, mut f: G) -> B
+ where
+ G: FnMut(B, Self::Item) -> B,
+ {
+ let mut pos = self.pos;
+ init = self.iter.fold(init, |acc, item| {
+ pos += 1;
+ f(acc, item)
+ });
+ (pos..self.min).map(self.filler).fold(init, f)
+ }
+}
+
+impl<I, F> DoubleEndedIterator for PadUsing<I, F>
+where
+ I: DoubleEndedIterator + ExactSizeIterator,
+ F: FnMut(usize) -> I::Item,
+{
+ fn next_back(&mut self) -> Option<Self::Item> {
+ if self.min == 0 {
+ self.iter.next_back()
+ } else if self.iter.len() >= self.min {
+ self.min -= 1;
+ self.iter.next_back()
+ } else {
+ self.min -= 1;
+ Some((self.filler)(self.min))
+ }
+ }
+
+ fn rfold<B, G>(self, mut init: B, mut f: G) -> B
+ where
+ G: FnMut(B, Self::Item) -> B,
+ {
+ init = (self.iter.len()..self.min)
+ .map(self.filler)
+ .rfold(init, &mut f);
+ self.iter.rfold(init, f)
+ }
+}
+
+impl<I, F> ExactSizeIterator for PadUsing<I, F>
+where
+ I: ExactSizeIterator,
+ F: FnMut(usize) -> I::Item,
+{
+}
+
+impl<I, F> FusedIterator for PadUsing<I, F>
+where
+ I: FusedIterator,
+ F: FnMut(usize) -> I::Item,
+{
+}