56 lines
1.4 KiB
Rust
56 lines
1.4 KiB
Rust
pub fn blocks_of_lines_seperated_by<'a>(
|
|
input: &'a str,
|
|
on_skip: impl Fn(&'a str) -> bool,
|
|
) -> impl Iterator<Item = Vec<&'a str>> {
|
|
let mut current_block = Vec::new();
|
|
let mut lines = input.lines();
|
|
std::iter::from_fn(move || {
|
|
while let Some(next_line) = lines.next() {
|
|
if on_skip(next_line) {
|
|
if !current_block.is_empty() {
|
|
let to_return = std::mem::take(&mut current_block);
|
|
return Some(to_return);
|
|
}
|
|
} else {
|
|
current_block.push(next_line);
|
|
}
|
|
}
|
|
|
|
if !current_block.is_empty() {
|
|
let to_return = std::mem::take(&mut current_block);
|
|
return Some(to_return);
|
|
}
|
|
None
|
|
})
|
|
}
|
|
pub fn blocks_of_lines_seperated_by_empty_lines<'a>(
|
|
input: &'a str,
|
|
) -> impl Iterator<Item = Vec<&'a str>> {
|
|
blocks_of_lines_seperated_by(input, |line| line.trim().is_empty())
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod testing {
|
|
use std::vec;
|
|
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn split_blocks_by_empty_lines() {
|
|
const INPUT: &str = "
|
|
1st
|
|
2st
|
|
|
|
|
|
3st
|
|
|
|
4st
|
|
|
|
5st
|
|
";
|
|
let expected = vec![vec!["1st", "2st"], vec!["3st"], vec!["4st"], vec!["5st"]];
|
|
let actual: Vec<Vec<&str>> =
|
|
blocks_of_lines_seperated_by(INPUT, |line| line.trim().is_empty()).collect();
|
|
assert_eq!(expected, actual);
|
|
}
|
|
}
|