seanmonstar / httparse

A push parser for the HTTP 1.x protocol in Rust.
https://docs.rs/httparse
Apache License 2.0
573 stars 113 forks source link

Usage example with async #59

Open MOZGIII opened 5 years ago

MOZGIII commented 5 years ago

Hello, I'm trying to use this crate to implement a parser, but I'm having difficulties implementing response reading loop.

Here's my crate's code: https://github.com/MOZGIII/http-proxy-client-async And I'm having issues with this section in particular: https://github.com/MOZGIII/http-proxy-client-async/blob/d5d29ec06c5cd912e17ec358ee77860c7e8b4f61/src/http.rs#L39-L54

pub async fn receive_response<'buf, ARW>(stream: &mut ARW) -> io::Result<Vec<u8>>
where
    ARW: AsyncRead + AsyncWrite + Unpin,
{
    let mut response_headers = [httparse::EMPTY_HEADER; 16];
    let mut buf = [0u8; 1024];
    let mut response = httparse::Response::new(&mut response_headers);

    let (consumed, total) = loop {
        let total = stream.read(&mut buf).await?;
        let result = response.parse(&buf[..total]);
        match result {
            Err(err) => return Err(io::Error::new(io::ErrorKind::InvalidData, err)),
            Ok(httparse::Status::Complete(consumed)) => break (consumed, total),
            Ok(httparse::Status::Partial) => continue,
        };
    };

    let leftovers = Vec::from(&buf[consumed..total]);
    Ok(leftovers)
}

The issue is with borrowing the buf:

error[E0502]: cannot borrow `buf` as mutable because it is also borrowed as immutable
  --> src/http.rs:44:33
   |
44 |         let total = stream.read(&mut buf).await?;
   |                                 ^^^^^^^^ mutable borrow occurs here
45 |         let result = response.parse(&buf[..total]);
   |                      --------        --- immutable borrow occurs here
   |                      |
   |                      immutable borrow later used here

Since this crate has a kind of unique API, how would you recommend solving this issue?