diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
commit | 9835e2ae736235810b4ea1c162ca5e65c547e770 (patch) | |
tree | 3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/winnow/examples/http/parser.rs | |
parent | Releasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff) | |
download | rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip |
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/winnow/examples/http/parser.rs')
-rw-r--r-- | vendor/winnow/examples/http/parser.rs | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/vendor/winnow/examples/http/parser.rs b/vendor/winnow/examples/http/parser.rs new file mode 100644 index 000000000..83402fe26 --- /dev/null +++ b/vendor/winnow/examples/http/parser.rs @@ -0,0 +1,141 @@ +use winnow::{bytes::take_while1, character::line_ending, multi::many1, IResult, Parser}; + +pub type Stream<'i> = &'i [u8]; + +#[rustfmt::skip] +#[derive(Debug)] +#[allow(dead_code)] +pub struct Request<'a> { + method: &'a [u8], + uri: &'a [u8], + version: &'a [u8], +} + +#[derive(Debug)] +#[allow(dead_code)] +pub struct Header<'a> { + name: &'a [u8], + value: Vec<&'a [u8]>, +} + +pub fn parse(data: &[u8]) -> Option<Vec<(Request<'_>, Vec<Header<'_>>)>> { + let mut buf = data; + let mut v = Vec::new(); + loop { + match request(buf) { + Ok((b, r)) => { + buf = b; + v.push(r); + + if b.is_empty() { + //println!("{}", i); + break; + } + } + Err(e) => { + println!("error: {:?}", e); + return None; + } + } + } + + Some(v) +} + +fn request(input: Stream<'_>) -> IResult<Stream<'_>, (Request<'_>, Vec<Header<'_>>)> { + let (input, req) = request_line(input)?; + let (input, h) = many1(message_header).parse_next(input)?; + let (input, _) = line_ending(input)?; + + Ok((input, (req, h))) +} + +fn request_line(input: Stream<'_>) -> IResult<Stream<'_>, Request<'_>> { + let (input, method) = take_while1(is_token).parse_next(input)?; + let (input, _) = take_while1(is_space).parse_next(input)?; + let (input, uri) = take_while1(is_not_space).parse_next(input)?; + let (input, _) = take_while1(is_space).parse_next(input)?; + let (input, version) = http_version(input)?; + let (input, _) = line_ending(input)?; + + Ok(( + input, + Request { + method, + uri, + version, + }, + )) +} + +fn http_version(input: Stream<'_>) -> IResult<Stream<'_>, &[u8]> { + let (input, _) = "HTTP/".parse_next(input)?; + let (input, version) = take_while1(is_version).parse_next(input)?; + + Ok((input, version)) +} + +fn message_header_value(input: Stream<'_>) -> IResult<Stream<'_>, &[u8]> { + let (input, _) = take_while1(is_horizontal_space).parse_next(input)?; + let (input, data) = take_while1(not_line_ending).parse_next(input)?; + let (input, _) = line_ending(input)?; + + Ok((input, data)) +} + +fn message_header(input: Stream<'_>) -> IResult<Stream<'_>, Header<'_>> { + let (input, name) = take_while1(is_token).parse_next(input)?; + let (input, _) = ':'.parse_next(input)?; + let (input, value) = many1(message_header_value).parse_next(input)?; + + Ok((input, Header { name, value })) +} + +#[rustfmt::skip] +#[allow(clippy::match_same_arms)] +#[allow(clippy::match_like_matches_macro)] +fn is_token(c: u8) -> bool { + match c { + 128..=255 => false, + 0..=31 => false, + b'(' => false, + b')' => false, + b'<' => false, + b'>' => false, + b'@' => false, + b',' => false, + b';' => false, + b':' => false, + b'\\' => false, + b'"' => false, + b'/' => false, + b'[' => false, + b']' => false, + b'?' => false, + b'=' => false, + b'{' => false, + b'}' => false, + b' ' => false, + _ => true, + } +} + +fn is_version(c: u8) -> bool { + (b'0'..=b'9').contains(&c) || c == b'.' +} + +fn not_line_ending(c: u8) -> bool { + c != b'\r' && c != b'\n' +} + +fn is_space(c: u8) -> bool { + c == b' ' +} + +fn is_not_space(c: u8) -> bool { + c != b' ' +} + +fn is_horizontal_space(c: u8) -> bool { + c == b' ' || c == b'\t' +} |