y-octo 0.0.3

High-performance and thread-safe CRDT implementation compatible with Yjs
Documentation
use super::*;

pub struct SyncMessageScanner<'a> {
    buffer: &'a [u8],
}

impl SyncMessageScanner<'_> {
    pub fn new(buffer: &[u8]) -> SyncMessageScanner<'_> {
        SyncMessageScanner { buffer }
    }
}

impl<'a> Iterator for SyncMessageScanner<'a> {
    type Item = Result<SyncMessage, nom::Err<nom::error::Error<&'a [u8]>>>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.buffer.is_empty() {
            return None;
        }

        match read_sync_message(self.buffer) {
            Ok((tail, message)) => {
                self.buffer = tail;
                Some(Ok(message))
            }
            Err(nom::Err::Incomplete(_))
            | Err(nom::Err::Error(nom::error::Error {
                code: nom::error::ErrorKind::Eof,
                ..
            }))
            | Err(nom::Err::Failure(nom::error::Error {
                code: nom::error::ErrorKind::Eof,
                ..
            })) => {
                debug!("incomplete sync message");
                None
            }

            Err(e) => Some(Err(e)),
        }
    }
}

#[cfg(test)]
mod tests {
    use proptest::{collection::vec, prelude::*};

    use super::*;

    proptest! {
        #[test]
        #[cfg_attr(miri, ignore)]
        fn test_sync_message_scanner(messages in vec(any::<SyncMessage>(), 0..10)) {
            let mut buffer = Vec::new();

            for message in &messages {
                write_sync_message(&mut buffer, message).unwrap();
            }

            let result: Result<Vec<SyncMessage>, _> = SyncMessageScanner::new(&buffer).collect();
            assert_eq!(result.unwrap(), messages);
        }
    }
}