Skip to content

Commit 82c5ec6

Browse files
committed
utils: Move iterator helpers to their own module
In the interest of cleanliness. Signed-off-by: Colin Walters <[email protected]>
1 parent f222c1e commit 82c5ec6

File tree

2 files changed

+96
-95
lines changed

2 files changed

+96
-95
lines changed

utils/src/iterators.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/// Given an iterator that's clonable, split it into two iterators
2+
/// at a given maximum number of elements.
3+
pub fn iterator_split<I>(
4+
it: I,
5+
max: usize,
6+
) -> (impl Iterator<Item = I::Item>, impl Iterator<Item = I::Item>)
7+
where
8+
I: Iterator + Clone,
9+
{
10+
let rest = it.clone();
11+
(it.take(max), rest.skip(max))
12+
}
13+
14+
/// Given an iterator that's clonable, split off the first N elements
15+
/// at the pivot point. If the iterator would be empty, return None.
16+
/// Return the count of the remainder.
17+
pub fn iterator_split_nonempty_rest_count<I>(
18+
it: I,
19+
max: usize,
20+
) -> Option<(impl Iterator<Item = I::Item>, usize)>
21+
where
22+
I: Iterator + Clone,
23+
{
24+
let rest = it.clone();
25+
let mut it = it.peekable();
26+
if it.peek().is_some() {
27+
Some((it.take(max), rest.skip(max).count()))
28+
} else {
29+
None
30+
}
31+
}
32+
33+
#[cfg(test)]
34+
mod tests {
35+
use super::*;
36+
37+
#[test]
38+
fn test_it_split() {
39+
let a: &[&str] = &[];
40+
for v in [0, 1, 5] {
41+
let (first, rest) = iterator_split(a.iter(), v);
42+
assert_eq!(first.count(), 0);
43+
assert_eq!(rest.count(), 0);
44+
}
45+
let a = &["foo"];
46+
for v in [1, 5] {
47+
let (first, rest) = iterator_split(a.iter(), v);
48+
assert_eq!(first.count(), 1);
49+
assert_eq!(rest.count(), 0);
50+
}
51+
let (first, rest) = iterator_split(a.iter(), 1);
52+
assert_eq!(first.count(), 1);
53+
assert_eq!(rest.count(), 0);
54+
let a = &["foo", "bar", "baz", "blah", "other"];
55+
let (first, rest) = iterator_split(a.iter(), 2);
56+
assert_eq!(first.count(), 2);
57+
assert_eq!(rest.count(), 3);
58+
}
59+
60+
#[test]
61+
fn test_split_empty_iterator() {
62+
let a: &[&str] = &[];
63+
for v in [0, 1, 5] {
64+
assert!(iterator_split_nonempty_rest_count(a.iter(), v).is_none());
65+
}
66+
}
67+
68+
#[test]
69+
fn test_split_nonempty_iterator() {
70+
let a = &["foo"];
71+
72+
let Some((elts, 1)) = iterator_split_nonempty_rest_count(a.iter(), 0) else {
73+
panic!()
74+
};
75+
assert_eq!(elts.count(), 0);
76+
77+
let Some((elts, 0)) = iterator_split_nonempty_rest_count(a.iter(), 1) else {
78+
panic!()
79+
};
80+
assert_eq!(elts.count(), 1);
81+
82+
let Some((elts, 0)) = iterator_split_nonempty_rest_count(a.iter(), 5) else {
83+
panic!()
84+
};
85+
assert_eq!(elts.count(), 1);
86+
87+
let a = &["foo", "bar", "baz", "blah", "other"];
88+
let Some((elts, 3)) = iterator_split_nonempty_rest_count(a.iter(), 2) else {
89+
panic!()
90+
};
91+
assert_eq!(elts.count(), 2);
92+
}
93+
}

utils/src/lib.rs

Lines changed: 3 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -3,100 +3,8 @@
33
//! "core" crates.
44
//!
55
mod command;
6-
mod tracing_util;
76
pub use command::*;
7+
mod iterators;
8+
pub use iterators::*;
9+
mod tracing_util;
810
pub use tracing_util::*;
9-
10-
/// Given an iterator that's clonable, split it into two iterators
11-
/// at a given maximum number of elements.
12-
pub fn iterator_split<I>(
13-
it: I,
14-
max: usize,
15-
) -> (impl Iterator<Item = I::Item>, impl Iterator<Item = I::Item>)
16-
where
17-
I: Iterator + Clone,
18-
{
19-
let rest = it.clone();
20-
(it.take(max), rest.skip(max))
21-
}
22-
23-
/// Given an iterator that's clonable, split off the first N elements
24-
/// at the pivot point. If the iterator would be empty, return None.
25-
/// Return the count of the remainder.
26-
pub fn iterator_split_nonempty_rest_count<I>(
27-
it: I,
28-
max: usize,
29-
) -> Option<(impl Iterator<Item = I::Item>, usize)>
30-
where
31-
I: Iterator + Clone,
32-
{
33-
let rest = it.clone();
34-
let mut it = it.peekable();
35-
if it.peek().is_some() {
36-
Some((it.take(max), rest.skip(max).count()))
37-
} else {
38-
None
39-
}
40-
}
41-
42-
#[cfg(test)]
43-
mod tests {
44-
use super::*;
45-
46-
#[test]
47-
fn test_it_split() {
48-
let a: &[&str] = &[];
49-
for v in [0, 1, 5] {
50-
let (first, rest) = iterator_split(a.iter(), v);
51-
assert_eq!(first.count(), 0);
52-
assert_eq!(rest.count(), 0);
53-
}
54-
let a = &["foo"];
55-
for v in [1, 5] {
56-
let (first, rest) = iterator_split(a.iter(), v);
57-
assert_eq!(first.count(), 1);
58-
assert_eq!(rest.count(), 0);
59-
}
60-
let (first, rest) = iterator_split(a.iter(), 1);
61-
assert_eq!(first.count(), 1);
62-
assert_eq!(rest.count(), 0);
63-
let a = &["foo", "bar", "baz", "blah", "other"];
64-
let (first, rest) = iterator_split(a.iter(), 2);
65-
assert_eq!(first.count(), 2);
66-
assert_eq!(rest.count(), 3);
67-
}
68-
69-
#[test]
70-
fn test_split_empty_iterator() {
71-
let a: &[&str] = &[];
72-
for v in [0, 1, 5] {
73-
assert!(iterator_split_nonempty_rest_count(a.iter(), v).is_none());
74-
}
75-
}
76-
77-
#[test]
78-
fn test_split_nonempty_iterator() {
79-
let a = &["foo"];
80-
81-
let Some((elts, 1)) = iterator_split_nonempty_rest_count(a.iter(), 0) else {
82-
panic!()
83-
};
84-
assert_eq!(elts.count(), 0);
85-
86-
let Some((elts, 0)) = iterator_split_nonempty_rest_count(a.iter(), 1) else {
87-
panic!()
88-
};
89-
assert_eq!(elts.count(), 1);
90-
91-
let Some((elts, 0)) = iterator_split_nonempty_rest_count(a.iter(), 5) else {
92-
panic!()
93-
};
94-
assert_eq!(elts.count(), 1);
95-
96-
let a = &["foo", "bar", "baz", "blah", "other"];
97-
let Some((elts, 3)) = iterator_split_nonempty_rest_count(a.iter(), 2) else {
98-
panic!()
99-
};
100-
assert_eq!(elts.count(), 2);
101-
}
102-
}

0 commit comments

Comments
 (0)