Skip to content

Commit

Permalink
Simplify the main parse_headers loop
Browse files Browse the repository at this point in the history
I added a macro `maybe_continue_after_obsolete_line_folding`, I simplified
the check macro used with `next_8`, and I reduced nesting in the
`'whitespace_after_colon` loop.
  • Loading branch information
nox authored and seanmonstar committed May 19, 2022
1 parent 7fd85d1 commit 1f1cfce
Showing 1 changed file with 55 additions and 68 deletions.
123 changes: 55 additions & 68 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -921,17 +921,44 @@ fn parse_headers_iter_uninit<'a, 'b>(

let mut iter = autoshrink.headers.iter_mut();

macro_rules! maybe_continue_after_obsolete_line_folding {
($bytes:ident, $label:lifetime) => {
if config.allow_obsolete_multiline_headers_in_responses {
match $bytes.peek() {
None => {
// Next byte may be a space, in which case that header
// is using obsolete line folding, so we may have more
// whitespace to skip after colon.
return Ok(Status::Partial);
}
Some(b' ') | Some(b'\t') => {
// The space will be consumed next iteration.
continue $label;
}
_ => {
// There is another byte after the end of the line,
// but it's not whitespace, so it's probably another
// header or the final line return. This header is thus
// empty.
},
}
}
}
}

'headers: loop {
// a newline here means the head is over!
let b = next!(bytes);
let mut b = next!(bytes);
if b == b'\r' {
expect!(bytes.next() == b'\n' => Err(Error::NewLine));
result = Ok(Status::Complete(count + bytes.pos()));
break;
} else if b == b'\n' {
}
if b == b'\n' {
result = Ok(Status::Complete(count + bytes.pos()));
break;
} else if !is_header_name_token(b) {
}
if !is_header_name_token(b) {
return Err(Error::HeaderName);
}

Expand Down Expand Up @@ -982,44 +1009,25 @@ fn parse_headers_iter_uninit<'a, 'b>(
count += bytes.pos();
bytes.slice();
continue 'whitespace_after_colon;
} else {
if !is_header_value_token(b) {
if b == b'\r' {
expect!(bytes.next() == b'\n' => Err(Error::HeaderValue));
} else if b != b'\n' {
return Err(Error::HeaderValue);
}
}
if is_header_value_token(b) {
break 'whitespace_after_colon;
}

if config.allow_obsolete_multiline_headers_in_responses {
match bytes.peek() {
None => {
// Next byte may be a space, in which case that header
// is using obsolete line folding, so we may have more
// whitespace to skip after colon.
return Ok(Status::Partial);
}
Some(b' ') | Some(b'\t') => {
// The space will be consumed next iteration.
continue 'whitespace_after_colon;
}
_ => {
// There is another byte after the end of the line,
// but it's not whitespace, so it's probably another
// header or the final line return. This header is thus
// empty.
},
}
}
if b == b'\r' {
expect!(bytes.next() == b'\n' => Err(Error::HeaderValue));
} else if b != b'\n' {
return Err(Error::HeaderValue);
}

count += bytes.pos();
let whitespace_slice = bytes.slice();
maybe_continue_after_obsolete_line_folding!(bytes, 'whitespace_after_colon);

// This produces an empty slice that points to the beginning
// of the whitespace.
break 'value &whitespace_slice[0..0];
}
break 'whitespace_after_colon;
}
count += bytes.pos();
let whitespace_slice = bytes.slice();

// This produces an empty slice that points to the beginning
// of the whitespace.
break 'value &whitespace_slice[0..0];
}

'value_lines: loop {
Expand All @@ -1036,19 +1044,16 @@ fn parse_headers_iter_uninit<'a, 'b>(
break 'value_line;
}
});
($bytes:ident) => ({
check!($bytes, _0);
check!($bytes, _1);
check!($bytes, _2);
check!($bytes, _3);
check!($bytes, _4);
check!($bytes, _5);
check!($bytes, _6);
check!($bytes, _7);
})
}

check!(bytes8);
check!(bytes8, _0);
check!(bytes8, _1);
check!(bytes8, _2);
check!(bytes8, _3);
check!(bytes8, _4);
check!(bytes8, _5);
check!(bytes8, _6);
check!(bytes8, _7);

continue 'value_line;
}
Expand All @@ -1069,25 +1074,7 @@ fn parse_headers_iter_uninit<'a, 'b>(
return Err(Error::HeaderValue);
};

if config.allow_obsolete_multiline_headers_in_responses {
match bytes.peek() {
None => {
// Next byte may be a space, in which case that header
// may be using line folding, so we need more data.
return Ok(Status::Partial);
}
Some(b' ') | Some(b'\t') => {
// The space will be consumed next iteration.
continue 'value_lines;
}
_ => {
// There is another byte after the end of the line,
// but it's not a space, so it's probably another
// header or the final line return. We are thus done
// with this current header.
},
}
}
maybe_continue_after_obsolete_line_folding!(bytes, 'value_lines);

count += bytes.pos();
// having just checked that a newline exists, it's safe to skip it.
Expand Down

0 comments on commit 1f1cfce

Please sign in to comment.