Skip to content

Commit c02acbc

Browse files
committed
feat: rewrite forwarded header module
Based on http-rs#508 by @kyrias
1 parent 21f7ffc commit c02acbc

File tree

4 files changed

+901
-499
lines changed

4 files changed

+901
-499
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ dist/
55
npm-debug.log*
66
Cargo.lock
77
.DS_Store
8+
.nvim/

Diff for: src/parse_utils.rs

+40-30
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::borrow::Cow;
22

3-
/// https://tools.ietf.org/html/rfc7230#section-3.2.6
4-
pub(crate) fn parse_token(input: &str) -> (Option<&str>, &str) {
3+
/// <https://tools.ietf.org/html/rfc7230#section-3.2.6>
4+
pub(crate) fn parse_token(input: &str) -> Option<(Cow<'_, str>, &str)> {
55
let mut end_of_token = 0;
66
for (i, c) in input.char_indices() {
77
if tchar(c) {
@@ -12,14 +12,15 @@ pub(crate) fn parse_token(input: &str) -> (Option<&str>, &str) {
1212
}
1313

1414
if end_of_token == 0 {
15-
(None, input)
15+
None
1616
} else {
17-
(Some(&input[..end_of_token]), &input[end_of_token..])
17+
let (token, rest) = input.split_at(end_of_token);
18+
Some((Cow::from(token), rest))
1819
}
1920
}
2021

21-
/// https://tools.ietf.org/html/rfc7230#section-3.2.6
22-
fn tchar(c: char) -> bool {
22+
/// <https://tools.ietf.org/html/rfc7230#section-3.2.6>
23+
pub(crate) fn tchar(c: char) -> bool {
2324
matches!(
2425
c, 'a'..='z'
2526
| 'A'..='Z'
@@ -42,16 +43,16 @@ fn tchar(c: char) -> bool {
4243
)
4344
}
4445

45-
/// https://tools.ietf.org/html/rfc7230#section-3.2.6
46+
/// <https://tools.ietf.org/html/rfc7230#section-3.2.6>
4647
fn vchar(c: char) -> bool {
4748
matches!(c as u8, b'\t' | 32..=126 | 128..=255)
4849
}
4950

50-
/// https://tools.ietf.org/html/rfc7230#section-3.2.6
51-
pub(crate) fn parse_quoted_string(input: &str) -> (Option<Cow<'_, str>>, &str) {
51+
/// <https://tools.ietf.org/html/rfc7230#section-3.2.6>
52+
pub(crate) fn parse_quoted_string(input: &str) -> Option<(Cow<'_, str>, &str)> {
5253
// quoted-string must start with a DQUOTE
5354
if !input.starts_with('"') {
54-
return (None, input);
55+
return None;
5556
}
5657

5758
let mut end_of_string = None;
@@ -61,7 +62,7 @@ pub(crate) fn parse_quoted_string(input: &str) -> (Option<Cow<'_, str>>, &str) {
6162
if i > 1 && backslashes.last() == Some(&(i - 2)) {
6263
if !vchar(c) {
6364
// only VCHARs can be escaped
64-
return (None, input);
65+
return None;
6566
}
6667
// otherwise, we skip over this character while parsing
6768
} else {
@@ -81,7 +82,7 @@ pub(crate) fn parse_quoted_string(input: &str) -> (Option<Cow<'_, str>>, &str) {
8182
b'\t' | b' ' | 15 | 35..=91 | 93..=126 | 128..=255 => {}
8283

8384
// unexpected character, bail
84-
_ => return (None, input),
85+
_ => return None,
8586
}
8687
}
8788
}
@@ -110,10 +111,10 @@ pub(crate) fn parse_quoted_string(input: &str) -> (Option<Cow<'_, str>>, &str) {
110111
.into()
111112
};
112113

113-
(Some(value), &input[end_of_string..])
114+
Some((value, &input[end_of_string..]))
114115
} else {
115116
// we never reached a closing DQUOTE, so we do not have a valid quoted-string
116-
(None, input)
117+
None
117118
}
118119
}
119120

@@ -122,42 +123,51 @@ mod test {
122123
use super::*;
123124
#[test]
124125
fn token_successful_parses() {
125-
assert_eq!(parse_token("key=value"), (Some("key"), "=value"));
126-
assert_eq!(parse_token("KEY=value"), (Some("KEY"), "=value"));
127-
assert_eq!(parse_token("0123)=value"), (Some("0123"), ")=value"));
128-
assert_eq!(parse_token("a=b"), (Some("a"), "=b"));
129-
assert_eq!(parse_token("!#$%&'*+-.^_`|~=value"), (Some("!#$%&'*+-.^_`|~"), "=value",));
126+
assert_eq!(parse_token("key=value"), Some(("key".into(), "=value")));
127+
assert_eq!(parse_token("KEY=value"), Some(("KEY".into(), "=value")));
128+
assert_eq!(parse_token("0123)=value"), Some(("0123".into(), ")=value")));
129+
assert_eq!(parse_token("a=b"), Some(("a".into(), "=b")));
130+
assert_eq!(
131+
parse_token("!#$%&'*+-.^_`|~=value"),
132+
Some(("!#$%&'*+-.^_`|~".into(), "=value"))
133+
);
130134
}
131135

132136
#[test]
133137
fn token_unsuccessful_parses() {
134-
assert_eq!(parse_token(""), (None, ""));
135-
assert_eq!(parse_token("=value"), (None, "=value"));
138+
assert_eq!(parse_token(""), None);
139+
assert_eq!(parse_token("=value"), None);
136140
for c in r#"(),/:;<=>?@[\]{}"#.chars() {
137141
let s = c.to_string();
138-
assert_eq!(parse_token(&s), (None, &*s));
142+
assert_eq!(parse_token(&s), None);
139143

140144
let s = format!("match{}rest", s);
141-
assert_eq!(parse_token(&s), (Some("match"), &*format!("{}rest", c)));
145+
assert_eq!(
146+
parse_token(&s),
147+
Some(("match".into(), &*format!("{}rest", c)))
148+
);
142149
}
143150
}
144151

145152
#[test]
146153
fn qstring_successful_parses() {
147-
assert_eq!(parse_quoted_string(r#""key"=value"#), (Some(Cow::Borrowed("key")), "=value"));
154+
assert_eq!(
155+
parse_quoted_string(r#""key"=value"#),
156+
Some((Cow::Borrowed("key"), "=value"))
157+
);
148158

149159
assert_eq!(
150160
parse_quoted_string(r#""escaped \" quote \""rest"#),
151-
(Some(Cow::Owned(String::from(r#"escaped " quote ""#))), r#"rest"#)
161+
Some((Cow::Owned(String::from(r#"escaped " quote ""#)), r#"rest"#))
152162
);
153163
}
154164

155165
#[test]
156166
fn qstring_unsuccessful_parses() {
157-
assert_eq!(parse_quoted_string(r#""abc"#), (None, "\"abc"));
158-
assert_eq!(parse_quoted_string(r#"hello""#), (None, "hello\"",));
159-
assert_eq!(parse_quoted_string(r#"=value\"#), (None, "=value\\"));
160-
assert_eq!(parse_quoted_string(r#"\""#), (None, r#"\""#));
161-
assert_eq!(parse_quoted_string(r#""\""#), (None, r#""\""#));
167+
assert_eq!(parse_quoted_string(r#""abc"#), None);
168+
assert_eq!(parse_quoted_string(r#"hello""#), None);
169+
assert_eq!(parse_quoted_string(r#"=value\"#), None);
170+
assert_eq!(parse_quoted_string(r#"\""#), None);
171+
assert_eq!(parse_quoted_string(r#""\""#), None);
162172
}
163173
}

0 commit comments

Comments
 (0)