maybe_fut/api/io/
split.rs

1use super::BufRead;
2
3#[derive(Debug)]
4pub struct Split<B> {
5    pub(crate) buf: B,
6    pub(crate) delim: u8,
7}
8
9impl<B: BufRead> Split<B> {
10    /// Returns next token from the buffer.
11    pub async fn next(&mut self) -> Option<std::io::Result<Vec<u8>>> {
12        let mut buf = Vec::new();
13        match self.buf.read_until(self.delim, &mut buf).await {
14            Ok(0) => None,
15            Ok(_n) => {
16                if buf[buf.len() - 1] == self.delim {
17                    buf.pop();
18                }
19                Some(Ok(buf))
20            }
21            Err(e) => Some(Err(e)),
22        }
23    }
24}
25
26#[cfg(test)]
27mod test {
28
29    use super::*;
30    use crate::io::{BufReader, Read};
31
32    #[tokio::test]
33    async fn test_should_return_tokens() {
34        let data = b"line1|line2|line3";
35        let buf = BufReader::new(Buffer::new(data.to_vec()));
36        let mut tokens = Split { buf, delim: b'|' };
37
38        assert_eq!(tokens.next().await.unwrap().unwrap(), b"line1");
39        assert_eq!(tokens.next().await.unwrap().unwrap(), b"line2");
40        assert_eq!(tokens.next().await.unwrap().unwrap(), b"line3");
41        assert!(tokens.next().await.is_none());
42    }
43
44    struct Buffer {
45        data: Vec<u8>,
46        pos: usize,
47    }
48
49    impl Buffer {
50        fn new(data: Vec<u8>) -> Self {
51            Self { data, pos: 0 }
52        }
53    }
54
55    impl Read for Buffer {
56        async fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
57            if self.pos >= self.data.len() {
58                return Ok(0);
59            }
60            let n = std::cmp::min(buf.len(), self.data.len() - self.pos);
61            buf[..n].copy_from_slice(&self.data[self.pos..self.pos + n]);
62            self.pos += n;
63            Ok(n)
64        }
65    }
66}