summaryrefslogtreecommitdiffstats
path: root/vendor/winnow/examples/http
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
commit9835e2ae736235810b4ea1c162ca5e65c547e770 (patch)
tree3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/winnow/examples/http
parentReleasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff)
downloadrustc-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')
-rw-r--r--vendor/winnow/examples/http/bench.rs36
-rw-r--r--vendor/winnow/examples/http/main.rs47
-rw-r--r--vendor/winnow/examples/http/parser.rs141
-rw-r--r--vendor/winnow/examples/http/parser_streaming.rs143
4 files changed, 367 insertions, 0 deletions
diff --git a/vendor/winnow/examples/http/bench.rs b/vendor/winnow/examples/http/bench.rs
new file mode 100644
index 000000000..a27a119a6
--- /dev/null
+++ b/vendor/winnow/examples/http/bench.rs
@@ -0,0 +1,36 @@
+mod parser;
+mod parser_streaming;
+
+fn one_test(c: &mut criterion::Criterion) {
+ let data = &b"GET / HTTP/1.1
+Host: www.reddit.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+
+"[..];
+
+ let mut http_group = c.benchmark_group("http");
+ http_group.throughput(criterion::Throughput::Bytes(data.len() as u64));
+ http_group.bench_with_input(
+ criterion::BenchmarkId::new("complete", data.len()),
+ data,
+ |b, data| {
+ b.iter(|| parser::parse(data).unwrap());
+ },
+ );
+ http_group.bench_with_input(
+ criterion::BenchmarkId::new("streaming", data.len()),
+ data,
+ |b, data| {
+ b.iter(|| parser_streaming::parse(data).unwrap());
+ },
+ );
+
+ http_group.finish();
+}
+
+criterion::criterion_group!(http, one_test);
+criterion::criterion_main!(http);
diff --git a/vendor/winnow/examples/http/main.rs b/vendor/winnow/examples/http/main.rs
new file mode 100644
index 000000000..b0e480fb5
--- /dev/null
+++ b/vendor/winnow/examples/http/main.rs
@@ -0,0 +1,47 @@
+mod parser;
+
+fn main() -> Result<(), lexopt::Error> {
+ let args = Args::parse()?;
+
+ let input = args.input.as_deref().unwrap_or(
+ "GET / HTTP/1.1
+Host: www.reddit.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+
+",
+ );
+
+ if let Some(result) = parser::parse(input.as_bytes()) {
+ println!(" {:#?}", result);
+ }
+
+ Ok(())
+}
+
+#[derive(Default)]
+struct Args {
+ input: Option<String>,
+}
+
+impl Args {
+ fn parse() -> Result<Self, lexopt::Error> {
+ use lexopt::prelude::*;
+
+ let mut res = Args::default();
+
+ let mut args = lexopt::Parser::from_env();
+ while let Some(arg) = args.next()? {
+ match arg {
+ Value(input) => {
+ res.input = Some(input.string()?);
+ }
+ _ => return Err(arg.unexpected()),
+ }
+ }
+ Ok(res)
+ }
+}
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'
+}
diff --git a/vendor/winnow/examples/http/parser_streaming.rs b/vendor/winnow/examples/http/parser_streaming.rs
new file mode 100644
index 000000000..f7774b7bc
--- /dev/null
+++ b/vendor/winnow/examples/http/parser_streaming.rs
@@ -0,0 +1,143 @@
+use winnow::{
+ bytes::take_while1, character::line_ending, multi::many1, stream::Partial, IResult, Parser,
+};
+
+pub type Stream<'i> = Partial<&'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 = Partial::new(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'
+}