zeptohttpc/
parse.rs

1use std::io::{
2    BufRead, Error as IoError,
3    ErrorKind::{Other, UnexpectedEof},
4};
5
6use httparse::Status::{self, Complete, Partial};
7
8use super::MAX_PARSE_BUF_LEN;
9
10pub fn parse<R, P, T, E>(mut reader: R, parser: P) -> Result<T, E>
11where
12    R: BufRead,
13    P: Fn(&[u8]) -> Result<Status<(usize, T)>, E>,
14    E: From<IoError>,
15{
16    let buf = reader.fill_buf()?;
17    if let Complete((parsed, val)) = parser(buf)? {
18        reader.consume(parsed);
19        return Ok(val);
20    }
21
22    parse_buffered(reader, parser)
23}
24
25#[cold]
26fn parse_buffered<R, P, T, E>(mut reader: R, parser: P) -> Result<T, E>
27where
28    R: BufRead,
29    P: Fn(&[u8]) -> Result<Status<(usize, T)>, E>,
30    E: From<IoError>,
31{
32    let mut buf1 = Vec::new();
33    loop {
34        let buf = reader.fill_buf()?;
35        if buf.is_empty() {
36            return Err(IoError::from(UnexpectedEof).into());
37        }
38        if buf1.len() + buf.len() > MAX_PARSE_BUF_LEN {
39            return Err(IoError::new(Other, "Maximum parse buffer length reached").into());
40        }
41        buf1.extend_from_slice(buf);
42
43        match parser(&buf1)? {
44            Complete((parsed, val)) => {
45                let amt = parsed - (buf1.len() - buf.len());
46                reader.consume(amt);
47
48                return Ok(val);
49            }
50            Partial => {
51                let amt = buf.len();
52                reader.consume(amt);
53            }
54        }
55    }
56}