oddity_rtsp_protocol/
buffer.rs

1use std::string::FromUtf8Error;
2
3pub use bytes::Buf;
4
5const LN: u8 = b'\x0a';
6const CR: u8 = b'\x0d';
7
8pub trait ReadLine {
9    fn read_line(&mut self) -> Option<Result<String, FromUtf8Error>>;
10}
11
12impl<T> ReadLine for T
13where
14    T: Buf,
15{
16    fn read_line(&mut self) -> Option<Result<String, FromUtf8Error>> {
17        if self.remaining() == 0 {
18            return None;
19        }
20
21        let mut found = false;
22        let mut end = 0; // Index of LN, CR or CRLN
23        let mut skip = 0; // Size of LN, CR or CRLN
24
25        let chunk = self.chunk();
26
27        for i in 0..chunk.len() - 1 {
28            if chunk[i] == CR && chunk[i + 1] == LN {
29                // Found CRLN at [i]
30                (found, end, skip) = (true, i, 2);
31                break;
32            }
33
34            if chunk[i] == CR || chunk[i] == LN {
35                // Found CR or LN at [i]
36                (found, end, skip) = (true, i, 1);
37                break;
38            }
39        }
40
41        if !found {
42            let last = chunk.len() - 1;
43            // Note that we explicitly do not check for CR here, since
44            // we can't know for sure if there isn't another LN coming
45            // after because this is the last character in the buffer.
46            if chunk[last] == LN {
47                // Found CRat [i]
48                (found, end, skip) = (true, last, 1);
49            }
50        }
51
52        if found {
53            let line = String::from_utf8(chunk[0..end].to_vec());
54            self.advance(end + skip);
55            Some(line)
56        } else {
57            None
58        }
59    }
60}