1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
#![no_std]
//! Iterator utility for getting the first non-matching element,
//! discarding any others, and the amount of discarded elements.
//!
//! To use, either `use discard_while::discard_while` to get the function,
//! or `use discard_while::DiscardWhile` to get the convenience trait.
/// Advance an iterator as long as a condition on the yielded items holds.
/// Returns the first item that no longer satisfies the condition, if any,
/// and the number of items discarded.
///
/// This is similar to a combination of [`find`] and [`position`].
///
/// # Overflow Behavior
///
/// The method does no guarding against overflows, so if there are more than `usize::MAX`
/// non-matching elements, it either produces the wrong result or panics.
/// If debug assertions are enabled, a panic is guaranteed.
///
/// # Panics
///
/// This function might panic if the iterator has more than `usize::MAX` non-matching elements.
///
/// # Example
///
/// Basic usage:
///
/// ```
/// # use discard_while::discard_while;
/// let mut range = 1..=10;
/// let result = discard_while(&mut range, |&n| n != 5);
/// assert_eq!(result, (Some(5), 4));
/// assert_eq!(range, 6..=10);
/// ```
///
/// If the iterator ends before an item that does not fulfill the condition
/// is encountered, [`None`] is returned as the first return value.
///
/// ```
/// # use discard_while::discard_while;
/// let mut range = 1..=10;
/// let result = discard_while(&mut range, |&n| true);
/// assert_eq!(result, (None, 10));
/// assert!(range.is_empty());
/// ```
///
/// If the first element that is encountered does not fulfill the condition,
/// `0` is returned as the second return value.
///
/// ```
/// # use discard_while::discard_while;
/// let mut range = 1..=10;
/// let result = discard_while(&mut range, |&n| false);
/// assert_eq!(result, (Some(1), 0));
/// assert_eq!(range, 2..=10);
/// ```
///
/// [`find`]: Iterator::find
/// [`position`]: Iterator::position
pub fn discard_while<T>(
iter: &mut impl Iterator<Item = T>,
mut cond: impl FnMut(&T) -> bool,
) -> (Option<T>, usize) {
let mut i = 0;
while let Some(next) = iter.next() {
if !cond(&next) {
return (Some(next), i);
}
i += 1;
}
(None, i)
}
/// Convenience trait to allow using [`discard_while`] as a method.
/// This trait is implemented for every [`Iterator`].
pub trait DiscardWhile: Iterator {
/// Advance the iterator as long as a condition on the yielded items holds.
/// Returns the first item that no longer satisfies the condition, if any,
/// and the number of items discarded.
///
/// This is similar to a combination of [`find`] and [`position`].
///
/// # Overflow Behavior
///
/// The method does no guarding against overflows, so if there are more than `usize::MAX`
/// non-matching elements, it either produces the wrong result or panics.
/// If debug assertions are enabled, a panic is guaranteed.
///
/// # Panics
///
/// This function might panic if the iterator has more than `usize::MAX` non-matching elements.
///
/// # Example
///
/// Basic usage:
///
/// ```
/// # use discard_while::DiscardWhile;
/// let mut range = 1..=10;
/// let result = range.discard_while(|&n| n != 5);
/// assert_eq!(result, (Some(5), 4));
/// assert_eq!(range, 6..=10);
/// ```
///
/// If the iterator ends before an item that does not fulfill the condition
/// is encountered, [`None`] is returned as the first return value.
///
/// ```
/// # use discard_while::DiscardWhile;
/// let mut range = 1..=10;
/// let result = range.discard_while(|&n| true);
/// assert_eq!(result, (None, 10));
/// assert!(range.is_empty());
/// ```
/// If the first element that is encountered does not fulfill the condition,
/// `0` is returned as the second return value.
///
/// ```
/// # use discard_while::DiscardWhile;
/// let mut range = 1..=10;
/// let result = range.discard_while(|&n| false);
/// assert_eq!(result, (Some(1), 0));
/// assert_eq!(range, 2..=10);
/// ```
/// [`find`]: Iterator::find
/// [`position`]: Iterator::position
fn discard_while(
&mut self,
cond: impl FnMut(&Self::Item) -> bool,
) -> (Option<Self::Item>, usize)
where
Self: Sized,
{
discard_while(self, cond)
}
}
impl<T: Iterator> DiscardWhile for T {}