1
2pub struct EnumerateSplit<Iter, T>
4where Iter: Iterator<Item = T>, T: PartialEq {
5 iter: Iter,
6 split_value: T,
7 block_number: usize,
8 block_position: usize
9}
10
11impl<Iter, T> EnumerateSplit<Iter, T>
12where Iter: Iterator<Item = T>, T: PartialEq {
13
14 #[inline]
15 fn nudge_block(&mut self) {
16 self.block_number += 1;
17 self.block_position = 0;
18 }
19
20 #[inline]
21 fn nudge_position(&mut self) {
22 self.block_position += 1;
23 }
24
25 #[inline]
26 fn get_position(&self) -> (usize, usize) {
27 (self.block_number, self.block_position)
28 }
29}
30
31pub fn enumerate_split<Iter, T>(iter: Iter, split_value: T) -> EnumerateSplit<Iter, T>
52where Iter: Iterator<Item = T>, T: PartialEq {
53 EnumerateSplit {
54 iter: iter,
55 split_value: split_value,
56 block_number: 0,
57 block_position: 0
58 }
59}
60
61impl<Iter, T> Iterator for EnumerateSplit<Iter, T>
62where Iter: Iterator<Item = T>, T: PartialEq {
63 type Item = (T, (usize, usize));
64 fn next(&mut self) -> Option<(T, (usize, usize))> {
65 match self.iter.next() {
66 Some(t) => {
67 let split = t == self.split_value;
68 let res = Some((t, self.get_position()));
69 if split {
70 self.nudge_block();
71 } else {
72 self.nudge_position();
73 }
74 res
75 }
76 None => None
77 }
78 }
79}
80
81#[cfg(test)]
83mod tests {
84 use std::io::prelude::*;
85
86 #[test]
87 fn enumerate_split() {
88 let mut input = super::enumerate_split("Some \n\nstring with a newline".chars(), '\n');
89 assert_eq!(input.next(), Some(('S', (0, 0))));
90 assert_eq!(input.next(), Some(('o', (0, 1))));
91 assert_eq!(input.next(), Some(('m', (0, 2))));
92 assert_eq!(input.next(), Some(('e', (0, 3))));
93 assert_eq!(input.next(), Some((' ', (0, 4))));
94 assert_eq!(input.next(), Some(('\n', (0, 5))));
95 assert_eq!(input.next(), Some(('\n', (1, 0))));
96 assert_eq!(input.next(), Some(('s', (2, 0))));
97 }
98}
99