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}