Skip to content

Commit 1f1cfce

Browse files
noxseanmonstar
authored andcommitted
Simplify the main parse_headers loop
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.
1 parent 7fd85d1 commit 1f1cfce

File tree

1 file changed

+55
-68
lines changed

1 file changed

+55
-68
lines changed

src/lib.rs

Lines changed: 55 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -921,17 +921,44 @@ fn parse_headers_iter_uninit<'a, 'b>(
921921

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

924+
macro_rules! maybe_continue_after_obsolete_line_folding {
925+
($bytes:ident, $label:lifetime) => {
926+
if config.allow_obsolete_multiline_headers_in_responses {
927+
match $bytes.peek() {
928+
None => {
929+
// Next byte may be a space, in which case that header
930+
// is using obsolete line folding, so we may have more
931+
// whitespace to skip after colon.
932+
return Ok(Status::Partial);
933+
}
934+
Some(b' ') | Some(b'\t') => {
935+
// The space will be consumed next iteration.
936+
continue $label;
937+
}
938+
_ => {
939+
// There is another byte after the end of the line,
940+
// but it's not whitespace, so it's probably another
941+
// header or the final line return. This header is thus
942+
// empty.
943+
},
944+
}
945+
}
946+
}
947+
}
948+
924949
'headers: loop {
925950
// a newline here means the head is over!
926-
let b = next!(bytes);
951+
let mut b = next!(bytes);
927952
if b == b'\r' {
928953
expect!(bytes.next() == b'\n' => Err(Error::NewLine));
929954
result = Ok(Status::Complete(count + bytes.pos()));
930955
break;
931-
} else if b == b'\n' {
956+
}
957+
if b == b'\n' {
932958
result = Ok(Status::Complete(count + bytes.pos()));
933959
break;
934-
} else if !is_header_name_token(b) {
960+
}
961+
if !is_header_name_token(b) {
935962
return Err(Error::HeaderName);
936963
}
937964

@@ -982,44 +1009,25 @@ fn parse_headers_iter_uninit<'a, 'b>(
9821009
count += bytes.pos();
9831010
bytes.slice();
9841011
continue 'whitespace_after_colon;
985-
} else {
986-
if !is_header_value_token(b) {
987-
if b == b'\r' {
988-
expect!(bytes.next() == b'\n' => Err(Error::HeaderValue));
989-
} else if b != b'\n' {
990-
return Err(Error::HeaderValue);
991-
}
1012+
}
1013+
if is_header_value_token(b) {
1014+
break 'whitespace_after_colon;
1015+
}
9921016

993-
if config.allow_obsolete_multiline_headers_in_responses {
994-
match bytes.peek() {
995-
None => {
996-
// Next byte may be a space, in which case that header
997-
// is using obsolete line folding, so we may have more
998-
// whitespace to skip after colon.
999-
return Ok(Status::Partial);
1000-
}
1001-
Some(b' ') | Some(b'\t') => {
1002-
// The space will be consumed next iteration.
1003-
continue 'whitespace_after_colon;
1004-
}
1005-
_ => {
1006-
// There is another byte after the end of the line,
1007-
// but it's not whitespace, so it's probably another
1008-
// header or the final line return. This header is thus
1009-
// empty.
1010-
},
1011-
}
1012-
}
1017+
if b == b'\r' {
1018+
expect!(bytes.next() == b'\n' => Err(Error::HeaderValue));
1019+
} else if b != b'\n' {
1020+
return Err(Error::HeaderValue);
1021+
}
10131022

1014-
count += bytes.pos();
1015-
let whitespace_slice = bytes.slice();
1023+
maybe_continue_after_obsolete_line_folding!(bytes, 'whitespace_after_colon);
10161024

1017-
// This produces an empty slice that points to the beginning
1018-
// of the whitespace.
1019-
break 'value &whitespace_slice[0..0];
1020-
}
1021-
break 'whitespace_after_colon;
1022-
}
1025+
count += bytes.pos();
1026+
let whitespace_slice = bytes.slice();
1027+
1028+
// This produces an empty slice that points to the beginning
1029+
// of the whitespace.
1030+
break 'value &whitespace_slice[0..0];
10231031
}
10241032

10251033
'value_lines: loop {
@@ -1036,19 +1044,16 @@ fn parse_headers_iter_uninit<'a, 'b>(
10361044
break 'value_line;
10371045
}
10381046
});
1039-
($bytes:ident) => ({
1040-
check!($bytes, _0);
1041-
check!($bytes, _1);
1042-
check!($bytes, _2);
1043-
check!($bytes, _3);
1044-
check!($bytes, _4);
1045-
check!($bytes, _5);
1046-
check!($bytes, _6);
1047-
check!($bytes, _7);
1048-
})
10491047
}
10501048

1051-
check!(bytes8);
1049+
check!(bytes8, _0);
1050+
check!(bytes8, _1);
1051+
check!(bytes8, _2);
1052+
check!(bytes8, _3);
1053+
check!(bytes8, _4);
1054+
check!(bytes8, _5);
1055+
check!(bytes8, _6);
1056+
check!(bytes8, _7);
10521057

10531058
continue 'value_line;
10541059
}
@@ -1069,25 +1074,7 @@ fn parse_headers_iter_uninit<'a, 'b>(
10691074
return Err(Error::HeaderValue);
10701075
};
10711076

1072-
if config.allow_obsolete_multiline_headers_in_responses {
1073-
match bytes.peek() {
1074-
None => {
1075-
// Next byte may be a space, in which case that header
1076-
// may be using line folding, so we need more data.
1077-
return Ok(Status::Partial);
1078-
}
1079-
Some(b' ') | Some(b'\t') => {
1080-
// The space will be consumed next iteration.
1081-
continue 'value_lines;
1082-
}
1083-
_ => {
1084-
// There is another byte after the end of the line,
1085-
// but it's not a space, so it's probably another
1086-
// header or the final line return. We are thus done
1087-
// with this current header.
1088-
},
1089-
}
1090-
}
1077+
maybe_continue_after_obsolete_line_folding!(bytes, 'value_lines);
10911078

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

0 commit comments

Comments
 (0)