From cec1877e180393eba0f6ddb0cf97bf3a791631c7 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 7 Jun 2024 07:48:42 +0200 Subject: Merging upstream version 1.75.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/winnow-0.4.7/examples/arithmetic/bench.rs | 19 ++ vendor/winnow-0.4.7/examples/arithmetic/main.rs | 75 +++++ vendor/winnow-0.4.7/examples/arithmetic/parser.rs | 103 ++++++ .../winnow-0.4.7/examples/arithmetic/parser_ast.rs | 162 +++++++++ vendor/winnow-0.4.7/examples/css/main.rs | 62 ++++ vendor/winnow-0.4.7/examples/css/parser.rs | 31 ++ vendor/winnow-0.4.7/examples/custom_error.rs | 42 +++ vendor/winnow-0.4.7/examples/http/bench.rs | 36 ++ vendor/winnow-0.4.7/examples/http/main.rs | 47 +++ vendor/winnow-0.4.7/examples/http/parser.rs | 141 ++++++++ .../winnow-0.4.7/examples/http/parser_streaming.rs | 143 ++++++++ vendor/winnow-0.4.7/examples/ini/bench.rs | 61 ++++ vendor/winnow-0.4.7/examples/ini/main.rs | 60 ++++ vendor/winnow-0.4.7/examples/ini/parser.rs | 146 +++++++++ vendor/winnow-0.4.7/examples/ini/parser_str.rs | 206 ++++++++++++ vendor/winnow-0.4.7/examples/iterator.rs | 81 +++++ vendor/winnow-0.4.7/examples/json/bench.rs | 60 ++++ vendor/winnow-0.4.7/examples/json/json.rs | 11 + vendor/winnow-0.4.7/examples/json/main.rs | 118 +++++++ vendor/winnow-0.4.7/examples/json/parser.rs | 315 ++++++++++++++++++ .../winnow-0.4.7/examples/json/parser_dispatch.rs | 322 ++++++++++++++++++ .../winnow-0.4.7/examples/json/parser_partial.rs | 338 +++++++++++++++++++ vendor/winnow-0.4.7/examples/json_iterator.rs | 305 +++++++++++++++++ vendor/winnow-0.4.7/examples/ndjson/example.ndjson | 158 +++++++++ vendor/winnow-0.4.7/examples/ndjson/main.rs | 113 +++++++ vendor/winnow-0.4.7/examples/ndjson/parser.rs | 328 +++++++++++++++++++ vendor/winnow-0.4.7/examples/s_expression/main.rs | 20 ++ .../winnow-0.4.7/examples/s_expression/parser.rs | 362 +++++++++++++++++++++ vendor/winnow-0.4.7/examples/string/main.rs | 70 ++++ vendor/winnow-0.4.7/examples/string/parser.rs | 165 ++++++++++ 30 files changed, 4100 insertions(+) create mode 100644 vendor/winnow-0.4.7/examples/arithmetic/bench.rs create mode 100644 vendor/winnow-0.4.7/examples/arithmetic/main.rs create mode 100644 vendor/winnow-0.4.7/examples/arithmetic/parser.rs create mode 100644 vendor/winnow-0.4.7/examples/arithmetic/parser_ast.rs create mode 100644 vendor/winnow-0.4.7/examples/css/main.rs create mode 100644 vendor/winnow-0.4.7/examples/css/parser.rs create mode 100644 vendor/winnow-0.4.7/examples/custom_error.rs create mode 100644 vendor/winnow-0.4.7/examples/http/bench.rs create mode 100644 vendor/winnow-0.4.7/examples/http/main.rs create mode 100644 vendor/winnow-0.4.7/examples/http/parser.rs create mode 100644 vendor/winnow-0.4.7/examples/http/parser_streaming.rs create mode 100644 vendor/winnow-0.4.7/examples/ini/bench.rs create mode 100644 vendor/winnow-0.4.7/examples/ini/main.rs create mode 100644 vendor/winnow-0.4.7/examples/ini/parser.rs create mode 100644 vendor/winnow-0.4.7/examples/ini/parser_str.rs create mode 100644 vendor/winnow-0.4.7/examples/iterator.rs create mode 100644 vendor/winnow-0.4.7/examples/json/bench.rs create mode 100644 vendor/winnow-0.4.7/examples/json/json.rs create mode 100644 vendor/winnow-0.4.7/examples/json/main.rs create mode 100644 vendor/winnow-0.4.7/examples/json/parser.rs create mode 100644 vendor/winnow-0.4.7/examples/json/parser_dispatch.rs create mode 100644 vendor/winnow-0.4.7/examples/json/parser_partial.rs create mode 100644 vendor/winnow-0.4.7/examples/json_iterator.rs create mode 100644 vendor/winnow-0.4.7/examples/ndjson/example.ndjson create mode 100644 vendor/winnow-0.4.7/examples/ndjson/main.rs create mode 100644 vendor/winnow-0.4.7/examples/ndjson/parser.rs create mode 100644 vendor/winnow-0.4.7/examples/s_expression/main.rs create mode 100644 vendor/winnow-0.4.7/examples/s_expression/parser.rs create mode 100644 vendor/winnow-0.4.7/examples/string/main.rs create mode 100644 vendor/winnow-0.4.7/examples/string/parser.rs (limited to 'vendor/winnow-0.4.7/examples') diff --git a/vendor/winnow-0.4.7/examples/arithmetic/bench.rs b/vendor/winnow-0.4.7/examples/arithmetic/bench.rs new file mode 100644 index 000000000..0f6ec8eef --- /dev/null +++ b/vendor/winnow-0.4.7/examples/arithmetic/bench.rs @@ -0,0 +1,19 @@ +mod parser; + +use parser::expr; + +#[allow(clippy::eq_op, clippy::erasing_op)] +fn arithmetic(c: &mut criterion::Criterion) { + let data = " 2*2 / ( 5 - 1) + 3 / 4 * (2 - 7 + 567 *12 /2) + 3*(1+2*( 45 /2));"; + + assert_eq!( + expr(data), + Ok((";", 2 * 2 / (5 - 1) + 3 * (1 + 2 * (45 / 2)),)) + ); + c.bench_function("arithmetic", |b| { + b.iter(|| expr(data).unwrap()); + }); +} + +criterion::criterion_group!(benches, arithmetic); +criterion::criterion_main!(benches); diff --git a/vendor/winnow-0.4.7/examples/arithmetic/main.rs b/vendor/winnow-0.4.7/examples/arithmetic/main.rs new file mode 100644 index 000000000..94a17d85d --- /dev/null +++ b/vendor/winnow-0.4.7/examples/arithmetic/main.rs @@ -0,0 +1,75 @@ +use winnow::prelude::*; + +mod parser; +mod parser_ast; + +fn main() -> Result<(), lexopt::Error> { + let args = Args::parse()?; + + let input = args.input.as_deref().unwrap_or("1 + 1"); + + println!("{} =", input); + match args.implementation { + Impl::Eval => match parser::expr.parse(input) { + Ok(result) => { + println!(" {}", result); + } + Err(err) => { + println!(" {}", err); + } + }, + Impl::Ast => match parser_ast::expr.parse(input) { + Ok(result) => { + println!(" {:#?}", result); + } + Err(err) => { + println!(" {}", err); + } + }, + } + + Ok(()) +} + +#[derive(Default)] +struct Args { + input: Option, + implementation: Impl, +} + +enum Impl { + Eval, + Ast, +} + +impl Default for Impl { + fn default() -> Self { + Self::Eval + } +} + +impl Args { + fn parse() -> Result { + use lexopt::prelude::*; + + let mut res = Args::default(); + + let mut args = lexopt::Parser::from_env(); + while let Some(arg) = args.next()? { + match arg { + Long("impl") => { + res.implementation = args.value()?.parse_with(|s| match s { + "eval" => Ok(Impl::Eval), + "ast" => Ok(Impl::Ast), + _ => Err("expected `eval`, `ast`"), + })?; + } + Value(input) => { + res.input = Some(input.string()?); + } + _ => return Err(arg.unexpected()), + } + } + Ok(res) + } +} diff --git a/vendor/winnow-0.4.7/examples/arithmetic/parser.rs b/vendor/winnow-0.4.7/examples/arithmetic/parser.rs new file mode 100644 index 000000000..ba6347a43 --- /dev/null +++ b/vendor/winnow-0.4.7/examples/arithmetic/parser.rs @@ -0,0 +1,103 @@ +use std::str::FromStr; + +use winnow::prelude::*; +use winnow::{ + ascii::{digit1 as digits, space0 as spaces}, + combinator::alt, + combinator::delimited, + combinator::fold_repeat, + token::one_of, + IResult, +}; + +// Parser definition + +pub fn expr(i: &str) -> IResult<&str, i64> { + let (i, init) = term(i)?; + + fold_repeat( + 0.., + (one_of("+-"), term), + move || init, + |acc, (op, val): (char, i64)| { + if op == '+' { + acc + val + } else { + acc - val + } + }, + ) + .parse_next(i) +} + +// We read an initial factor and for each time we find +// a * or / operator followed by another factor, we do +// the math by folding everything +fn term(i: &str) -> IResult<&str, i64> { + let (i, init) = factor(i)?; + + fold_repeat( + 0.., + (one_of("*/"), factor), + move || init, + |acc, (op, val): (char, i64)| { + if op == '*' { + acc * val + } else { + acc / val + } + }, + ) + .parse_next(i) +} + +// We transform an integer string into a i64, ignoring surrounding whitespaces +// We look for a digit suite, and try to convert it. +// If either str::from_utf8 or FromStr::from_str fail, +// we fallback to the parens parser defined above +fn factor(i: &str) -> IResult<&str, i64> { + delimited( + spaces, + alt(( + digits.try_map(FromStr::from_str), + delimited('(', expr, ')'), + parens, + )), + spaces, + ) + .parse_next(i) +} + +// We parse any expr surrounded by parens, ignoring all whitespaces around those +fn parens(i: &str) -> IResult<&str, i64> { + delimited('(', expr, ')').parse_next(i) +} + +#[test] +fn factor_test() { + assert_eq!(factor("3"), Ok(("", 3))); + assert_eq!(factor(" 12"), Ok(("", 12))); + assert_eq!(factor("537 "), Ok(("", 537))); + assert_eq!(factor(" 24 "), Ok(("", 24))); +} + +#[test] +fn term_test() { + assert_eq!(term(" 12 *2 / 3"), Ok(("", 8))); + assert_eq!(term(" 2* 3 *2 *2 / 3"), Ok(("", 8))); + assert_eq!(term(" 48 / 3/2"), Ok(("", 8))); +} + +#[test] +fn expr_test() { + assert_eq!(expr(" 1 + 2 "), Ok(("", 3))); + assert_eq!(expr(" 12 + 6 - 4+ 3"), Ok(("", 17))); + assert_eq!(expr(" 1 + 2*3 + 4"), Ok(("", 11))); +} + +#[test] +fn parens_test() { + assert_eq!(expr(" ( 2 )"), Ok(("", 2))); + assert_eq!(expr(" 2* ( 3 + 4 ) "), Ok(("", 14))); + assert_eq!(expr(" 2*2 / ( 5 - 1) + 3"), Ok(("", 4))); +} diff --git a/vendor/winnow-0.4.7/examples/arithmetic/parser_ast.rs b/vendor/winnow-0.4.7/examples/arithmetic/parser_ast.rs new file mode 100644 index 000000000..fcf897e34 --- /dev/null +++ b/vendor/winnow-0.4.7/examples/arithmetic/parser_ast.rs @@ -0,0 +1,162 @@ +use std::fmt; +use std::fmt::{Debug, Display, Formatter}; + +use std::str::FromStr; + +use winnow::prelude::*; +use winnow::{ + ascii::{digit1 as digit, multispace0 as multispace}, + combinator::alt, + combinator::repeat, + combinator::{delimited, preceded}, + IResult, +}; + +#[derive(Debug)] +pub enum Expr { + Value(i64), + Add(Box, Box), + Sub(Box, Box), + Mul(Box, Box), + Div(Box, Box), + Paren(Box), +} + +#[derive(Debug)] +pub enum Oper { + Add, + Sub, + Mul, + Div, +} + +impl Display for Expr { + fn fmt(&self, format: &mut Formatter<'_>) -> fmt::Result { + use Expr::{Add, Div, Mul, Paren, Sub, Value}; + match *self { + Value(val) => write!(format, "{}", val), + Add(ref left, ref right) => write!(format, "{} + {}", left, right), + Sub(ref left, ref right) => write!(format, "{} - {}", left, right), + Mul(ref left, ref right) => write!(format, "{} * {}", left, right), + Div(ref left, ref right) => write!(format, "{} / {}", left, right), + Paren(ref expr) => write!(format, "({})", expr), + } + } +} + +pub fn expr(i: &str) -> IResult<&str, Expr> { + let (i, initial) = term(i)?; + let (i, remainder) = repeat( + 0.., + alt(( + |i| { + let (i, add) = preceded("+", term).parse_next(i)?; + Ok((i, (Oper::Add, add))) + }, + |i| { + let (i, sub) = preceded("-", term).parse_next(i)?; + Ok((i, (Oper::Sub, sub))) + }, + )), + ) + .parse_next(i)?; + + Ok((i, fold_exprs(initial, remainder))) +} + +fn term(i: &str) -> IResult<&str, Expr> { + let (i, initial) = factor(i)?; + let (i, remainder) = repeat( + 0.., + alt(( + |i| { + let (i, mul) = preceded("*", factor).parse_next(i)?; + Ok((i, (Oper::Mul, mul))) + }, + |i| { + let (i, div) = preceded("/", factor).parse_next(i)?; + Ok((i, (Oper::Div, div))) + }, + )), + ) + .parse_next(i)?; + + Ok((i, fold_exprs(initial, remainder))) +} + +fn factor(i: &str) -> IResult<&str, Expr> { + alt(( + delimited(multispace, digit, multispace) + .try_map(FromStr::from_str) + .map(Expr::Value), + parens, + )) + .parse_next(i) +} + +fn parens(i: &str) -> IResult<&str, Expr> { + delimited( + multispace, + delimited("(", expr.map(|e| Expr::Paren(Box::new(e))), ")"), + multispace, + ) + .parse_next(i) +} + +fn fold_exprs(initial: Expr, remainder: Vec<(Oper, Expr)>) -> Expr { + remainder.into_iter().fold(initial, |acc, pair| { + let (oper, expr) = pair; + match oper { + Oper::Add => Expr::Add(Box::new(acc), Box::new(expr)), + Oper::Sub => Expr::Sub(Box::new(acc), Box::new(expr)), + Oper::Mul => Expr::Mul(Box::new(acc), Box::new(expr)), + Oper::Div => Expr::Div(Box::new(acc), Box::new(expr)), + } + }) +} + +#[test] +fn factor_test() { + assert_eq!( + factor(" 3 ").map(|(i, x)| (i, format!("{:?}", x))), + Ok(("", String::from("Value(3)"))) + ); +} + +#[test] +fn term_test() { + assert_eq!( + term(" 3 * 5 ").map(|(i, x)| (i, format!("{:?}", x))), + Ok(("", String::from("Mul(Value(3), Value(5))"))) + ); +} + +#[test] +fn expr_test() { + assert_eq!( + expr(" 1 + 2 * 3 ").map(|(i, x)| (i, format!("{:?}", x))), + Ok(("", String::from("Add(Value(1), Mul(Value(2), Value(3)))"))) + ); + assert_eq!( + expr(" 1 + 2 * 3 / 4 - 5 ").map(|(i, x)| (i, format!("{:?}", x))), + Ok(( + "", + String::from("Sub(Add(Value(1), Div(Mul(Value(2), Value(3)), Value(4))), Value(5))") + )) + ); + assert_eq!( + expr(" 72 / 2 / 3 ").map(|(i, x)| (i, format!("{:?}", x))), + Ok(("", String::from("Div(Div(Value(72), Value(2)), Value(3))"))) + ); +} + +#[test] +fn parens_test() { + assert_eq!( + expr(" ( 1 + 2 ) * 3 ").map(|(i, x)| (i, format!("{:?}", x))), + Ok(( + "", + String::from("Mul(Paren(Add(Value(1), Value(2))), Value(3))") + )) + ); +} diff --git a/vendor/winnow-0.4.7/examples/css/main.rs b/vendor/winnow-0.4.7/examples/css/main.rs new file mode 100644 index 000000000..26c1b9212 --- /dev/null +++ b/vendor/winnow-0.4.7/examples/css/main.rs @@ -0,0 +1,62 @@ +use winnow::prelude::*; + +mod parser; + +use parser::hex_color; + +fn main() -> Result<(), lexopt::Error> { + let args = Args::parse()?; + + let input = args.input.as_deref().unwrap_or("#AAAAAA"); + + println!("{} =", input); + match hex_color.parse(input) { + Ok(result) => { + println!(" {:?}", result); + } + Err(err) => { + println!(" {}", err); + } + } + + Ok(()) +} + +#[derive(Default)] +struct Args { + input: Option, +} + +impl Args { + fn parse() -> Result { + 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) + } +} + +#[test] +fn parse_color() { + assert_eq!( + hex_color("#2F14DF"), + Ok(( + "", + parser::Color { + red: 47, + green: 20, + blue: 223, + } + )) + ); +} diff --git a/vendor/winnow-0.4.7/examples/css/parser.rs b/vendor/winnow-0.4.7/examples/css/parser.rs new file mode 100644 index 000000000..9b3238e2e --- /dev/null +++ b/vendor/winnow-0.4.7/examples/css/parser.rs @@ -0,0 +1,31 @@ +use winnow::prelude::*; +use winnow::token::take_while; + +#[derive(Debug, Eq, PartialEq)] +pub struct Color { + pub red: u8, + pub green: u8, + pub blue: u8, +} + +impl std::str::FromStr for Color { + // The error must be owned + type Err = winnow::error::Error; + + fn from_str(s: &str) -> Result { + hex_color.parse(s).map_err(winnow::error::Error::into_owned) + } +} + +pub fn hex_color(input: &str) -> IResult<&str, Color> { + let (input, _) = "#".parse_next(input)?; + let (input, (red, green, blue)) = (hex_primary, hex_primary, hex_primary).parse_next(input)?; + + Ok((input, Color { red, green, blue })) +} + +fn hex_primary(input: &str) -> IResult<&str, u8> { + take_while(2, |c: char| c.is_ascii_hexdigit()) + .try_map(|input| u8::from_str_radix(input, 16)) + .parse_next(input) +} diff --git a/vendor/winnow-0.4.7/examples/custom_error.rs b/vendor/winnow-0.4.7/examples/custom_error.rs new file mode 100644 index 000000000..954452a20 --- /dev/null +++ b/vendor/winnow-0.4.7/examples/custom_error.rs @@ -0,0 +1,42 @@ +use winnow::error::ErrMode; +use winnow::error::ErrorKind; +use winnow::error::ParseError; +use winnow::IResult; + +#[derive(Debug, PartialEq, Eq)] +pub enum CustomError { + MyError, + Nom(I, ErrorKind), +} + +impl ParseError for CustomError { + fn from_error_kind(input: I, kind: ErrorKind) -> Self { + CustomError::Nom(input, kind) + } + + fn append(self, _: I, _: ErrorKind) -> Self { + self + } +} + +pub fn parse(_input: &str) -> IResult<&str, &str, CustomError<&str>> { + Err(ErrMode::Backtrack(CustomError::MyError)) +} + +fn main() {} + +#[cfg(test)] +mod tests { + use super::parse; + use super::CustomError; + use winnow::error::ErrMode; + + #[test] + fn it_works() { + let err = parse("").unwrap_err(); + match err { + ErrMode::Backtrack(e) => assert_eq!(e, CustomError::MyError), + _ => panic!("Unexpected error: {:?}", err), + } + } +} diff --git a/vendor/winnow-0.4.7/examples/http/bench.rs b/vendor/winnow-0.4.7/examples/http/bench.rs new file mode 100644 index 000000000..a27a119a6 --- /dev/null +++ b/vendor/winnow-0.4.7/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-0.4.7/examples/http/main.rs b/vendor/winnow-0.4.7/examples/http/main.rs new file mode 100644 index 000000000..b0e480fb5 --- /dev/null +++ b/vendor/winnow-0.4.7/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, +} + +impl Args { + fn parse() -> Result { + 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-0.4.7/examples/http/parser.rs b/vendor/winnow-0.4.7/examples/http/parser.rs new file mode 100644 index 000000000..f03b77eb7 --- /dev/null +++ b/vendor/winnow-0.4.7/examples/http/parser.rs @@ -0,0 +1,141 @@ +use winnow::{ascii::line_ending, combinator::repeat, token::take_while, 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>)>> { + 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, (Request<'_>, Vec>)> { + let (input, req) = request_line(input)?; + let (input, h) = repeat(1.., message_header).parse_next(input)?; + let (input, _) = line_ending(input)?; + + Ok((input, (req, h))) +} + +fn request_line(input: Stream<'_>) -> IResult, Request<'_>> { + let (input, method) = take_while(1.., is_token).parse_next(input)?; + let (input, _) = take_while(1.., is_space).parse_next(input)?; + let (input, uri) = take_while(1.., is_not_space).parse_next(input)?; + let (input, _) = take_while(1.., 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, &[u8]> { + let (input, _) = "HTTP/".parse_next(input)?; + let (input, version) = take_while(1.., is_version).parse_next(input)?; + + Ok((input, version)) +} + +fn message_header_value(input: Stream<'_>) -> IResult, &[u8]> { + let (input, _) = take_while(1.., is_horizontal_space).parse_next(input)?; + let (input, data) = take_while(1.., not_line_ending).parse_next(input)?; + let (input, _) = line_ending(input)?; + + Ok((input, data)) +} + +fn message_header(input: Stream<'_>) -> IResult, Header<'_>> { + let (input, name) = take_while(1.., is_token).parse_next(input)?; + let (input, _) = ':'.parse_next(input)?; + let (input, value) = repeat(1.., 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-0.4.7/examples/http/parser_streaming.rs b/vendor/winnow-0.4.7/examples/http/parser_streaming.rs new file mode 100644 index 000000000..d3b2c4aaa --- /dev/null +++ b/vendor/winnow-0.4.7/examples/http/parser_streaming.rs @@ -0,0 +1,143 @@ +use winnow::{ + ascii::line_ending, combinator::repeat, stream::Partial, token::take_while, 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>)>> { + 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, (Request<'_>, Vec>)> { + let (input, req) = request_line(input)?; + let (input, h) = repeat(1.., message_header).parse_next(input)?; + let (input, _) = line_ending(input)?; + + Ok((input, (req, h))) +} + +fn request_line(input: Stream<'_>) -> IResult, Request<'_>> { + let (input, method) = take_while(1.., is_token).parse_next(input)?; + let (input, _) = take_while(1.., is_space).parse_next(input)?; + let (input, uri) = take_while(1.., is_not_space).parse_next(input)?; + let (input, _) = take_while(1.., 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, &[u8]> { + let (input, _) = "HTTP/".parse_next(input)?; + let (input, version) = take_while(1.., is_version).parse_next(input)?; + + Ok((input, version)) +} + +fn message_header_value(input: Stream<'_>) -> IResult, &[u8]> { + let (input, _) = take_while(1.., is_horizontal_space).parse_next(input)?; + let (input, data) = take_while(1.., not_line_ending).parse_next(input)?; + let (input, _) = line_ending(input)?; + + Ok((input, data)) +} + +fn message_header(input: Stream<'_>) -> IResult, Header<'_>> { + let (input, name) = take_while(1.., is_token).parse_next(input)?; + let (input, _) = ':'.parse_next(input)?; + let (input, value) = repeat(1.., 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-0.4.7/examples/ini/bench.rs b/vendor/winnow-0.4.7/examples/ini/bench.rs new file mode 100644 index 000000000..cffea3b84 --- /dev/null +++ b/vendor/winnow-0.4.7/examples/ini/bench.rs @@ -0,0 +1,61 @@ +use winnow::combinator::repeat; +use winnow::prelude::*; + +mod parser; +mod parser_str; + +fn bench_ini(c: &mut criterion::Criterion) { + let str = "[owner] +name=John Doe +organization=Acme Widgets Inc. + +[database] +server=192.0.2.62 +port=143 +file=payroll.dat +\0"; + + let mut group = c.benchmark_group("ini"); + group.throughput(criterion::Throughput::Bytes(str.len() as u64)); + group.bench_function(criterion::BenchmarkId::new("bytes", str.len()), |b| { + b.iter(|| parser::categories(str.as_bytes()).unwrap()); + }); + group.bench_function(criterion::BenchmarkId::new("str", str.len()), |b| { + b.iter(|| parser_str::categories(str).unwrap()) + }); +} + +fn bench_ini_keys_and_values(c: &mut criterion::Criterion) { + let str = "server=192.0.2.62 +port=143 +file=payroll.dat +\0"; + + fn acc(i: parser::Stream<'_>) -> IResult, Vec<(&str, &str)>> { + repeat(0.., parser::key_value).parse_next(i) + } + + let mut group = c.benchmark_group("ini keys and values"); + group.throughput(criterion::Throughput::Bytes(str.len() as u64)); + group.bench_function(criterion::BenchmarkId::new("bytes", str.len()), |b| { + b.iter(|| acc(str.as_bytes()).unwrap()); + }); +} + +fn bench_ini_key_value(c: &mut criterion::Criterion) { + let str = "server=192.0.2.62\n"; + + let mut group = c.benchmark_group("ini key value"); + group.throughput(criterion::Throughput::Bytes(str.len() as u64)); + group.bench_function(criterion::BenchmarkId::new("bytes", str.len()), |b| { + b.iter(|| parser::key_value(str.as_bytes()).unwrap()); + }); +} + +criterion::criterion_group!( + benches, + bench_ini, + bench_ini_keys_and_values, + bench_ini_key_value +); +criterion::criterion_main!(benches); diff --git a/vendor/winnow-0.4.7/examples/ini/main.rs b/vendor/winnow-0.4.7/examples/ini/main.rs new file mode 100644 index 000000000..8f61d18e8 --- /dev/null +++ b/vendor/winnow-0.4.7/examples/ini/main.rs @@ -0,0 +1,60 @@ +use winnow::prelude::*; + +mod parser; +mod parser_str; + +fn main() -> Result<(), lexopt::Error> { + let args = Args::parse()?; + + let input = args.input.as_deref().unwrap_or("1 + 1"); + + if args.binary { + match parser::categories.parse(input.as_bytes()) { + Ok(result) => { + println!(" {:?}", result); + } + Err(err) => { + println!(" {:?}", err); + } + } + } else { + match parser_str::categories.parse(input) { + Ok(result) => { + println!(" {:?}", result); + } + Err(err) => { + println!(" {}", err); + } + } + } + + Ok(()) +} + +#[derive(Default)] +struct Args { + input: Option, + binary: bool, +} + +impl Args { + fn parse() -> Result { + use lexopt::prelude::*; + + let mut res = Args::default(); + + let mut args = lexopt::Parser::from_env(); + while let Some(arg) = args.next()? { + match arg { + Long("binary") => { + res.binary = true; + } + Value(input) => { + res.input = Some(input.string()?); + } + _ => return Err(arg.unexpected()), + } + } + Ok(res) + } +} diff --git a/vendor/winnow-0.4.7/examples/ini/parser.rs b/vendor/winnow-0.4.7/examples/ini/parser.rs new file mode 100644 index 000000000..8852b6d30 --- /dev/null +++ b/vendor/winnow-0.4.7/examples/ini/parser.rs @@ -0,0 +1,146 @@ +use std::collections::HashMap; +use std::str; + +use winnow::prelude::*; +use winnow::{ + ascii::{alphanumeric1 as alphanumeric, multispace0 as multispace, space0 as space}, + combinator::opt, + combinator::repeat, + combinator::{delimited, separated_pair, terminated}, + token::take_while, +}; + +pub type Stream<'i> = &'i [u8]; + +pub fn categories(i: Stream<'_>) -> IResult, HashMap<&str, HashMap<&str, &str>>> { + repeat( + 0.., + separated_pair( + category, + opt(multispace), + repeat(0.., terminated(key_value, opt(multispace))), + ), + ) + .parse_next(i) +} + +fn category(i: Stream<'_>) -> IResult, &str> { + delimited('[', take_while(0.., |c| c != b']'), ']') + .try_map(str::from_utf8) + .parse_next(i) +} + +pub fn key_value(i: Stream<'_>) -> IResult, (&str, &str)> { + let (i, key) = alphanumeric.try_map(str::from_utf8).parse_next(i)?; + let (i, _) = (opt(space), '=', opt(space)).parse_next(i)?; + let (i, val) = take_while(0.., |c| c != b'\n' && c != b';') + .try_map(str::from_utf8) + .parse_next(i)?; + let (i, _) = opt((';', take_while(0.., |c| c != b'\n'))).parse_next(i)?; + Ok((i, (key, val))) +} + +#[test] +fn parse_category_test() { + let ini_file = &b"[category] + +parameter=value +key = value2"[..]; + + let ini_without_category = &b"\n\nparameter=value +key = value2"[..]; + + let res = category(ini_file); + println!("{:?}", res); + match res { + Ok((i, o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_category, "category"))); +} + +#[test] +fn parse_key_value_test() { + let ini_file = &b"parameter=value +key = value2"[..]; + + let ini_without_key_value = &b"\nkey = value2"[..]; + + let res = key_value(ini_file); + println!("{:?}", res); + match res { + Ok((i, (o1, o2))) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); +} + +#[test] +fn parse_key_value_with_space_test() { + let ini_file = &b"parameter = value +key = value2"[..]; + + let ini_without_key_value = &b"\nkey = value2"[..]; + + let res = key_value(ini_file); + println!("{:?}", res); + match res { + Ok((i, (o1, o2))) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); +} + +#[test] +fn parse_key_value_with_comment_test() { + let ini_file = &b"parameter=value;abc +key = value2"[..]; + + let ini_without_key_value = &b"\nkey = value2"[..]; + + let res = key_value(ini_file); + println!("{:?}", res); + match res { + Ok((i, (o1, o2))) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); +} + +#[test] +fn parse_multiple_categories_test() { + let ini_file = &b"[abcd] + +parameter=value;abc + +key = value2 + +[category] +parameter3=value3 +key4 = value4 +"[..]; + + let ini_after_parser = &b""[..]; + + let res = categories(ini_file); + //println!("{:?}", res); + match res { + Ok((i, ref o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o), + _ => println!("error"), + } + + let mut expected_1: HashMap<&str, &str> = HashMap::new(); + expected_1.insert("parameter", "value"); + expected_1.insert("key", "value2"); + let mut expected_2: HashMap<&str, &str> = HashMap::new(); + expected_2.insert("parameter3", "value3"); + expected_2.insert("key4", "value4"); + let mut expected_h: HashMap<&str, HashMap<&str, &str>> = HashMap::new(); + expected_h.insert("abcd", expected_1); + expected_h.insert("category", expected_2); + assert_eq!(res, Ok((ini_after_parser, expected_h))); +} diff --git a/vendor/winnow-0.4.7/examples/ini/parser_str.rs b/vendor/winnow-0.4.7/examples/ini/parser_str.rs new file mode 100644 index 000000000..eb084a9b8 --- /dev/null +++ b/vendor/winnow-0.4.7/examples/ini/parser_str.rs @@ -0,0 +1,206 @@ +use std::collections::HashMap; + +use winnow::prelude::*; +use winnow::{ + ascii::{alphanumeric1 as alphanumeric, space0 as space}, + combinator::opt, + combinator::repeat, + combinator::{delimited, terminated}, + token::{take_till0, take_while}, +}; + +pub type Stream<'i> = &'i str; + +pub fn categories(input: Stream<'_>) -> IResult, HashMap<&str, HashMap<&str, &str>>> { + repeat(0.., category_and_keys).parse_next(input) +} + +fn category_and_keys(i: Stream<'_>) -> IResult, (&str, HashMap<&str, &str>)> { + (category, keys_and_values).parse_next(i) +} + +fn category(i: Stream<'_>) -> IResult, &str> { + terminated( + delimited('[', take_while(0.., |c| c != ']'), ']'), + opt(take_while(1.., " \r\n")), + ) + .parse_next(i) +} + +fn keys_and_values(input: Stream<'_>) -> IResult, HashMap<&str, &str>> { + repeat(0.., key_value).parse_next(input) +} + +fn key_value(i: Stream<'_>) -> IResult, (&str, &str)> { + let (i, key) = alphanumeric(i)?; + let (i, _) = (opt(space), "=", opt(space)).parse_next(i)?; + let (i, val) = take_till0(is_line_ending_or_comment).parse_next(i)?; + let (i, _) = opt(space).parse_next(i)?; + let (i, _) = opt((";", not_line_ending)).parse_next(i)?; + let (i, _) = opt(space_or_line_ending).parse_next(i)?; + + Ok((i, (key, val))) +} + +fn is_line_ending_or_comment(chr: char) -> bool { + chr == ';' || chr == '\n' +} + +fn not_line_ending(i: Stream<'_>) -> IResult, &str> { + take_while(0.., |c| c != '\r' && c != '\n').parse_next(i) +} + +fn space_or_line_ending(i: Stream<'_>) -> IResult, &str> { + take_while(1.., " \r\n").parse_next(i) +} + +#[test] +fn parse_category_test() { + let ini_file = "[category] + +parameter=value +key = value2"; + + let ini_without_category = "parameter=value +key = value2"; + + let res = category(ini_file); + println!("{:?}", res); + match res { + Ok((i, o)) => println!("i: {} | o: {:?}", i, o), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_category, "category"))); +} + +#[test] +fn parse_key_value_test() { + let ini_file = "parameter=value +key = value2"; + + let ini_without_key_value = "key = value2"; + + let res = key_value(ini_file); + println!("{:?}", res); + match res { + Ok((i, (o1, o2))) => println!("i: {} | o: ({:?},{:?})", i, o1, o2), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); +} + +#[test] +fn parse_key_value_with_space_test() { + let ini_file = "parameter = value +key = value2"; + + let ini_without_key_value = "key = value2"; + + let res = key_value(ini_file); + println!("{:?}", res); + match res { + Ok((i, (o1, o2))) => println!("i: {} | o: ({:?},{:?})", i, o1, o2), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); +} + +#[test] +fn parse_key_value_with_comment_test() { + let ini_file = "parameter=value;abc +key = value2"; + + let ini_without_key_value = "key = value2"; + + let res = key_value(ini_file); + println!("{:?}", res); + match res { + Ok((i, (o1, o2))) => println!("i: {} | o: ({:?},{:?})", i, o1, o2), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); +} + +#[test] +fn parse_multiple_keys_and_values_test() { + let ini_file = "parameter=value;abc + +key = value2 + +[category]"; + + let ini_without_key_value = "[category]"; + + let res = keys_and_values(ini_file); + println!("{:?}", res); + match res { + Ok((i, ref o)) => println!("i: {} | o: {:?}", i, o), + _ => println!("error"), + } + + let mut expected: HashMap<&str, &str> = HashMap::new(); + expected.insert("parameter", "value"); + expected.insert("key", "value2"); + assert_eq!(res, Ok((ini_without_key_value, expected))); +} + +#[test] +fn parse_category_then_multiple_keys_and_values_test() { + //FIXME: there can be an empty line or a comment line after a category + let ini_file = "[abcd] +parameter=value;abc + +key = value2 + +[category]"; + + let ini_after_parser = "[category]"; + + let res = category_and_keys(ini_file); + println!("{:?}", res); + match res { + Ok((i, ref o)) => println!("i: {} | o: {:?}", i, o), + _ => println!("error"), + } + + let mut expected_h: HashMap<&str, &str> = HashMap::new(); + expected_h.insert("parameter", "value"); + expected_h.insert("key", "value2"); + assert_eq!(res, Ok((ini_after_parser, ("abcd", expected_h)))); +} + +#[test] +fn parse_multiple_categories_test() { + let ini_file = "[abcd] + +parameter=value;abc + +key = value2 + +[category] +parameter3=value3 +key4 = value4 +"; + + let res = categories(ini_file); + //println!("{:?}", res); + match res { + Ok((i, ref o)) => println!("i: {} | o: {:?}", i, o), + _ => println!("error"), + } + + let mut expected_1: HashMap<&str, &str> = HashMap::new(); + expected_1.insert("parameter", "value"); + expected_1.insert("key", "value2"); + let mut expected_2: HashMap<&str, &str> = HashMap::new(); + expected_2.insert("parameter3", "value3"); + expected_2.insert("key4", "value4"); + let mut expected_h: HashMap<&str, HashMap<&str, &str>> = HashMap::new(); + expected_h.insert("abcd", expected_1); + expected_h.insert("category", expected_2); + assert_eq!(res, Ok(("", expected_h))); +} diff --git a/vendor/winnow-0.4.7/examples/iterator.rs b/vendor/winnow-0.4.7/examples/iterator.rs new file mode 100644 index 000000000..826eff3aa --- /dev/null +++ b/vendor/winnow-0.4.7/examples/iterator.rs @@ -0,0 +1,81 @@ +use std::collections::HashMap; +use std::iter::Iterator; + +use winnow::ascii::alphanumeric1; +use winnow::combinator::iterator; +use winnow::combinator::{separated_pair, terminated}; +use winnow::prelude::*; + +fn main() { + let mut data = "abcabcabcabc"; + + fn parser(i: &str) -> IResult<&str, &str> { + "abc".parse_next(i) + } + + // `from_fn` (available from Rust 1.34) can create an iterator + // from a closure + let it = std::iter::from_fn(move || { + match parser(data) { + // when successful, a parser returns a tuple of + // the remaining input and the output value. + // So we replace the captured input data with the + // remaining input, to be parsed on the next call + Ok((i, o)) => { + data = i; + Some(o) + } + _ => None, + } + }); + + for value in it { + println!("parser returned: {}", value); + } + + println!("\n********************\n"); + + let data = "abcabcabcabc"; + + // if `from_fn` is not available, it is possible to fold + // over an iterator of functions + let res = std::iter::repeat(parser).take(3).try_fold( + (data, Vec::new()), + |(data, mut acc), parser| { + parser(data).map(|(i, o)| { + acc.push(o); + (i, acc) + }) + }, + ); + + // will print "parser iterator returned: Ok(("abc", ["abc", "abc", "abc"]))" + println!("\nparser iterator returned: {:?}", res); + + println!("\n********************\n"); + + let data = "key1:value1,key2:value2,key3:value3,;"; + + // `winnow::combinator::iterator` will return an iterator + // producing the parsed values. Compared to the previous + // solutions: + // - we can work with a normal iterator like `from_fn` + // - we can get the remaining input afterwards, like with the `try_fold` trick + let mut winnow_it = iterator( + data, + terminated(separated_pair(alphanumeric1, ":", alphanumeric1), ","), + ); + + let res = winnow_it + .map(|(k, v)| (k.to_uppercase(), v)) + .collect::>(); + + let parser_result: IResult<_, _> = winnow_it.finish(); + let (remaining_input, ()) = parser_result.unwrap(); + + // will print "iterator returned {"key1": "value1", "key3": "value3", "key2": "value2"}, remaining input is ';'" + println!( + "iterator returned {:?}, remaining input is '{}'", + res, remaining_input + ); +} diff --git a/vendor/winnow-0.4.7/examples/json/bench.rs b/vendor/winnow-0.4.7/examples/json/bench.rs new file mode 100644 index 000000000..0a2fd4ffa --- /dev/null +++ b/vendor/winnow-0.4.7/examples/json/bench.rs @@ -0,0 +1,60 @@ +use winnow::Partial; + +mod json; +mod parser; +mod parser_dispatch; +mod parser_partial; + +fn json_bench(c: &mut criterion::Criterion) { + let data = [("small", SMALL), ("canada", CANADA)]; + let mut group = c.benchmark_group("json"); + for (name, sample) in data { + let len = sample.len(); + group.throughput(criterion::Throughput::Bytes(len as u64)); + + group.bench_with_input(criterion::BenchmarkId::new("basic", name), &len, |b, _| { + type Error<'i> = winnow::error::Error>; + + b.iter(|| parser::json::(sample).unwrap()); + }); + group.bench_with_input( + criterion::BenchmarkId::new("verbose", name), + &len, + |b, _| { + type Error<'i> = winnow::error::VerboseError>; + + b.iter(|| parser::json::(sample).unwrap()); + }, + ); + group.bench_with_input( + criterion::BenchmarkId::new("dispatch", name), + &len, + |b, _| { + type Error<'i> = winnow::error::Error>; + + b.iter(|| parser_dispatch::json::(sample).unwrap()); + }, + ); + group.bench_with_input( + criterion::BenchmarkId::new("streaming", name), + &len, + |b, _| { + type Error<'i> = winnow::error::Error>; + + b.iter(|| parser_partial::json::(Partial::new(sample)).unwrap()); + }, + ); + } + group.finish(); +} + +const SMALL: &str = " { \"a\"\t: 42, + \"b\": [ \"x\", \"y\", 12 ,\"\\u2014\", \"\\uD83D\\uDE10\"] , + \"c\": { \"hello\" : \"world\" + } + } "; + +const CANADA: &str = include_str!("../../third_party/nativejson-benchmark/data/canada.json"); + +criterion::criterion_group!(benches, json_bench,); +criterion::criterion_main!(benches); diff --git a/vendor/winnow-0.4.7/examples/json/json.rs b/vendor/winnow-0.4.7/examples/json/json.rs new file mode 100644 index 000000000..6912d60e3 --- /dev/null +++ b/vendor/winnow-0.4.7/examples/json/json.rs @@ -0,0 +1,11 @@ +use std::collections::HashMap; + +#[derive(Debug, PartialEq, Clone)] +pub enum JsonValue { + Null, + Boolean(bool), + Str(String), + Num(f64), + Array(Vec), + Object(HashMap), +} diff --git a/vendor/winnow-0.4.7/examples/json/main.rs b/vendor/winnow-0.4.7/examples/json/main.rs new file mode 100644 index 000000000..f738a1f05 --- /dev/null +++ b/vendor/winnow-0.4.7/examples/json/main.rs @@ -0,0 +1,118 @@ +mod json; +mod parser; +mod parser_dispatch; +#[allow(dead_code)] +mod parser_partial; + +use winnow::error::convert_error; +use winnow::error::Error; +use winnow::error::VerboseError; +use winnow::prelude::*; + +fn main() -> Result<(), lexopt::Error> { + let args = Args::parse()?; + + let data = args.input.as_deref().unwrap_or(if args.invalid { + " { \"a\"\t: 42, + \"b\": [ \"x\", \"y\", 12 ] , + \"c\": { 1\"hello\" : \"world\" + } + } " + } else { + " { \"a\"\t: 42, + \"b\": [ \"x\", \"y\", 12 ] , + \"c\": { \"hello\" : \"world\" + } + } " + }); + + if args.verbose { + match parser::json::>.parse(data) { + Ok(json) => { + println!("{:#?}", json); + } + Err(err) => { + if args.pretty { + println!("{}", convert_error(data, err)); + } else { + println!("{:#?}", err); + } + } + } + } else { + let result = match args.implementation { + Impl::Naive => parser::json::>.parse(data), + Impl::Dispatch => parser_dispatch::json::>.parse(data), + }; + match result { + Ok(json) => { + println!("{:#?}", json); + } + Err(err) => { + println!("{:?}", err); + } + } + } + + Ok(()) +} + +#[derive(Default)] +struct Args { + input: Option, + invalid: bool, + verbose: bool, + pretty: bool, + implementation: Impl, +} + +enum Impl { + Naive, + Dispatch, +} + +impl Default for Impl { + fn default() -> Self { + Self::Naive + } +} + +impl Args { + fn parse() -> Result { + use lexopt::prelude::*; + + let mut res = Args::default(); + + let mut args = lexopt::Parser::from_env(); + while let Some(arg) = args.next()? { + match arg { + Long("invalid") => { + res.invalid = true; + } + Long("verbose") => { + res.verbose = true; + // Only case where verbose matters + res.invalid = true; + } + Long("pretty") => { + res.verbose = true; + // Only case where pretty matters + res.pretty = true; + res.invalid = true; + } + Long("impl") => { + res.implementation = args.value()?.parse_with(|s| match s { + "naive" => Ok(Impl::Naive), + "dispatch" => Ok(Impl::Dispatch), + _ => Err("expected `naive`, `dispatch`"), + })?; + } + Value(input) => { + res.input = Some(input.string()?); + } + _ => return Err(arg.unexpected()), + } + } + Ok(res) + } +} diff --git a/vendor/winnow-0.4.7/examples/json/parser.rs b/vendor/winnow-0.4.7/examples/json/parser.rs new file mode 100644 index 000000000..719dea5d9 --- /dev/null +++ b/vendor/winnow-0.4.7/examples/json/parser.rs @@ -0,0 +1,315 @@ +use std::collections::HashMap; +use std::str; + +use winnow::prelude::*; +use winnow::{ + ascii::float, + combinator::alt, + combinator::cut_err, + combinator::{delimited, preceded, separated_pair, terminated}, + combinator::{fold_repeat, separated0}, + error::{ContextError, ParseError}, + token::{any, none_of, take, take_while}, +}; + +use crate::json::JsonValue; + +pub type Stream<'i> = &'i str; + +/// The root element of a JSON parser is any value +/// +/// A parser has the following signature: +/// `Stream -> IResult`, with `IResult` defined as: +/// `type IResult = Result<(I, O), Err>;` +/// +/// most of the times you can ignore the error type and use the default (but this +/// examples shows custom error types later on!) +/// +/// Here we use `&str` as input type, but parsers can be generic over +/// the input type, work directly with `&[u8]`, or any other type that +/// implements the required traits. +pub fn json<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, JsonValue, E> { + delimited(ws, json_value, ws).parse_next(input) +} + +/// `alt` is a combinator that tries multiple parsers one by one, until +/// one of them succeeds +fn json_value<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, JsonValue, E> { + // `alt` combines the each value parser. It returns the result of the first + // successful parser, or an error + alt(( + null.value(JsonValue::Null), + boolean.map(JsonValue::Boolean), + string.map(JsonValue::Str), + float.map(JsonValue::Num), + array.map(JsonValue::Array), + object.map(JsonValue::Object), + )) + .parse_next(input) +} + +/// `tag(string)` generates a parser that recognizes the argument string. +/// +/// This also shows returning a sub-slice of the original input +fn null<'i, E: ParseError>>(input: Stream<'i>) -> IResult, &'i str, E> { + // This is a parser that returns `"null"` if it sees the string "null", and + // an error otherwise + "null".parse_next(input) +} + +/// We can combine `tag` with other functions, like `value` which returns a given constant value on +/// success. +fn boolean<'i, E: ParseError>>(input: Stream<'i>) -> IResult, bool, E> { + // This is a parser that returns `true` if it sees the string "true", and + // an error otherwise + let parse_true = "true".value(true); + + // This is a parser that returns `false` if it sees the string "false", and + // an error otherwise + let parse_false = "false".value(false); + + alt((parse_true, parse_false)).parse_next(input) +} + +/// This parser gathers all `char`s up into a `String`with a parse to recognize the double quote +/// character, before the string (using `preceded`) and after the string (using `terminated`). +fn string<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, String, E> { + preceded( + '\"', + // `cut_err` transforms an `ErrMode::Backtrack(e)` to `ErrMode::Cut(e)`, signaling to + // combinators like `alt` that they should not try other parsers. We were in the + // right branch (since we found the `"` character) but encountered an error when + // parsing the string + cut_err(terminated( + fold_repeat(0.., character, String::new, |mut string, c| { + string.push(c); + string + }), + '\"', + )), + ) + // `context` lets you add a static string to errors to provide more information in the + // error chain (to indicate which parser had an error) + .context("string") + .parse_next(input) +} + +/// You can mix the above declarative parsing with an imperative style to handle more unique cases, +/// like escaping +fn character<'i, E: ParseError>>(input: Stream<'i>) -> IResult, char, E> { + let (input, c) = none_of("\"").parse_next(input)?; + if c == '\\' { + alt(( + any.verify_map(|c| { + Some(match c { + '"' | '\\' | '/' => c, + 'b' => '\x08', + 'f' => '\x0C', + 'n' => '\n', + 'r' => '\r', + 't' => '\t', + _ => return None, + }) + }), + preceded('u', unicode_escape), + )) + .parse_next(input) + } else { + Ok((input, c)) + } +} + +fn unicode_escape<'i, E: ParseError>>( + input: Stream<'i>, +) -> IResult, char, E> { + alt(( + // Not a surrogate + u16_hex + .verify(|cp| !(0xD800..0xE000).contains(cp)) + .map(|cp| cp as u32), + // See https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF for details + separated_pair(u16_hex, "\\u", u16_hex) + .verify(|(high, low)| (0xD800..0xDC00).contains(high) && (0xDC00..0xE000).contains(low)) + .map(|(high, low)| { + let high_ten = (high as u32) - 0xD800; + let low_ten = (low as u32) - 0xDC00; + (high_ten << 10) + low_ten + 0x10000 + }), + )) + .verify_map( + // Could be probably replaced with .unwrap() or _unchecked due to the verify checks + std::char::from_u32, + ) + .parse_next(input) +} + +fn u16_hex<'i, E: ParseError>>(input: Stream<'i>) -> IResult, u16, E> { + take(4usize) + .verify_map(|s| u16::from_str_radix(s, 16).ok()) + .parse_next(input) +} + +/// Some combinators, like `separated0` or `many0`, will call a parser repeatedly, +/// accumulating results in a `Vec`, until it encounters an error. +/// If you want more control on the parser application, check out the `iterator` +/// combinator (cf `examples/iterator.rs`) +fn array<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, Vec, E> { + preceded( + ('[', ws), + cut_err(terminated(separated0(json_value, (ws, ',', ws)), (ws, ']'))), + ) + .context("array") + .parse_next(input) +} + +fn object<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, HashMap, E> { + preceded( + ('{', ws), + cut_err(terminated(separated0(key_value, (ws, ',', ws)), (ws, '}'))), + ) + .context("object") + .parse_next(input) +} + +fn key_value<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, (String, JsonValue), E> { + separated_pair(string, cut_err((ws, ':', ws)), json_value).parse_next(input) +} + +/// Parser combinators are constructed from the bottom up: +/// first we write parsers for the smallest elements (here a space character), +/// then we'll combine them in larger parsers +fn ws<'i, E: ParseError>>(input: Stream<'i>) -> IResult, &'i str, E> { + // Combinators like `take_while` return a function. That function is the + // parser,to which we can pass the input + take_while(0.., WS).parse_next(input) +} + +const WS: &str = " \t\r\n"; + +#[cfg(test)] +mod test { + #[allow(clippy::useless_attribute)] + #[allow(dead_code)] // its dead for benches + use super::*; + + #[allow(clippy::useless_attribute)] + #[allow(dead_code)] // its dead for benches + type Error<'i> = winnow::error::Error<&'i str>; + + #[test] + fn json_string() { + assert_eq!(string::>("\"\""), Ok(("", "".to_string()))); + assert_eq!(string::>("\"abc\""), Ok(("", "abc".to_string()))); + assert_eq!( + string::>("\"abc\\\"\\\\\\/\\b\\f\\n\\r\\t\\u0001\\u2014\u{2014}def\""), + Ok(("", "abc\"\\/\x08\x0C\n\r\t\x01β€”β€”def".to_string())), + ); + assert_eq!( + string::>("\"\\uD83D\\uDE10\""), + Ok(("", "😐".to_string())) + ); + + assert!(string::>("\"").is_err()); + assert!(string::>("\"abc").is_err()); + assert!(string::>("\"\\\"").is_err()); + assert!(string::>("\"\\u123\"").is_err()); + assert!(string::>("\"\\uD800\"").is_err()); + assert!(string::>("\"\\uD800\\uD800\"").is_err()); + assert!(string::>("\"\\uDC00\"").is_err()); + } + + #[test] + fn json_object() { + use JsonValue::{Num, Object, Str}; + + let input = r#"{"a":42,"b":"x"}"#; + + let expected = Object( + vec![ + ("a".to_string(), Num(42.0)), + ("b".to_string(), Str("x".to_string())), + ] + .into_iter() + .collect(), + ); + + assert_eq!(json::>(input), Ok(("", expected))); + } + + #[test] + fn json_array() { + use JsonValue::{Array, Num, Str}; + + let input = r#"[42,"x"]"#; + + let expected = Array(vec![Num(42.0), Str("x".to_string())]); + + assert_eq!(json::>(input), Ok(("", expected))); + } + + #[test] + fn json_whitespace() { + use JsonValue::{Array, Boolean, Null, Num, Object, Str}; + + let input = r#" + { + "null" : null, + "true" :true , + "false": false , + "number" : 123e4 , + "string" : " abc 123 " , + "array" : [ false , 1 , "two" ] , + "object" : { "a" : 1.0 , "b" : "c" } , + "empty_array" : [ ] , + "empty_object" : { } + } + "#; + + assert_eq!( + json::>(input), + Ok(( + "", + Object( + vec![ + ("null".to_string(), Null), + ("true".to_string(), Boolean(true)), + ("false".to_string(), Boolean(false)), + ("number".to_string(), Num(123e4)), + ("string".to_string(), Str(" abc 123 ".to_string())), + ( + "array".to_string(), + Array(vec![Boolean(false), Num(1.0), Str("two".to_string())]) + ), + ( + "object".to_string(), + Object( + vec![ + ("a".to_string(), Num(1.0)), + ("b".to_string(), Str("c".to_string())), + ] + .into_iter() + .collect() + ) + ), + ("empty_array".to_string(), Array(vec![]),), + ("empty_object".to_string(), Object(HashMap::new()),), + ] + .into_iter() + .collect() + ) + )) + ); + } +} diff --git a/vendor/winnow-0.4.7/examples/json/parser_dispatch.rs b/vendor/winnow-0.4.7/examples/json/parser_dispatch.rs new file mode 100644 index 000000000..29d6d5f90 --- /dev/null +++ b/vendor/winnow-0.4.7/examples/json/parser_dispatch.rs @@ -0,0 +1,322 @@ +use std::collections::HashMap; +use std::str; + +use winnow::prelude::*; +use winnow::{ + ascii::float, + combinator::cut_err, + combinator::fail, + combinator::peek, + combinator::success, + combinator::{alt, dispatch}, + combinator::{delimited, preceded, separated_pair, terminated}, + combinator::{fold_repeat, separated0}, + error::{ContextError, ParseError}, + token::{any, none_of, take, take_while}, +}; + +use crate::json::JsonValue; + +pub type Stream<'i> = &'i str; + +/// The root element of a JSON parser is any value +/// +/// A parser has the following signature: +/// `Stream -> IResult`, with `IResult` defined as: +/// `type IResult = Result<(I, O), Err>;` +/// +/// most of the times you can ignore the error type and use the default (but this +/// examples shows custom error types later on!) +/// +/// Here we use `&str` as input type, but parsers can be generic over +/// the input type, work directly with `&[u8]`, or any other type that +/// implements the required traits. +pub fn json<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, JsonValue, E> { + delimited(ws, json_value, ws).parse_next(input) +} + +/// `alt` is a combinator that tries multiple parsers one by one, until +/// one of them succeeds +fn json_value<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, JsonValue, E> { + // `dispatch` gives you `match`-like behavior compared to `alt` successively trying different + // implementations. + dispatch!(peek(any); + 'n' => null.value(JsonValue::Null), + 't' => true_.map(JsonValue::Boolean), + 'f' => false_.map(JsonValue::Boolean), + '"' => string.map(JsonValue::Str), + '+' => float.map(JsonValue::Num), + '-' => float.map(JsonValue::Num), + '0'..='9' => float.map(JsonValue::Num), + '[' => array.map(JsonValue::Array), + '{' => object.map(JsonValue::Object), + _ => fail, + ) + .parse_next(input) +} + +/// `tag(string)` generates a parser that recognizes the argument string. +/// +/// This also shows returning a sub-slice of the original input +fn null<'i, E: ParseError>>(input: Stream<'i>) -> IResult, &'i str, E> { + // This is a parser that returns `"null"` if it sees the string "null", and + // an error otherwise + "null".parse_next(input) +} + +/// We can combine `tag` with other functions, like `value` which returns a given constant value on +/// success. +fn true_<'i, E: ParseError>>(input: Stream<'i>) -> IResult, bool, E> { + // This is a parser that returns `true` if it sees the string "true", and + // an error otherwise + "true".value(true).parse_next(input) +} + +/// We can combine `tag` with other functions, like `value` which returns a given constant value on +/// success. +fn false_<'i, E: ParseError>>(input: Stream<'i>) -> IResult, bool, E> { + // This is a parser that returns `false` if it sees the string "false", and + // an error otherwise + "false".value(false).parse_next(input) +} + +/// This parser gathers all `char`s up into a `String`with a parse to recognize the double quote +/// character, before the string (using `preceded`) and after the string (using `terminated`). +fn string<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, String, E> { + preceded( + '\"', + // `cut_err` transforms an `ErrMode::Backtrack(e)` to `ErrMode::Cut(e)`, signaling to + // combinators like `alt` that they should not try other parsers. We were in the + // right branch (since we found the `"` character) but encountered an error when + // parsing the string + cut_err(terminated( + fold_repeat(0.., character, String::new, |mut string, c| { + string.push(c); + string + }), + '\"', + )), + ) + // `context` lets you add a static string to errors to provide more information in the + // error chain (to indicate which parser had an error) + .context("string") + .parse_next(input) +} + +/// You can mix the above declarative parsing with an imperative style to handle more unique cases, +/// like escaping +fn character<'i, E: ParseError>>(input: Stream<'i>) -> IResult, char, E> { + let (input, c) = none_of("\"").parse_next(input)?; + if c == '\\' { + dispatch!(any; + '"' => success('"'), + '\\' => success('\\'), + '/' => success('/'), + 'b' => success('\x08'), + 'f' => success('\x0C'), + 'n' => success('\n'), + 'r' => success('\r'), + 't' => success('\t'), + 'u' => unicode_escape, + _ => fail, + ) + .parse_next(input) + } else { + Ok((input, c)) + } +} + +fn unicode_escape<'i, E: ParseError>>( + input: Stream<'i>, +) -> IResult, char, E> { + alt(( + // Not a surrogate + u16_hex + .verify(|cp| !(0xD800..0xE000).contains(cp)) + .map(|cp| cp as u32), + // See https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF for details + separated_pair(u16_hex, "\\u", u16_hex) + .verify(|(high, low)| (0xD800..0xDC00).contains(high) && (0xDC00..0xE000).contains(low)) + .map(|(high, low)| { + let high_ten = (high as u32) - 0xD800; + let low_ten = (low as u32) - 0xDC00; + (high_ten << 10) + low_ten + 0x10000 + }), + )) + .verify_map( + // Could be probably replaced with .unwrap() or _unchecked due to the verify checks + std::char::from_u32, + ) + .parse_next(input) +} + +fn u16_hex<'i, E: ParseError>>(input: Stream<'i>) -> IResult, u16, E> { + take(4usize) + .verify_map(|s| u16::from_str_radix(s, 16).ok()) + .parse_next(input) +} + +/// Some combinators, like `separated0` or `many0`, will call a parser repeatedly, +/// accumulating results in a `Vec`, until it encounters an error. +/// If you want more control on the parser application, check out the `iterator` +/// combinator (cf `examples/iterator.rs`) +fn array<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, Vec, E> { + preceded( + ('[', ws), + cut_err(terminated(separated0(json_value, (ws, ',', ws)), (ws, ']'))), + ) + .context("array") + .parse_next(input) +} + +fn object<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, HashMap, E> { + preceded( + ('{', ws), + cut_err(terminated(separated0(key_value, (ws, ',', ws)), (ws, '}'))), + ) + .context("object") + .parse_next(input) +} + +fn key_value<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, (String, JsonValue), E> { + separated_pair(string, cut_err((ws, ':', ws)), json_value).parse_next(input) +} + +/// Parser combinators are constructed from the bottom up: +/// first we write parsers for the smallest elements (here a space character), +/// then we'll combine them in larger parsers +fn ws<'i, E: ParseError>>(input: Stream<'i>) -> IResult, &'i str, E> { + // Combinators like `take_while` return a function. That function is the + // parser,to which we can pass the input + take_while(0.., WS).parse_next(input) +} + +const WS: &str = " \t\r\n"; + +#[cfg(test)] +mod test { + #[allow(clippy::useless_attribute)] + #[allow(dead_code)] // its dead for benches + use super::*; + + #[allow(clippy::useless_attribute)] + #[allow(dead_code)] // its dead for benches + type Error<'i> = winnow::error::Error<&'i str>; + + #[test] + fn json_string() { + assert_eq!(string::>("\"\""), Ok(("", "".to_string()))); + assert_eq!(string::>("\"abc\""), Ok(("", "abc".to_string()))); + assert_eq!( + string::>("\"abc\\\"\\\\\\/\\b\\f\\n\\r\\t\\u0001\\u2014\u{2014}def\""), + Ok(("", "abc\"\\/\x08\x0C\n\r\t\x01β€”β€”def".to_string())), + ); + assert_eq!( + string::>("\"\\uD83D\\uDE10\""), + Ok(("", "😐".to_string())) + ); + + assert!(string::>("\"").is_err()); + assert!(string::>("\"abc").is_err()); + assert!(string::>("\"\\\"").is_err()); + assert!(string::>("\"\\u123\"").is_err()); + assert!(string::>("\"\\uD800\"").is_err()); + assert!(string::>("\"\\uD800\\uD800\"").is_err()); + assert!(string::>("\"\\uDC00\"").is_err()); + } + + #[test] + fn json_object() { + use JsonValue::{Num, Object, Str}; + + let input = r#"{"a":42,"b":"x"}"#; + + let expected = Object( + vec![ + ("a".to_string(), Num(42.0)), + ("b".to_string(), Str("x".to_string())), + ] + .into_iter() + .collect(), + ); + + assert_eq!(json::>(input), Ok(("", expected))); + } + + #[test] + fn json_array() { + use JsonValue::{Array, Num, Str}; + + let input = r#"[42,"x"]"#; + + let expected = Array(vec![Num(42.0), Str("x".to_string())]); + + assert_eq!(json::>(input), Ok(("", expected))); + } + + #[test] + fn json_whitespace() { + use JsonValue::{Array, Boolean, Null, Num, Object, Str}; + + let input = r#" + { + "null" : null, + "true" :true , + "false": false , + "number" : 123e4 , + "string" : " abc 123 " , + "array" : [ false , 1 , "two" ] , + "object" : { "a" : 1.0 , "b" : "c" } , + "empty_array" : [ ] , + "empty_object" : { } + } + "#; + + assert_eq!( + json::>(input), + Ok(( + "", + Object( + vec![ + ("null".to_string(), Null), + ("true".to_string(), Boolean(true)), + ("false".to_string(), Boolean(false)), + ("number".to_string(), Num(123e4)), + ("string".to_string(), Str(" abc 123 ".to_string())), + ( + "array".to_string(), + Array(vec![Boolean(false), Num(1.0), Str("two".to_string())]) + ), + ( + "object".to_string(), + Object( + vec![ + ("a".to_string(), Num(1.0)), + ("b".to_string(), Str("c".to_string())), + ] + .into_iter() + .collect() + ) + ), + ("empty_array".to_string(), Array(vec![]),), + ("empty_object".to_string(), Object(HashMap::new()),), + ] + .into_iter() + .collect() + ) + )) + ); + } +} diff --git a/vendor/winnow-0.4.7/examples/json/parser_partial.rs b/vendor/winnow-0.4.7/examples/json/parser_partial.rs new file mode 100644 index 000000000..4b6d143f9 --- /dev/null +++ b/vendor/winnow-0.4.7/examples/json/parser_partial.rs @@ -0,0 +1,338 @@ +use std::collections::HashMap; +use std::str; + +use winnow::prelude::*; +use winnow::{ + ascii::float, + combinator::alt, + combinator::{cut_err, rest}, + combinator::{delimited, preceded, separated_pair, terminated}, + combinator::{fold_repeat, separated0}, + error::{ContextError, ParseError}, + stream::Partial, + token::{any, none_of, take, take_while}, +}; + +use crate::json::JsonValue; + +pub type Stream<'i> = Partial<&'i str>; + +/// The root element of a JSON parser is any value +/// +/// A parser has the following signature: +/// `Stream -> IResult`, with `IResult` defined as: +/// `type IResult = Result<(I, O), Err>;` +/// +/// most of the times you can ignore the error type and use the default (but this +/// examples shows custom error types later on!) +/// +/// Here we use `&str` as input type, but parsers can be generic over +/// the input type, work directly with `&[u8]`, or any other type that +/// implements the required traits. +pub fn json<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, JsonValue, E> { + delimited(ws, json_value, ws_or_eof).parse_next(input) +} + +/// `alt` is a combinator that tries multiple parsers one by one, until +/// one of them succeeds +fn json_value<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, JsonValue, E> { + // `alt` combines the each value parser. It returns the result of the first + // successful parser, or an error + alt(( + null.value(JsonValue::Null), + boolean.map(JsonValue::Boolean), + string.map(JsonValue::Str), + float.map(JsonValue::Num), + array.map(JsonValue::Array), + object.map(JsonValue::Object), + )) + .parse_next(input) +} + +/// `tag(string)` generates a parser that recognizes the argument string. +/// +/// This also shows returning a sub-slice of the original input +fn null<'i, E: ParseError>>(input: Stream<'i>) -> IResult, &'i str, E> { + // This is a parser that returns `"null"` if it sees the string "null", and + // an error otherwise + "null".parse_next(input) +} + +/// We can combine `tag` with other functions, like `value` which returns a given constant value on +/// success. +fn boolean<'i, E: ParseError>>(input: Stream<'i>) -> IResult, bool, E> { + // This is a parser that returns `true` if it sees the string "true", and + // an error otherwise + let parse_true = "true".value(true); + + // This is a parser that returns `false` if it sees the string "false", and + // an error otherwise + let parse_false = "false".value(false); + + alt((parse_true, parse_false)).parse_next(input) +} + +/// This parser gathers all `char`s up into a `String`with a parse to recognize the double quote +/// character, before the string (using `preceded`) and after the string (using `terminated`). +fn string<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, String, E> { + preceded( + '\"', + // `cut_err` transforms an `ErrMode::Backtrack(e)` to `ErrMode::Cut(e)`, signaling to + // combinators like `alt` that they should not try other parsers. We were in the + // right branch (since we found the `"` character) but encountered an error when + // parsing the string + cut_err(terminated( + fold_repeat(0.., character, String::new, |mut string, c| { + string.push(c); + string + }), + '\"', + )), + ) + // `context` lets you add a static string to errors to provide more information in the + // error chain (to indicate which parser had an error) + .context("string") + .parse_next(input) +} + +/// You can mix the above declarative parsing with an imperative style to handle more unique cases, +/// like escaping +fn character<'i, E: ParseError>>(input: Stream<'i>) -> IResult, char, E> { + let (input, c) = none_of("\"").parse_next(input)?; + if c == '\\' { + alt(( + any.verify_map(|c| { + Some(match c { + '"' | '\\' | '/' => c, + 'b' => '\x08', + 'f' => '\x0C', + 'n' => '\n', + 'r' => '\r', + 't' => '\t', + _ => return None, + }) + }), + preceded('u', unicode_escape), + )) + .parse_next(input) + } else { + Ok((input, c)) + } +} + +fn unicode_escape<'i, E: ParseError>>( + input: Stream<'i>, +) -> IResult, char, E> { + alt(( + // Not a surrogate + u16_hex + .verify(|cp| !(0xD800..0xE000).contains(cp)) + .map(|cp| cp as u32), + // See https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF for details + separated_pair(u16_hex, "\\u", u16_hex) + .verify(|(high, low)| (0xD800..0xDC00).contains(high) && (0xDC00..0xE000).contains(low)) + .map(|(high, low)| { + let high_ten = (high as u32) - 0xD800; + let low_ten = (low as u32) - 0xDC00; + (high_ten << 10) + low_ten + 0x10000 + }), + )) + .verify_map( + // Could be probably replaced with .unwrap() or _unchecked due to the verify checks + std::char::from_u32, + ) + .parse_next(input) +} + +fn u16_hex<'i, E: ParseError>>(input: Stream<'i>) -> IResult, u16, E> { + take(4usize) + .verify_map(|s| u16::from_str_radix(s, 16).ok()) + .parse_next(input) +} + +/// Some combinators, like `separated0` or `many0`, will call a parser repeatedly, +/// accumulating results in a `Vec`, until it encounters an error. +/// If you want more control on the parser application, check out the `iterator` +/// combinator (cf `examples/iterator.rs`) +fn array<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, Vec, E> { + preceded( + ('[', ws), + cut_err(terminated(separated0(json_value, (ws, ',', ws)), (ws, ']'))), + ) + .context("array") + .parse_next(input) +} + +fn object<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, HashMap, E> { + preceded( + ('{', ws), + cut_err(terminated(separated0(key_value, (ws, ',', ws)), (ws, '}'))), + ) + .context("object") + .parse_next(input) +} + +fn key_value<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, (String, JsonValue), E> { + separated_pair(string, cut_err((ws, ':', ws)), json_value).parse_next(input) +} + +/// Parser combinators are constructed from the bottom up: +/// first we write parsers for the smallest elements (here a space character), +/// then we'll combine them in larger parsers +fn ws<'i, E: ParseError>>(input: Stream<'i>) -> IResult, &'i str, E> { + // Combinators like `take_while` return a function. That function is the + // parser,to which we can pass the input + take_while(0.., WS).parse_next(input) +} + +fn ws_or_eof<'i, E: ParseError>>(input: Stream<'i>) -> IResult, &'i str, E> { + rest.verify(|s: &str| s.chars().all(|c| WS.contains(c))) + .parse_next(input) +} + +const WS: &str = " \t\r\n"; + +#[cfg(test)] +mod test { + #[allow(clippy::useless_attribute)] + #[allow(dead_code)] // its dead for benches + use super::*; + + #[allow(clippy::useless_attribute)] + #[allow(dead_code)] // its dead for benches + type Error<'i> = winnow::error::Error>; + + #[test] + fn json_string() { + assert_eq!( + string::>(Partial::new("\"\"")), + Ok((Partial::new(""), "".to_string())) + ); + assert_eq!( + string::>(Partial::new("\"abc\"")), + Ok((Partial::new(""), "abc".to_string())) + ); + assert_eq!( + string::>(Partial::new( + "\"abc\\\"\\\\\\/\\b\\f\\n\\r\\t\\u0001\\u2014\u{2014}def\"" + )), + Ok(( + Partial::new(""), + "abc\"\\/\x08\x0C\n\r\t\x01β€”β€”def".to_string() + )), + ); + assert_eq!( + string::>(Partial::new("\"\\uD83D\\uDE10\"")), + Ok((Partial::new(""), "😐".to_string())) + ); + + assert!(string::>(Partial::new("\"")).is_err()); + assert!(string::>(Partial::new("\"abc")).is_err()); + assert!(string::>(Partial::new("\"\\\"")).is_err()); + assert!(string::>(Partial::new("\"\\u123\"")).is_err()); + assert!(string::>(Partial::new("\"\\uD800\"")).is_err()); + assert!(string::>(Partial::new("\"\\uD800\\uD800\"")).is_err()); + assert!(string::>(Partial::new("\"\\uDC00\"")).is_err()); + } + + #[test] + fn json_object() { + use JsonValue::{Num, Object, Str}; + + let input = r#"{"a":42,"b":"x"}"#; + + let expected = Object( + vec![ + ("a".to_string(), Num(42.0)), + ("b".to_string(), Str("x".to_string())), + ] + .into_iter() + .collect(), + ); + + assert_eq!( + json::>(Partial::new(input)), + Ok((Partial::new(""), expected)) + ); + } + + #[test] + fn json_array() { + use JsonValue::{Array, Num, Str}; + + let input = r#"[42,"x"]"#; + + let expected = Array(vec![Num(42.0), Str("x".to_string())]); + + assert_eq!( + json::>(Partial::new(input)), + Ok((Partial::new(""), expected)) + ); + } + + #[test] + fn json_whitespace() { + use JsonValue::{Array, Boolean, Null, Num, Object, Str}; + + let input = r#" + { + "null" : null, + "true" :true , + "false": false , + "number" : 123e4 , + "string" : " abc 123 " , + "array" : [ false , 1 , "two" ] , + "object" : { "a" : 1.0 , "b" : "c" } , + "empty_array" : [ ] , + "empty_object" : { } + } + "#; + + assert_eq!( + json::>(Partial::new(input)), + Ok(( + Partial::new(""), + Object( + vec![ + ("null".to_string(), Null), + ("true".to_string(), Boolean(true)), + ("false".to_string(), Boolean(false)), + ("number".to_string(), Num(123e4)), + ("string".to_string(), Str(" abc 123 ".to_string())), + ( + "array".to_string(), + Array(vec![Boolean(false), Num(1.0), Str("two".to_string())]) + ), + ( + "object".to_string(), + Object( + vec![ + ("a".to_string(), Num(1.0)), + ("b".to_string(), Str("c".to_string())), + ] + .into_iter() + .collect() + ) + ), + ("empty_array".to_string(), Array(vec![]),), + ("empty_object".to_string(), Object(HashMap::new()),), + ] + .into_iter() + .collect() + ) + )) + ); + } +} diff --git a/vendor/winnow-0.4.7/examples/json_iterator.rs b/vendor/winnow-0.4.7/examples/json_iterator.rs new file mode 100644 index 000000000..f4d8ead2a --- /dev/null +++ b/vendor/winnow-0.4.7/examples/json_iterator.rs @@ -0,0 +1,305 @@ +use std::collections::HashMap; + +use winnow::prelude::*; +use winnow::{ + ascii::{alphanumeric1 as alphanumeric, escaped, float}, + combinator::alt, + combinator::cut_err, + combinator::separated0, + combinator::{preceded, separated_pair, terminated}, + error::ParseError, + token::one_of, + token::{tag, take_while}, + IResult, +}; + +use std::cell::Cell; +use std::str; + +#[derive(Clone, Debug)] +pub struct JsonValue<'a, 'b> { + input: &'a str, + pub offset: &'b Cell, +} + +impl<'a, 'b: 'a> JsonValue<'a, 'b> { + pub fn new(input: &'a str, offset: &'b Cell) -> JsonValue<'a, 'b> { + JsonValue { input, offset } + } + + pub fn offset(&self, input: &'a str) { + let offset = input.as_ptr() as usize - self.input.as_ptr() as usize; + self.offset.set(offset); + } + + pub fn data(&self) -> &'a str { + &self.input[self.offset.get()..] + } + + pub fn string(&self) -> Option<&'a str> { + println!("string()"); + match string(self.data()) { + Ok((i, s)) => { + self.offset(i); + println!("-> {}", s); + Some(s) + } + _ => None, + } + } + + pub fn boolean(&self) -> Option { + println!("boolean()"); + match boolean(self.data()) { + Ok((i, o)) => { + self.offset(i); + println!("-> {}", o); + Some(o) + } + _ => None, + } + } + + pub fn number(&self) -> Option { + println!("number()"); + match float::<_, _, ()>(self.data()) { + Ok((i, o)) => { + self.offset(i); + println!("-> {}", o); + Some(o) + } + _ => None, + } + } + + pub fn array(&self) -> Option>> { + println!("array()"); + + match tag::<_, _, ()>("[").parse_next(self.data()) { + Err(_) => None, + Ok((i, _)) => { + println!("["); + self.offset(i); + let mut first = true; + let mut done = false; + let mut previous = std::usize::MAX; + + let v = self.clone(); + + Some(std::iter::from_fn(move || { + if done { + return None; + } + + // if we ignored one of the items, skip over the value + if v.offset.get() == previous { + println!("skipping value"); + if let Ok((i, _)) = value(v.data()) { + v.offset(i); + } + } + + if let Ok((i, _)) = tag::<_, _, ()>("]").parse_next(v.data()) { + println!("]"); + v.offset(i); + done = true; + return None; + } + + if first { + first = false; + } else { + match tag::<_, _, ()>(",").parse_next(v.data()) { + Ok((i, _)) => { + println!(","); + v.offset(i); + } + Err(_) => { + done = true; + return None; + } + } + } + + println!("-> {}", v.data()); + previous = v.offset.get(); + Some(v.clone()) + })) + } + } + } + + pub fn object(&self) -> Option)>> { + println!("object()"); + match tag::<_, _, ()>("{").parse_next(self.data()) { + Err(_) => None, + Ok((i, _)) => { + self.offset(i); + + println!("{{"); + + let mut first = true; + let mut done = false; + let mut previous = std::usize::MAX; + + let v = self.clone(); + + Some(std::iter::from_fn(move || { + if done { + return None; + } + + // if we ignored one of the items, skip over the value + if v.offset.get() == previous { + println!("skipping value"); + if let Ok((i, _)) = value(v.data()) { + v.offset(i); + } + } + + if let Ok((i, _)) = tag::<_, _, ()>("}").parse_next(v.data()) { + println!("}}"); + v.offset(i); + done = true; + return None; + } + + if first { + first = false; + } else { + match tag::<_, _, ()>(",").parse_next(v.data()) { + Ok((i, _)) => { + println!(","); + v.offset(i); + } + Err(_) => { + done = true; + return None; + } + } + } + + match string(v.data()) { + Ok((i, key)) => { + v.offset(i); + + match tag::<_, _, ()>(":").parse_next(v.data()) { + Err(_) => None, + Ok((i, _)) => { + v.offset(i); + + previous = v.offset.get(); + + println!("-> {} => {}", key, v.data()); + Some((key, v.clone())) + } + } + } + _ => None, + } + })) + } + } + } +} + +fn sp<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> { + let chars = " \t\r\n"; + + take_while(0.., move |c| chars.contains(c)).parse_next(i) +} + +fn parse_str<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> { + escaped(alphanumeric, '\\', one_of("\"n\\")).parse_next(i) +} + +fn string(i: &str) -> IResult<&str, &str> { + preceded('\"', cut_err(terminated(parse_str, '\"'))) + .context("string") + .parse_next(i) +} + +fn boolean(input: &str) -> IResult<&str, bool> { + alt(("false".map(|_| false), "true".map(|_| true))).parse_next(input) +} + +fn array(i: &str) -> IResult<&str, ()> { + preceded( + '[', + cut_err(terminated( + separated0(value, preceded(sp, ',')), + preceded(sp, ']'), + )), + ) + .context("array") + .parse_next(i) +} + +fn key_value(i: &str) -> IResult<&str, (&str, ())> { + separated_pair(preceded(sp, string), cut_err(preceded(sp, ':')), value).parse_next(i) +} + +fn hash(i: &str) -> IResult<&str, ()> { + preceded( + '{', + cut_err(terminated( + separated0(key_value, preceded(sp, ',')), + preceded(sp, '}'), + )), + ) + .context("map") + .parse_next(i) +} + +fn value(i: &str) -> IResult<&str, ()> { + preceded( + sp, + alt(( + hash, + array, + string.map(|_| ()), + float::<_, f64, _>.map(|_| ()), + boolean.map(|_| ()), + )), + ) + .parse_next(i) +} + +/// object(input) -> iterator over (key, `JsonValue`) +/// array(input) -> iterator over `JsonValue` +/// +/// JsonValue.string -> iterator over String (returns None after first successful call) +/// +/// object(input).filter(|(k, _)| k == "users").flatten(|(_, v)| v.object()).filter(|(k, _)| k == "city").flatten(|(_,v)| v.string()) +fn main() { + /*let data = "{ + \"users\": { + \"user1\" : { \"city\": \"Nantes\", \"country\": \"France\" }, + \"user2\" : { \"city\": \"Bruxelles\", \"country\": \"Belgium\" }, + \"user3\": { \"city\": \"Paris\", \"country\": \"France\", \"age\": 30 } + }, + \"countries\": [\"France\", \"Belgium\"] + }"; + */ + let data = "{\"users\":{\"user1\":{\"city\":\"Nantes\",\"country\":\"France\"},\"user2\":{\"city\":\"Bruxelles\",\"country\":\"Belgium\"},\"user3\":{\"city\":\"Paris\",\"country\":\"France\",\"age\":30}},\"countries\":[\"France\",\"Belgium\"]}"; + + let offset = Cell::new(0); + { + let parser = JsonValue::new(data, &offset); + + if let Some(o) = parser.object() { + let s: HashMap<&str, &str> = o + .filter(|(k, _)| *k == "users") + .filter_map(|(_, v)| v.object()) + .flatten() + .filter_map(|(user, v)| v.object().map(|o| (user, o))) + .flat_map(|(user, o)| { + o.filter(|(k, _)| *k == "city") + .filter_map(move |(_, v)| v.string().map(|s| (user, s))) + }) + .collect(); + + println!("res = {:?}", s); + } + }; +} diff --git a/vendor/winnow-0.4.7/examples/ndjson/example.ndjson b/vendor/winnow-0.4.7/examples/ndjson/example.ndjson new file mode 100644 index 000000000..7f1fca0ca --- /dev/null +++ b/vendor/winnow-0.4.7/examples/ndjson/example.ndjson @@ -0,0 +1,158 @@ +{"reason":"compiler-artifact","package_id":"proc-macro2 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro2-1.0.46/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro2-1.0.46/build.rs","edition":"2018","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","proc-macro"],"filenames":["/home/epage/src/personal/winnow/target/debug/build/proc-macro2-d6a7808ec27a845d/build-script-build"],"executable":null,"fresh":true} +{"reason":"build-script-executed","package_id":"proc-macro2 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)","linked_libs":[],"linked_paths":[],"cfgs":["use_proc_macro","wrap_proc_macro"],"env":[],"out_dir":"/home/epage/src/personal/winnow/target/debug/build/proc-macro2-e500f83d0dabcc00/out"} +{"reason":"compiler-artifact","package_id":"quote 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/quote-1.0.21/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/quote-1.0.21/build.rs","edition":"2018","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","proc-macro"],"filenames":["/home/epage/src/personal/winnow/target/debug/build/quote-e70da9bace8e108a/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"libc 0.2.139 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.139/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.139/build.rs","edition":"2015","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","extra_traits","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/build/libc-ea536a8e67e0b7eb/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"unicode-ident 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/unicode-ident-1.0.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"unicode-ident","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/unicode-ident-1.0.5/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libunicode_ident-e72d3e3fa5fdcbf4.rlib","/home/epage/src/personal/winnow/target/debug/deps/libunicode_ident-e72d3e3fa5fdcbf4.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"proc-macro2 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro2-1.0.46/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"proc-macro2","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro2-1.0.46/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","proc-macro"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libproc_macro2-559e547b03a7ac1e.rlib","/home/epage/src/personal/winnow/target/debug/deps/libproc_macro2-559e547b03a7ac1e.rmeta"],"executable":null,"fresh":true} +{"reason":"build-script-executed","package_id":"libc 0.2.139 (registry+https://github.com/rust-lang/crates.io-index)","linked_libs":[],"linked_paths":[],"cfgs":["freebsd11","libc_priv_mod_use","libc_union","libc_const_size_of","libc_align","libc_int128","libc_core_cvoid","libc_packedN","libc_cfg_target_vendor","libc_non_exhaustive","libc_ptr_addr_of","libc_underscore_const_names","libc_const_extern_fn"],"env":[],"out_dir":"/home/epage/src/personal/winnow/target/debug/build/libc-94d2f48bd38a8056/out"} +{"reason":"build-script-executed","package_id":"quote 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)","linked_libs":[],"linked_paths":[],"cfgs":[],"env":[],"out_dir":"/home/epage/src/personal/winnow/target/debug/build/quote-a2754428d152a498/out"} +{"reason":"compiler-artifact","package_id":"syn 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/syn-1.0.102/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/syn-1.0.102/build.rs","edition":"2018","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["clone-impls","default","derive","parsing","printing","proc-macro","quote"],"filenames":["/home/epage/src/personal/winnow/target/debug/build/syn-c9e8af729632e4e4/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/cfg-if-1.0.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cfg-if","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/cfg-if-1.0.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libcfg_if-047a17fcf848a7e5.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"autocfg 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/autocfg-1.1.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"autocfg","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/autocfg-1.1.0/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libautocfg-25db3455927a66e1.rlib","/home/epage/src/personal/winnow/target/debug/deps/libautocfg-25db3455927a66e1.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"serde_derive 1.0.145 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_derive-1.0.145/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_derive-1.0.145/build.rs","edition":"2015","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default"],"filenames":["/home/epage/src/personal/winnow/target/debug/build/serde_derive-fcc2f4aec2a2d4ab/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"serde 1.0.145 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.145/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.145/build.rs","edition":"2015","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","derive","serde_derive","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/build/serde-3f78a53b92e21d4d/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"libc 0.2.139 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.139/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"libc","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.139/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","extra_traits","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/liblibc-5b6dd9f3e6fc0120.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"quote 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/quote-1.0.21/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"quote","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/quote-1.0.21/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","proc-macro"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libquote-9a0c3a96b2cdc59c.rlib","/home/epage/src/personal/winnow/target/debug/deps/libquote-9a0c3a96b2cdc59c.rmeta"],"executable":null,"fresh":true} +{"reason":"build-script-executed","package_id":"syn 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)","linked_libs":[],"linked_paths":[],"cfgs":["syn_disable_nightly_tests"],"env":[],"out_dir":"/home/epage/src/personal/winnow/target/debug/build/syn-0a9a191063f1b2fc/out"} +{"reason":"build-script-executed","package_id":"serde_derive 1.0.145 (registry+https://github.com/rust-lang/crates.io-index)","linked_libs":[],"linked_paths":[],"cfgs":[],"env":[],"out_dir":"/home/epage/src/personal/winnow/target/debug/build/serde_derive-ead5e900bac8546f/out"} +{"reason":"build-script-executed","package_id":"serde 1.0.145 (registry+https://github.com/rust-lang/crates.io-index)","linked_libs":[],"linked_paths":[],"cfgs":[],"env":[],"out_dir":"/home/epage/src/personal/winnow/target/debug/build/serde-03f4af86861cbc3e/out"} +{"reason":"compiler-artifact","package_id":"thiserror 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/thiserror-1.0.38/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/thiserror-1.0.38/build.rs","edition":"2018","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/build/thiserror-66462325c558a4d5/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"ryu 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/ryu-1.0.11/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"ryu","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/ryu-1.0.11/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libryu-0e7b0d46c4589f15.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"crossbeam-utils 0.8.12 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/crossbeam-utils-0.8.12/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/crossbeam-utils-0.8.12/build.rs","edition":"2018","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/build/crossbeam-utils-c9170234d86239e2/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/memchr-2.5.0/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/memchr-2.5.0/build.rs","edition":"2018","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/build/memchr-99ffc1dfd2c517c1/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"serde_json 1.0.86 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_json-1.0.86/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_json-1.0.86/build.rs","edition":"2018","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/build/serde_json-3051866d1babe853/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"memoffset 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/memoffset-0.6.5/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/memoffset-0.6.5/build.rs","edition":"2015","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default"],"filenames":["/home/epage/src/personal/winnow/target/debug/build/memoffset-37767cb27e2441e6/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"bitflags 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/bitflags-1.3.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"bitflags","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/bitflags-1.3.2/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libbitflags-ea9a4e086e887550.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"itoa 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/itoa-1.0.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"itoa","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/itoa-1.0.4/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libitoa-69c375d2fd4189a8.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"crossbeam-epoch 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/crossbeam-epoch-0.9.11/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/crossbeam-epoch-0.9.11/build.rs","edition":"2018","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["alloc","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/build/crossbeam-epoch-ec0452f91ac732bb/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"ucd-trie 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/ucd-trie-0.1.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"ucd-trie","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/ucd-trie-0.1.5/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libucd_trie-eb38f7c85a03bb9d.rlib","/home/epage/src/personal/winnow/target/debug/deps/libucd_trie-eb38f7c85a03bb9d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"io-lifetimes 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/io-lifetimes-1.0.5/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/io-lifetimes-1.0.5/build.rs","edition":"2018","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["close","default","libc","windows-sys"],"filenames":["/home/epage/src/personal/winnow/target/debug/build/io-lifetimes-18d168bedd0c64e8/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.4.17/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.4.17/build.rs","edition":"2015","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/build/log-52c513d099058ca0/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"num-traits 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/num-traits-0.2.15/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/num-traits-0.2.15/build.rs","edition":"2015","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/build/num-traits-77d338745cc017c3/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"rayon-core 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-core-1.9.3/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-core-1.9.3/build.rs","edition":"2018","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/build/rayon-core-eecac7c574986103/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"rustix 0.36.8 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rustix-0.36.8/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rustix-0.36.8/build.rs","edition":"2018","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","io-lifetimes","libc","std","termios","use-libc-auxv"],"filenames":["/home/epage/src/personal/winnow/target/debug/build/rustix-32859c5d0061115d/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"syn 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/syn-1.0.102/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"syn","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/syn-1.0.102/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["clone-impls","default","derive","parsing","printing","proc-macro","quote"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libsyn-c9741af862298610.rlib","/home/epage/src/personal/winnow/target/debug/deps/libsyn-c9741af862298610.rmeta"],"executable":null,"fresh":true} +{"reason":"build-script-executed","package_id":"thiserror 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)","linked_libs":[],"linked_paths":[],"cfgs":[],"env":[],"out_dir":"/home/epage/src/personal/winnow/target/debug/build/thiserror-37d8ebe1b01cc51d/out"} +{"reason":"build-script-executed","package_id":"memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)","linked_libs":[],"linked_paths":[],"cfgs":["memchr_runtime_simd","memchr_runtime_sse2","memchr_runtime_sse42","memchr_runtime_avx"],"env":[],"out_dir":"/home/epage/src/personal/winnow/target/debug/build/memchr-743d739a8480f48a/out"} +{"reason":"build-script-executed","package_id":"crossbeam-utils 0.8.12 (registry+https://github.com/rust-lang/crates.io-index)","linked_libs":[],"linked_paths":[],"cfgs":[],"env":[],"out_dir":"/home/epage/src/personal/winnow/target/debug/build/crossbeam-utils-1975bdb7ecfbff2a/out"} +{"reason":"build-script-executed","package_id":"serde_json 1.0.86 (registry+https://github.com/rust-lang/crates.io-index)","linked_libs":[],"linked_paths":[],"cfgs":["limb_width_64"],"env":[],"out_dir":"/home/epage/src/personal/winnow/target/debug/build/serde_json-3f569e9655a7cd7e/out"} +{"reason":"build-script-executed","package_id":"memoffset 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)","linked_libs":[],"linked_paths":[],"cfgs":["tuple_ty","allow_clippy","maybe_uninit","doctests","raw_ref_macros"],"env":[],"out_dir":"/home/epage/src/personal/winnow/target/debug/build/memoffset-27100c1e8e709074/out"} +{"reason":"build-script-executed","package_id":"crossbeam-epoch 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)","linked_libs":[],"linked_paths":[],"cfgs":[],"env":[],"out_dir":"/home/epage/src/personal/winnow/target/debug/build/crossbeam-epoch-7f643445aebfa633/out"} +{"reason":"compiler-artifact","package_id":"getrandom 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/getrandom-0.2.7/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"getrandom","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/getrandom-0.2.7/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libgetrandom-d2efdd8bbd217458.rmeta"],"executable":null,"fresh":true} +{"reason":"build-script-executed","package_id":"log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)","linked_libs":[],"linked_paths":[],"cfgs":["atomic_cas","has_atomics"],"env":[],"out_dir":"/home/epage/src/personal/winnow/target/debug/build/log-b56bc898d3207792/out"} +{"reason":"build-script-executed","package_id":"io-lifetimes 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)","linked_libs":[],"linked_paths":[],"cfgs":["io_safety_is_in_std","panic_in_const_fn"],"env":[],"out_dir":"/home/epage/src/personal/winnow/target/debug/build/io-lifetimes-701560b8574ef205/out"} +{"reason":"compiler-artifact","package_id":"once_cell 1.15.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/once_cell-1.15.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"once_cell","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/once_cell-1.15.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["alloc","default","race","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libonce_cell-c9f9ea925d35da52.rlib","/home/epage/src/personal/winnow/target/debug/deps/libonce_cell-c9f9ea925d35da52.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/scopeguard-1.1.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"scopeguard","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/scopeguard-1.1.0/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libscopeguard-13a4bbff1ce24cc7.rmeta"],"executable":null,"fresh":true} +{"reason":"build-script-executed","package_id":"rayon-core 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)","linked_libs":[],"linked_paths":[],"cfgs":[],"env":[],"out_dir":"/home/epage/src/personal/winnow/target/debug/build/rayon-core-b008d521ccec1e7b/out"} +{"reason":"build-script-executed","package_id":"rustix 0.36.8 (registry+https://github.com/rust-lang/crates.io-index)","linked_libs":[],"linked_paths":[],"cfgs":["linux_raw","asm"],"env":[],"out_dir":"/home/epage/src/personal/winnow/target/debug/build/rustix-e16304a596230d21/out"} +{"reason":"build-script-executed","package_id":"num-traits 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)","linked_libs":[],"linked_paths":[],"cfgs":["has_i128","has_to_int_unchecked","has_reverse_bits","has_leading_trailing_ones","has_int_assignop_ref","has_div_euclid","has_copysign"],"env":[],"out_dir":"/home/epage/src/personal/winnow/target/debug/build/num-traits-6888d3d0832572a9/out"} +{"reason":"compiler-artifact","package_id":"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/lazy_static-1.4.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"lazy_static","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/lazy_static-1.4.0/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/liblazy_static-afa8b761bb5d6b57.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"unicode-width 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/unicode-width-0.1.10/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"unicode-width","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/unicode-width-0.1.10/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libunicode_width-8dcd31c030e77d42.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"either 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/either-1.8.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"either","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/either-1.8.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["use_std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libeither-3c87d508139ef632.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"linux-raw-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/linux-raw-sys-0.1.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"linux-raw-sys","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/linux-raw-sys-0.1.4/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["errno","general","ioctl","no_std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/liblinux_raw_sys-297593f8ceab708f.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"num_cpus 1.13.1 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/num_cpus-1.13.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"num_cpus","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/num_cpus-1.13.1/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libnum_cpus-539d2b6f1744794b.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"serde_derive 1.0.145 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_derive-1.0.145/Cargo.toml","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"serde_derive","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_derive-1.0.145/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libserde_derive-7934298a61c1a1a2.so"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"thiserror-impl 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/thiserror-impl-1.0.38/Cargo.toml","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"thiserror-impl","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/thiserror-impl-1.0.38/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libthiserror_impl-213d86e6d4b69b5f.so"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/memchr-2.5.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"memchr","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/memchr-2.5.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libmemchr-ae9722f3894e3314.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"crossbeam-utils 0.8.12 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/crossbeam-utils-0.8.12/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"crossbeam-utils","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/crossbeam-utils-0.8.12/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libcrossbeam_utils-59f0a08b7eefe073.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"memoffset 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/memoffset-0.6.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"memoffset","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/memoffset-0.6.5/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libmemoffset-4787845978faa8b8.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"io-lifetimes 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/io-lifetimes-1.0.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"io-lifetimes","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/io-lifetimes-1.0.5/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["close","default","libc","windows-sys"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libio_lifetimes-0d158e24024d572c.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.4.17/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"log","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/log-0.4.17/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/liblog-3242a8c3b3d72769.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"rand_core 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rand_core-0.6.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"rand_core","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rand_core-0.6.4/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["alloc","getrandom","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/librand_core-aa1df72cb81e420e.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"num-traits 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/num-traits-0.2.15/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"num-traits","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/num-traits-0.2.15/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libnum_traits-1c8d0251ac4ea61d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"rayon 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-1.5.3/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-1.5.3/build.rs","edition":"2018","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/build/rayon-4f0513187044c0f2/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"escargot 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/escargot-0.5.7/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/escargot-0.5.7/build.rs","edition":"2018","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/build/escargot-44a89e78cfd0d26f/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"yansi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/yansi-0.5.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"yansi","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/yansi-0.5.1/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libyansi-62809433fc3ff8e9.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"regex-automata 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/regex-automata-0.1.10/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"regex-automata","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/regex-automata-0.1.10/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libregex_automata-741e79c4b6938d7d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"remove_dir_all 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/remove_dir_all-0.5.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"remove_dir_all","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/remove_dir_all-0.5.3/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libremove_dir_all-bcafaf4f00d8e4a4.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"regex-syntax 0.6.27 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/regex-syntax-0.6.27/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"regex-syntax","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/regex-syntax-0.6.27/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","unicode","unicode-age","unicode-bool","unicode-case","unicode-gencat","unicode-perl","unicode-script","unicode-segment"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libregex_syntax-3fe0a07eb00f644f.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"ucd-trie 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/ucd-trie-0.1.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"ucd-trie","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/ucd-trie-0.1.5/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libucd_trie-b01a07ea40c7e7ed.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"plotters-backend 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/plotters-backend-0.3.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"plotters-backend","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/plotters-backend-0.3.4/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libplotters_backend-34c8fa8c2b121eeb.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"ppv-lite86 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/ppv-lite86-0.2.16/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"ppv-lite86","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/ppv-lite86-0.2.16/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["simd","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libppv_lite86-3b9c603c4b32aff6.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"fastrand 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/fastrand-1.8.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"fastrand","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/fastrand-1.8.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libfastrand-52ad6b37c39c8a90.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"itertools 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/itertools-0.10.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"itertools","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/itertools-0.10.5/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","use_alloc","use_std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libitertools-ba05d1064477b941.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"serde 1.0.145 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.145/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"serde","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.145/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","derive","serde_derive","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libserde-e026f194fb97de03.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"thiserror 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/thiserror-1.0.38/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"thiserror","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/thiserror-1.0.38/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libthiserror-4481f6326f711f93.rlib","/home/epage/src/personal/winnow/target/debug/deps/libthiserror-4481f6326f711f93.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"crossbeam-epoch 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/crossbeam-epoch-0.9.11/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"crossbeam-epoch","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/crossbeam-epoch-0.9.11/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["alloc","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libcrossbeam_epoch-caa786e06425cee9.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"thiserror 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/thiserror-1.0.38/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"thiserror","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/thiserror-1.0.38/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libthiserror-9187d79370422188.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"rustix 0.36.8 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rustix-0.36.8/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"rustix","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rustix-0.36.8/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","io-lifetimes","libc","std","termios","use-libc-auxv"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/librustix-ec48622574cca747.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"crossbeam-channel 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/crossbeam-channel-0.5.6/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"crossbeam-channel","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/crossbeam-channel-0.5.6/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["crossbeam-utils","default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libcrossbeam_channel-a9b11ccef7773884.rmeta"],"executable":null,"fresh":true} +{"reason":"build-script-executed","package_id":"escargot 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)","linked_libs":[],"linked_paths":[],"cfgs":[],"env":[],"out_dir":"/home/epage/src/personal/winnow/target/debug/build/escargot-5711ac23b4781245/out"} +{"reason":"compiler-artifact","package_id":"tempfile 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/tempfile-3.3.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tempfile","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/tempfile-3.3.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libtempfile-8b83de608c2a0658.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"rand_chacha 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rand_chacha-0.3.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"rand_chacha","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rand_chacha-0.3.1/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/librand_chacha-5967d0068d39b018.rmeta"],"executable":null,"fresh":true} +{"reason":"build-script-executed","package_id":"rayon 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)","linked_libs":[],"linked_paths":[],"cfgs":["has_step_by_rev","has_min_const_generics","has_control_flow"],"env":[],"out_dir":"/home/epage/src/personal/winnow/target/debug/build/rayon-d01aa17f59a1e98f/out"} +{"reason":"compiler-artifact","package_id":"plotters-svg 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/plotters-svg-0.3.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"plotters-svg","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/plotters-svg-0.3.3/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libplotters_svg-2bb014e4a5d863b1.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"csv-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/csv-core-0.1.10/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"csv-core","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/csv-core-0.1.10/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libcsv_core-bf47a6ecf716f212.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/textwrap-0.11.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"textwrap","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/textwrap-0.11.0/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libtextwrap-1f9a5b633ba2872d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/atty-0.2.14/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"atty","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/atty-0.2.14/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libatty-7590cc9da5872c3b.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"wait-timeout 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/wait-timeout-0.2.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"wait-timeout","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/wait-timeout-0.2.0/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libwait_timeout-d79299ed1c2df76b.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"diff 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/diff-0.1.13/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"diff","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/diff-0.1.13/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libdiff-a3c1327ada950886.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"concolor-query 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/concolor-query-0.1.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"concolor-query","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/concolor-query-0.1.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["windows"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libconcolor_query-1b1f33bda6da9636.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/same-file-1.0.6/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"same-file","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/same-file-1.0.6/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libsame_file-8dba8c6e6bbcef0a.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"bit-vec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/bit-vec-0.6.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"bit-vec","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/bit-vec-0.6.3/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libbit_vec-5cc1be6dbbb7d172.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/fnv-1.0.7/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"fnv","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/fnv-1.0.7/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libfnv-e811c8615aede027.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"serde_json 1.0.86 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_json-1.0.86/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"serde_json","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_json-1.0.86/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libserde_json-10d232e85191c379.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"pest 2.5.5 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/pest-2.5.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"pest","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/pest-2.5.5/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","std","thiserror"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libpest-c28124a2ace8ce41.rlib","/home/epage/src/personal/winnow/target/debug/deps/libpest-c28124a2ace8ce41.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"crossbeam-deque 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/crossbeam-deque-0.8.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"crossbeam-deque","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/crossbeam-deque-0.8.2/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["crossbeam-epoch","crossbeam-utils","default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libcrossbeam_deque-a531937c1e514cf3.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"bstr 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/bstr-0.2.17/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"bstr","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/bstr-0.2.17/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","lazy_static","regex-automata","serde","serde1","serde1-nostd","std","unicode"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libbstr-3245cbc7e1b4eee0.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"is-terminal 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/is-terminal-0.4.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"is-terminal","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/is-terminal-0.4.3/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libis_terminal-ddb4d6f1cea88415.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"pest 2.5.5 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/pest-2.5.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"pest","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/pest-2.5.5/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","std","thiserror"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libpest-3fe2406158c36e91.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"doc-comment 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/doc-comment-0.3.3/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/doc-comment-0.3.3/build.rs","edition":"2015","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/build/doc-comment-476a3be5ae9523a0/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"cast 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.3.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cast","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.3.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libcast-0f6ca0f808d89c22.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"half 1.8.2 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/half-1.8.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"half","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/half-1.8.2/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libhalf-ec0164f76c2e0030.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/quick-error-1.2.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"quick-error","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/quick-error-1.2.3/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libquick_error-e7675fcf1fdb276d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"once_cell 1.15.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/once_cell-1.15.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"once_cell","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/once_cell-1.15.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["alloc","default","race","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libonce_cell-6a83ca81f3790104.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"itoa 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/itoa-0.4.8/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"itoa","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/itoa-0.4.8/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libitoa-af0357b7d39004b0.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"plotters 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/plotters-0.3.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"plotters","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/plotters-0.3.4/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["area_series","line_series","plotters-svg","svg_backend"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libplotters-c6ddec411d8166e5.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"walkdir 2.3.2 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/walkdir-2.3.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"walkdir","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/walkdir-2.3.2/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libwalkdir-9e7e41a0b2bf038d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"bit-set 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/bit-set-0.5.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"bit-set","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/bit-set-0.5.3/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libbit_set-2aef4909cbe7f4dc.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"pretty_assertions 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/pretty_assertions-1.3.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"pretty_assertions","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/pretty_assertions-1.3.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libpretty_assertions-917f731810bb748b.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"clap 2.34.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/clap-2.34.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"clap","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/clap-2.34.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libclap-af397f0f338fc8b9.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"rand 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.8.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"rand","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.8.5/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["alloc","getrandom","libc","rand_chacha","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/librand-79231f927b479fcb.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"quick-xml 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/quick-xml-0.23.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"quick-xml","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/quick-xml-0.23.1/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libquick_xml-56f1f63175d80ec8.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"rand_xorshift 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rand_xorshift-0.3.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"rand_xorshift","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rand_xorshift-0.3.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/librand_xorshift-52cda07a05fef0b5.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"pest_meta 2.5.5 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/pest_meta-2.5.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"pest_meta","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/pest_meta-2.5.5/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libpest_meta-e592b8a19ab895e0.rlib","/home/epage/src/personal/winnow/target/debug/deps/libpest_meta-e592b8a19ab895e0.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"rayon-core 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-core-1.9.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"rayon-core","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-core-1.9.3/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/librayon_core-28c7fd349d6eb8a3.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"tinytemplate 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/tinytemplate-1.2.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tinytemplate","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/tinytemplate-1.2.1/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libtinytemplate-1e34f9b3f54388b1.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"serde_cbor 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_cbor-0.11.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"serde_cbor","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_cbor-0.11.2/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libserde_cbor-a6696a57f0dc1b3e.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"escargot 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/escargot-0.5.7/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"escargot","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/escargot-0.5.7/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libescargot-8a922c953f0ce0d3.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"csv 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/csv-1.1.6/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"csv","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/csv-1.1.6/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libcsv-66898c2026240d6e.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"rusty-fork 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rusty-fork-0.3.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"rusty-fork","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rusty-fork-0.3.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["timeout","wait-timeout"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/librusty_fork-3ff190906b9b0c88.rmeta"],"executable":null,"fresh":true} +{"reason":"build-script-executed","package_id":"doc-comment 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)","linked_libs":[],"linked_paths":[],"cfgs":[],"env":[],"out_dir":"/home/epage/src/personal/winnow/target/debug/build/doc-comment-9f27b6aeba0913e7/out"} +{"reason":"compiler-artifact","package_id":"criterion-plot 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/criterion-plot-0.4.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"criterion-plot","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/criterion-plot-0.4.5/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libcriterion_plot-dc7b9242779f53d6.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"concolor 0.0.11 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/concolor-0.0.11/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"concolor","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/concolor-0.0.11/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["auto","bitflags","clicolor","concolor-query","core","interactive","no_color","std","term","windows"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libconcolor-c2d97e9aa66666d7.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"regex 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/regex-1.6.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"regex","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/regex-1.6.0/src/lib.rs","edition":"2018","doc":true,"doctest":false,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libregex-14a9fe50552aac49.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"os_pipe 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/os_pipe-1.1.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"os_pipe","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/os_pipe-1.1.3/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libos_pipe-be2a22288f932a49.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"quick-error 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/quick-error-2.0.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"quick-error","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/quick-error-2.0.1/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libquick_error-280edfc32cc83812.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"normalize-line-endings 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/normalize-line-endings-0.3.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"normalize-line-endings","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/normalize-line-endings-0.3.0/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libnormalize_line_endings-8a66ba357a389996.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"bytecount 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/bytecount-0.6.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"bytecount","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/bytecount-0.6.3/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libbytecount-c083e2cdbbb4f003.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"snapbox-macros 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/snapbox-macros-0.3.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"snapbox-macros","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/snapbox-macros-0.3.1/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libsnapbox_macros-d9da77d55f4279bc.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"oorandom 11.1.3 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/oorandom-11.1.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"oorandom","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/oorandom-11.1.3/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/liboorandom-052fb0be6ac16c94.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"byteorder 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/byteorder-1.4.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"byteorder","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/byteorder-1.4.3/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libbyteorder-9f6a3ecb302657b0.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"similar 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/similar-2.2.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"similar","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/similar-2.2.1/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","inline","text"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libsimilar-ca2082771c207a3c.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"termcolor 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/termcolor-1.2.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"termcolor","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/termcolor-1.2.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libtermcolor-dad1a04bc5d2f742.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"pest_generator 2.5.5 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/pest_generator-2.5.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"pest_generator","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/pest_generator-2.5.5/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libpest_generator-17d62a3fe28e46f5.rlib","/home/epage/src/personal/winnow/target/debug/deps/libpest_generator-17d62a3fe28e46f5.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"rayon 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-1.5.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"rayon","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/rayon-1.5.3/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/librayon-41dd0a10f9292557.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"proptest 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/proptest-1.0.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"proptest","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/proptest-1.0.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["bit-set","break-dead-code","default","fork","lazy_static","quick-error","regex-syntax","rusty-fork","std","tempfile","timeout"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libproptest-7f94966e4936da95.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"snapbox 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/snapbox-0.4.6/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"snapbox","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/snapbox-0.4.6/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["color","color-auto","concolor","default","diff","examples"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libsnapbox-d99468a5201f9b87.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"doc-comment 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/doc-comment-0.3.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"doc_comment","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/doc-comment-0.3.3/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libdoc_comment-5644793091a6953d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"lexopt 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/lexopt-0.3.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"lexopt","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/lexopt-0.3.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/liblexopt-c945e030a97b8e1f.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"circular 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/circular-0.3.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"circular","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/circular-0.3.0/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libcircular-6190d46717d189a0.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"winnow 0.3.1 (path+file:///home/epage/src/personal/winnow)","manifest_path":"/home/epage/src/personal/winnow/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"winnow","src_path":"/home/epage/src/personal/winnow/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["alloc","default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libwinnow-a64b99fd45b2e97c.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"pest_derive 2.5.5 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/pest_derive-2.5.5/Cargo.toml","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"pest_derive","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/pest_derive-2.5.5/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libpest_derive-23acec6b80f586aa.so"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"criterion 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/criterion-0.3.6/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"criterion","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/criterion-0.3.6/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["cargo_bench_support","default"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libcriterion-864d2d30e85a25cf.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"handlebars 4.3.6 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-4.3.6/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"handlebars","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-4.3.6/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libhandlebars-8f7ca769e2915c7a.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"term-transcript 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)","manifest_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/term-transcript-0.2.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"term-transcript","src_path":"/home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/term-transcript-0.2.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["atty","default","handlebars","pretty_assertions","quick-xml","serde","svg","test"],"filenames":["/home/epage/src/personal/winnow/target/debug/deps/libterm_transcript-67537cf74f0568cc.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"winnow 0.3.1 (path+file:///home/epage/src/personal/winnow)","manifest_path":"/home/epage/src/personal/winnow/Cargo.toml","target":{"kind":["example"],"crate_types":["bin"],"name":"ini","src_path":"/home/epage/src/personal/winnow/examples/ini/main.rs","edition":"2021","required-features":["std"],"doc":false,"doctest":false,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["alloc","default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/examples/libini-029ff669d11d054a.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"winnow 0.3.1 (path+file:///home/epage/src/personal/winnow)","manifest_path":"/home/epage/src/personal/winnow/Cargo.toml","target":{"kind":["example"],"crate_types":["bin"],"name":"custom_error","src_path":"/home/epage/src/personal/winnow/examples/custom_error.rs","edition":"2021","required-features":["alloc"],"doc":false,"doctest":false,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["alloc","default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/examples/libcustom_error-8382fb7d49937909.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"winnow 0.3.1 (path+file:///home/epage/src/personal/winnow)","manifest_path":"/home/epage/src/personal/winnow/Cargo.toml","target":{"kind":["example"],"crate_types":["bin"],"name":"s_expression","src_path":"/home/epage/src/personal/winnow/examples/s_expression/main.rs","edition":"2021","required-features":["alloc"],"doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["alloc","default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/examples/libs_expression-0161e16eb3795e0c.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"winnow 0.3.1 (path+file:///home/epage/src/personal/winnow)","manifest_path":"/home/epage/src/personal/winnow/Cargo.toml","target":{"kind":["example"],"crate_types":["bin"],"name":"css","src_path":"/home/epage/src/personal/winnow/examples/css/main.rs","edition":"2021","doc":false,"doctest":false,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["alloc","default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/examples/libcss-d003331b0eaf24a5.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"winnow 0.3.1 (path+file:///home/epage/src/personal/winnow)","manifest_path":"/home/epage/src/personal/winnow/Cargo.toml","target":{"kind":["example"],"crate_types":["bin"],"name":"json","src_path":"/home/epage/src/personal/winnow/examples/json/main.rs","edition":"2021","required-features":["std"],"doc":false,"doctest":false,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["alloc","default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/examples/libjson-20da0c01e9db35aa.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"winnow 0.3.1 (path+file:///home/epage/src/personal/winnow)","manifest_path":"/home/epage/src/personal/winnow/Cargo.toml","target":{"kind":["example"],"crate_types":["bin"],"name":"ndjson","src_path":"/home/epage/src/personal/winnow/examples/ndjson/main.rs","edition":"2021","required-features":["std"],"doc":false,"doctest":false,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["alloc","default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/examples/libndjson-17afbe6b158251ab.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"winnow 0.3.1 (path+file:///home/epage/src/personal/winnow)","manifest_path":"/home/epage/src/personal/winnow/Cargo.toml","target":{"kind":["example"],"crate_types":["bin"],"name":"http","src_path":"/home/epage/src/personal/winnow/examples/http/main.rs","edition":"2021","required-features":["alloc"],"doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["alloc","default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/examples/libhttp-08613cd431f59551.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"winnow 0.3.1 (path+file:///home/epage/src/personal/winnow)","manifest_path":"/home/epage/src/personal/winnow/Cargo.toml","target":{"kind":["example"],"crate_types":["bin"],"name":"iterator","src_path":"/home/epage/src/personal/winnow/examples/iterator.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["alloc","default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/examples/libiterator-46a33f71a5378497.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"winnow 0.3.1 (path+file:///home/epage/src/personal/winnow)","manifest_path":"/home/epage/src/personal/winnow/Cargo.toml","target":{"kind":["example"],"crate_types":["bin"],"name":"string","src_path":"/home/epage/src/personal/winnow/examples/string/main.rs","edition":"2021","required-features":["alloc"],"doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["alloc","default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/examples/libstring-73fadc9999eff689.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"winnow 0.3.1 (path+file:///home/epage/src/personal/winnow)","manifest_path":"/home/epage/src/personal/winnow/Cargo.toml","target":{"kind":["example"],"crate_types":["bin"],"name":"arithmetic","src_path":"/home/epage/src/personal/winnow/examples/arithmetic/main.rs","edition":"2021","required-features":["alloc"],"doc":false,"doctest":false,"test":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["alloc","default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/examples/libarithmetic-04ca5fb45c28ebc2.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"winnow 0.3.1 (path+file:///home/epage/src/personal/winnow)","manifest_path":"/home/epage/src/personal/winnow/Cargo.toml","target":{"kind":["example"],"crate_types":["bin"],"name":"json_iterator","src_path":"/home/epage/src/personal/winnow/examples/json_iterator.rs","edition":"2021","required-features":["std"],"doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["alloc","default","std"],"filenames":["/home/epage/src/personal/winnow/target/debug/examples/libjson_iterator-9bb330a957b0d53d.rmeta"],"executable":null,"fresh":true} +{"reason":"build-finished","success":true} + diff --git a/vendor/winnow-0.4.7/examples/ndjson/main.rs b/vendor/winnow-0.4.7/examples/ndjson/main.rs new file mode 100644 index 000000000..d81b6900f --- /dev/null +++ b/vendor/winnow-0.4.7/examples/ndjson/main.rs @@ -0,0 +1,113 @@ +mod parser; + +use std::io::Read; + +use winnow::error::ErrMode; +use winnow::error::Error; +use winnow::error::Needed; +use winnow::stream::Offset; + +fn main() -> Result<(), lexopt::Error> { + let args = Args::parse()?; + let input = args.input.ok_or_else(|| lexopt::Error::MissingValue { + option: Some("".to_owned()), + })?; + + let mut file = std::fs::File::open(&input).map_err(to_lexopt)?; + + // Intentionally starting with a small buffer to make it easier to show `Incomplete` handling + let buffer_size = 10; + let min_buffer_growth = 100; + let buffer_growth_factor = 2; + let mut buffer = circular::Buffer::with_capacity(buffer_size); + loop { + let read = file.read(buffer.space()).map_err(to_lexopt)?; + eprintln!("read {}", read); + if read == 0 { + // Should be EOF since we always make sure there is `available_space` + assert_ne!(buffer.available_space(), 0); + assert_eq!( + buffer.available_data(), + 0, + "leftover data: {}", + String::from_utf8_lossy(buffer.data()) + ); + break; + } + buffer.fill(read); + + loop { + let input = parser::Stream::new(std::str::from_utf8(buffer.data()).map_err(to_lexopt)?); + match parser::ndjson::>(input) { + Ok((remainder, value)) => { + println!("{:?}", value); + println!(); + // Tell the buffer how much we read + let consumed = input.offset_to(&remainder); + buffer.consume(consumed); + } + Err(ErrMode::Backtrack(e)) | Err(ErrMode::Cut(e)) => { + return Err(fmt_lexopt(e.to_string())); + } + Err(ErrMode::Incomplete(Needed::Size(size))) => { + // Without the format telling us how much space is required, we really should + // treat this the same as `Unknown` but are doing this to demonstrate how to + // handle `Size`. + // + // Even when the format has a header to tell us `Size`, we could hit incidental + // `Size(1)`s, so make sure we buffer more space than that to avoid reading + // one byte at a time + let head_room = size.get().max(min_buffer_growth); + let new_capacity = buffer.available_data() + head_room; + eprintln!("growing buffer to {}", new_capacity); + buffer.grow(new_capacity); + if buffer.available_space() < head_room { + eprintln!("buffer shift"); + buffer.shift(); + } + break; + } + Err(ErrMode::Incomplete(Needed::Unknown)) => { + let new_capacity = buffer_growth_factor * buffer.capacity(); + eprintln!("growing buffer to {}", new_capacity); + buffer.grow(new_capacity); + break; + } + } + } + } + + Ok(()) +} + +#[derive(Default)] +struct Args { + input: Option, +} + +impl Args { + fn parse() -> Result { + 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.into()); + } + _ => return Err(arg.unexpected()), + } + } + Ok(res) + } +} + +fn to_lexopt(e: impl std::error::Error + Send + Sync + 'static) -> lexopt::Error { + lexopt::Error::Custom(Box::new(e)) +} + +fn fmt_lexopt(e: String) -> lexopt::Error { + lexopt::Error::Custom(e.into()) +} diff --git a/vendor/winnow-0.4.7/examples/ndjson/parser.rs b/vendor/winnow-0.4.7/examples/ndjson/parser.rs new file mode 100644 index 000000000..2a60952e3 --- /dev/null +++ b/vendor/winnow-0.4.7/examples/ndjson/parser.rs @@ -0,0 +1,328 @@ +use std::collections::HashMap; +use std::str; + +use winnow::prelude::*; +use winnow::{ + ascii::float, + ascii::line_ending, + combinator::alt, + combinator::cut_err, + combinator::{delimited, preceded, separated_pair, terminated}, + combinator::{fold_repeat, separated0}, + error::{ContextError, ParseError}, + stream::Partial, + token::{any, none_of, take, take_while}, +}; + +#[derive(Debug, PartialEq, Clone)] +pub enum JsonValue { + Null, + Boolean(bool), + Str(String), + Num(f64), + Array(Vec), + Object(HashMap), +} + +/// Use `Partial` to cause `ErrMode::Incomplete` while parsing +pub type Stream<'i> = Partial<&'i str>; + +pub fn ndjson<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, Option, E> { + alt(( + terminated(delimited(ws, json_value, ws), line_ending).map(Some), + line_ending.value(None), + )) + .parse_next(input) +} + +// --Besides `WS`, same as a regular json parser ---------------------------- + +/// `alt` is a combinator that tries multiple parsers one by one, until +/// one of them succeeds +fn json_value<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, JsonValue, E> { + // `alt` combines the each value parser. It returns the result of the first + // successful parser, or an error + alt(( + null.value(JsonValue::Null), + boolean.map(JsonValue::Boolean), + string.map(JsonValue::Str), + float.map(JsonValue::Num), + array.map(JsonValue::Array), + object.map(JsonValue::Object), + )) + .parse_next(input) +} + +/// `tag(string)` generates a parser that recognizes the argument string. +/// +/// This also shows returning a sub-slice of the original input +fn null<'i, E: ParseError>>(input: Stream<'i>) -> IResult, &'i str, E> { + // This is a parser that returns `"null"` if it sees the string "null", and + // an error otherwise + "null".parse_next(input) +} + +/// We can combine `tag` with other functions, like `value` which returns a given constant value on +/// success. +fn boolean<'i, E: ParseError>>(input: Stream<'i>) -> IResult, bool, E> { + // This is a parser that returns `true` if it sees the string "true", and + // an error otherwise + let parse_true = "true".value(true); + + // This is a parser that returns `false` if it sees the string "false", and + // an error otherwise + let parse_false = "false".value(false); + + alt((parse_true, parse_false)).parse_next(input) +} + +/// This parser gathers all `char`s up into a `String`with a parse to recognize the double quote +/// character, before the string (using `preceded`) and after the string (using `terminated`). +fn string<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, String, E> { + preceded( + '\"', + // `cut_err` transforms an `ErrMode::Backtrack(e)` to `ErrMode::Cut(e)`, signaling to + // combinators like `alt` that they should not try other parsers. We were in the + // right branch (since we found the `"` character) but encountered an error when + // parsing the string + cut_err(terminated( + fold_repeat(0.., character, String::new, |mut string, c| { + string.push(c); + string + }), + '\"', + )), + ) + // `context` lets you add a static string to errors to provide more information in the + // error chain (to indicate which parser had an error) + .context("string") + .parse_next(input) +} + +/// You can mix the above declarative parsing with an imperative style to handle more unique cases, +/// like escaping +fn character<'i, E: ParseError>>(input: Stream<'i>) -> IResult, char, E> { + let (input, c) = none_of("\"").parse_next(input)?; + if c == '\\' { + alt(( + any.verify_map(|c| { + Some(match c { + '"' | '\\' | '/' => c, + 'b' => '\x08', + 'f' => '\x0C', + 'n' => '\n', + 'r' => '\r', + 't' => '\t', + _ => return None, + }) + }), + preceded('u', unicode_escape), + )) + .parse_next(input) + } else { + Ok((input, c)) + } +} + +fn unicode_escape<'i, E: ParseError>>( + input: Stream<'i>, +) -> IResult, char, E> { + alt(( + // Not a surrogate + u16_hex + .verify(|cp| !(0xD800..0xE000).contains(cp)) + .map(|cp| cp as u32), + // See https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF for details + separated_pair(u16_hex, "\\u", u16_hex) + .verify(|(high, low)| (0xD800..0xDC00).contains(high) && (0xDC00..0xE000).contains(low)) + .map(|(high, low)| { + let high_ten = (high as u32) - 0xD800; + let low_ten = (low as u32) - 0xDC00; + (high_ten << 10) + low_ten + 0x10000 + }), + )) + .verify_map( + // Could be probably replaced with .unwrap() or _unchecked due to the verify checks + std::char::from_u32, + ) + .parse_next(input) +} + +fn u16_hex<'i, E: ParseError>>(input: Stream<'i>) -> IResult, u16, E> { + take(4usize) + .verify_map(|s| u16::from_str_radix(s, 16).ok()) + .parse_next(input) +} + +/// Some combinators, like `separated0` or `many0`, will call a parser repeatedly, +/// accumulating results in a `Vec`, until it encounters an error. +/// If you want more control on the parser application, check out the `iterator` +/// combinator (cf `examples/iterator.rs`) +fn array<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, Vec, E> { + preceded( + ('[', ws), + cut_err(terminated(separated0(json_value, (ws, ',', ws)), (ws, ']'))), + ) + .context("array") + .parse_next(input) +} + +fn object<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, HashMap, E> { + preceded( + ('{', ws), + cut_err(terminated(separated0(key_value, (ws, ',', ws)), (ws, '}'))), + ) + .context("object") + .parse_next(input) +} + +fn key_value<'i, E: ParseError> + ContextError, &'static str>>( + input: Stream<'i>, +) -> IResult, (String, JsonValue), E> { + separated_pair(string, cut_err((ws, ':', ws)), json_value).parse_next(input) +} + +/// Parser combinators are constructed from the bottom up: +/// first we write parsers for the smallest elements (here a space character), +/// then we'll combine them in larger parsers +fn ws<'i, E: ParseError>>(input: Stream<'i>) -> IResult, &'i str, E> { + // Combinators like `take_while` return a function. That function is the + // parser,to which we can pass the input + take_while(0.., WS).parse_next(input) +} + +const WS: &str = " \t"; + +#[cfg(test)] +mod test { + #[allow(clippy::useless_attribute)] + #[allow(dead_code)] // its dead for benches + use super::*; + + #[allow(clippy::useless_attribute)] + #[allow(dead_code)] // its dead for benches + type Error<'i> = winnow::error::Error>; + + #[test] + fn json_string() { + assert_eq!( + string::>(Partial::new("\"\"")), + Ok((Partial::new(""), "".to_string())) + ); + assert_eq!( + string::>(Partial::new("\"abc\"")), + Ok((Partial::new(""), "abc".to_string())) + ); + assert_eq!( + string::>(Partial::new( + "\"abc\\\"\\\\\\/\\b\\f\\n\\r\\t\\u0001\\u2014\u{2014}def\"" + )), + Ok(( + Partial::new(""), + "abc\"\\/\x08\x0C\n\r\t\x01β€”β€”def".to_string() + )), + ); + assert_eq!( + string::>(Partial::new("\"\\uD83D\\uDE10\"")), + Ok((Partial::new(""), "😐".to_string())) + ); + + assert!(string::>(Partial::new("\"")).is_err()); + assert!(string::>(Partial::new("\"abc")).is_err()); + assert!(string::>(Partial::new("\"\\\"")).is_err()); + assert!(string::>(Partial::new("\"\\u123\"")).is_err()); + assert!(string::>(Partial::new("\"\\uD800\"")).is_err()); + assert!(string::>(Partial::new("\"\\uD800\\uD800\"")).is_err()); + assert!(string::>(Partial::new("\"\\uDC00\"")).is_err()); + } + + #[test] + fn json_object() { + use JsonValue::{Num, Object, Str}; + + let input = r#"{"a":42,"b":"x"} +"#; + + let expected = Object( + vec![ + ("a".to_string(), Num(42.0)), + ("b".to_string(), Str("x".to_string())), + ] + .into_iter() + .collect(), + ); + + assert_eq!( + ndjson::>(Partial::new(input)), + Ok((Partial::new(""), Some(expected))) + ); + } + + #[test] + fn json_array() { + use JsonValue::{Array, Num, Str}; + + let input = r#"[42,"x"] +"#; + + let expected = Array(vec![Num(42.0), Str("x".to_string())]); + + assert_eq!( + ndjson::>(Partial::new(input)), + Ok((Partial::new(""), Some(expected))) + ); + } + + #[test] + fn json_whitespace() { + use JsonValue::{Array, Boolean, Null, Num, Object, Str}; + + let input = r#" { "null" : null, "true" :true , "false": false , "number" : 123e4 , "string" : " abc 123 " , "array" : [ false , 1 , "two" ] , "object" : { "a" : 1.0 , "b" : "c" } , "empty_array" : [ ] , "empty_object" : { } } +"#; + + assert_eq!( + ndjson::>(Partial::new(input)), + Ok(( + Partial::new(""), + Some(Object( + vec![ + ("null".to_string(), Null), + ("true".to_string(), Boolean(true)), + ("false".to_string(), Boolean(false)), + ("number".to_string(), Num(123e4)), + ("string".to_string(), Str(" abc 123 ".to_string())), + ( + "array".to_string(), + Array(vec![Boolean(false), Num(1.0), Str("two".to_string())]) + ), + ( + "object".to_string(), + Object( + vec![ + ("a".to_string(), Num(1.0)), + ("b".to_string(), Str("c".to_string())), + ] + .into_iter() + .collect() + ) + ), + ("empty_array".to_string(), Array(vec![]),), + ("empty_object".to_string(), Object(HashMap::new()),), + ] + .into_iter() + .collect() + )) + )) + ); + } +} diff --git a/vendor/winnow-0.4.7/examples/s_expression/main.rs b/vendor/winnow-0.4.7/examples/s_expression/main.rs new file mode 100644 index 000000000..da055bed8 --- /dev/null +++ b/vendor/winnow-0.4.7/examples/s_expression/main.rs @@ -0,0 +1,20 @@ +//! In this example we build an [S-expression](https://en.wikipedia.org/wiki/S-expression) +//! parser and tiny [lisp](https://en.wikipedia.org/wiki/Lisp_(programming_language)) interpreter. +//! Lisp is a simple type of language made up of Atoms and Lists, forming easily parsable trees. + +#![cfg(feature = "alloc")] + +mod parser; + +fn main() { + let expression_1 = "((if (= (+ 3 (/ 9 3)) + (* 2 3)) + * + /) + 456 123)"; + println!( + "\"{}\"\nevaled gives us: {:?}", + expression_1, + parser::eval_from_str(expression_1) + ); +} diff --git a/vendor/winnow-0.4.7/examples/s_expression/parser.rs b/vendor/winnow-0.4.7/examples/s_expression/parser.rs new file mode 100644 index 000000000..9a1686e1c --- /dev/null +++ b/vendor/winnow-0.4.7/examples/s_expression/parser.rs @@ -0,0 +1,362 @@ +//! In this example we build an [S-expression](https://en.wikipedia.org/wiki/S-expression) +//! parser and tiny [lisp](https://en.wikipedia.org/wiki/Lisp_(programming_language)) interpreter. +//! Lisp is a simple type of language made up of Atoms and Lists, forming easily parsable trees. + +use winnow::{ + ascii::{alpha1, digit1, multispace0, multispace1}, + combinator::alt, + combinator::repeat, + combinator::{cut_err, opt}, + combinator::{delimited, preceded, terminated}, + error::VerboseError, + token::one_of, + IResult, Parser, +}; + +/// We start with a top-level function to tie everything together, letting +/// us call eval on a string directly +pub fn eval_from_str(src: &str) -> Result { + parse_expr(src) + .map_err(|e: winnow::error::ErrMode>| format!("{:#?}", e)) + .and_then(|(_, exp)| eval_expression(exp).ok_or_else(|| "Eval failed".to_string())) +} + +/// For parsing, we start by defining the types that define the shape of data that we want. +/// In this case, we want something tree-like + +/// The remaining half is Lists. We implement these as recursive Expressions. +/// For a list of numbers, we have `'(1 2 3)`, which we'll parse to: +/// ``` +/// Expr::Quote(vec![Expr::Constant(Atom::Num(1)), +/// Expr::Constant(Atom::Num(2)), +/// Expr::Constant(Atom::Num(3))]) +/// Quote takes an S-expression and prevents evaluation of it, making it a data +/// structure that we can deal with programmatically. Thus any valid expression +/// is also a valid data structure in Lisp itself. +#[derive(Debug, Eq, PartialEq, Clone)] +pub enum Expr { + Constant(Atom), + /// (func-name arg1 arg2) + Application(Box, Vec), + /// (if predicate do-this) + If(Box, Box), + /// (if predicate do-this otherwise-do-this) + IfElse(Box, Box, Box), + /// '(3 (if (+ 3 3) 4 5) 7) + Quote(Vec), +} + +/// We now wrap this type and a few other primitives into our Atom type. +/// Remember from before that Atoms form one half of our language. +#[derive(Debug, Eq, PartialEq, Clone)] +pub enum Atom { + Num(i32), + Keyword(String), + Boolean(bool), + BuiltIn(BuiltIn), +} + +/// Now, the most basic type. We define some built-in functions that our lisp has +#[derive(Debug, Eq, PartialEq, Clone, Copy)] +pub enum BuiltIn { + Plus, + Minus, + Times, + Divide, + Equal, + Not, +} + +/// With types defined, we move onto the top-level expression parser! +fn parse_expr(i: &str) -> IResult<&str, Expr, VerboseError<&str>> { + preceded( + multispace0, + alt((parse_constant, parse_application, parse_if, parse_quote)), + ) + .parse_next(i) +} + +/// We then add the Expr layer on top +fn parse_constant(i: &str) -> IResult<&str, Expr, VerboseError<&str>> { + parse_atom.map(Expr::Constant).parse_next(i) +} + +/// Now we take all these simple parsers and connect them. +/// We can now parse half of our language! +fn parse_atom(i: &str) -> IResult<&str, Atom, VerboseError<&str>> { + alt(( + parse_num, + parse_bool, + parse_builtin.map(Atom::BuiltIn), + parse_keyword, + )) + .parse_next(i) +} + +/// Next up is number parsing. We're keeping it simple here by accepting any number (> 1) +/// of digits but ending the program if it doesn't fit into an i32. +fn parse_num(i: &str) -> IResult<&str, Atom, VerboseError<&str>> { + alt(( + digit1.try_map(|digit_str: &str| digit_str.parse::().map(Atom::Num)), + preceded("-", digit1).map(|digit_str: &str| Atom::Num(-digit_str.parse::().unwrap())), + )) + .parse_next(i) +} + +/// Our boolean values are also constant, so we can do it the same way +fn parse_bool(i: &str) -> IResult<&str, Atom, VerboseError<&str>> { + alt(( + "#t".map(|_| Atom::Boolean(true)), + "#f".map(|_| Atom::Boolean(false)), + )) + .parse_next(i) +} + +fn parse_builtin(i: &str) -> IResult<&str, BuiltIn, VerboseError<&str>> { + // alt gives us the result of first parser that succeeds, of the series of + // parsers we give it + alt(( + parse_builtin_op, + // map lets us process the parsed output, in this case we know what we parsed, + // so we ignore the input and return the BuiltIn directly + "not".map(|_| BuiltIn::Not), + )) + .parse_next(i) +} + +/// Continuing the trend of starting from the simplest piece and building up, +/// we start by creating a parser for the built-in operator functions. +fn parse_builtin_op(i: &str) -> IResult<&str, BuiltIn, VerboseError<&str>> { + // one_of matches one of the characters we give it + let (i, t) = one_of("+-*/=").parse_next(i)?; + + // because we are matching single character tokens, we can do the matching logic + // on the returned value + Ok(( + i, + match t { + '+' => BuiltIn::Plus, + '-' => BuiltIn::Minus, + '*' => BuiltIn::Times, + '/' => BuiltIn::Divide, + '=' => BuiltIn::Equal, + _ => unreachable!(), + }, + )) +} + +/// The next easiest thing to parse are keywords. +/// We introduce some error handling combinators: `context` for human readable errors +/// and `cut_err` to prevent back-tracking. +/// +/// Put plainly: `preceded(":", cut_err(alpha1))` means that once we see the `:` +/// character, we have to see one or more alphabetic characters or the input is invalid. +fn parse_keyword(i: &str) -> IResult<&str, Atom, VerboseError<&str>> { + preceded(":", cut_err(alpha1)) + .context("keyword") + .map(|sym_str: &str| Atom::Keyword(sym_str.to_string())) + .parse_next(i) +} + +/// We can now use our new combinator to define the rest of the `Expr`s. +/// +/// Starting with function application, we can see how the parser mirrors our data +/// definitions: our definition is `Application(Box, Vec)`, so we know +/// that we need to parse an expression and then parse 0 or more expressions, all +/// wrapped in an S-expression. +/// +/// tuples are themselves a parser, used to sequence parsers together, so we can translate this +/// directly and then map over it to transform the output into an `Expr::Application` +fn parse_application(i: &str) -> IResult<&str, Expr, VerboseError<&str>> { + let application_inner = (parse_expr, repeat(0.., parse_expr)) + .map(|(head, tail)| Expr::Application(Box::new(head), tail)); + // finally, we wrap it in an s-expression + s_exp(application_inner).parse_next(i) +} + +/// Because `Expr::If` and `Expr::IfElse` are so similar (we easily could have +/// defined `Expr::If` to have an `Option` for the else block), we parse both +/// in a single function. +/// +/// In fact, we define our parser as if `Expr::If` was defined with an Option in it, +/// we have the `opt` combinator which fits very nicely here. +fn parse_if(i: &str) -> IResult<&str, Expr, VerboseError<&str>> { + let if_inner = preceded( + // here to avoid ambiguity with other names starting with `if`, if we added + // variables to our language, we say that if must be terminated by at least + // one whitespace character + terminated("if", multispace1), + cut_err((parse_expr, parse_expr, opt(parse_expr))), + ) + .map(|(pred, true_branch, maybe_false_branch)| { + if let Some(false_branch) = maybe_false_branch { + Expr::IfElse( + Box::new(pred), + Box::new(true_branch), + Box::new(false_branch), + ) + } else { + Expr::If(Box::new(pred), Box::new(true_branch)) + } + }) + .context("if expression"); + s_exp(if_inner).parse_next(i) +} + +/// A quoted S-expression is list data structure. +/// +/// This example doesn't have the symbol atom, but by adding variables and changing +/// the definition of quote to not always be around an S-expression, we'd get them +/// naturally. +fn parse_quote(i: &str) -> IResult<&str, Expr, VerboseError<&str>> { + // this should look very straight-forward after all we've done: + // we find the `'` (quote) character, use cut_err to say that we're unambiguously + // looking for an s-expression of 0 or more expressions, and then parse them + preceded("'", cut_err(s_exp(repeat(0.., parse_expr)))) + .context("quote") + .map(Expr::Quote) + .parse_next(i) +} + +/// Before continuing, we need a helper function to parse lists. +/// A list starts with `(` and ends with a matching `)`. +/// By putting whitespace and newline parsing here, we can avoid having to worry about it +/// in much of the rest of the parser. +//.parse_next/ +/// Unlike the previous functions, this function doesn't take or consume input, instead it +/// takes a parsing function and returns a new parsing function. +fn s_exp<'a, O1, F>(inner: F) -> impl Parser<&'a str, O1, VerboseError<&'a str>> +where + F: Parser<&'a str, O1, VerboseError<&'a str>>, +{ + delimited( + '(', + preceded(multispace0, inner), + cut_err(preceded(multispace0, ')')).context("closing paren"), + ) +} + +/// And that's it! +/// We can now parse our entire lisp language. +/// +/// But in order to make it a little more interesting, we can hack together +/// a little interpreter to take an Expr, which is really an +/// [Abstract Syntax Tree](https://en.wikipedia.org/wiki/Abstract_syntax_tree) (AST), +/// and give us something back + +/// This function tries to reduce the AST. +/// This has to return an Expression rather than an Atom because quoted `s_expressions` +/// can't be reduced +fn eval_expression(e: Expr) -> Option { + match e { + // Constants and quoted s-expressions are our base-case + Expr::Constant(_) | Expr::Quote(_) => Some(e), + // we then recursively `eval_expression` in the context of our special forms + // and built-in operators + Expr::If(pred, true_branch) => { + let reduce_pred = eval_expression(*pred)?; + if get_bool_from_expr(reduce_pred)? { + eval_expression(*true_branch) + } else { + None + } + } + Expr::IfElse(pred, true_branch, false_branch) => { + let reduce_pred = eval_expression(*pred)?; + if get_bool_from_expr(reduce_pred)? { + eval_expression(*true_branch) + } else { + eval_expression(*false_branch) + } + } + Expr::Application(head, tail) => { + let reduced_head = eval_expression(*head)?; + let reduced_tail = tail + .into_iter() + .map(eval_expression) + .collect::>>()?; + if let Expr::Constant(Atom::BuiltIn(bi)) = reduced_head { + Some(Expr::Constant(match bi { + BuiltIn::Plus => Atom::Num( + reduced_tail + .into_iter() + .map(get_num_from_expr) + .collect::>>()? + .into_iter() + .sum(), + ), + BuiltIn::Times => Atom::Num( + reduced_tail + .into_iter() + .map(get_num_from_expr) + .collect::>>()? + .into_iter() + .product(), + ), + BuiltIn::Equal => Atom::Boolean( + reduced_tail + .iter() + .zip(reduced_tail.iter().skip(1)) + .all(|(a, b)| a == b), + ), + BuiltIn::Not => { + if reduced_tail.len() != 1 { + return None; + } else { + Atom::Boolean(!get_bool_from_expr( + reduced_tail.first().cloned().unwrap(), + )?) + } + } + BuiltIn::Minus => { + Atom::Num(if let Some(first_elem) = reduced_tail.first().cloned() { + let fe = get_num_from_expr(first_elem)?; + reduced_tail + .into_iter() + .map(get_num_from_expr) + .collect::>>()? + .into_iter() + .skip(1) + .fold(fe, |a, b| a - b) + } else { + Default::default() + }) + } + BuiltIn::Divide => { + Atom::Num(if let Some(first_elem) = reduced_tail.first().cloned() { + let fe = get_num_from_expr(first_elem)?; + reduced_tail + .into_iter() + .map(get_num_from_expr) + .collect::>>()? + .into_iter() + .skip(1) + .fold(fe, |a, b| a / b) + } else { + Default::default() + }) + } + })) + } else { + None + } + } + } +} + +/// To start we define a couple of helper functions +fn get_num_from_expr(e: Expr) -> Option { + if let Expr::Constant(Atom::Num(n)) = e { + Some(n) + } else { + None + } +} + +fn get_bool_from_expr(e: Expr) -> Option { + if let Expr::Constant(Atom::Boolean(b)) = e { + Some(b) + } else { + None + } +} diff --git a/vendor/winnow-0.4.7/examples/string/main.rs b/vendor/winnow-0.4.7/examples/string/main.rs new file mode 100644 index 000000000..0c2647e42 --- /dev/null +++ b/vendor/winnow-0.4.7/examples/string/main.rs @@ -0,0 +1,70 @@ +//! This example shows an example of how to parse an escaped string. The +//! rules for the string are similar to JSON and rust. A string is: +//! +//! - Enclosed by double quotes +//! - Can contain any raw unescaped code point besides \ and " +//! - Matches the following escape sequences: \b, \f, \n, \r, \t, \", \\, \/ +//! - Matches code points like Rust: \u{XXXX}, where XXXX can be up to 6 +//! hex characters +//! - an escape followed by whitespace consumes all whitespace between the +//! escape and the next non-whitespace character + +#![cfg(feature = "alloc")] + +mod parser; + +use winnow::prelude::*; + +fn main() -> Result<(), lexopt::Error> { + let args = Args::parse()?; + + let data = args.input.as_deref().unwrap_or("\"abc\""); + let result = parser::parse_string::<()>.parse(data); + match result { + Ok(data) => println!("{}", data), + Err(err) => println!("{:?}", err), + } + + Ok(()) +} + +#[derive(Default)] +struct Args { + input: Option, +} + +impl Args { + fn parse() -> Result { + 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) + } +} + +#[test] +fn simple() { + let data = "\"abc\""; + let result = parser::parse_string::<()>.parse(data); + assert_eq!(result, Ok(String::from("abc"))); +} + +#[test] +fn escaped() { + let data = "\"tab:\\tafter tab, newline:\\nnew line, quote: \\\", emoji: \\u{1F602}, newline:\\nescaped whitespace: \\ abc\""; + let result = parser::parse_string::<()>.parse(data); + assert_eq!( + result, + Ok(String::from("tab:\tafter tab, newline:\nnew line, quote: \", emoji: πŸ˜‚, newline:\nescaped whitespace: abc")) + ); +} diff --git a/vendor/winnow-0.4.7/examples/string/parser.rs b/vendor/winnow-0.4.7/examples/string/parser.rs new file mode 100644 index 000000000..dcd87f272 --- /dev/null +++ b/vendor/winnow-0.4.7/examples/string/parser.rs @@ -0,0 +1,165 @@ +//! This example shows an example of how to parse an escaped string. The +//! rules for the string are similar to JSON and rust. A string is: +//! +//! - Enclosed by double quotes +//! - Can contain any raw unescaped code point besides \ and " +//! - Matches the following escape sequences: \b, \f, \n, \r, \t, \", \\, \/ +//! - Matches code points like Rust: \u{XXXX}, where XXXX can be up to 6 +//! hex characters +//! - an escape followed by whitespace consumes all whitespace between the +//! escape and the next non-whitespace character + +use winnow::ascii::multispace1; +use winnow::combinator::alt; +use winnow::combinator::fold_repeat; +use winnow::combinator::{delimited, preceded}; +use winnow::error::{FromExternalError, ParseError}; +use winnow::prelude::*; +use winnow::token::{take_till1, take_while}; + +/// Parse a string. Use a loop of `parse_fragment` and push all of the fragments +/// into an output string. +pub fn parse_string<'a, E>(input: &'a str) -> IResult<&'a str, String, E> +where + E: ParseError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>, +{ + // fold_repeat is the equivalent of iterator::fold. It runs a parser in a loop, + // and for each output value, calls a folding function on each output value. + let build_string = fold_repeat( + 0.., + // Our parser function – parses a single string fragment + parse_fragment, + // Our init value, an empty string + String::new, + // Our folding function. For each fragment, append the fragment to the + // string. + |mut string, fragment| { + match fragment { + StringFragment::Literal(s) => string.push_str(s), + StringFragment::EscapedChar(c) => string.push(c), + StringFragment::EscapedWS => {} + } + string + }, + ); + + // Finally, parse the string. Note that, if `build_string` could accept a raw + // " character, the closing delimiter " would never match. When using + // `delimited` with a looping parser (like fold_repeat), be sure that the + // loop won't accidentally match your closing delimiter! + delimited('"', build_string, '"').parse_next(input) +} + +/// A string fragment contains a fragment of a string being parsed: either +/// a non-empty Literal (a series of non-escaped characters), a single +/// parsed escaped character, or a block of escaped whitespace. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum StringFragment<'a> { + Literal(&'a str), + EscapedChar(char), + EscapedWS, +} + +/// Combine `parse_literal`, `parse_escaped_whitespace`, and `parse_escaped_char` +/// into a `StringFragment`. +fn parse_fragment<'a, E>(input: &'a str) -> IResult<&'a str, StringFragment<'a>, E> +where + E: ParseError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>, +{ + alt(( + // The `map` combinator runs a parser, then applies a function to the output + // of that parser. + parse_literal.map(StringFragment::Literal), + parse_escaped_char.map(StringFragment::EscapedChar), + parse_escaped_whitespace.value(StringFragment::EscapedWS), + )) + .parse_next(input) +} + +/// Parse a non-empty block of text that doesn't include \ or " +fn parse_literal<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, &'a str, E> { + // `take_till1` parses a string of 0 or more characters that aren't one of the + // given characters. + let not_quote_slash = take_till1("\"\\"); + + // `verify` runs a parser, then runs a verification function on the output of + // the parser. The verification function accepts the output only if it + // returns true. In this case, we want to ensure that the output of take_till1 + // is non-empty. + not_quote_slash + .verify(|s: &str| !s.is_empty()) + .parse_next(input) +} + +// parser combinators are constructed from the bottom up: +// first we write parsers for the smallest elements (escaped characters), +// then combine them into larger parsers. + +/// Parse an escaped character: \n, \t, \r, \u{00AC}, etc. +fn parse_escaped_char<'a, E>(input: &'a str) -> IResult<&'a str, char, E> +where + E: ParseError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>, +{ + preceded( + '\\', + // `alt` tries each parser in sequence, returning the result of + // the first successful match + alt(( + parse_unicode, + // The `value` parser returns a fixed value (the first argument) if its + // parser (the second argument) succeeds. In these cases, it looks for + // the marker characters (n, r, t, etc) and returns the matching + // character (\n, \r, \t, etc). + 'n'.value('\n'), + 'r'.value('\r'), + 't'.value('\t'), + 'b'.value('\u{08}'), + 'f'.value('\u{0C}'), + '\\'.value('\\'), + '/'.value('/'), + '"'.value('"'), + )), + ) + .parse_next(input) +} + +/// Parse a unicode sequence, of the form u{XXXX}, where XXXX is 1 to 6 +/// hexadecimal numerals. We will combine this later with `parse_escaped_char` +/// to parse sequences like \u{00AC}. +fn parse_unicode<'a, E>(input: &'a str) -> IResult<&'a str, char, E> +where + E: ParseError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>, +{ + // `take_while` parses between `m` and `n` bytes (inclusive) that match + // a predicate. `parse_hex` here parses between 1 and 6 hexadecimal numerals. + let parse_hex = take_while(1..=6, |c: char| c.is_ascii_hexdigit()); + + // `preceded` takes a prefix parser, and if it succeeds, returns the result + // of the body parser. In this case, it parses u{XXXX}. + let parse_delimited_hex = preceded( + 'u', + // `delimited` is like `preceded`, but it parses both a prefix and a suffix. + // It returns the result of the middle parser. In this case, it parses + // {XXXX}, where XXXX is 1 to 6 hex numerals, and returns XXXX + delimited('{', parse_hex, '}'), + ); + + // `try_map` takes the result of a parser and applies a function that returns + // a Result. In this case we take the hex bytes from parse_hex and attempt to + // convert them to a u32. + let parse_u32 = parse_delimited_hex.try_map(move |hex| u32::from_str_radix(hex, 16)); + + // verify_map is like try_map, but it takes an Option instead of a Result. If + // the function returns None, verify_map returns an error. In this case, because + // not all u32 values are valid unicode code points, we have to fallibly + // convert to char with from_u32. + parse_u32.verify_map(std::char::from_u32).parse_next(input) +} + +/// Parse a backslash, followed by any amount of whitespace. This is used later +/// to discard any escaped whitespace. +fn parse_escaped_whitespace<'a, E: ParseError<&'a str>>( + input: &'a str, +) -> IResult<&'a str, &'a str, E> { + preceded('\\', multispace1).parse_next(input) +} -- cgit v1.2.3