Skip to content
This repository has been archived by the owner on Feb 14, 2023. It is now read-only.

Commit

Permalink
Refactor field::with_headers() to not rely on broken lifetimes in `…
Browse files Browse the repository at this point in the history
…httparse::parse_headers()` (seanmonstar/httparse#34)
  • Loading branch information
abonander committed Mar 5, 2017
1 parent 5072bc9 commit ff61536
Showing 1 changed file with 15 additions and 14 deletions.
29 changes: 15 additions & 14 deletions src/server/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

//! `multipart` field header parsing.

use super::httparse::{self, EMPTY_HEADER, Status};
use super::httparse::{self, EMPTY_HEADER, Header, Status};

use self::ReadEntryResult::*;

Expand Down Expand Up @@ -46,15 +46,13 @@ pub struct StrHeader<'a> {

const MAX_ATTEMPTS: usize = 5;

fn with_headers<R, F, Ret>(r: &mut R, f: F) -> io::Result<Ret>
fn with_headers<R, F, Ret>(r: &mut R, closure: F) -> io::Result<Ret>
where R: BufRead, F: FnOnce(&[StrHeader]) -> Ret {
const HEADER_LEN: usize = 4;

// These are only written once so they don't need to be `mut` or initialized.
let consume;
let header_len;

let mut headers = [EMPTY_STR_HEADER; HEADER_LEN];
let ret;

{
let mut raw_headers = [EMPTY_HEADER; HEADER_LEN];
Expand All @@ -74,26 +72,29 @@ where R: BufRead, F: FnOnce(&[StrHeader]) -> Ret {
match try_io!(httparse::parse_headers(buf, &mut raw_headers)) {
Status::Complete((consume_, raw_headers)) => {
consume = consume_;
header_len = raw_headers.len();
let mut headers = [EMPTY_STR_HEADER; HEADER_LEN];
let headers = try!(copy_headers(raw_headers, headers));
debug!("Parsed headers: {:?}", headers);
ret = closure(headers);
break;
},
Status::Partial => attempts += 1,
}
}

for (raw, header) in raw_headers.iter().take(header_len).zip(&mut headers) {
header.name = raw.name;
header.val = try!(io_str_utf8(raw.value));
}
}

r.consume(consume);

let headers = &headers[..header_len];
Ok(ret)
}

debug!("Parsed headers: {:?}", headers);
fn copy_headers(raw: &[Header], headers: &mut [StrHeader]) -> io::Result<&[StrHeader]> {
for (raw, header) in raw_headers.iter().zip(&mut headers) {
header.name = raw.name;
header.val = try!(io_str_utf8(raw.value));
}

Ok(f(headers))
Ok(&mut headers[..raw.len()])
}

/// The headers that (may) appear before a `multipart/form-data` field.
Expand Down

0 comments on commit ff61536

Please sign in to comment.