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);
    }
}