msd 0.4.0

A library for reading and writing MSD files.
Documentation
enum State {
    TrimmingBeginning,
    ReturningBytes,
    IntermediateWhitespace,
    Completed,
}

pub(super) struct Trim<I> {
    iter: I,
    state: State,
}

impl<I> Trim<I> {
    pub(super) fn new(iter: I) -> Self {
        Self {
            iter,
            state: State::TrimmingBeginning,
        }
    }
}

impl<I> Iterator for Trim<I>
where
    I: Iterator<Item = u8> + Clone,
{
    type Item = u8;

    fn next(&mut self) -> Option<Self::Item> {
        match self.state {
            State::TrimmingBeginning => loop {
                let byte = self.iter.next()?;

                if !byte.is_ascii_whitespace() {
                    self.state = State::ReturningBytes;
                    return Some(byte);
                }
            },
            State::ReturningBytes => {
                let byte = self.iter.next()?;

                if byte.is_ascii_whitespace() {
                    match self.iter.clone().find(|b| !b.is_ascii_whitespace()) {
                        Some(_) => {
                            self.state = State::IntermediateWhitespace;
                            Some(byte)
                        }
                        None => {
                            self.state = State::Completed;
                            None
                        }
                    }
                } else {
                    Some(byte)
                }
            }
            State::IntermediateWhitespace => {
                let byte = self.iter.next()?;
                if !byte.is_ascii_whitespace() {
                    self.state = State::ReturningBytes;
                }
                Some(byte)
            }
            State::Completed => None,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Trim;

    #[test]
    fn empty() {
        assert_eq!(Trim::new(b"".iter().copied()).collect::<Vec<_>>(), b"");
    }

    #[test]
    fn nothing_to_trim() {
        assert_eq!(
            Trim::new(b"foo".iter().copied()).collect::<Vec<_>>(),
            b"foo"
        );
    }

    #[test]
    fn trims_front() {
        assert_eq!(
            Trim::new(b" \t\nfoo".iter().copied()).collect::<Vec<_>>(),
            b"foo"
        );
    }

    #[test]
    fn trims_back() {
        assert_eq!(
            Trim::new(b"foo\n \t".iter().copied()).collect::<Vec<_>>(),
            b"foo"
        );
    }

    #[test]
    fn trims_front_and_back() {
        assert_eq!(
            Trim::new(b" \t\nfoo\n \t".iter().copied()).collect::<Vec<_>>(),
            b"foo"
        );
    }

    #[test]
    fn trims_with_whitespace_in_middle() {
        assert_eq!(
            Trim::new(b" \t\nfoo  bar\n \t".iter().copied()).collect::<Vec<_>>(),
            b"foo  bar"
        );
    }

    #[test]
    fn trims_to_empty() {
        assert_eq!(
            Trim::new(b" \t\n  \n".iter().copied()).collect::<Vec<_>>(),
            b""
        );
    }
}