From efe1b5073d5b744d8d2162007a935b96abe65f4d Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 8 Feb 2023 09:04:13 -0600 Subject: [PATCH] style: Use standard rustfmt rules (IGNORE THIS) --- benches/number.rs | 68 +- examples/arithmetic/bench.rs | 16 +- examples/arithmetic/main.rs | 52 +- examples/arithmetic/parser.rs | 106 +- examples/arithmetic_ast/main.rs | 52 +- examples/arithmetic_ast/parser.rs | 210 +-- examples/css/main.rs | 74 +- examples/css/parser.rs | 34 +- examples/custom_error.rs | 38 +- examples/http/bench.rs | 36 +- examples/http/main.rs | 46 +- examples/http/parser.rs | 118 +- examples/http/parser_streaming.rs | 120 +- examples/ini/bench.rs | 56 +- examples/ini/main.rs | 84 +- examples/ini/parser.rs | 154 +- examples/ini/parser_str.rs | 204 +-- examples/iterator.rs | 116 +- examples/json/bench.rs | 70 +- examples/json/json.rs | 12 +- examples/json/main.rs | 150 +- examples/json/parser.rs | 428 ++--- examples/json/parser_dispatch.rs | 440 ++--- examples/json/parser_streaming.rs | 475 +++-- examples/json_iterator.rs | 486 ++--- examples/s_expression.rs | 436 ++--- examples/string.rs | 212 +-- rustfmt.toml | 2 - src/bits/complete.rs | 264 +-- src/bits/mod.rs | 132 +- src/bits/streaming.rs | 270 +-- src/bits/tests.rs | 196 +- src/branch/mod.rs | 22 +- src/branch/tests.rs | 226 +-- src/bytes/complete.rs | 1152 ++++++------ src/bytes/mod.rs | 270 +-- src/bytes/streaming.rs | 1484 +++++++-------- src/bytes/tests.rs | 1006 +++++----- src/character/complete.rs | 1292 ++++++------- src/character/mod.rs | 932 +++++----- src/character/streaming.rs | 1472 +++++++-------- src/character/tests.rs | 2840 ++++++++++++++--------------- src/combinator/mod.rs | 1173 ++++++------ src/combinator/tests.rs | 610 +++---- src/error.rs | 806 ++++---- src/input.rs | 2558 +++++++++++++------------- src/lib.rs | 70 +- src/multi/mod.rs | 846 ++++----- src/multi/tests.rs | 1154 ++++++------ src/number/complete.rs | 1770 +++++++++--------- src/number/mod.rs | 696 +++---- src/number/streaming.rs | 2205 +++++++++++----------- src/number/tests.rs | 1919 +++++++++---------- src/parser.rs | 1354 +++++++------- src/sequence/mod.rs | 112 +- src/sequence/tests.rs | 522 +++--- tests/testsuite/custom_errors.rs | 34 +- tests/testsuite/float.rs | 45 +- tests/testsuite/fnmut.rs | 48 +- tests/testsuite/issues.rs | 418 ++--- tests/testsuite/multiline.rs | 28 +- tests/testsuite/overflow.rs | 204 +-- tests/testsuite/reborrow_fold.rs | 28 +- tests/testsuite/utf8.rs | 906 ++++----- 64 files changed, 16697 insertions(+), 16662 deletions(-) delete mode 100644 rustfmt.toml diff --git a/benches/number.rs b/benches/number.rs index e3e99521..45b93272 100644 --- a/benches/number.rs +++ b/benches/number.rs @@ -14,56 +14,56 @@ use winnow::prelude::*; type Input<'i> = &'i [u8]; fn parser(i: Input<'_>) -> IResult, u64> { - be_u64(i) + be_u64(i) } fn number(c: &mut Criterion) { - let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; - parser(&data[..]).expect("should parse correctly"); - c.bench_function("number", move |b| { - b.iter(|| parser(&data[..]).unwrap()); - }); + parser(&data[..]).expect("should parse correctly"); + c.bench_function("number", move |b| { + b.iter(|| parser(&data[..]).unwrap()); + }); } fn float_bytes(c: &mut Criterion) { - println!( - "float_bytes result: {:?}", - float::<_, f64, Error<_>, false>(&b"-1.234E-12"[..]) - ); - c.bench_function("float bytes", |b| { - b.iter(|| float::<_, f64, Error<_>, false>(&b"-1.234E-12"[..])); - }); + println!( + "float_bytes result: {:?}", + float::<_, f64, Error<_>, false>(&b"-1.234E-12"[..]) + ); + c.bench_function("float bytes", |b| { + b.iter(|| float::<_, f64, Error<_>, false>(&b"-1.234E-12"[..])); + }); } fn float_str(c: &mut Criterion) { - println!( - "float_str result: {:?}", - float::<_, f64, Error<_>, false>("-1.234E-12") - ); - c.bench_function("float str", |b| { - b.iter(|| float::<_, f64, Error<_>, false>("-1.234E-12")); - }); + println!( + "float_str result: {:?}", + float::<_, f64, Error<_>, false>("-1.234E-12") + ); + c.bench_function("float str", |b| { + b.iter(|| float::<_, f64, Error<_>, false>("-1.234E-12")); + }); } fn std_float(input: &[u8]) -> IResult<&[u8], f64, Error<&[u8]>> { - match input.parse_slice() { - Some(n) => Ok((&[], n)), - None => Err(ErrMode::Backtrack(Error { - input, - kind: ErrorKind::Float, - })), - } + match input.parse_slice() { + Some(n) => Ok((&[], n)), + None => Err(ErrMode::Backtrack(Error { + input, + kind: ErrorKind::Float, + })), + } } fn std_float_bytes(c: &mut Criterion) { - println!( - "std_float_bytes result: {:?}", - std_float(&b"-1.234E-12"[..]) - ); - c.bench_function("std_float bytes", |b| { - b.iter(|| std_float(&b"-1.234E-12"[..])); - }); + println!( + "std_float_bytes result: {:?}", + std_float(&b"-1.234E-12"[..]) + ); + c.bench_function("std_float bytes", |b| { + b.iter(|| std_float(&b"-1.234E-12"[..])); + }); } criterion_group!(benches, number, float_bytes, std_float_bytes, float_str); diff --git a/examples/arithmetic/bench.rs b/examples/arithmetic/bench.rs index 9671f679..0f6ec8ee 100644 --- a/examples/arithmetic/bench.rs +++ b/examples/arithmetic/bench.rs @@ -4,15 +4,15 @@ 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));"; + 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()); - }); + 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); diff --git a/examples/arithmetic/main.rs b/examples/arithmetic/main.rs index cbff7b5c..e647e356 100644 --- a/examples/arithmetic/main.rs +++ b/examples/arithmetic/main.rs @@ -5,43 +5,43 @@ mod parser; use parser::expr; fn main() -> Result<(), lexopt::Error> { - let args = Args::parse()?; + let args = Args::parse()?; - let input = args.input.as_deref().unwrap_or("1 + 1"); + let input = args.input.as_deref().unwrap_or("1 + 1"); - println!("{} =", input); - match expr.parse_next(input).finish() { - Ok(result) => { - println!(" {}", result); - } - Err(err) => { - println!(" {}", err); + println!("{} =", input); + match expr.parse_next(input).finish() { + Ok(result) => { + println!(" {}", result); + } + Err(err) => { + println!(" {}", err); + } } - } - Ok(()) + Ok(()) } #[derive(Default)] struct Args { - input: Option, + 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()?); + 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()), + } } - _ => return Err(arg.unexpected()), - } + Ok(res) } - Ok(res) - } } diff --git a/examples/arithmetic/parser.rs b/examples/arithmetic/parser.rs index f73369f0..8b81638a 100644 --- a/examples/arithmetic/parser.rs +++ b/examples/arithmetic/parser.rs @@ -2,49 +2,49 @@ use std::str::FromStr; use winnow::prelude::*; use winnow::{ - branch::alt, - bytes::one_of, - character::{digit1 as digits, space0 as spaces}, - multi::fold_many0, - sequence::delimited, - IResult, + branch::alt, + bytes::one_of, + character::{digit1 as digits, space0 as spaces}, + multi::fold_many0, + sequence::delimited, + IResult, }; // Parser definition pub fn expr(i: &str) -> IResult<&str, i64> { - let (i, init) = term(i)?; + let (i, init) = term(i)?; - fold_many0( - (one_of("+-"), term), - move || init, - |acc, (op, val): (char, i64)| { - if op == '+' { - acc + val - } else { - acc - val - } - }, - )(i) + fold_many0( + (one_of("+-"), term), + move || init, + |acc, (op, val): (char, i64)| { + if op == '+' { + acc + val + } else { + acc - val + } + }, + )(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)?; + let (i, init) = factor(i)?; - fold_many0( - (one_of("*/"), factor), - move || init, - |acc, (op, val): (char, i64)| { - if op == '*' { - acc * val - } else { - acc / val - } - }, - )(i) + fold_many0( + (one_of("*/"), factor), + move || init, + |acc, (op, val): (char, i64)| { + if op == '*' { + acc * val + } else { + acc / val + } + }, + )(i) } // We transform an integer string into a i64, ignoring surrounding whitespaces @@ -52,47 +52,47 @@ fn term(i: &str) -> IResult<&str, i64> { // 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.map_res(FromStr::from_str), - delimited(one_of('('), expr, one_of(')')), - parens, - )), - spaces, - )(i) + delimited( + spaces, + alt(( + digits.map_res(FromStr::from_str), + delimited(one_of('('), expr, one_of(')')), + parens, + )), + spaces, + )(i) } // We parse any expr surrounded by parens, ignoring all whitespaces around those fn parens(i: &str) -> IResult<&str, i64> { - delimited(one_of('('), expr, one_of(')'))(i) + delimited(one_of('('), expr, one_of(')'))(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))); + 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))); + 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))); + 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))); + 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/examples/arithmetic_ast/main.rs b/examples/arithmetic_ast/main.rs index cbff7b5c..e647e356 100644 --- a/examples/arithmetic_ast/main.rs +++ b/examples/arithmetic_ast/main.rs @@ -5,43 +5,43 @@ mod parser; use parser::expr; fn main() -> Result<(), lexopt::Error> { - let args = Args::parse()?; + let args = Args::parse()?; - let input = args.input.as_deref().unwrap_or("1 + 1"); + let input = args.input.as_deref().unwrap_or("1 + 1"); - println!("{} =", input); - match expr.parse_next(input).finish() { - Ok(result) => { - println!(" {}", result); - } - Err(err) => { - println!(" {}", err); + println!("{} =", input); + match expr.parse_next(input).finish() { + Ok(result) => { + println!(" {}", result); + } + Err(err) => { + println!(" {}", err); + } } - } - Ok(()) + Ok(()) } #[derive(Default)] struct Args { - input: Option, + 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()?); + 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()), + } } - _ => return Err(arg.unexpected()), - } + Ok(res) } - Ok(res) - } } diff --git a/examples/arithmetic_ast/parser.rs b/examples/arithmetic_ast/parser.rs index 27f56f16..1094a6d6 100644 --- a/examples/arithmetic_ast/parser.rs +++ b/examples/arithmetic_ast/parser.rs @@ -5,155 +5,155 @@ use std::str::FromStr; use winnow::prelude::*; use winnow::{ - branch::alt, - character::{digit1 as digit, multispace0 as multispace}, - multi::many0, - sequence::{delimited, preceded}, - IResult, + branch::alt, + character::{digit1 as digit, multispace0 as multispace}, + multi::many0, + sequence::{delimited, preceded}, + IResult, }; pub enum Expr { - Value(i64), - Add(Box, Box), - Sub(Box, Box), - Mul(Box, Box), - Div(Box, Box), - Paren(Box), + 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, + Add, + Sub, + Mul, + Div, } impl Display for Expr { - fn fmt(&self, format: &mut Formatter<'_>) -> fmt::Result { - use self::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), + fn fmt(&self, format: &mut Formatter<'_>) -> fmt::Result { + use self::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), + } } - } } impl Debug for Expr { - fn fmt(&self, format: &mut Formatter<'_>) -> fmt::Result { - use self::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), + fn fmt(&self, format: &mut Formatter<'_>) -> fmt::Result { + use self::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) = many0(alt(( - |i| { - let (i, add) = preceded("+", term)(i)?; - Ok((i, (Oper::Add, add))) - }, - |i| { - let (i, sub) = preceded("-", term)(i)?; - Ok((i, (Oper::Sub, sub))) - }, - )))(i)?; - - Ok((i, fold_exprs(initial, remainder))) + let (i, initial) = term(i)?; + let (i, remainder) = many0(alt(( + |i| { + let (i, add) = preceded("+", term)(i)?; + Ok((i, (Oper::Add, add))) + }, + |i| { + let (i, sub) = preceded("-", term)(i)?; + Ok((i, (Oper::Sub, sub))) + }, + )))(i)?; + + Ok((i, fold_exprs(initial, remainder))) } fn term(i: &str) -> IResult<&str, Expr> { - let (i, initial) = factor(i)?; - let (i, remainder) = many0(alt(( - |i| { - let (i, mul) = preceded("*", factor)(i)?; - Ok((i, (Oper::Mul, mul))) - }, - |i| { - let (i, div) = preceded("/", factor)(i)?; - Ok((i, (Oper::Div, div))) - }, - )))(i)?; - - Ok((i, fold_exprs(initial, remainder))) + let (i, initial) = factor(i)?; + let (i, remainder) = many0(alt(( + |i| { + let (i, mul) = preceded("*", factor)(i)?; + Ok((i, (Oper::Mul, mul))) + }, + |i| { + let (i, div) = preceded("/", factor)(i)?; + Ok((i, (Oper::Div, div))) + }, + )))(i)?; + + Ok((i, fold_exprs(initial, remainder))) } fn factor(i: &str) -> IResult<&str, Expr> { - alt(( - delimited(multispace, digit, multispace) - .map_res(FromStr::from_str) - .map(Expr::Value), - parens, - ))(i) + alt(( + delimited(multispace, digit, multispace) + .map_res(FromStr::from_str) + .map(Expr::Value), + parens, + ))(i) } fn parens(i: &str) -> IResult<&str, Expr> { - delimited( - multispace, - delimited("(", expr.map(|e| Expr::Paren(Box::new(e))), ")"), - multispace, - )(i) + delimited( + multispace, + delimited("(", expr.map(|e| Expr::Paren(Box::new(e))), ")"), + multispace, + )(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)), - } - }) + 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("3"))) - ); + assert_eq!( + factor(" 3 ").map(|(i, x)| (i, format!("{:?}", x))), + Ok(("", String::from("3"))) + ); } #[test] fn term_test() { - assert_eq!( - term(" 3 * 5 ").map(|(i, x)| (i, format!("{:?}", x))), - Ok(("", String::from("(3 * 5)"))) - ); + assert_eq!( + term(" 3 * 5 ").map(|(i, x)| (i, format!("{:?}", x))), + Ok(("", String::from("(3 * 5)"))) + ); } #[test] fn expr_test() { - assert_eq!( - expr(" 1 + 2 * 3 ").map(|(i, x)| (i, format!("{:?}", x))), - Ok(("", String::from("(1 + (2 * 3))"))) - ); - assert_eq!( - expr(" 1 + 2 * 3 / 4 - 5 ").map(|(i, x)| (i, format!("{:?}", x))), - Ok(("", String::from("((1 + ((2 * 3) / 4)) - 5)"))) - ); - assert_eq!( - expr(" 72 / 2 / 3 ").map(|(i, x)| (i, format!("{:?}", x))), - Ok(("", String::from("((72 / 2) / 3)"))) - ); + assert_eq!( + expr(" 1 + 2 * 3 ").map(|(i, x)| (i, format!("{:?}", x))), + Ok(("", String::from("(1 + (2 * 3))"))) + ); + assert_eq!( + expr(" 1 + 2 * 3 / 4 - 5 ").map(|(i, x)| (i, format!("{:?}", x))), + Ok(("", String::from("((1 + ((2 * 3) / 4)) - 5)"))) + ); + assert_eq!( + expr(" 72 / 2 / 3 ").map(|(i, x)| (i, format!("{:?}", x))), + Ok(("", String::from("((72 / 2) / 3)"))) + ); } #[test] fn parens_test() { - assert_eq!( - expr(" ( 1 + 2 ) * 3 ").map(|(i, x)| (i, format!("{:?}", x))), - Ok(("", String::from("([(1 + 2)] * 3)"))) - ); + assert_eq!( + expr(" ( 1 + 2 ) * 3 ").map(|(i, x)| (i, format!("{:?}", x))), + Ok(("", String::from("([(1 + 2)] * 3)"))) + ); } diff --git a/examples/css/main.rs b/examples/css/main.rs index c57dc572..2d37b184 100644 --- a/examples/css/main.rs +++ b/examples/css/main.rs @@ -5,58 +5,58 @@ mod parser; use parser::hex_color; fn main() -> Result<(), lexopt::Error> { - let args = Args::parse()?; + let args = Args::parse()?; - let input = args.input.as_deref().unwrap_or("#AAAAAA"); + let input = args.input.as_deref().unwrap_or("#AAAAAA"); - println!("{} =", input); - match hex_color.parse_next(input).finish() { - Ok(result) => { - println!(" {:?}", result); - } - Err(err) => { - println!(" {}", err); + println!("{} =", input); + match hex_color.parse_next(input).finish() { + Ok(result) => { + println!(" {:?}", result); + } + Err(err) => { + println!(" {}", err); + } } - } - Ok(()) + Ok(()) } #[derive(Default)] struct Args { - input: Option, + 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()?); + 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()), + } } - _ => return Err(arg.unexpected()), - } + Ok(res) } - Ok(res) - } } #[test] fn parse_color() { - assert_eq!( - hex_color("#2F14DF"), - Ok(( - "", - parser::Color { - red: 47, - green: 20, - blue: 223, - } - )) - ); + assert_eq!( + hex_color("#2F14DF"), + Ok(( + "", + parser::Color { + red: 47, + green: 20, + blue: 223, + } + )) + ); } diff --git a/examples/css/parser.rs b/examples/css/parser.rs index 210b01ac..e7cac64a 100644 --- a/examples/css/parser.rs +++ b/examples/css/parser.rs @@ -3,32 +3,32 @@ use winnow::prelude::*; #[derive(Debug, Eq, PartialEq)] pub struct Color { - pub red: u8, - pub green: u8, - pub blue: u8, + 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; + // The error must be owned + type Err = winnow::error::Error; - fn from_str(s: &str) -> Result { - hex_color(s).finish().map_err(|err| winnow::error::Error { - input: err.input.to_owned(), - kind: err.kind, - }) - } + fn from_str(s: &str) -> Result { + hex_color(s).finish().map_err(|err| winnow::error::Error { + input: err.input.to_owned(), + kind: err.kind, + }) + } } pub fn hex_color(input: &str) -> IResult<&str, Color> { - let (input, _) = tag("#")(input)?; - let (input, (red, green, blue)) = (hex_primary, hex_primary, hex_primary).parse_next(input)?; + let (input, _) = tag("#")(input)?; + let (input, (red, green, blue)) = (hex_primary, hex_primary, hex_primary).parse_next(input)?; - Ok((input, Color { red, green, blue })) + Ok((input, Color { red, green, blue })) } fn hex_primary(input: &str) -> IResult<&str, u8> { - take_while_m_n(2, 2, |c: char| c.is_ascii_hexdigit()) - .map_res(|input| u8::from_str_radix(input, 16)) - .parse_next(input) + take_while_m_n(2, 2, |c: char| c.is_ascii_hexdigit()) + .map_res(|input| u8::from_str_radix(input, 16)) + .parse_next(input) } diff --git a/examples/custom_error.rs b/examples/custom_error.rs index 2abe4309..954452a2 100644 --- a/examples/custom_error.rs +++ b/examples/custom_error.rs @@ -5,38 +5,38 @@ use winnow::IResult; #[derive(Debug, PartialEq, Eq)] pub enum CustomError { - MyError, - Nom(I, ErrorKind), + MyError, + Nom(I, ErrorKind), } impl ParseError for CustomError { - fn from_error_kind(input: I, kind: ErrorKind) -> Self { - CustomError::Nom(input, kind) - } + fn from_error_kind(input: I, kind: ErrorKind) -> Self { + CustomError::Nom(input, kind) + } - fn append(self, _: I, _: ErrorKind) -> Self { - self - } + fn append(self, _: I, _: ErrorKind) -> Self { + self + } } pub fn parse(_input: &str) -> IResult<&str, &str, CustomError<&str>> { - Err(ErrMode::Backtrack(CustomError::MyError)) + Err(ErrMode::Backtrack(CustomError::MyError)) } fn main() {} #[cfg(test)] mod tests { - use super::parse; - use super::CustomError; - use winnow::error::ErrMode; + 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), + #[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/examples/http/bench.rs b/examples/http/bench.rs index 568faaa0..a27a119a 100644 --- a/examples/http/bench.rs +++ b/examples/http/bench.rs @@ -2,7 +2,7 @@ mod parser; mod parser_streaming; fn one_test(c: &mut criterion::Criterion) { - let data = &b"GET / HTTP/1.1 + 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 @@ -12,24 +12,24 @@ 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()); - }, - ); + 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(); + http_group.finish(); } criterion::criterion_group!(http, one_test); diff --git a/examples/http/main.rs b/examples/http/main.rs index 769ddd2b..b0e480fb 100644 --- a/examples/http/main.rs +++ b/examples/http/main.rs @@ -1,10 +1,10 @@ mod parser; fn main() -> Result<(), lexopt::Error> { - let args = Args::parse()?; + let args = Args::parse()?; - let input = args.input.as_deref().unwrap_or( - "GET / HTTP/1.1 + 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 @@ -13,35 +13,35 @@ Accept-Encoding: gzip, deflate Connection: keep-alive ", - ); + ); - if let Some(result) = parser::parse(input.as_bytes()) { - println!(" {:#?}", result); - } + if let Some(result) = parser::parse(input.as_bytes()) { + println!(" {:#?}", result); + } - Ok(()) + Ok(()) } #[derive(Default)] struct Args { - input: Option, + 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()?); + 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()), + } } - _ => return Err(arg.unexpected()), - } + Ok(res) } - Ok(res) - } } diff --git a/examples/http/parser.rs b/examples/http/parser.rs index 68cc85a9..551c69db 100644 --- a/examples/http/parser.rs +++ b/examples/http/parser.rs @@ -1,8 +1,8 @@ use winnow::{ - bytes::{one_of, tag, take_while1}, - character::line_ending, - multi::many1, - IResult, + bytes::{one_of, tag, take_while1}, + character::line_ending, + multi::many1, + IResult, }; pub type Input<'i> = &'i [u8]; @@ -19,81 +19,81 @@ pub struct Request<'a> { #[derive(Debug)] #[allow(dead_code)] pub struct Header<'a> { - name: &'a [u8], - value: Vec<&'a [u8]>, + 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; + 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; + } } - } - Err(e) => { - println!("error: {:?}", e); - return None; - } } - } - Some(v) + Some(v) } fn request(input: Input<'_>) -> IResult, (Request<'_>, Vec>)> { - let (input, req) = request_line(input)?; - let (input, h) = many1(message_header)(input)?; - let (input, _) = line_ending(input)?; + let (input, req) = request_line(input)?; + let (input, h) = many1(message_header)(input)?; + let (input, _) = line_ending(input)?; - Ok((input, (req, h))) + Ok((input, (req, h))) } fn request_line(input: Input<'_>) -> IResult, Request<'_>> { - let (input, method) = take_while1(is_token)(input)?; - let (input, _) = take_while1(is_space)(input)?; - let (input, uri) = take_while1(is_not_space)(input)?; - let (input, _) = take_while1(is_space)(input)?; - let (input, version) = http_version(input)?; - let (input, _) = line_ending(input)?; - - Ok(( - input, - Request { - method, - uri, - version, - }, - )) + let (input, method) = take_while1(is_token)(input)?; + let (input, _) = take_while1(is_space)(input)?; + let (input, uri) = take_while1(is_not_space)(input)?; + let (input, _) = take_while1(is_space)(input)?; + let (input, version) = http_version(input)?; + let (input, _) = line_ending(input)?; + + Ok(( + input, + Request { + method, + uri, + version, + }, + )) } fn http_version(input: Input<'_>) -> IResult, &[u8]> { - let (input, _) = tag("HTTP/")(input)?; - let (input, version) = take_while1(is_version)(input)?; + let (input, _) = tag("HTTP/")(input)?; + let (input, version) = take_while1(is_version)(input)?; - Ok((input, version)) + Ok((input, version)) } fn message_header_value(input: Input<'_>) -> IResult, &[u8]> { - let (input, _) = take_while1(is_horizontal_space)(input)?; - let (input, data) = take_while1(not_line_ending)(input)?; - let (input, _) = line_ending(input)?; + let (input, _) = take_while1(is_horizontal_space)(input)?; + let (input, data) = take_while1(not_line_ending)(input)?; + let (input, _) = line_ending(input)?; - Ok((input, data)) + Ok((input, data)) } fn message_header(input: Input<'_>) -> IResult, Header<'_>> { - let (input, name) = take_while1(is_token)(input)?; - let (input, _) = one_of(':')(input)?; - let (input, value) = many1(message_header_value)(input)?; + let (input, name) = take_while1(is_token)(input)?; + let (input, _) = one_of(':')(input)?; + let (input, value) = many1(message_header_value)(input)?; - Ok((input, Header { name, value })) + Ok((input, Header { name, value })) } #[rustfmt::skip] @@ -126,21 +126,21 @@ fn is_token(c: u8) -> bool { } fn is_version(c: u8) -> bool { - (b'0'..=b'9').contains(&c) || c == b'.' + (b'0'..=b'9').contains(&c) || c == b'.' } fn not_line_ending(c: u8) -> bool { - c != b'\r' && c != b'\n' + c != b'\r' && c != b'\n' } fn is_space(c: u8) -> bool { - c == b' ' + c == b' ' } fn is_not_space(c: u8) -> bool { - c != b' ' + c != b' ' } fn is_horizontal_space(c: u8) -> bool { - c == b' ' || c == b'\t' + c == b' ' || c == b'\t' } diff --git a/examples/http/parser_streaming.rs b/examples/http/parser_streaming.rs index 991cc220..e865620c 100644 --- a/examples/http/parser_streaming.rs +++ b/examples/http/parser_streaming.rs @@ -1,9 +1,9 @@ use winnow::{ - bytes::{one_of, tag, take_while1}, - character::line_ending, - input::Streaming, - multi::many1, - IResult, + bytes::{one_of, tag, take_while1}, + character::line_ending, + input::Streaming, + multi::many1, + IResult, }; pub type Input<'i> = Streaming<&'i [u8]>; @@ -20,81 +20,81 @@ pub struct Request<'a> { #[derive(Debug)] #[allow(dead_code)] pub struct Header<'a> { - name: &'a [u8], - value: Vec<&'a [u8]>, + name: &'a [u8], + value: Vec<&'a [u8]>, } pub fn parse(data: &[u8]) -> Option, Vec>)>> { - let mut buf = Streaming(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; + let mut buf = Streaming(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; + } } - } - Err(e) => { - println!("error: {:?}", e); - return None; - } } - } - Some(v) + Some(v) } fn request(input: Input<'_>) -> IResult, (Request<'_>, Vec>)> { - let (input, req) = request_line(input)?; - let (input, h) = many1(message_header)(input)?; - let (input, _) = line_ending(input)?; + let (input, req) = request_line(input)?; + let (input, h) = many1(message_header)(input)?; + let (input, _) = line_ending(input)?; - Ok((input, (req, h))) + Ok((input, (req, h))) } fn request_line(input: Input<'_>) -> IResult, Request<'_>> { - let (input, method) = take_while1(is_token)(input)?; - let (input, _) = take_while1(is_space)(input)?; - let (input, uri) = take_while1(is_not_space)(input)?; - let (input, _) = take_while1(is_space)(input)?; - let (input, version) = http_version(input)?; - let (input, _) = line_ending(input)?; - - Ok(( - input, - Request { - method, - uri, - version, - }, - )) + let (input, method) = take_while1(is_token)(input)?; + let (input, _) = take_while1(is_space)(input)?; + let (input, uri) = take_while1(is_not_space)(input)?; + let (input, _) = take_while1(is_space)(input)?; + let (input, version) = http_version(input)?; + let (input, _) = line_ending(input)?; + + Ok(( + input, + Request { + method, + uri, + version, + }, + )) } fn http_version(input: Input<'_>) -> IResult, &[u8]> { - let (input, _) = tag("HTTP/")(input)?; - let (input, version) = take_while1(is_version)(input)?; + let (input, _) = tag("HTTP/")(input)?; + let (input, version) = take_while1(is_version)(input)?; - Ok((input, version)) + Ok((input, version)) } fn message_header_value(input: Input<'_>) -> IResult, &[u8]> { - let (input, _) = take_while1(is_horizontal_space)(input)?; - let (input, data) = take_while1(not_line_ending)(input)?; - let (input, _) = line_ending(input)?; + let (input, _) = take_while1(is_horizontal_space)(input)?; + let (input, data) = take_while1(not_line_ending)(input)?; + let (input, _) = line_ending(input)?; - Ok((input, data)) + Ok((input, data)) } fn message_header(input: Input<'_>) -> IResult, Header<'_>> { - let (input, name) = take_while1(is_token)(input)?; - let (input, _) = one_of(':')(input)?; - let (input, value) = many1(message_header_value)(input)?; + let (input, name) = take_while1(is_token)(input)?; + let (input, _) = one_of(':')(input)?; + let (input, value) = many1(message_header_value)(input)?; - Ok((input, Header { name, value })) + Ok((input, Header { name, value })) } #[rustfmt::skip] @@ -127,21 +127,21 @@ fn is_token(c: u8) -> bool { } fn is_version(c: u8) -> bool { - (b'0'..=b'9').contains(&c) || c == b'.' + (b'0'..=b'9').contains(&c) || c == b'.' } fn not_line_ending(c: u8) -> bool { - c != b'\r' && c != b'\n' + c != b'\r' && c != b'\n' } fn is_space(c: u8) -> bool { - c == b' ' + c == b' ' } fn is_not_space(c: u8) -> bool { - c != b' ' + c != b' ' } fn is_horizontal_space(c: u8) -> bool { - c == b' ' || c == b'\t' + c == b' ' || c == b'\t' } diff --git a/examples/ini/bench.rs b/examples/ini/bench.rs index 8cef0409..62bf05a5 100644 --- a/examples/ini/bench.rs +++ b/examples/ini/bench.rs @@ -5,7 +5,7 @@ mod parser; mod parser_str; fn bench_ini(c: &mut criterion::Criterion) { - let str = "[owner] + let str = "[owner] name=John Doe organization=Acme Widgets Inc. @@ -15,47 +15,47 @@ 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()) - }); + 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 + let str = "server=192.0.2.62 port=143 file=payroll.dat \0"; - fn acc(i: parser::Input<'_>) -> IResult, Vec<(&str, &str)>> { - many0(parser::key_value)(i) - } + fn acc(i: parser::Input<'_>) -> IResult, Vec<(&str, &str)>> { + many0(parser::key_value)(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()); - }); + 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 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()); - }); + 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 + benches, + bench_ini, + bench_ini_keys_and_values, + bench_ini_key_value ); criterion::criterion_main!(benches); diff --git a/examples/ini/main.rs b/examples/ini/main.rs index 36fca97f..7793c212 100644 --- a/examples/ini/main.rs +++ b/examples/ini/main.rs @@ -4,57 +4,57 @@ 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_next(input.as_bytes()).finish() { - Ok(result) => { - println!(" {:?}", result); - } - Err(err) => { - println!(" {:?}", err); - } - } - } else { - match parser_str::categories.parse_next(input).finish() { - Ok(result) => { - println!(" {:?}", result); - } - Err(err) => { - println!(" {}", err); - } + let args = Args::parse()?; + + let input = args.input.as_deref().unwrap_or("1 + 1"); + + if args.binary { + match parser::categories.parse_next(input.as_bytes()).finish() { + Ok(result) => { + println!(" {:?}", result); + } + Err(err) => { + println!(" {:?}", err); + } + } + } else { + match parser_str::categories.parse_next(input).finish() { + Ok(result) => { + println!(" {:?}", result); + } + Err(err) => { + println!(" {}", err); + } + } } - } - Ok(()) + Ok(()) } #[derive(Default)] struct Args { - input: Option, - binary: bool, + 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()?); + 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()), + } } - _ => return Err(arg.unexpected()), - } + Ok(res) } - Ok(res) - } } diff --git a/examples/ini/parser.rs b/examples/ini/parser.rs index fa77b32d..50d9e98a 100644 --- a/examples/ini/parser.rs +++ b/examples/ini/parser.rs @@ -3,114 +3,114 @@ use std::str; use winnow::prelude::*; use winnow::{ - bytes::take_while0, - character::{alphanumeric1 as alphanumeric, multispace0 as multispace, space0 as space}, - combinator::opt, - multi::many0, - sequence::{delimited, separated_pair, terminated}, + bytes::take_while0, + character::{alphanumeric1 as alphanumeric, multispace0 as multispace, space0 as space}, + combinator::opt, + multi::many0, + sequence::{delimited, separated_pair, terminated}, }; pub type Input<'i> = &'i [u8]; pub fn categories(i: Input<'_>) -> IResult, HashMap<&str, HashMap<&str, &str>>> { - many0(separated_pair( - category, - opt(multispace), - many0(terminated(key_value, opt(multispace))), - )) - .parse_next(i) + many0(separated_pair( + category, + opt(multispace), + many0(terminated(key_value, opt(multispace))), + )) + .parse_next(i) } fn category(i: Input<'_>) -> IResult, &str> { - delimited('[', take_while0(|c| c != b']'), ']') - .map_res(str::from_utf8) - .parse_next(i) + delimited('[', take_while0(|c| c != b']'), ']') + .map_res(str::from_utf8) + .parse_next(i) } pub fn key_value(i: Input<'_>) -> IResult, (&str, &str)> { - let (i, key) = alphanumeric.map_res(str::from_utf8).parse_next(i)?; - let (i, _) = (opt(space), '=', opt(space)).parse_next(i)?; - let (i, val) = take_while0(|c| c != b'\n' && c != b';') - .map_res(str::from_utf8) - .parse_next(i)?; - let (i, _) = opt((';', take_while0(|c| c != b'\n')))(i)?; - Ok((i, (key, val))) + let (i, key) = alphanumeric.map_res(str::from_utf8).parse_next(i)?; + let (i, _) = (opt(space), '=', opt(space)).parse_next(i)?; + let (i, val) = take_while0(|c| c != b'\n' && c != b';') + .map_res(str::from_utf8) + .parse_next(i)?; + let (i, _) = opt((';', take_while0(|c| c != b'\n')))(i)?; + Ok((i, (key, val))) } #[test] fn parse_category_test() { - let ini_file = &b"[category] + let ini_file = &b"[category] parameter=value key = value2"[..]; - let ini_without_category = &b"\n\nparameter=value + 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"), - } + 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"))); + assert_eq!(res, Ok((ini_without_category, "category"))); } #[test] fn parse_key_value_test() { - let ini_file = &b"parameter=value + let ini_file = &b"parameter=value key = value2"[..]; - let ini_without_key_value = &b"\nkey = 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"), - } + 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")))); + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); } #[test] fn parse_key_value_with_space_test() { - let ini_file = &b"parameter = value + let ini_file = &b"parameter = value key = value2"[..]; - let ini_without_key_value = &b"\nkey = 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"), - } + 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")))); + 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 + let ini_file = &b"parameter=value;abc key = value2"[..]; - let ini_without_key_value = &b"\nkey = 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"), - } + 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")))); + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); } #[test] fn parse_multiple_categories_test() { - let ini_file = &b"[abcd] + let ini_file = &b"[abcd] parameter=value;abc @@ -121,23 +121,23 @@ 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))); + 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/examples/ini/parser_str.rs b/examples/ini/parser_str.rs index 426c7786..dba38d99 100644 --- a/examples/ini/parser_str.rs +++ b/examples/ini/parser_str.rs @@ -2,179 +2,179 @@ use std::collections::HashMap; use winnow::prelude::*; use winnow::{ - bytes::{take_till0, take_while0, take_while1}, - character::{alphanumeric1 as alphanumeric, space0 as space}, - combinator::opt, - multi::many0, - sequence::{delimited, terminated}, + bytes::{take_till0, take_while0, take_while1}, + character::{alphanumeric1 as alphanumeric, space0 as space}, + combinator::opt, + multi::many0, + sequence::{delimited, terminated}, }; pub type Input<'i> = &'i str; pub fn categories(input: Input<'_>) -> IResult, HashMap<&str, HashMap<&str, &str>>> { - many0(category_and_keys)(input) + many0(category_and_keys)(input) } fn category_and_keys(i: Input<'_>) -> IResult, (&str, HashMap<&str, &str>)> { - (category, keys_and_values).parse_next(i) + (category, keys_and_values).parse_next(i) } fn category(i: Input<'_>) -> IResult, &str> { - terminated( - delimited('[', take_while0(|c| c != ']'), ']'), - opt(take_while1(" \r\n")), - )(i) + terminated( + delimited('[', take_while0(|c| c != ']'), ']'), + opt(take_while1(" \r\n")), + )(i) } fn keys_and_values(input: Input<'_>) -> IResult, HashMap<&str, &str>> { - many0(key_value)(input) + many0(key_value)(input) } fn key_value(i: Input<'_>) -> 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)(i)?; - let (i, _) = opt(space)(i)?; - let (i, _) = opt((";", not_line_ending))(i)?; - let (i, _) = opt(space_or_line_ending)(i)?; - - Ok((i, (key, val))) + let (i, key) = alphanumeric(i)?; + let (i, _) = (opt(space), "=", opt(space)).parse_next(i)?; + let (i, val) = take_till0(is_line_ending_or_comment)(i)?; + let (i, _) = opt(space)(i)?; + let (i, _) = opt((";", not_line_ending))(i)?; + let (i, _) = opt(space_or_line_ending)(i)?; + + Ok((i, (key, val))) } fn is_line_ending_or_comment(chr: char) -> bool { - chr == ';' || chr == '\n' + chr == ';' || chr == '\n' } fn not_line_ending(i: Input<'_>) -> IResult, &str> { - take_while0(|c| c != '\r' && c != '\n')(i) + take_while0(|c| c != '\r' && c != '\n')(i) } fn space_or_line_ending(i: Input<'_>) -> IResult, &str> { - take_while1(" \r\n")(i) + take_while1(" \r\n")(i) } #[test] fn parse_category_test() { - let ini_file = "[category] + let ini_file = "[category] parameter=value key = value2"; - let ini_without_category = "parameter=value + 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"), - } + 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"))); + assert_eq!(res, Ok((ini_without_category, "category"))); } #[test] fn parse_key_value_test() { - let ini_file = "parameter=value + let ini_file = "parameter=value key = value2"; - let ini_without_key_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"), - } + 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")))); + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); } #[test] fn parse_key_value_with_space_test() { - let ini_file = "parameter = value + let ini_file = "parameter = value key = value2"; - let ini_without_key_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"), - } + 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")))); + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); } #[test] fn parse_key_value_with_comment_test() { - let ini_file = "parameter=value;abc + let ini_file = "parameter=value;abc key = value2"; - let ini_without_key_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"), - } + 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")))); + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); } #[test] fn parse_multiple_keys_and_values_test() { - let ini_file = "parameter=value;abc + let ini_file = "parameter=value;abc key = value2 [category]"; - let ini_without_key_value = "[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 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))); + 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] + //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 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 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)))); + 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] + let ini_file = "[abcd] parameter=value;abc @@ -185,21 +185,21 @@ 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))); + 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/examples/iterator.rs b/examples/iterator.rs index 68e375af..3445637f 100644 --- a/examples/iterator.rs +++ b/examples/iterator.rs @@ -8,75 +8,75 @@ use winnow::sequence::{separated_pair, terminated}; use winnow::IResult; fn main() { - let mut data = "abcabcabcabc"; + let mut data = "abcabcabcabc"; - fn parser(i: &str) -> IResult<&str, &str> { - tag("abc")(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 nom 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, + fn parser(i: &str) -> IResult<&str, &str> { + tag("abc")(i) } - }); - for value in it { - println!("parser returned: {}", value); - } + // `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 nom 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"); + println!("\n********************\n"); - let data = "abcabcabcabc"; + 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) - }) - }); + // 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); + // will print "parser iterator returned: Ok(("abc", ["abc", "abc", "abc"]))" + println!("\nparser iterator returned: {:?}", res); - println!("\n********************\n"); + println!("\n********************\n"); - let data = "key1:value1,key2:value2,key3:value3,;"; + 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 nom_it = iterator( - data, - terminated(separated_pair(alphanumeric1, ":", alphanumeric1), ","), - ); + // `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 nom_it = iterator( + data, + terminated(separated_pair(alphanumeric1, ":", alphanumeric1), ","), + ); - let res = nom_it - .map(|(k, v)| (k.to_uppercase(), v)) - .collect::>(); + let res = nom_it + .map(|(k, v)| (k.to_uppercase(), v)) + .collect::>(); - let parser_result: IResult<_, _> = nom_it.finish(); - let (remaining_input, ()) = parser_result.unwrap(); + let parser_result: IResult<_, _> = nom_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 - ); + // 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/examples/json/bench.rs b/examples/json/bench.rs index 1e7e897b..85a124f0 100644 --- a/examples/json/bench.rs +++ b/examples/json/bench.rs @@ -6,41 +6,41 @@ mod parser_dispatch; mod parser_streaming; 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("complete", name), - &len, - |b, _| { - type Error<'i> = winnow::error::Error>; - - 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_streaming::json::(Streaming(sample)).unwrap()); - }, - ); - } - group.finish(); + 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("complete", name), + &len, + |b, _| { + type Error<'i> = winnow::error::Error>; + + 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_streaming::json::(Streaming(sample)).unwrap()); + }, + ); + } + group.finish(); } const SMALL: &str = " { \"a\"\t: 42, diff --git a/examples/json/json.rs b/examples/json/json.rs index d504782d..6912d60e 100644 --- a/examples/json/json.rs +++ b/examples/json/json.rs @@ -2,10 +2,10 @@ use std::collections::HashMap; #[derive(Debug, PartialEq, Clone)] pub enum JsonValue { - Null, - Boolean(bool), - Str(String), - Num(f64), - Array(Vec), - Object(HashMap), + Null, + Boolean(bool), + Str(String), + Num(f64), + Array(Vec), + Object(HashMap), } diff --git a/examples/json/main.rs b/examples/json/main.rs index 75d62e30..f56cc01c 100644 --- a/examples/json/main.rs +++ b/examples/json/main.rs @@ -10,109 +10,109 @@ use winnow::error::VerboseError; use winnow::prelude::*; fn main() -> Result<(), lexopt::Error> { - let args = Args::parse()?; + let args = Args::parse()?; - let data = args.input.as_deref().unwrap_or(if args.invalid { - " { \"a\"\t: 42, + 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, + } else { + " { \"a\"\t: 42, \"b\": [ \"x\", \"y\", 12 ] , \"c\": { \"hello\" : \"world\" } } " - }); + }); - if args.verbose { - match parser::json::>(data).finish() { - Ok(json) => { - println!("{:#?}", json); - } - Err(err) => { - if args.pretty { - println!("{}", convert_error(data, err)); - } else { - println!("{:#?}", err); + if args.verbose { + match parser::json::>(data).finish() { + 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::>(data).finish(), + Impl::Dispatch => parser_dispatch::json::>(data).finish(), + }; + match result { + Ok(json) => { + println!("{:#?}", json); + } + Err(err) => { + println!("{:?}", err); + } } - } - } - } else { - let result = match args.implementation { - Impl::Naive => parser::json::>(data).finish(), - Impl::Dispatch => parser_dispatch::json::>(data).finish(), - }; - match result { - Ok(json) => { - println!("{:#?}", json); - } - Err(err) => { - println!("{:?}", err); - } } - } - Ok(()) + Ok(()) } #[derive(Default)] struct Args { - input: Option, - invalid: bool, - verbose: bool, - pretty: bool, - implementation: Impl, + input: Option, + invalid: bool, + verbose: bool, + pretty: bool, + implementation: Impl, } enum Impl { - Naive, - Dispatch, + Naive, + Dispatch, } impl Default for Impl { - fn default() -> Self { - Self::Naive - } + fn default() -> Self { + Self::Naive + } } impl Args { - fn parse() -> Result { - use lexopt::prelude::*; + fn parse() -> Result { + use lexopt::prelude::*; - let mut res = Args::default(); + 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; + 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()), + } } - 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) } - Ok(res) - } } diff --git a/examples/json/parser.rs b/examples/json/parser.rs index 15f74145..70cb6781 100644 --- a/examples/json/parser.rs +++ b/examples/json/parser.rs @@ -3,13 +3,13 @@ use std::str; use winnow::prelude::*; use winnow::{ - branch::alt, - bytes::{any, none_of, tag, take, take_while0}, - character::float, - combinator::cut_err, - error::{ContextError, ParseError}, - multi::{fold_many0, separated_list0}, - sequence::{delimited, preceded, separated_pair, terminated}, + branch::alt, + bytes::{any, none_of, tag, take, take_while0}, + character::float, + combinator::cut_err, + error::{ContextError, ParseError}, + multi::{fold_many0, separated_list0}, + sequence::{delimited, preceded, separated_pair, terminated}, }; use crate::json::JsonValue; @@ -29,126 +29,126 @@ pub type Input<'i> = &'i str; /// 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: Input<'i>, + input: Input<'i>, ) -> IResult, JsonValue, E> { - delimited(ws, json_value, ws)(input) + delimited(ws, json_value, ws)(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: Input<'i>, + input: Input<'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), - ))(input) + // `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), + ))(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: Input<'i>) -> IResult, &'i str, E> { - // This is a parser that returns `"null"` if it sees the string "null", and - // an error otherwise - tag("null").parse_next(input) + // This is a parser that returns `"null"` if it sees the string "null", and + // an error otherwise + tag("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: Input<'i>) -> IResult, bool, E> { - // This is a parser that returns `true` if it sees the string "true", and - // an error otherwise - let parse_true = tag("true").value(true); + // This is a parser that returns `true` if it sees the string "true", and + // an error otherwise + let parse_true = tag("true").value(true); - // This is a parser that returns `false` if it sees the string "false", and - // an error otherwise - let parse_false = tag("false").value(false); + // This is a parser that returns `false` if it sees the string "false", and + // an error otherwise + let parse_false = tag("false").value(false); - alt((parse_true, parse_false))(input) + alt((parse_true, parse_false))(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: Input<'i>, + input: Input<'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_many0(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) + 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_many0(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: Input<'i>) -> IResult, char, E> { - let (input, c) = none_of("\"")(input)?; - if c == '\\' { - alt(( - any.map_opt(|c| { - Some(match c { - '"' | '\\' | '/' => c, - 'b' => '\x08', - 'f' => '\x0C', - 'n' => '\n', - 'r' => '\r', - 't' => '\t', - _ => return None, - }) - }), - preceded('u', unicode_escape), - ))(input) - } else { - Ok((input, c)) - } + let (input, c) = none_of("\"")(input)?; + if c == '\\' { + alt(( + any.map_opt(|c| { + Some(match c { + '"' | '\\' | '/' => c, + 'b' => '\x08', + 'f' => '\x0C', + 'n' => '\n', + 'r' => '\r', + 't' => '\t', + _ => return None, + }) + }), + preceded('u', unicode_escape), + ))(input) + } else { + Ok((input, c)) + } } fn unicode_escape<'i, E: ParseError>>(input: Input<'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 - }), - )) - .map_opt( - // Could be probably replaced with .unwrap() or _unchecked due to the verify checks - std::char::from_u32, - ) - .parse_next(input) + 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 + }), + )) + .map_opt( + // 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: Input<'i>) -> IResult, u16, E> { - take(4usize) - .map_opt(|s| u16::from_str_radix(s, 16).ok()) - .parse_next(input) + take(4usize) + .map_opt(|s| u16::from_str_radix(s, 16).ok()) + .parse_next(input) } /// Some combinators, like `separated_list0` or `many0`, will call a parser repeatedly, @@ -156,116 +156,116 @@ fn u16_hex<'i, E: ParseError>>(input: Input<'i>) -> IResult, /// 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: Input<'i>, + input: Input<'i>, ) -> IResult, Vec, E> { - preceded( - ('[', ws), - cut_err(terminated( - separated_list0((ws, ',', ws), json_value), - (ws, ']'), - )), - ) - .context("array") - .parse_next(input) + preceded( + ('[', ws), + cut_err(terminated( + separated_list0((ws, ',', ws), json_value), + (ws, ']'), + )), + ) + .context("array") + .parse_next(input) } fn object<'i, E: ParseError> + ContextError, &'static str>>( - input: Input<'i>, + input: Input<'i>, ) -> IResult, HashMap, E> { - preceded( - ('{', ws), - cut_err(terminated( - separated_list0((ws, ',', ws), key_value), - (ws, '}'), - )), - ) - .context("object") - .parse_next(input) + preceded( + ('{', ws), + cut_err(terminated( + separated_list0((ws, ',', ws), key_value), + (ws, '}'), + )), + ) + .context("object") + .parse_next(input) } fn key_value<'i, E: ParseError> + ContextError, &'static str>>( - input: Input<'i>, + input: Input<'i>, ) -> IResult, (String, JsonValue), E> { - separated_pair(string, cut_err((ws, ':', ws)), json_value)(input) + separated_pair(string, cut_err((ws, ':', ws)), json_value)(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: Input<'i>) -> IResult, &'i str, E> { - // nom combinators like `take_while0` return a function. That function is the - // parser,to which we can pass the input - take_while0(WS)(input) + // nom combinators like `take_while0` return a function. That function is the + // parser,to which we can pass the input + take_while0(WS)(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#" + #[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 , @@ -279,39 +279,39 @@ mod test { } "#; - 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() - ) - )) - ); - } + 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/examples/json/parser_dispatch.rs b/examples/json/parser_dispatch.rs index 7246706d..86add311 100644 --- a/examples/json/parser_dispatch.rs +++ b/examples/json/parser_dispatch.rs @@ -3,16 +3,16 @@ use std::str; use winnow::prelude::*; use winnow::{ - branch::{alt, dispatch}, - bytes::{any, none_of, tag, take, take_while0}, - character::float, - combinator::cut_err, - combinator::fail, - combinator::peek, - combinator::success, - error::{ContextError, ParseError}, - multi::{fold_many0, separated_list0}, - sequence::{delimited, preceded, separated_pair, terminated}, + branch::{alt, dispatch}, + bytes::{any, none_of, tag, take, take_while0}, + character::float, + combinator::cut_err, + combinator::fail, + combinator::peek, + combinator::success, + error::{ContextError, ParseError}, + multi::{fold_many0, separated_list0}, + sequence::{delimited, preceded, separated_pair, terminated}, }; use crate::json::JsonValue; @@ -32,132 +32,132 @@ pub type Input<'i> = &'i str; /// 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: Input<'i>, + input: Input<'i>, ) -> IResult, JsonValue, E> { - delimited(ws, json_value, ws)(input) + delimited(ws, json_value, ws)(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: Input<'i>, + input: Input<'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) + // `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: Input<'i>) -> IResult, &'i str, E> { - // This is a parser that returns `"null"` if it sees the string "null", and - // an error otherwise - tag("null").parse_next(input) + // This is a parser that returns `"null"` if it sees the string "null", and + // an error otherwise + tag("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: Input<'i>) -> IResult, bool, E> { - // This is a parser that returns `true` if it sees the string "true", and - // an error otherwise - tag("true").value(true).parse_next(input) + // This is a parser that returns `true` if it sees the string "true", and + // an error otherwise + tag("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: Input<'i>) -> IResult, bool, E> { - // This is a parser that returns `false` if it sees the string "false", and - // an error otherwise - tag("false").value(false).parse_next(input) + // This is a parser that returns `false` if it sees the string "false", and + // an error otherwise + tag("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: Input<'i>, + input: Input<'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_many0(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) + 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_many0(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: Input<'i>) -> IResult, char, E> { - let (input, c) = none_of("\"")(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)) - } + let (input, c) = none_of("\"")(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: Input<'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 - }), - )) - .map_opt( - // Could be probably replaced with .unwrap() or _unchecked due to the verify checks - std::char::from_u32, - ) - .parse_next(input) + 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 + }), + )) + .map_opt( + // 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: Input<'i>) -> IResult, u16, E> { - take(4usize) - .map_opt(|s| u16::from_str_radix(s, 16).ok()) - .parse_next(input) + take(4usize) + .map_opt(|s| u16::from_str_radix(s, 16).ok()) + .parse_next(input) } /// Some combinators, like `separated_list0` or `many0`, will call a parser repeatedly, @@ -165,116 +165,116 @@ fn u16_hex<'i, E: ParseError>>(input: Input<'i>) -> IResult, /// 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: Input<'i>, + input: Input<'i>, ) -> IResult, Vec, E> { - preceded( - ('[', ws), - cut_err(terminated( - separated_list0((ws, ',', ws), json_value), - (ws, ']'), - )), - ) - .context("array") - .parse_next(input) + preceded( + ('[', ws), + cut_err(terminated( + separated_list0((ws, ',', ws), json_value), + (ws, ']'), + )), + ) + .context("array") + .parse_next(input) } fn object<'i, E: ParseError> + ContextError, &'static str>>( - input: Input<'i>, + input: Input<'i>, ) -> IResult, HashMap, E> { - preceded( - ('{', ws), - cut_err(terminated( - separated_list0((ws, ',', ws), key_value), - (ws, '}'), - )), - ) - .context("object") - .parse_next(input) + preceded( + ('{', ws), + cut_err(terminated( + separated_list0((ws, ',', ws), key_value), + (ws, '}'), + )), + ) + .context("object") + .parse_next(input) } fn key_value<'i, E: ParseError> + ContextError, &'static str>>( - input: Input<'i>, + input: Input<'i>, ) -> IResult, (String, JsonValue), E> { - separated_pair(string, cut_err((ws, ':', ws)), json_value)(input) + separated_pair(string, cut_err((ws, ':', ws)), json_value)(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: Input<'i>) -> IResult, &'i str, E> { - // nom combinators like `take_while0` return a function. That function is the - // parser,to which we can pass the input - take_while0(WS)(input) + // nom combinators like `take_while0` return a function. That function is the + // parser,to which we can pass the input + take_while0(WS)(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#" + #[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 , @@ -288,39 +288,39 @@ mod test { } "#; - 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() - ) - )) - ); - } + 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/examples/json/parser_streaming.rs b/examples/json/parser_streaming.rs index f325e241..d6fd5e24 100644 --- a/examples/json/parser_streaming.rs +++ b/examples/json/parser_streaming.rs @@ -3,24 +3,24 @@ use std::str; use winnow::prelude::*; use winnow::{ - branch::alt, - bytes::{any, none_of, one_of, tag, take, take_while0}, - character::float, - combinator::{cut_err, rest}, - error::{ContextError, ParseError}, - input::Streaming, - multi::{fold_many0, separated_list0}, - sequence::{delimited, preceded, separated_pair, terminated}, + branch::alt, + bytes::{any, none_of, one_of, tag, take, take_while0}, + character::float, + combinator::{cut_err, rest}, + error::{ContextError, ParseError}, + input::Streaming, + multi::{fold_many0, separated_list0}, + sequence::{delimited, preceded, separated_pair, terminated}, }; #[derive(Debug, PartialEq, Clone)] pub enum JsonValue { - Null, - Boolean(bool), - Str(String), - Num(f64), - Array(Vec), - Object(HashMap), + Null, + Boolean(bool), + Str(String), + Num(f64), + Array(Vec), + Object(HashMap), } pub type Input<'i> = Streaming<&'i str>; @@ -38,126 +38,126 @@ pub type Input<'i> = Streaming<&'i str>; /// 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: Input<'i>, + input: Input<'i>, ) -> IResult, JsonValue, E> { - delimited(ws, json_value, ws_or_eof)(input) + delimited(ws, json_value, ws_or_eof)(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: Input<'i>, + input: Input<'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), - ))(input) + // `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), + ))(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: Input<'i>) -> IResult, &'i str, E> { - // This is a parser that returns `"null"` if it sees the string "null", and - // an error otherwise - tag("null").parse_next(input) + // This is a parser that returns `"null"` if it sees the string "null", and + // an error otherwise + tag("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: Input<'i>) -> IResult, bool, E> { - // This is a parser that returns `true` if it sees the string "true", and - // an error otherwise - let parse_true = tag("true").value(true); + // This is a parser that returns `true` if it sees the string "true", and + // an error otherwise + let parse_true = tag("true").value(true); - // This is a parser that returns `false` if it sees the string "false", and - // an error otherwise - let parse_false = tag("false").value(false); + // This is a parser that returns `false` if it sees the string "false", and + // an error otherwise + let parse_false = tag("false").value(false); - alt((parse_true, parse_false))(input) + alt((parse_true, parse_false))(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: Input<'i>, + input: Input<'i>, ) -> IResult, String, E> { - preceded( - one_of('\"'), - // `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_many0(character, String::new, |mut string, c| { - string.push(c); - string - }), - one_of('\"'), - )), - ) - // `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) + preceded( + one_of('\"'), + // `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_many0(character, String::new, |mut string, c| { + string.push(c); + string + }), + one_of('\"'), + )), + ) + // `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: Input<'i>) -> IResult, char, E> { - let (input, c) = none_of("\"")(input)?; - if c == '\\' { - alt(( - any.map_opt(|c| { - Some(match c { - '"' | '\\' | '/' => c, - 'b' => '\x08', - 'f' => '\x0C', - 'n' => '\n', - 'r' => '\r', - 't' => '\t', - _ => return None, - }) - }), - preceded(one_of('u'), unicode_escape), - ))(input) - } else { - Ok((input, c)) - } + let (input, c) = none_of("\"")(input)?; + if c == '\\' { + alt(( + any.map_opt(|c| { + Some(match c { + '"' | '\\' | '/' => c, + 'b' => '\x08', + 'f' => '\x0C', + 'n' => '\n', + 'r' => '\r', + 't' => '\t', + _ => return None, + }) + }), + preceded(one_of('u'), unicode_escape), + ))(input) + } else { + Ok((input, c)) + } } fn unicode_escape<'i, E: ParseError>>(input: Input<'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, tag("\\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 - }), - )) - .map_opt( - // Could be probably replaced with .unwrap() or _unchecked due to the verify checks - std::char::from_u32, - ) - .parse_next(input) + 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, tag("\\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 + }), + )) + .map_opt( + // 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: Input<'i>) -> IResult, u16, E> { - take(4usize) - .map_opt(|s| u16::from_str_radix(s, 16).ok()) - .parse_next(input) + take(4usize) + .map_opt(|s| u16::from_str_radix(s, 16).ok()) + .parse_next(input) } /// Some combinators, like `separated_list0` or `many0`, will call a parser repeatedly, @@ -165,136 +165,135 @@ fn u16_hex<'i, E: ParseError>>(input: Input<'i>) -> IResult, /// 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: Input<'i>, + input: Input<'i>, ) -> IResult, Vec, E> { - preceded( - (one_of('['), ws), - cut_err(terminated( - separated_list0((ws, one_of(','), ws), json_value), - (ws, one_of(']')), - )), - ) - .context("array") - .parse_next(input) + preceded( + (one_of('['), ws), + cut_err(terminated( + separated_list0((ws, one_of(','), ws), json_value), + (ws, one_of(']')), + )), + ) + .context("array") + .parse_next(input) } fn object<'i, E: ParseError> + ContextError, &'static str>>( - input: Input<'i>, + input: Input<'i>, ) -> IResult, HashMap, E> { - preceded( - (one_of('{'), ws), - cut_err(terminated( - separated_list0((ws, one_of(','), ws), key_value), - (ws, one_of('}')), - )), - ) - .context("object") - .parse_next(input) + preceded( + (one_of('{'), ws), + cut_err(terminated( + separated_list0((ws, one_of(','), ws), key_value), + (ws, one_of('}')), + )), + ) + .context("object") + .parse_next(input) } fn key_value<'i, E: ParseError> + ContextError, &'static str>>( - input: Input<'i>, + input: Input<'i>, ) -> IResult, (String, JsonValue), E> { - separated_pair(string, cut_err((ws, one_of(':'), ws)), json_value)(input) + separated_pair(string, cut_err((ws, one_of(':'), ws)), json_value)(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: Input<'i>) -> IResult, &'i str, E> { - // nom combinators like `take_while0` return a function. That function is the - // parser,to which we can pass the input - take_while0(WS)(input) + // nom combinators like `take_while0` return a function. That function is the + // parser,to which we can pass the input + take_while0(WS)(input) } fn ws_or_eof<'i, E: ParseError>>(input: Input<'i>) -> IResult, &'i str, E> { - rest - .verify(|s: &str| s.chars().all(|c| WS.contains(c))) - .parse_next(input) + 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::>(Streaming("\"\"")), - Ok((Streaming(""), "".to_string())) - ); - assert_eq!( - string::>(Streaming("\"abc\"")), - Ok((Streaming(""), "abc".to_string())) - ); - assert_eq!( - string::>(Streaming( - "\"abc\\\"\\\\\\/\\b\\f\\n\\r\\t\\u0001\\u2014\u{2014}def\"" - )), - Ok((Streaming(""), "abc\"\\/\x08\x0C\n\r\t\x01——def".to_string())), - ); - assert_eq!( - string::>(Streaming("\"\\uD83D\\uDE10\"")), - Ok((Streaming(""), "😐".to_string())) - ); - - assert!(string::>(Streaming("\"")).is_err()); - assert!(string::>(Streaming("\"abc")).is_err()); - assert!(string::>(Streaming("\"\\\"")).is_err()); - assert!(string::>(Streaming("\"\\u123\"")).is_err()); - assert!(string::>(Streaming("\"\\uD800\"")).is_err()); - assert!(string::>(Streaming("\"\\uD800\\uD800\"")).is_err()); - assert!(string::>(Streaming("\"\\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::>(Streaming(input)), - Ok((Streaming(""), 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::>(Streaming(input)), - Ok((Streaming(""), expected)) - ); - } - - #[test] - fn json_whitespace() { - use JsonValue::{Array, Boolean, Null, Num, Object, Str}; - - let input = r#" + #[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::>(Streaming("\"\"")), + Ok((Streaming(""), "".to_string())) + ); + assert_eq!( + string::>(Streaming("\"abc\"")), + Ok((Streaming(""), "abc".to_string())) + ); + assert_eq!( + string::>(Streaming( + "\"abc\\\"\\\\\\/\\b\\f\\n\\r\\t\\u0001\\u2014\u{2014}def\"" + )), + Ok((Streaming(""), "abc\"\\/\x08\x0C\n\r\t\x01——def".to_string())), + ); + assert_eq!( + string::>(Streaming("\"\\uD83D\\uDE10\"")), + Ok((Streaming(""), "😐".to_string())) + ); + + assert!(string::>(Streaming("\"")).is_err()); + assert!(string::>(Streaming("\"abc")).is_err()); + assert!(string::>(Streaming("\"\\\"")).is_err()); + assert!(string::>(Streaming("\"\\u123\"")).is_err()); + assert!(string::>(Streaming("\"\\uD800\"")).is_err()); + assert!(string::>(Streaming("\"\\uD800\\uD800\"")).is_err()); + assert!(string::>(Streaming("\"\\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::>(Streaming(input)), + Ok((Streaming(""), 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::>(Streaming(input)), + Ok((Streaming(""), expected)) + ); + } + + #[test] + fn json_whitespace() { + use JsonValue::{Array, Boolean, Null, Num, Object, Str}; + + let input = r#" { "null" : null, "true" :true , @@ -308,39 +307,39 @@ mod test { } "#; - assert_eq!( - json::>(Streaming(input)), - Ok(( - Streaming(""), - 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() - ) - )) - ); - } + assert_eq!( + json::>(Streaming(input)), + Ok(( + Streaming(""), + 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/examples/json_iterator.rs b/examples/json_iterator.rs index a10c4c5e..ab77ee31 100644 --- a/examples/json_iterator.rs +++ b/examples/json_iterator.rs @@ -2,15 +2,15 @@ use std::collections::HashMap; use winnow::prelude::*; use winnow::{ - branch::alt, - bytes::one_of, - bytes::{tag, take_while0}, - character::{alphanumeric1 as alphanumeric, escaped, float}, - combinator::cut_err, - error::ParseError, - multi::separated_list0, - sequence::{preceded, separated_pair, terminated}, - IResult, + branch::alt, + bytes::one_of, + bytes::{tag, take_while0}, + character::{alphanumeric1 as alphanumeric, escaped, float}, + combinator::cut_err, + error::ParseError, + multi::separated_list0, + sequence::{preceded, separated_pair, terminated}, + IResult, }; use std::cell::Cell; @@ -18,250 +18,250 @@ use std::str; #[derive(Clone, Debug)] pub struct JsonValue<'a, 'b> { - input: &'a str, - pub offset: &'b Cell, + 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 new(input: &'a str, offset: &'b Cell) -> JsonValue<'a, 'b> { + JsonValue { input, offset } } - } - - 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::<_, _, (), false>(self.data()) { - Ok((i, o)) => { - self.offset(i); - println!("-> {}", o); - Some(o) - } - _ => None, - } - } - - pub fn array(&self) -> Option>> { - println!("array()"); - - match tag::<_, _, (), false>("[")(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::<_, _, (), false>("]")(v.data()) { - println!("]"); - v.offset(i); - done = true; - return None; - } - - if first { - first = false; - } else { - match tag::<_, _, (), false>(",")(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 offset(&self, input: &'a str) { + let offset = input.as_ptr() as usize - self.input.as_ptr() as usize; + self.offset.set(offset); } - } - - pub fn object(&self) -> Option)>> { - println!("object()"); - match tag::<_, _, (), false>("{")(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; - } + pub fn data(&self) -> &'a str { + &self.input[self.offset.get()..] + } - // 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::<_, _, (), false>("}")(v.data()) { - println!("}}"); - v.offset(i); - done = true; - return None; - } - - if first { - first = false; - } else { - match tag::<_, _, (), false>(",")(v.data()) { - Ok((i, _)) => { - println!(","); - v.offset(i); - } - Err(_) => { - done = true; - return None; - } + pub fn string(&self) -> Option<&'a str> { + println!("string()"); + match string(self.data()) { + Ok((i, s)) => { + self.offset(i); + println!("-> {}", s); + Some(s) } - } + _ => None, + } + } - match string(v.data()) { - Ok((i, key)) => { - v.offset(i); + pub fn boolean(&self) -> Option { + println!("boolean()"); + match boolean(self.data()) { + Ok((i, o)) => { + self.offset(i); + println!("-> {}", o); + Some(o) + } + _ => None, + } + } - match tag::<_, _, (), false>(":")(v.data()) { - Err(_) => None, - Ok((i, _)) => { - v.offset(i); + pub fn number(&self) -> Option { + println!("number()"); + match float::<_, _, (), false>(self.data()) { + Ok((i, o)) => { + self.offset(i); + println!("-> {}", o); + Some(o) + } + _ => None, + } + } - previous = v.offset.get(); + pub fn array(&self) -> Option>> { + println!("array()"); + + match tag::<_, _, (), false>("[")(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::<_, _, (), false>("]")(v.data()) { + println!("]"); + v.offset(i); + done = true; + return None; + } + + if first { + first = false; + } else { + match tag::<_, _, (), false>(",")(v.data()) { + Ok((i, _)) => { + println!(","); + v.offset(i); + } + Err(_) => { + done = true; + return None; + } + } + } + + println!("-> {}", v.data()); + previous = v.offset.get(); + Some(v.clone()) + })) + } + } + } - println!("-> {} => {}", key, v.data()); - Some((key, v.clone())) - } - } + pub fn object(&self) -> Option)>> { + println!("object()"); + match tag::<_, _, (), false>("{")(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::<_, _, (), false>("}")(v.data()) { + println!("}}"); + v.offset(i); + done = true; + return None; + } + + if first { + first = false; + } else { + match tag::<_, _, (), false>(",")(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::<_, _, (), false>(":")(v.data()) { + Err(_) => None, + Ok((i, _)) => { + v.offset(i); + + previous = v.offset.get(); + + println!("-> {} => {}", key, v.data()); + Some((key, v.clone())) + } + } + } + _ => None, + } + })) } - _ => None, - } - })) - } + } } - } } fn sp<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> { - let chars = " \t\r\n"; + let chars = " \t\r\n"; - take_while0(move |c| chars.contains(c))(i) + take_while0(move |c| chars.contains(c))(i) } fn parse_str<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> { - escaped(alphanumeric, '\\', one_of("\"n\\"))(i) + escaped(alphanumeric, '\\', one_of("\"n\\"))(i) } fn string(i: &str) -> IResult<&str, &str> { - preceded('\"', cut_err(terminated(parse_str, '\"'))) - .context("string") - .parse_next(i) + preceded('\"', cut_err(terminated(parse_str, '\"'))) + .context("string") + .parse_next(i) } fn boolean(input: &str) -> IResult<&str, bool> { - alt((tag("false").map(|_| false), tag("true").map(|_| true)))(input) + alt((tag("false").map(|_| false), tag("true").map(|_| true)))(input) } fn array(i: &str) -> IResult<&str, ()> { - preceded( - '[', - cut_err(terminated( - separated_list0(preceded(sp, ','), value), - preceded(sp, ']'), - )), - ) - .context("array") - .parse_next(i) + preceded( + '[', + cut_err(terminated( + separated_list0(preceded(sp, ','), value), + 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)(i) + separated_pair(preceded(sp, string), cut_err(preceded(sp, ':')), value)(i) } fn hash(i: &str) -> IResult<&str, ()> { - preceded( - '{', - cut_err(terminated( - separated_list0(preceded(sp, ','), key_value), - preceded(sp, '}'), - )), - ) - .context("map") - .parse_next(i) + preceded( + '{', + cut_err(terminated( + separated_list0(preceded(sp, ','), key_value), + preceded(sp, '}'), + )), + ) + .context("map") + .parse_next(i) } fn value(i: &str) -> IResult<&str, ()> { - preceded( - sp, - alt(( - hash, - array, - string.map(|_| ()), - float::<_, f64, _, false>.map(|_| ()), - boolean.map(|_| ()), - )), - )(i) + preceded( + sp, + alt(( + hash, + array, + string.map(|_| ()), + float::<_, f64, _, false>.map(|_| ()), + boolean.map(|_| ()), + )), + )(i) } /// object(input) -> iterator over (key, `JsonValue`) @@ -271,34 +271,34 @@ fn value(i: &str) -> IResult<&str, ()> { /// /// 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); - } - }; + /*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/examples/s_expression.rs b/examples/s_expression.rs index cbceedbd..87b544c9 100644 --- a/examples/s_expression.rs +++ b/examples/s_expression.rs @@ -5,15 +5,15 @@ #![cfg(feature = "alloc")] use winnow::{ - branch::alt, - bytes::one_of, - bytes::tag, - character::{alpha1, digit1, multispace0, multispace1}, - combinator::{cut_err, opt}, - error::VerboseError, - multi::many0, - sequence::{delimited, preceded, terminated}, - IResult, Parser, + branch::alt, + bytes::one_of, + bytes::tag, + character::{alpha1, digit1, multispace0, multispace1}, + combinator::{cut_err, opt}, + error::VerboseError, + multi::many0, + sequence::{delimited, preceded, terminated}, + IResult, Parser, }; /// We start by defining the types that define the shape of data that we want. @@ -22,12 +22,12 @@ use winnow::{ /// Starting from the most basic, 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, + Plus, + Minus, + Times, + Divide, + Equal, + Not, } /// We now wrap this type and a few other primitives into our Atom type. @@ -35,10 +35,10 @@ pub enum BuiltIn { #[derive(Debug, Eq, PartialEq, Clone)] pub enum Atom { - Num(i32), - Keyword(String), - Boolean(bool), - BuiltIn(BuiltIn), + Num(i32), + Keyword(String), + Boolean(bool), + BuiltIn(BuiltIn), } /// The remaining half is Lists. We implement these as recursive Expressions. @@ -53,55 +53,55 @@ pub enum Atom { #[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), + 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), } /// 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("+-*/=")(i)?; + // one_of matches one of the characters we give it + let (i, t) = one_of("+-*/=")(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!(), - }, - )) + // 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!(), + }, + )) } 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 - tag("not").map(|_| BuiltIn::Not), - ))(i) + // 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 + tag("not").map(|_| BuiltIn::Not), + ))(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(( - tag("#t").map(|_| Atom::Boolean(true)), - tag("#f").map(|_| Atom::Boolean(false)), - ))(i) + alt(( + tag("#t").map(|_| Atom::Boolean(true)), + tag("#f").map(|_| Atom::Boolean(false)), + ))(i) } /// The next easiest thing to parse are keywords. @@ -111,35 +111,35 @@ fn parse_bool(i: &str) -> IResult<&str, Atom, VerboseError<&str>> { /// Put plainly: `preceded(":", cut_err(alpha1))` means that once we see the `:` /// character, we have to see one or more alphabetic chararcters 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) + preceded(":", cut_err(alpha1)) + .context("keyword") + .map(|sym_str: &str| Atom::Keyword(sym_str.to_string())) + .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.map_res(|digit_str: &str| digit_str.parse::().map(Atom::Num)), - preceded("-", digit1).map(|digit_str: &str| Atom::Num(-digit_str.parse::().unwrap())), - ))(i) + alt(( + digit1.map_res(|digit_str: &str| digit_str.parse::().map(Atom::Num)), + preceded("-", digit1).map(|digit_str: &str| Atom::Num(-digit_str.parse::().unwrap())), + ))(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, - ))(i) + alt(( + parse_num, + parse_bool, + parse_builtin.map(Atom::BuiltIn), + parse_keyword, + ))(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) + parse_atom.map(Expr::Constant).parse_next(i) } /// Before continuing, we need a helper function to parse lists. @@ -151,13 +151,13 @@ fn parse_constant(i: &str) -> IResult<&str, Expr, VerboseError<&str>> { /// takes a parsing function and returns a new parsing function. fn s_exp<'a, O1, F>(inner: F) -> impl FnMut(&'a str) -> IResult<&'a str, O1, VerboseError<&'a str>> where - F: Parser<&'a str, O1, VerboseError<&'a str>>, + F: Parser<&'a str, O1, VerboseError<&'a str>>, { - delimited( - '(', - preceded(multispace0, inner), - cut_err(preceded(multispace0, ')')).context("closing paren"), - ) + delimited( + '(', + preceded(multispace0, inner), + cut_err(preceded(multispace0, ')')).context("closing paren"), + ) } /// We can now use our new combinator to define the rest of the `Expr`s. @@ -170,10 +170,10 @@ where /// 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, many0(parse_expr)).map(|(head, tail)| Expr::Application(Box::new(head), tail)); - // finally, we wrap it in an s-expression - s_exp(application_inner)(i) + let application_inner = + (parse_expr, many0(parse_expr)).map(|(head, tail)| Expr::Application(Box::new(head), tail)); + // finally, we wrap it in an s-expression + s_exp(application_inner)(i) } /// Because `Expr::If` and `Expr::IfElse` are so similar (we easily could have @@ -183,26 +183,26 @@ fn parse_application(i: &str) -> IResult<&str, Expr, VerboseError<&str>> { /// 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)(i) + 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)(i) } /// A quoted S-expression is list data structure. @@ -211,22 +211,22 @@ fn parse_if(i: &str) -> IResult<&str, Expr, VerboseError<&str>> { /// 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(many0(parse_expr)))) - .context("quote") - .map(Expr::Quote) - .parse_next(i) + // 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(many0(parse_expr)))) + .context("quote") + .map(Expr::Quote) + .parse_next(i) } /// We tie them all together again, making a 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)), - )(i) + preceded( + multispace0, + alt((parse_constant, parse_application, parse_if, parse_quote)), + )(i) } /// And that's it! @@ -239,132 +239,138 @@ fn parse_expr(i: &str) -> IResult<&str, Expr, VerboseError<&str>> { /// 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 - } + 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 - } + if let Expr::Constant(Atom::Boolean(b)) = e { + Some(b) + } else { + None + } } /// 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; + 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 { - Atom::Boolean(!get_bool_from_expr(reduced_tail.first().cloned().unwrap())?) + None } - } - 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 - } + } + 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 + } + } } - } } /// And we add one more top-level function to tie everything together, letting /// us call eval on a string directly 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())) + parse_expr(src) + .map_err(|e: winnow::error::ErrMode>| format!("{:#?}", e)) + .and_then(|(_, exp)| eval_expression(exp).ok_or_else(|| "Eval failed".to_string())) } fn main() { - let expression_1 = "((if (= (+ 3 (/ 9 3)) + let expression_1 = "((if (= (+ 3 (/ 9 3)) (* 2 3)) * /) 456 123)"; - println!( - "\"{}\"\nevaled gives us: {:?}", - expression_1, - eval_from_str(expression_1) - ); + println!( + "\"{}\"\nevaled gives us: {:?}", + expression_1, + eval_from_str(expression_1) + ); } diff --git a/examples/string.rs b/examples/string.rs index 4b27a0bf..ba16e904 100644 --- a/examples/string.rs +++ b/examples/string.rs @@ -29,82 +29,82 @@ use winnow::IResult; /// 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>, + E: ParseError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>, { - // `take_while_m_n` 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_m_n(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, '}'), - ); - - // `map_res` 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.map_res(move |hex| u32::from_str_radix(hex, 16)); - - // map_opt is like map_res, but it takes an Option instead of a Result. If - // the function returns None, map_opt 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.map_opt(std::char::from_u32).parse_next(input) + // `take_while_m_n` 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_m_n(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, '}'), + ); + + // `map_res` 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.map_res(move |hex| u32::from_str_radix(hex, 16)); + + // map_opt is like map_res, but it takes an Option instead of a Result. If + // the function returns None, map_opt 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.map_opt(std::char::from_u32).parse_next(input) } /// 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>, + 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). - one_of('n').value('\n'), - one_of('r').value('\r'), - one_of('t').value('\t'), - one_of('b').value('\u{08}'), - one_of('f').value('\u{0C}'), - one_of('\\').value('\\'), - one_of('/').value('/'), - one_of('"').value('"'), - )), - )(input) + 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). + one_of('n').value('\n'), + one_of('r').value('\r'), + one_of('t').value('\t'), + one_of('b').value('\u{08}'), + one_of('f').value('\u{0C}'), + one_of('\\').value('\\'), + one_of('/').value('/'), + one_of('"').value('"'), + )), + )(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, + input: &'a str, ) -> IResult<&'a str, &'a str, E> { - preceded('\\', multispace1)(input) + preceded('\\', multispace1)(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 out 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) + // `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 out 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) } /// A string fragment contains a fragment of a string being parsed: either @@ -112,77 +112,77 @@ fn parse_literal<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, /// parsed escaped character, or a block of escaped whitespace. #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum StringFragment<'a> { - Literal(&'a str), - EscapedChar(char), - EscapedWS, + 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>, + 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), - ))(input) + 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), + ))(input) } /// Parse a string. Use a loop of `parse_fragment` and push all of the fragments /// into an output string. fn parse_string<'a, E>(input: &'a str) -> IResult<&'a str, String, E> where - E: ParseError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>, + E: ParseError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>, { - // fold_many0 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_many0( - // 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_many0), be sure that the - // loop won't accidentally match your closing delimiter! - delimited('"', build_string, '"')(input) + // fold_many0 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_many0( + // 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_many0), be sure that the + // loop won't accidentally match your closing delimiter! + delimited('"', build_string, '"')(input) } fn main() { - let data = "\"abc\""; - println!("EXAMPLE 1:\nParsing a simple input string: {}", data); - let result = parse_string::<()>(data); - assert_eq!(result, Ok(("", String::from("abc")))); - println!("Result: {}\n\n", result.unwrap().1); - - let data = "\"tab:\\tafter tab, newline:\\nnew line, quote: \\\", emoji: \\u{1F602}, newline:\\nescaped whitespace: \\ abc\""; - println!( + let data = "\"abc\""; + println!("EXAMPLE 1:\nParsing a simple input string: {}", data); + let result = parse_string::<()>(data); + assert_eq!(result, Ok(("", String::from("abc")))); + println!("Result: {}\n\n", result.unwrap().1); + + let data = "\"tab:\\tafter tab, newline:\\nnew line, quote: \\\", emoji: \\u{1F602}, newline:\\nescaped whitespace: \\ abc\""; + println!( "EXAMPLE 2:\nParsing a string with escape sequences, newline literal, and escaped whitespace:\n\n{}\n", data ); - let result = parse_string::<()>(data); - assert_eq!( + let result = parse_string::<()>(data); + assert_eq!( result, Ok(( "", String::from("tab:\tafter tab, newline:\nnew line, quote: \", emoji: 😂, newline:\nescaped whitespace: abc") )) ); - println!("Result:\n\n{}", result.unwrap().1); + println!("Result:\n\n{}", result.unwrap().1); } diff --git a/rustfmt.toml b/rustfmt.toml deleted file mode 100644 index 346c9d28..00000000 --- a/rustfmt.toml +++ /dev/null @@ -1,2 +0,0 @@ -tab_spaces = 2 -max_width = 100 diff --git a/src/bits/complete.rs b/src/bits/complete.rs index be1cc84d..38d5e242 100644 --- a/src/bits/complete.rs +++ b/src/bits/complete.rs @@ -36,64 +36,64 @@ use crate::IResult; /// **WARNING:** Deprecated, replaced with [`winnow::bits::take`][crate::bits::take] #[deprecated(since = "0.1.0", note = "Replaced with `winnow::bits::take`")] pub fn take>( - count: C, + count: C, ) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E> where - I: Input + AsBytes, - C: ToUsize, - O: From + AddAssign + Shl + Shr, + I: Input + AsBytes, + C: ToUsize, + O: From + AddAssign + Shl + Shr, { - let count = count.to_usize(); - move |input: (I, usize)| take_internal(input, count) + let count = count.to_usize(); + move |input: (I, usize)| take_internal(input, count) } pub(crate) fn take_internal>( - (input, bit_offset): (I, usize), - count: usize, + (input, bit_offset): (I, usize), + count: usize, ) -> IResult<(I, usize), O, E> where - I: Input + AsBytes, - O: From + AddAssign + Shl + Shr, + I: Input + AsBytes, + O: From + AddAssign + Shl + Shr, { - if count == 0 { - Ok(((input, bit_offset), 0u8.into())) - } else { - let cnt = (count + bit_offset).div(8); - if input.input_len() * 8 < count + bit_offset { - Err(ErrMode::from_error_kind( - (input, bit_offset), - ErrorKind::Eof, - )) + if count == 0 { + Ok(((input, bit_offset), 0u8.into())) } else { - let mut acc: O = 0_u8.into(); - let mut offset: usize = bit_offset; - let mut remaining: usize = count; - let mut end_offset: usize = 0; - - for byte in input.as_bytes().iter().copied().take(cnt + 1) { - if remaining == 0 { - break; - } - let val: O = if offset == 0 { - byte.into() - } else { - (byte << offset >> offset).into() - }; - - if remaining < 8 - offset { - acc += val >> (8 - offset - remaining); - end_offset = remaining + offset; - break; + let cnt = (count + bit_offset).div(8); + if input.input_len() * 8 < count + bit_offset { + Err(ErrMode::from_error_kind( + (input, bit_offset), + ErrorKind::Eof, + )) } else { - acc += val << (remaining - (8 - offset)); - remaining -= 8 - offset; - offset = 0; + let mut acc: O = 0_u8.into(); + let mut offset: usize = bit_offset; + let mut remaining: usize = count; + let mut end_offset: usize = 0; + + for byte in input.as_bytes().iter().copied().take(cnt + 1) { + if remaining == 0 { + break; + } + let val: O = if offset == 0 { + byte.into() + } else { + (byte << offset >> offset).into() + }; + + if remaining < 8 - offset { + acc += val >> (8 - offset - remaining); + end_offset = remaining + offset; + break; + } else { + acc += val << (remaining - (8 - offset)); + remaining -= 8 - offset; + offset = 0; + } + } + let (input, _) = input.next_slice(cnt); + Ok(((input, end_offset), acc)) } - } - let (input, _) = input.next_slice(cnt); - Ok(((input, end_offset), acc)) } - } } /// Generates a parser taking `count` bits and comparing them to `pattern` @@ -101,36 +101,36 @@ where /// **WARNING:** Deprecated, replaced with [`winnow::bits::tag`][crate::bits::tag] #[deprecated(since = "0.1.0", note = "Replaced with `winnow::bits::tag`")] pub fn tag>( - pattern: O, - count: C, + pattern: O, + count: C, ) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E> where - I: Input + AsBytes, - C: ToUsize, - O: From + AddAssign + Shl + Shr + PartialEq, + I: Input + AsBytes, + C: ToUsize, + O: From + AddAssign + Shl + Shr + PartialEq, { - let count = count.to_usize(); - move |input: (I, usize)| tag_internal(input, &pattern, count) + let count = count.to_usize(); + move |input: (I, usize)| tag_internal(input, &pattern, count) } pub(crate) fn tag_internal>( - input: (I, usize), - pattern: &O, - count: usize, + input: (I, usize), + pattern: &O, + count: usize, ) -> IResult<(I, usize), O, E> where - I: Input + AsBytes, - O: From + AddAssign + Shl + Shr + PartialEq, + I: Input + AsBytes, + O: From + AddAssign + Shl + Shr + PartialEq, { - let inp = input.clone(); + let inp = input.clone(); - take_internal(input, count).and_then(|(i, o)| { - if *pattern == o { - Ok((i, o)) - } else { - Err(ErrMode::Backtrack(error_position!(inp, ErrorKind::TagBits))) - } - }) + take_internal(input, count).and_then(|(i, o)| { + if *pattern == o { + Ok((i, o)) + } else { + Err(ErrMode::Backtrack(error_position!(inp, ErrorKind::TagBits))) + } + }) } /// Parses one specific bit as a bool. @@ -152,76 +152,76 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::bits::bool`")] pub fn bool>(input: (I, usize)) -> IResult<(I, usize), bool, E> where - I: Input + AsBytes, + I: Input + AsBytes, { - let (res, bit): (_, u32) = take(1usize)(input)?; - Ok((res, bit != 0)) + let (res, bit): (_, u32) = take(1usize)(input)?; + Ok((res, bit != 0)) } #[cfg(test)] mod test { - use super::*; - - #[test] - fn test_take_0() { - let input = [0b00010010].as_ref(); - let count = 0usize; - assert_eq!(count, 0usize); - let offset = 0usize; - - let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset)); - - assert_eq!(result, Ok(((input, offset), 0))); - } - - #[test] - fn test_take_eof() { - let input = [0b00010010].as_ref(); - - let result: crate::IResult<(&[u8], usize), usize> = take(1usize)((input, 8)); - - assert_eq!( - result, - Err(crate::error::ErrMode::Backtrack(crate::error::Error { - input: (input, 8), - kind: ErrorKind::Eof - })) - ); - } - - #[test] - fn test_take_span_over_multiple_bytes() { - let input = [0b00010010, 0b00110100, 0b11111111, 0b11111111].as_ref(); - - let result: crate::IResult<(&[u8], usize), usize> = take(24usize)((input, 4)); - - assert_eq!( - result, - Ok((([0b11111111].as_ref(), 4), 0b1000110100111111111111)) - ); - } - - #[test] - fn test_bool_0() { - let input = [0b10000000].as_ref(); - - let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0)); - - assert_eq!(result, Ok(((input, 1), true))); - } - - #[test] - fn test_bool_eof() { - let input = [0b10000000].as_ref(); - - let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8)); - - assert_eq!( - result, - Err(crate::error::ErrMode::Backtrack(crate::error::Error { - input: (input, 8), - kind: ErrorKind::Eof - })) - ); - } + use super::*; + + #[test] + fn test_take_0() { + let input = [0b00010010].as_ref(); + let count = 0usize; + assert_eq!(count, 0usize); + let offset = 0usize; + + let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset)); + + assert_eq!(result, Ok(((input, offset), 0))); + } + + #[test] + fn test_take_eof() { + let input = [0b00010010].as_ref(); + + let result: crate::IResult<(&[u8], usize), usize> = take(1usize)((input, 8)); + + assert_eq!( + result, + Err(crate::error::ErrMode::Backtrack(crate::error::Error { + input: (input, 8), + kind: ErrorKind::Eof + })) + ); + } + + #[test] + fn test_take_span_over_multiple_bytes() { + let input = [0b00010010, 0b00110100, 0b11111111, 0b11111111].as_ref(); + + let result: crate::IResult<(&[u8], usize), usize> = take(24usize)((input, 4)); + + assert_eq!( + result, + Ok((([0b11111111].as_ref(), 4), 0b1000110100111111111111)) + ); + } + + #[test] + fn test_bool_0() { + let input = [0b10000000].as_ref(); + + let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0)); + + assert_eq!(result, Ok(((input, 1), true))); + } + + #[test] + fn test_bool_eof() { + let input = [0b10000000].as_ref(); + + let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8)); + + assert_eq!( + result, + Err(crate::error::ErrMode::Backtrack(crate::error::Error { + input: (input, 8), + kind: ErrorKind::Eof + })) + ); + } } diff --git a/src/bits/mod.rs b/src/bits/mod.rs index d855b73d..76c95f4c 100644 --- a/src/bits/mod.rs +++ b/src/bits/mod.rs @@ -40,23 +40,23 @@ use crate::{IResult, Parser}; /// ``` pub fn bits(mut parser: P) -> impl FnMut(I) -> IResult where - E1: ParseError<(I, usize)> + ErrorConvert, - E2: ParseError, - I: Input, - P: Parser<(I, usize), O, E1>, + E1: ParseError<(I, usize)> + ErrorConvert, + E2: ParseError, + I: Input, + P: Parser<(I, usize), O, E1>, { - move |input: I| match parser.parse_next((input, 0)) { - Ok(((rest, offset), result)) => { - // If the next byte has been partially read, it will be sliced away as well. - // The parser functions might already slice away all fully read bytes. - // That's why `offset / 8` isn't necessarily needed at all times. - let remaining_bytes_index = offset / 8 + if offset % 8 == 0 { 0 } else { 1 }; - let (input, _) = rest.next_slice(remaining_bytes_index); - Ok((input, result)) + move |input: I| match parser.parse_next((input, 0)) { + Ok(((rest, offset), result)) => { + // If the next byte has been partially read, it will be sliced away as well. + // The parser functions might already slice away all fully read bytes. + // That's why `offset / 8` isn't necessarily needed at all times. + let remaining_bytes_index = offset / 8 + if offset % 8 == 0 { 0 } else { 1 }; + let (input, _) = rest.next_slice(remaining_bytes_index); + Ok((input, result)) + } + Err(ErrMode::Incomplete(n)) => Err(ErrMode::Incomplete(n.map(|u| u.get() / 8 + 1))), + Err(e) => Err(e.convert()), } - Err(ErrMode::Incomplete(n)) => Err(ErrMode::Incomplete(n.map(|u| u.get() / 8 + 1))), - Err(e) => Err(e.convert()), - } } /// Counterpart to `bits`, `bytes` transforms its bit stream input into a byte slice for the underlying @@ -85,28 +85,28 @@ where /// ``` pub fn bytes(mut parser: P) -> impl FnMut((I, usize)) -> IResult<(I, usize), O, E2> where - E1: ParseError + ErrorConvert, - E2: ParseError<(I, usize)>, - I: Input, - P: Parser, + E1: ParseError + ErrorConvert, + E2: ParseError<(I, usize)>, + I: Input, + P: Parser, { - move |(input, offset): (I, usize)| { - let (inner, _) = if offset % 8 != 0 { - input.next_slice(1 + offset / 8) - } else { - input.next_slice(offset / 8) - }; - let i = (input, offset); - match parser.parse_next(inner) { - Ok((rest, res)) => Ok(((rest, 0), res)), - Err(ErrMode::Incomplete(Needed::Unknown)) => Err(ErrMode::Incomplete(Needed::Unknown)), - Err(ErrMode::Incomplete(Needed::Size(sz))) => Err(match sz.get().checked_mul(8) { - Some(v) => ErrMode::Incomplete(Needed::new(v)), - None => ErrMode::Cut(E2::from_error_kind(i, ErrorKind::TooLarge)), - }), - Err(e) => Err(e.convert()), + move |(input, offset): (I, usize)| { + let (inner, _) = if offset % 8 != 0 { + input.next_slice(1 + offset / 8) + } else { + input.next_slice(offset / 8) + }; + let i = (input, offset); + match parser.parse_next(inner) { + Ok((rest, res)) => Ok(((rest, 0), res)), + Err(ErrMode::Incomplete(Needed::Unknown)) => Err(ErrMode::Incomplete(Needed::Unknown)), + Err(ErrMode::Incomplete(Needed::Size(sz))) => Err(match sz.get().checked_mul(8) { + Some(v) => ErrMode::Incomplete(Needed::new(v)), + None => ErrMode::Cut(E2::from_error_kind(i, ErrorKind::TooLarge)), + }), + Err(e) => Err(e.convert()), + } } - } } /// Generates a parser taking `count` bits @@ -135,21 +135,21 @@ where /// ``` #[inline(always)] pub fn take, const STREAMING: bool>( - count: C, + count: C, ) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E> where - I: Input + AsBytes + InputIsStreaming, - C: ToUsize, - O: From + AddAssign + Shl + Shr, + I: Input + AsBytes + InputIsStreaming, + C: ToUsize, + O: From + AddAssign + Shl + Shr, { - let count = count.to_usize(); - move |input: (I, usize)| { - if STREAMING { - streaming::take_internal(input, count) - } else { - complete::take_internal(input, count) + let count = count.to_usize(); + move |input: (I, usize)| { + if STREAMING { + streaming::take_internal(input, count) + } else { + complete::take_internal(input, count) + } } - } } /// Generates a parser taking `count` bits and comparing them to `pattern` @@ -198,22 +198,22 @@ where /// ``` #[inline(always)] pub fn tag, const STREAMING: bool>( - pattern: O, - count: C, + pattern: O, + count: C, ) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E> where - I: Input + AsBytes + InputIsStreaming, - C: ToUsize, - O: From + AddAssign + Shl + Shr + PartialEq, + I: Input + AsBytes + InputIsStreaming, + C: ToUsize, + O: From + AddAssign + Shl + Shr + PartialEq, { - let count = count.to_usize(); - move |input: (I, usize)| { - if STREAMING { - streaming::tag_internal(input, &pattern, count) - } else { - complete::tag_internal(input, &pattern, count) + let count = count.to_usize(); + move |input: (I, usize)| { + if STREAMING { + streaming::tag_internal(input, &pattern, count) + } else { + complete::tag_internal(input, &pattern, count) + } } - } } /// Parses one specific bit as a bool. @@ -233,15 +233,15 @@ where /// assert_eq!(parse(([0b10000000].as_ref(), 1)), Ok((([0b10000000].as_ref(), 2), false))); /// ``` pub fn bool, const STREAMING: bool>( - input: (I, usize), + input: (I, usize), ) -> IResult<(I, usize), bool, E> where - I: Input + AsBytes + InputIsStreaming, + I: Input + AsBytes + InputIsStreaming, { - #![allow(deprecated)] - if STREAMING { - streaming::bool(input) - } else { - complete::bool(input) - } + #![allow(deprecated)] + if STREAMING { + streaming::bool(input) + } else { + complete::bool(input) + } } diff --git a/src/bits/streaming.rs b/src/bits/streaming.rs index de5cad59..25e0b892 100644 --- a/src/bits/streaming.rs +++ b/src/bits/streaming.rs @@ -12,105 +12,105 @@ use crate::IResult; /// /// **WARNING:** Deprecated, replaced with [`winnow::bits::take`][crate::bits::take] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::bits::take` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::bits::take` with input wrapped in `winnow::input::Streaming`" )] pub fn take>( - count: C, + count: C, ) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E> where - I: Input + AsBytes, - C: ToUsize, - O: From + AddAssign + Shl + Shr, + I: Input + AsBytes, + C: ToUsize, + O: From + AddAssign + Shl + Shr, { - let count = count.to_usize(); - move |input: (I, usize)| take_internal(input, count) + let count = count.to_usize(); + move |input: (I, usize)| take_internal(input, count) } pub(crate) fn take_internal>( - (input, bit_offset): (I, usize), - count: usize, + (input, bit_offset): (I, usize), + count: usize, ) -> IResult<(I, usize), O, E> where - I: Input + AsBytes, - O: From + AddAssign + Shl + Shr, + I: Input + AsBytes, + O: From + AddAssign + Shl + Shr, { - if count == 0 { - Ok(((input, bit_offset), 0u8.into())) - } else { - let cnt = (count + bit_offset).div(8); - if input.input_len() * 8 < count + bit_offset { - Err(ErrMode::Incomplete(Needed::new(count))) + if count == 0 { + Ok(((input, bit_offset), 0u8.into())) } else { - let mut acc: O = 0_u8.into(); - let mut offset: usize = bit_offset; - let mut remaining: usize = count; - let mut end_offset: usize = 0; - - for byte in input.as_bytes().iter().copied().take(cnt + 1) { - if remaining == 0 { - break; - } - let val: O = if offset == 0 { - byte.into() - } else { - (byte << offset >> offset).into() - }; - - if remaining < 8 - offset { - acc += val >> (8 - offset - remaining); - end_offset = remaining + offset; - break; + let cnt = (count + bit_offset).div(8); + if input.input_len() * 8 < count + bit_offset { + Err(ErrMode::Incomplete(Needed::new(count))) } else { - acc += val << (remaining - (8 - offset)); - remaining -= 8 - offset; - offset = 0; + let mut acc: O = 0_u8.into(); + let mut offset: usize = bit_offset; + let mut remaining: usize = count; + let mut end_offset: usize = 0; + + for byte in input.as_bytes().iter().copied().take(cnt + 1) { + if remaining == 0 { + break; + } + let val: O = if offset == 0 { + byte.into() + } else { + (byte << offset >> offset).into() + }; + + if remaining < 8 - offset { + acc += val >> (8 - offset - remaining); + end_offset = remaining + offset; + break; + } else { + acc += val << (remaining - (8 - offset)); + remaining -= 8 - offset; + offset = 0; + } + } + let (input, _) = input.next_slice(cnt); + Ok(((input, end_offset), acc)) } - } - let (input, _) = input.next_slice(cnt); - Ok(((input, end_offset), acc)) } - } } /// Generates a parser taking `count` bits and comparing them to `pattern` /// /// **WARNING:** Deprecated, replaced with [`winnow::bits::tag`][crate::bits::tag] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::bits::tag` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::bits::tag` with input wrapped in `winnow::input::Streaming`" )] pub fn tag>( - pattern: O, - count: C, + pattern: O, + count: C, ) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E> where - I: Input + AsBytes, - C: ToUsize, - O: From + AddAssign + Shl + Shr + PartialEq, + I: Input + AsBytes, + C: ToUsize, + O: From + AddAssign + Shl + Shr + PartialEq, { - let count = count.to_usize(); - move |input: (I, usize)| tag_internal(input, &pattern, count) + let count = count.to_usize(); + move |input: (I, usize)| tag_internal(input, &pattern, count) } pub(crate) fn tag_internal>( - input: (I, usize), - pattern: &O, - count: usize, + input: (I, usize), + pattern: &O, + count: usize, ) -> IResult<(I, usize), O, E> where - I: Input + AsBytes, - O: From + AddAssign + Shl + Shr + PartialEq, + I: Input + AsBytes, + O: From + AddAssign + Shl + Shr + PartialEq, { - let inp = input.clone(); + let inp = input.clone(); - take(count)(input).and_then(|(i, o)| { - if *pattern == o { - Ok((i, o)) - } else { - Err(ErrMode::Backtrack(error_position!(inp, ErrorKind::TagBits))) - } - }) + take(count)(input).and_then(|(i, o)| { + if *pattern == o { + Ok((i, o)) + } else { + Err(ErrMode::Backtrack(error_position!(inp, ErrorKind::TagBits))) + } + }) } /// Parses one specific bit as a bool. @@ -132,78 +132,78 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::bits::bool`")] pub fn bool>(input: (I, usize)) -> IResult<(I, usize), bool, E> where - I: Input + AsBytes, + I: Input + AsBytes, { - let (res, bit): (_, u32) = take(1usize)(input)?; - Ok((res, bit != 0)) + let (res, bit): (_, u32) = take(1usize)(input)?; + Ok((res, bit != 0)) } #[cfg(test)] mod test { - use super::*; - - #[test] - fn test_take_0() { - let input = [].as_ref(); - let count = 0usize; - assert_eq!(count, 0usize); - let offset = 0usize; - - let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset)); - - assert_eq!(result, Ok(((input, offset), 0))); - } - - #[test] - fn test_tag_ok() { - let input = [0b00011111].as_ref(); - let offset = 0usize; - let bits_to_take = 4usize; - let value_to_tag = 0b0001; - - let result: crate::IResult<(&[u8], usize), usize> = - tag(value_to_tag, bits_to_take)((input, offset)); - - assert_eq!(result, Ok(((input, bits_to_take), value_to_tag))); - } - - #[test] - fn test_tag_err() { - let input = [0b00011111].as_ref(); - let offset = 0usize; - let bits_to_take = 4usize; - let value_to_tag = 0b1111; - - let result: crate::IResult<(&[u8], usize), usize> = - tag(value_to_tag, bits_to_take)((input, offset)); - - assert_eq!( - result, - Err(crate::error::ErrMode::Backtrack(crate::error::Error { - input: (input, offset), - kind: ErrorKind::TagBits - })) - ); - } - - #[test] - fn test_bool_0() { - let input = [0b10000000].as_ref(); - - let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0)); - - assert_eq!(result, Ok(((input, 1), true))); - } - - #[test] - fn test_bool_eof() { - let input = [0b10000000].as_ref(); - - let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8)); - - assert_eq!( - result, - Err(crate::error::ErrMode::Incomplete(Needed::new(1))) - ); - } + use super::*; + + #[test] + fn test_take_0() { + let input = [].as_ref(); + let count = 0usize; + assert_eq!(count, 0usize); + let offset = 0usize; + + let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset)); + + assert_eq!(result, Ok(((input, offset), 0))); + } + + #[test] + fn test_tag_ok() { + let input = [0b00011111].as_ref(); + let offset = 0usize; + let bits_to_take = 4usize; + let value_to_tag = 0b0001; + + let result: crate::IResult<(&[u8], usize), usize> = + tag(value_to_tag, bits_to_take)((input, offset)); + + assert_eq!(result, Ok(((input, bits_to_take), value_to_tag))); + } + + #[test] + fn test_tag_err() { + let input = [0b00011111].as_ref(); + let offset = 0usize; + let bits_to_take = 4usize; + let value_to_tag = 0b1111; + + let result: crate::IResult<(&[u8], usize), usize> = + tag(value_to_tag, bits_to_take)((input, offset)); + + assert_eq!( + result, + Err(crate::error::ErrMode::Backtrack(crate::error::Error { + input: (input, offset), + kind: ErrorKind::TagBits + })) + ); + } + + #[test] + fn test_bool_0() { + let input = [0b10000000].as_ref(); + + let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0)); + + assert_eq!(result, Ok(((input, 1), true))); + } + + #[test] + fn test_bool_eof() { + let input = [0b10000000].as_ref(); + + let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8)); + + assert_eq!( + result, + Err(crate::error::ErrMode::Incomplete(Needed::new(1))) + ); + } } diff --git a/src/bits/tests.rs b/src/bits/tests.rs index e6197344..3ee630ca 100644 --- a/src/bits/tests.rs +++ b/src/bits/tests.rs @@ -6,21 +6,23 @@ use crate::input::Streaming; /// Take the `bits` function and assert that remaining bytes are correctly returned, if the /// previous bytes are fully consumed fn test_complete_byte_consumption_bits() { - let input = &[0x12, 0x34, 0x56, 0x78][..]; + let input = &[0x12, 0x34, 0x56, 0x78][..]; - // Take 3 bit slices with sizes [4, 8, 4]. - let result: IResult<&[u8], (u8, u8, u8)> = - bits::<_, _, Error<(&[u8], usize)>, _, _>((take(4usize), take(8usize), take(4usize)))(input); + // Take 3 bit slices with sizes [4, 8, 4]. + let result: IResult<&[u8], (u8, u8, u8)> = + bits::<_, _, Error<(&[u8], usize)>, _, _>((take(4usize), take(8usize), take(4usize)))( + input, + ); - let output = result.expect("We take 2 bytes and the input is longer than 2 bytes"); + let output = result.expect("We take 2 bytes and the input is longer than 2 bytes"); - let remaining = output.0; - assert_eq!(remaining, [0x56, 0x78]); + let remaining = output.0; + assert_eq!(remaining, [0x56, 0x78]); - let parsed = output.1; - assert_eq!(parsed.0, 0x01); - assert_eq!(parsed.1, 0x23); - assert_eq!(parsed.2, 0x04); + let parsed = output.1; + assert_eq!(parsed.0, 0x01); + assert_eq!(parsed.1, 0x23); + assert_eq!(parsed.2, 0x04); } #[test] @@ -29,159 +31,161 @@ fn test_complete_byte_consumption_bits() { /// I.e. if we consume 1.5 bytes of 4 bytes, 2 bytes will be returned, bits 13-16 will be /// dropped. fn test_partial_byte_consumption_bits() { - let input = &[0x12, 0x34, 0x56, 0x78][..]; + let input = &[0x12, 0x34, 0x56, 0x78][..]; - // Take bit slices with sizes [4, 8]. - let result: IResult<&[u8], (u8, u8)> = - bits::<_, _, Error<(&[u8], usize)>, _, _>((take(4usize), take(8usize)))(input); + // Take bit slices with sizes [4, 8]. + let result: IResult<&[u8], (u8, u8)> = + bits::<_, _, Error<(&[u8], usize)>, _, _>((take(4usize), take(8usize)))(input); - let output = result.expect("We take 1.5 bytes and the input is longer than 2 bytes"); + let output = result.expect("We take 1.5 bytes and the input is longer than 2 bytes"); - let remaining = output.0; - assert_eq!(remaining, [0x56, 0x78]); + let remaining = output.0; + assert_eq!(remaining, [0x56, 0x78]); - let parsed = output.1; - assert_eq!(parsed.0, 0x01); - assert_eq!(parsed.1, 0x23); + let parsed = output.1; + assert_eq!(parsed.0, 0x01); + assert_eq!(parsed.1, 0x23); } #[test] #[cfg(feature = "std")] /// Ensure that in Incomplete error is thrown, if too few bytes are passed for a given parser. fn test_incomplete_bits() { - let input = Streaming(&[0x12][..]); + let input = Streaming(&[0x12][..]); - // Take bit slices with sizes [4, 8]. - let result: IResult<_, (u8, u8)> = - bits::<_, _, Error<(_, usize)>, _, _>((take(4usize), take(8usize)))(input); + // Take bit slices with sizes [4, 8]. + let result: IResult<_, (u8, u8)> = + bits::<_, _, Error<(_, usize)>, _, _>((take(4usize), take(8usize)))(input); - assert!(result.is_err()); - let error = result.err().unwrap(); - assert_eq!("Parsing requires 2 bytes/chars", error.to_string()); + assert!(result.is_err()); + let error = result.err().unwrap(); + assert_eq!("Parsing requires 2 bytes/chars", error.to_string()); } #[test] fn test_take_complete_0() { - let input = &[0b00010010][..]; - let count = 0usize; - assert_eq!(count, 0usize); - let offset = 0usize; + let input = &[0b00010010][..]; + let count = 0usize; + assert_eq!(count, 0usize); + let offset = 0usize; - let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset)); + let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset)); - assert_eq!(result, Ok(((input, offset), 0))); + assert_eq!(result, Ok(((input, offset), 0))); } #[test] fn test_take_complete_eof() { - let input = &[0b00010010][..]; + let input = &[0b00010010][..]; - let result: crate::IResult<(&[u8], usize), usize> = take(1usize)((input, 8)); + let result: crate::IResult<(&[u8], usize), usize> = take(1usize)((input, 8)); - assert_eq!( - result, - Err(crate::error::ErrMode::Backtrack(crate::error::Error { - input: (input, 8), - kind: ErrorKind::Eof - })) - ); + assert_eq!( + result, + Err(crate::error::ErrMode::Backtrack(crate::error::Error { + input: (input, 8), + kind: ErrorKind::Eof + })) + ); } #[test] fn test_take_complete_span_over_multiple_bytes() { - let input = &[0b00010010, 0b00110100, 0b11111111, 0b11111111][..]; + let input = &[0b00010010, 0b00110100, 0b11111111, 0b11111111][..]; - let result: crate::IResult<(&[u8], usize), usize> = take(24usize)((input, 4)); + let result: crate::IResult<(&[u8], usize), usize> = take(24usize)((input, 4)); - assert_eq!( - result, - Ok((([0b11111111].as_ref(), 4), 0b1000110100111111111111)) - ); + assert_eq!( + result, + Ok((([0b11111111].as_ref(), 4), 0b1000110100111111111111)) + ); } #[test] fn test_take_streaming_0() { - let input = Streaming(&[][..]); - let count = 0usize; - assert_eq!(count, 0usize); - let offset = 0usize; + let input = Streaming(&[][..]); + let count = 0usize; + assert_eq!(count, 0usize); + let offset = 0usize; - let result: crate::IResult<(_, usize), usize> = take(count)((input, offset)); + let result: crate::IResult<(_, usize), usize> = take(count)((input, offset)); - assert_eq!(result, Ok(((input, offset), 0))); + assert_eq!(result, Ok(((input, offset), 0))); } #[test] fn test_tag_streaming_ok() { - let input = Streaming(&[0b00011111][..]); - let offset = 0usize; - let bits_to_take = 4usize; - let value_to_tag = 0b0001; + let input = Streaming(&[0b00011111][..]); + let offset = 0usize; + let bits_to_take = 4usize; + let value_to_tag = 0b0001; - let result: crate::IResult<(_, usize), usize> = tag(value_to_tag, bits_to_take)((input, offset)); + let result: crate::IResult<(_, usize), usize> = + tag(value_to_tag, bits_to_take)((input, offset)); - assert_eq!(result, Ok(((input, bits_to_take), value_to_tag))); + assert_eq!(result, Ok(((input, bits_to_take), value_to_tag))); } #[test] fn test_tag_streaming_err() { - let input = Streaming(&[0b00011111][..]); - let offset = 0usize; - let bits_to_take = 4usize; - let value_to_tag = 0b1111; - - let result: crate::IResult<(_, usize), usize> = tag(value_to_tag, bits_to_take)((input, offset)); - - assert_eq!( - result, - Err(crate::error::ErrMode::Backtrack(crate::error::Error { - input: (input, offset), - kind: ErrorKind::TagBits - })) - ); + let input = Streaming(&[0b00011111][..]); + let offset = 0usize; + let bits_to_take = 4usize; + let value_to_tag = 0b1111; + + let result: crate::IResult<(_, usize), usize> = + tag(value_to_tag, bits_to_take)((input, offset)); + + assert_eq!( + result, + Err(crate::error::ErrMode::Backtrack(crate::error::Error { + input: (input, offset), + kind: ErrorKind::TagBits + })) + ); } #[test] fn test_bool_0_complete() { - let input = [0b10000000].as_ref(); + let input = [0b10000000].as_ref(); - let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0)); + let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0)); - assert_eq!(result, Ok(((input, 1), true))); + assert_eq!(result, Ok(((input, 1), true))); } #[test] fn test_bool_eof_complete() { - let input = [0b10000000].as_ref(); + let input = [0b10000000].as_ref(); - let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8)); + let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8)); - assert_eq!( - result, - Err(crate::error::ErrMode::Backtrack(crate::error::Error { - input: (input, 8), - kind: ErrorKind::Eof - })) - ); + assert_eq!( + result, + Err(crate::error::ErrMode::Backtrack(crate::error::Error { + input: (input, 8), + kind: ErrorKind::Eof + })) + ); } #[test] fn test_bool_0_streaming() { - let input = Streaming([0b10000000].as_ref()); + let input = Streaming([0b10000000].as_ref()); - let result: crate::IResult<(Streaming<&[u8]>, usize), bool> = bool((input, 0)); + let result: crate::IResult<(Streaming<&[u8]>, usize), bool> = bool((input, 0)); - assert_eq!(result, Ok(((input, 1), true))); + assert_eq!(result, Ok(((input, 1), true))); } #[test] fn test_bool_eof_streaming() { - let input = Streaming([0b10000000].as_ref()); + let input = Streaming([0b10000000].as_ref()); - let result: crate::IResult<(Streaming<&[u8]>, usize), bool> = bool((input, 8)); + let result: crate::IResult<(Streaming<&[u8]>, usize), bool> = bool((input, 8)); - assert_eq!( - result, - Err(crate::error::ErrMode::Incomplete(Needed::new(1))) - ); + assert_eq!( + result, + Err(crate::error::ErrMode::Incomplete(Needed::new(1))) + ); } diff --git a/src/branch/mod.rs b/src/branch/mod.rs index 1d913622..7ad431df 100644 --- a/src/branch/mod.rs +++ b/src/branch/mod.rs @@ -15,8 +15,8 @@ pub use crate::dispatch; /// /// This trait is implemented for tuples of up to 21 elements pub trait Alt { - /// Tests each parser in the tuple and returns the result of the first one that succeeds - fn choice(&mut self, input: I) -> IResult; + /// Tests each parser in the tuple and returns the result of the first one that succeeds + fn choice(&mut self, input: I) -> IResult; } /// Tests a list of parsers one by one until one succeeds. @@ -54,17 +54,17 @@ pub trait Alt { /// # } /// ``` pub fn alt, List: Alt>( - mut l: List, + mut l: List, ) -> impl FnMut(I) -> IResult { - move |i: I| l.choice(i) + move |i: I| l.choice(i) } /// Helper trait for the [permutation()] combinator. /// /// This trait is implemented for tuples of up to 21 elements pub trait Permutation { - /// Tries to apply all parsers in the tuple in various orders until all of them succeed - fn permutation(&mut self, input: I) -> IResult; + /// Tries to apply all parsers in the tuple in various orders until all of them succeed + fn permutation(&mut self, input: I) -> IResult; } /// Applies a list of parsers in any order. @@ -113,9 +113,9 @@ pub trait Permutation { /// ``` /// pub fn permutation, List: Permutation>( - mut l: List, + mut l: List, ) -> impl FnMut(I) -> IResult { - move |i: I| l.permutation(i) + move |i: I| l.permutation(i) } macro_rules! alt_trait( @@ -169,9 +169,9 @@ alt_trait!(Alt2 Alt3 Alt4 Alt5 Alt6 Alt7 Alt8 Alt9 Alt10 Alt11 Alt12 Alt13 Alt14 // Manually implement Alt for (A,), the 1-tuple type impl, A: Parser> Alt for (A,) { - fn choice(&mut self, input: I) -> IResult { - self.0.parse_next(input) - } + fn choice(&mut self, input: I) -> IResult { + self.0.parse_next(input) + } } macro_rules! permutation_trait( diff --git a/src/branch/tests.rs b/src/branch/tests.rs index e7c225da..9f535c3a 100644 --- a/src/branch/tests.rs +++ b/src/branch/tests.rs @@ -7,11 +7,11 @@ use crate::input::Streaming; use crate::IResult; #[cfg(feature = "alloc")] use crate::{ - error::ParseError, - lib::std::{ - fmt::Debug, - string::{String, ToString}, - }, + error::ParseError, + lib::std::{ + fmt::Debug, + string::{String, ToString}, + }, }; #[cfg(feature = "alloc")] @@ -20,133 +20,133 @@ pub struct ErrorStr(String); #[cfg(feature = "alloc")] impl From for ErrorStr { - fn from(i: u32) -> Self { - ErrorStr(format!("custom error code: {}", i)) - } + fn from(i: u32) -> Self { + ErrorStr(format!("custom error code: {}", i)) + } } #[cfg(feature = "alloc")] impl<'a> From<&'a str> for ErrorStr { - fn from(i: &'a str) -> Self { - ErrorStr(format!("custom error message: {}", i)) - } + fn from(i: &'a str) -> Self { + ErrorStr(format!("custom error message: {}", i)) + } } #[cfg(feature = "alloc")] impl ParseError for ErrorStr { - fn from_error_kind(input: I, kind: ErrorKind) -> Self { - ErrorStr(format!("custom error message: ({:?}, {:?})", input, kind)) - } - - fn append(self, input: I, kind: ErrorKind) -> Self { - ErrorStr(format!( - "custom error message: ({:?}, {:?}) - {:?}", - input, kind, self - )) - } + fn from_error_kind(input: I, kind: ErrorKind) -> Self { + ErrorStr(format!("custom error message: ({:?}, {:?})", input, kind)) + } + + fn append(self, input: I, kind: ErrorKind) -> Self { + ErrorStr(format!( + "custom error message: ({:?}, {:?}) - {:?}", + input, kind, self + )) + } } #[cfg(feature = "alloc")] #[test] fn alt_test() { - fn work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { - Ok((&b""[..], input)) - } - - #[allow(unused_variables)] - fn dont_work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { - Err(ErrMode::Backtrack(ErrorStr("abcd".to_string()))) - } - - fn work2(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { - Ok((input, &b""[..])) - } - - fn alt1(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { - alt((dont_work, dont_work))(i) - } - fn alt2(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { - alt((dont_work, work))(i) - } - fn alt3(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { - alt((dont_work, dont_work, work2, dont_work))(i) - } - //named!(alt1, alt!(dont_work | dont_work)); - //named!(alt2, alt!(dont_work | work)); - //named!(alt3, alt!(dont_work | dont_work | work2 | dont_work)); - - let a = &b"abcd"[..]; - assert_eq!( - alt1(a), - Err(ErrMode::Backtrack(error_node_position!( - a, - ErrorKind::Alt, - ErrorStr("abcd".to_string()) - ))) - ); - assert_eq!(alt2(a), Ok((&b""[..], a))); - assert_eq!(alt3(a), Ok((a, &b""[..]))); - - fn alt4(i: &[u8]) -> IResult<&[u8], &[u8]> { - alt((tag("abcd"), tag("efgh")))(i) - } - let b = &b"efgh"[..]; - assert_eq!(alt4(a), Ok((&b""[..], a))); - assert_eq!(alt4(b), Ok((&b""[..], b))); + fn work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { + Ok((&b""[..], input)) + } + + #[allow(unused_variables)] + fn dont_work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { + Err(ErrMode::Backtrack(ErrorStr("abcd".to_string()))) + } + + fn work2(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { + Ok((input, &b""[..])) + } + + fn alt1(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { + alt((dont_work, dont_work))(i) + } + fn alt2(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { + alt((dont_work, work))(i) + } + fn alt3(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> { + alt((dont_work, dont_work, work2, dont_work))(i) + } + //named!(alt1, alt!(dont_work | dont_work)); + //named!(alt2, alt!(dont_work | work)); + //named!(alt3, alt!(dont_work | dont_work | work2 | dont_work)); + + let a = &b"abcd"[..]; + assert_eq!( + alt1(a), + Err(ErrMode::Backtrack(error_node_position!( + a, + ErrorKind::Alt, + ErrorStr("abcd".to_string()) + ))) + ); + assert_eq!(alt2(a), Ok((&b""[..], a))); + assert_eq!(alt3(a), Ok((a, &b""[..]))); + + fn alt4(i: &[u8]) -> IResult<&[u8], &[u8]> { + alt((tag("abcd"), tag("efgh")))(i) + } + let b = &b"efgh"[..]; + assert_eq!(alt4(a), Ok((&b""[..], a))); + assert_eq!(alt4(b), Ok((&b""[..], b))); } #[test] fn alt_incomplete() { - fn alt1(i: Streaming<&[u8]>) -> IResult, &[u8]> { - alt((tag("a"), tag("bc"), tag("def")))(i) - } - - let a = &b""[..]; - assert_eq!(alt1(Streaming(a)), Err(ErrMode::Incomplete(Needed::new(1)))); - let a = &b"b"[..]; - assert_eq!(alt1(Streaming(a)), Err(ErrMode::Incomplete(Needed::new(1)))); - let a = &b"bcd"[..]; - assert_eq!(alt1(Streaming(a)), Ok((Streaming(&b"d"[..]), &b"bc"[..]))); - let a = &b"cde"[..]; - assert_eq!( - alt1(Streaming(a)), - Err(ErrMode::Backtrack(error_position!( - Streaming(a), - ErrorKind::Tag - ))) - ); - let a = &b"de"[..]; - assert_eq!(alt1(Streaming(a)), Err(ErrMode::Incomplete(Needed::new(1)))); - let a = &b"defg"[..]; - assert_eq!(alt1(Streaming(a)), Ok((Streaming(&b"g"[..]), &b"def"[..]))); + fn alt1(i: Streaming<&[u8]>) -> IResult, &[u8]> { + alt((tag("a"), tag("bc"), tag("def")))(i) + } + + let a = &b""[..]; + assert_eq!(alt1(Streaming(a)), Err(ErrMode::Incomplete(Needed::new(1)))); + let a = &b"b"[..]; + assert_eq!(alt1(Streaming(a)), Err(ErrMode::Incomplete(Needed::new(1)))); + let a = &b"bcd"[..]; + assert_eq!(alt1(Streaming(a)), Ok((Streaming(&b"d"[..]), &b"bc"[..]))); + let a = &b"cde"[..]; + assert_eq!( + alt1(Streaming(a)), + Err(ErrMode::Backtrack(error_position!( + Streaming(a), + ErrorKind::Tag + ))) + ); + let a = &b"de"[..]; + assert_eq!(alt1(Streaming(a)), Err(ErrMode::Incomplete(Needed::new(1)))); + let a = &b"defg"[..]; + assert_eq!(alt1(Streaming(a)), Ok((Streaming(&b"g"[..]), &b"def"[..]))); } #[test] fn permutation_test() { - #[allow(clippy::type_complexity)] - fn perm(i: Streaming<&[u8]>) -> IResult, (&[u8], &[u8], &[u8])> { - permutation((tag("abcd"), tag("efg"), tag("hi")))(i) - } - - let expected = (&b"abcd"[..], &b"efg"[..], &b"hi"[..]); - - let a = &b"abcdefghijk"[..]; - assert_eq!(perm(Streaming(a)), Ok((Streaming(&b"jk"[..]), expected))); - let b = &b"efgabcdhijk"[..]; - assert_eq!(perm(Streaming(b)), Ok((Streaming(&b"jk"[..]), expected))); - let c = &b"hiefgabcdjk"[..]; - assert_eq!(perm(Streaming(c)), Ok((Streaming(&b"jk"[..]), expected))); - - let d = &b"efgxyzabcdefghi"[..]; - assert_eq!( - perm(Streaming(d)), - Err(ErrMode::Backtrack(error_node_position!( - Streaming(&b"efgxyzabcdefghi"[..]), - ErrorKind::Permutation, - error_position!(Streaming(&b"xyzabcdefghi"[..]), ErrorKind::Tag) - ))) - ); - - let e = &b"efgabc"[..]; - assert_eq!(perm(Streaming(e)), Err(ErrMode::Incomplete(Needed::new(1)))); + #[allow(clippy::type_complexity)] + fn perm(i: Streaming<&[u8]>) -> IResult, (&[u8], &[u8], &[u8])> { + permutation((tag("abcd"), tag("efg"), tag("hi")))(i) + } + + let expected = (&b"abcd"[..], &b"efg"[..], &b"hi"[..]); + + let a = &b"abcdefghijk"[..]; + assert_eq!(perm(Streaming(a)), Ok((Streaming(&b"jk"[..]), expected))); + let b = &b"efgabcdhijk"[..]; + assert_eq!(perm(Streaming(b)), Ok((Streaming(&b"jk"[..]), expected))); + let c = &b"hiefgabcdjk"[..]; + assert_eq!(perm(Streaming(c)), Ok((Streaming(&b"jk"[..]), expected))); + + let d = &b"efgxyzabcdefghi"[..]; + assert_eq!( + perm(Streaming(d)), + Err(ErrMode::Backtrack(error_node_position!( + Streaming(&b"efgxyzabcdefghi"[..]), + ErrorKind::Permutation, + error_position!(Streaming(&b"xyzabcdefghi"[..]), ErrorKind::Tag) + ))) + ); + + let e = &b"efgabc"[..]; + assert_eq!(perm(Streaming(e)), Err(ErrMode::Incomplete(Needed::new(1)))); } diff --git a/src/bytes/complete.rs b/src/bytes/complete.rs index f81f3d69..8301c94f 100644 --- a/src/bytes/complete.rs +++ b/src/bytes/complete.rs @@ -6,19 +6,19 @@ use crate::error::ErrMode; use crate::error::ErrorKind; use crate::error::ParseError; use crate::input::{ - split_at_offset1_complete, split_at_offset_complete, Compare, CompareResult, ContainsToken, - FindSlice, Input, Offset, SliceLen, ToUsize, + split_at_offset1_complete, split_at_offset_complete, Compare, CompareResult, ContainsToken, + FindSlice, Input, Offset, SliceLen, ToUsize, }; use crate::lib::std::result::Result::Ok; use crate::{IResult, Parser}; pub(crate) fn any>(input: I) -> IResult::Token, E> where - I: Input, + I: Input, { - input - .next_token() - .ok_or_else(|| ErrMode::from_error_kind(input, ErrorKind::Eof)) + input + .next_token() + .ok_or_else(|| ErrMode::from_error_kind(input, ErrorKind::Eof)) } /// Recognizes a pattern @@ -44,31 +44,31 @@ where /// **WARNING:** Deprecated, replaced with [`winnow::bytes::tag`][crate::bytes::tag] #[deprecated(since = "0.1.0", note = "Replaced with `winnow::bytes::tag`")] pub fn tag>( - tag: T, + tag: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input + Compare, - T: SliceLen + Clone, + I: Input + Compare, + T: SliceLen + Clone, { - move |i: I| tag_internal(i, tag.clone()) + move |i: I| tag_internal(i, tag.clone()) } pub(crate) fn tag_internal>( - i: I, - t: T, + i: I, + t: T, ) -> IResult::Slice, Error> where - I: Input + Compare, - T: SliceLen, + I: Input + Compare, + T: SliceLen, { - let tag_len = t.slice_len(); - match i.compare(t) { - CompareResult::Ok => Ok(i.next_slice(tag_len)), - CompareResult::Incomplete | CompareResult::Error => { - let e: ErrorKind = ErrorKind::Tag; - Err(ErrMode::from_error_kind(i, e)) + let tag_len = t.slice_len(); + match i.compare(t) { + CompareResult::Ok => Ok(i.next_slice(tag_len)), + CompareResult::Incomplete | CompareResult::Error => { + let e: ErrorKind = ErrorKind::Tag; + Err(ErrMode::from_error_kind(i, e)) + } } - } } /// Recognizes a case insensitive pattern. @@ -96,62 +96,62 @@ where /// **WARNING:** Deprecated, replaced with [`winnow::bytes::tag_no_case`][crate::bytes::tag_no_case] #[deprecated(since = "0.1.0", note = "Replaced with `winnow::bytes::tag_no_case`")] pub fn tag_no_case>( - tag: T, + tag: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input + Compare, - T: SliceLen + Clone, + I: Input + Compare, + T: SliceLen + Clone, { - move |i: I| tag_no_case_internal(i, tag.clone()) + move |i: I| tag_no_case_internal(i, tag.clone()) } pub(crate) fn tag_no_case_internal>( - i: I, - t: T, + i: I, + t: T, ) -> IResult::Slice, Error> where - I: Input + Compare, - T: SliceLen, + I: Input + Compare, + T: SliceLen, { - let tag_len = t.slice_len(); + let tag_len = t.slice_len(); - match (i).compare_no_case(t) { - CompareResult::Ok => Ok(i.next_slice(tag_len)), - CompareResult::Incomplete | CompareResult::Error => { - let e: ErrorKind = ErrorKind::Tag; - Err(ErrMode::from_error_kind(i, e)) + match (i).compare_no_case(t) { + CompareResult::Ok => Ok(i.next_slice(tag_len)), + CompareResult::Incomplete | CompareResult::Error => { + let e: ErrorKind = ErrorKind::Tag; + Err(ErrMode::from_error_kind(i, e)) + } } - } } pub(crate) fn one_of_internal>( - input: I, - list: &T, + input: I, + list: &T, ) -> IResult::Token, E> where - I: Input, - ::Token: Copy, - T: ContainsToken<::Token>, + I: Input, + ::Token: Copy, + T: ContainsToken<::Token>, { - input - .next_token() - .filter(|(_, t)| list.contains_token(*t)) - .ok_or_else(|| ErrMode::from_error_kind(input, ErrorKind::OneOf)) + input + .next_token() + .filter(|(_, t)| list.contains_token(*t)) + .ok_or_else(|| ErrMode::from_error_kind(input, ErrorKind::OneOf)) } pub(crate) fn none_of_internal>( - input: I, - list: &T, + input: I, + list: &T, ) -> IResult::Token, E> where - I: Input, - ::Token: Copy, - T: ContainsToken<::Token>, + I: Input, + ::Token: Copy, + T: ContainsToken<::Token>, { - input - .next_token() - .filter(|(_, t)| !list.contains_token(*t)) - .ok_or_else(|| ErrMode::from_error_kind(input, ErrorKind::NoneOf)) + input + .next_token() + .filter(|(_, t)| !list.contains_token(*t)) + .ok_or_else(|| ErrMode::from_error_kind(input, ErrorKind::NoneOf)) } /// Parse till certain characters are met. @@ -179,25 +179,25 @@ where /// **WARNING:** Deprecated, replaced with [`winnow::bytes::take_till1`][crate::bytes::take_till1] #[deprecated(since = "0.1.0", note = "Replaced with `winnow::bytes::take_till1`")] pub fn is_not>( - arr: T, + arr: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - move |i: I| is_not_internal(i, &arr) + move |i: I| is_not_internal(i, &arr) } pub(crate) fn is_not_internal>( - i: I, - arr: &T, + i: I, + arr: &T, ) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - let e: ErrorKind = ErrorKind::IsNot; - split_at_offset1_complete(&i, |c| arr.contains_token(c), e) + let e: ErrorKind = ErrorKind::IsNot; + split_at_offset1_complete(&i, |c| arr.contains_token(c), e) } /// Returns the longest slice of the matches the pattern. @@ -225,25 +225,25 @@ where /// **WARNING:** Deprecated, replaced with [`winnow::bytes::take_while1`][crate::bytes::take_while1`] #[deprecated(since = "0.1.0", note = "Replaced with `winnow::bytes::take_while1`")] pub fn is_a>( - arr: T, + arr: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - move |i: I| is_a_internal(i, &arr) + move |i: I| is_a_internal(i, &arr) } pub(crate) fn is_a_internal>( - i: I, - arr: &T, + i: I, + arr: &T, ) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - let e: ErrorKind = ErrorKind::IsA; - split_at_offset1_complete(&i, |c| !arr.contains_token(c), e) + let e: ErrorKind = ErrorKind::IsA; + split_at_offset1_complete(&i, |c| !arr.contains_token(c), e) } /// Returns the longest input slice (if any) that matches the predicate. @@ -269,24 +269,24 @@ where /// **WARNING:** Deprecated, replaced with [`winnow::bytes::take_while0`][crate::bytes::take_while0] #[deprecated(since = "0.1.0", note = "Replaced with `winnow::bytes::take_while0`")] pub fn take_while>( - list: T, + list: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - move |i: I| take_while_internal(i, &list) + move |i: I| take_while_internal(i, &list) } pub(crate) fn take_while_internal>( - i: I, - list: &T, + i: I, + list: &T, ) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - split_at_offset_complete(&i, |c| !list.contains_token(c)) + split_at_offset_complete(&i, |c| !list.contains_token(c)) } /// Returns the longest (at least 1) input slice that matches the predicate. @@ -313,25 +313,25 @@ where /// **WARNING:** Deprecated, replaced with [`winnow::bytes::take_while1`][crate::bytes::take_while1] #[deprecated(since = "0.1.0", note = "Replaced with `winnow::bytes::take_while1`")] pub fn take_while1>( - list: T, + list: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - move |i: I| take_while1_internal(i, &list) + move |i: I| take_while1_internal(i, &list) } pub(crate) fn take_while1_internal>( - i: I, - list: &T, + i: I, + list: &T, ) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - let e: ErrorKind = ErrorKind::TakeWhile1; - split_at_offset1_complete(&i, |c| !list.contains_token(c), e) + let e: ErrorKind = ErrorKind::TakeWhile1; + split_at_offset1_complete(&i, |c| !list.contains_token(c), e) } /// Returns the longest (m <= len <= n) input slice that matches the predicate. @@ -360,56 +360,56 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::bytes::take_while_m_n`][crate::bytes::take_while_m_n] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::bytes::take_while_m_n`" + since = "0.1.0", + note = "Replaced with `winnow::bytes::take_while_m_n`" )] pub fn take_while_m_n>( - m: usize, - n: usize, - list: T, + m: usize, + n: usize, + list: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - move |i: I| take_while_m_n_internal(i, m, n, &list) + move |i: I| take_while_m_n_internal(i, m, n, &list) } pub(crate) fn take_while_m_n_internal>( - input: I, - m: usize, - n: usize, - list: &T, + input: I, + m: usize, + n: usize, + list: &T, ) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - if n < m { - return Err(ErrMode::from_error_kind(input, ErrorKind::TakeWhileMN)); - } - - let mut final_count = 0; - for (processed, (offset, token)) in input.iter_offsets().enumerate() { - if !list.contains_token(token) { - if processed < m { + if n < m { return Err(ErrMode::from_error_kind(input, ErrorKind::TakeWhileMN)); - } else { - return Ok(input.next_slice(offset)); - } - } else { - if processed == n { - return Ok(input.next_slice(offset)); - } - final_count = processed + 1; } - } - if m <= final_count { - Ok(input.next_slice(input.input_len())) - } else { - Err(ErrMode::from_error_kind(input, ErrorKind::TakeWhileMN)) - } + let mut final_count = 0; + for (processed, (offset, token)) in input.iter_offsets().enumerate() { + if !list.contains_token(token) { + if processed < m { + return Err(ErrMode::from_error_kind(input, ErrorKind::TakeWhileMN)); + } else { + return Ok(input.next_slice(offset)); + } + } else { + if processed == n { + return Ok(input.next_slice(offset)); + } + final_count = processed + 1; + } + } + + if m <= final_count { + Ok(input.next_slice(input.input_len())) + } else { + Err(ErrMode::from_error_kind(input, ErrorKind::TakeWhileMN)) + } } /// Returns the longest input slice (if any) till a predicate is met. @@ -435,24 +435,24 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::bytes::take_till0`")] #[allow(clippy::redundant_closure)] pub fn take_till>( - list: T, + list: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - move |i: I| take_till_internal(i, &list) + move |i: I| take_till_internal(i, &list) } pub(crate) fn take_till_internal>( - i: I, - list: &T, + i: I, + list: &T, ) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - split_at_offset_complete(&i, |c| list.contains_token(c)) + split_at_offset_complete(&i, |c| list.contains_token(c)) } /// Returns the longest (at least 1) input slice till a predicate is met. @@ -481,25 +481,25 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::bytes::take_till1`")] #[allow(clippy::redundant_closure)] pub fn take_till1>( - list: T, + list: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - move |i: I| take_till1_internal(i, &list) + move |i: I| take_till1_internal(i, &list) } pub(crate) fn take_till1_internal>( - i: I, - list: &T, + i: I, + list: &T, ) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - let e: ErrorKind = ErrorKind::TakeTill1; - split_at_offset1_complete(&i, |c| list.contains_token(c), e) + let e: ErrorKind = ErrorKind::TakeTill1; + split_at_offset1_complete(&i, |c| list.contains_token(c), e) } /// Returns an input slice containing the first N input elements (I[..N]). @@ -535,27 +535,27 @@ where /// **WARNING:** Deprecated, replaced with [`winnow::bytes::take`][crate::bytes::take] #[deprecated(since = "0.1.0", note = "Replaced with `winnow::bytes::take`")] pub fn take>( - count: C, + count: C, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input, - C: ToUsize, + I: Input, + C: ToUsize, { - let c = count.to_usize(); - move |i: I| take_internal(i, c) + let c = count.to_usize(); + move |i: I| take_internal(i, c) } pub(crate) fn take_internal>( - i: I, - c: usize, + i: I, + c: usize, ) -> IResult::Slice, Error> where - I: Input, + I: Input, { - match i.offset_at(c) { - Ok(offset) => Ok(i.next_slice(offset)), - Err(_needed) => Err(ErrMode::from_error_kind(i, ErrorKind::Eof)), - } + match i.offset_at(c) { + Ok(offset) => Ok(i.next_slice(offset)), + Err(_needed) => Err(ErrMode::from_error_kind(i, ErrorKind::Eof)), + } } /// Returns the input slice up to the first occurrence of the pattern. @@ -580,27 +580,27 @@ where /// **WARNING:** Deprecated, replaced with [`winnow::bytes::take_until0`][crate::bytes::take_until0] #[deprecated(since = "0.1.0", note = "Replaced with `winnow::bytes::take_until0`")] pub fn take_until>( - tag: T, + tag: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input + FindSlice, - T: SliceLen + Clone, + I: Input + FindSlice, + T: SliceLen + Clone, { - move |i: I| take_until_internal(i, tag.clone()) + move |i: I| take_until_internal(i, tag.clone()) } pub(crate) fn take_until_internal>( - i: I, - t: T, + i: I, + t: T, ) -> IResult::Slice, Error> where - I: Input + FindSlice, - T: SliceLen, + I: Input + FindSlice, + T: SliceLen, { - match i.find_slice(t) { - Some(offset) => Ok(i.next_slice(offset)), - None => Err(ErrMode::from_error_kind(i, ErrorKind::TakeUntil)), - } + match i.find_slice(t) { + Some(offset) => Ok(i.next_slice(offset)), + None => Err(ErrMode::from_error_kind(i, ErrorKind::TakeUntil)), + } } /// Returns the non empty input slice up to the first occurrence of the pattern. @@ -626,27 +626,27 @@ where /// **WARNING:** Deprecated, replaced with [`winnow::bytes::take_until1`][crate::bytes::take_until1] #[deprecated(since = "0.1.0", note = "Replaced with `winnow::bytes::take_until1`")] pub fn take_until1>( - tag: T, + tag: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input + FindSlice, - T: SliceLen + Clone, + I: Input + FindSlice, + T: SliceLen + Clone, { - move |i: I| take_until1_internal(i, tag.clone()) + move |i: I| take_until1_internal(i, tag.clone()) } pub(crate) fn take_until1_internal>( - i: I, - t: T, + i: I, + t: T, ) -> IResult::Slice, Error> where - I: Input + FindSlice, - T: SliceLen, + I: Input + FindSlice, + T: SliceLen, { - match i.find_slice(t) { - None | Some(0) => Err(ErrMode::from_error_kind(i, ErrorKind::TakeUntil)), - Some(offset) => Ok(i.next_slice(offset)), - } + match i.find_slice(t) { + None | Some(0) => Err(ErrMode::from_error_kind(i, ErrorKind::TakeUntil)), + Some(offset) => Ok(i.next_slice(offset)), + } } /// Matches a byte string with escaped characters. @@ -673,85 +673,85 @@ where /// **WARNING:** Deprecated, replaced with [`winnow::character::escaped`][crate::character::escaped] #[deprecated(since = "0.1.0", note = "Replaced with `winnow::character::escaped`")] pub fn escaped<'a, I: 'a, Error, F, G, O1, O2>( - mut normal: F, - control_char: char, - mut escapable: G, + mut normal: F, + control_char: char, + mut escapable: G, ) -> impl FnMut(I) -> IResult::Slice, Error> where - I: Input + Offset, - ::Token: crate::input::AsChar, - F: Parser, - G: Parser, - Error: ParseError, + I: Input + Offset, + ::Token: crate::input::AsChar, + F: Parser, + G: Parser, + Error: ParseError, { - move |input: I| escaped_internal(input, &mut normal, control_char, &mut escapable) + move |input: I| escaped_internal(input, &mut normal, control_char, &mut escapable) } pub(crate) fn escaped_internal<'a, I: 'a, Error, F, G, O1, O2>( - input: I, - normal: &mut F, - control_char: char, - escapable: &mut G, + input: I, + normal: &mut F, + control_char: char, + escapable: &mut G, ) -> IResult::Slice, Error> where - I: Input + Offset, - ::Token: crate::input::AsChar, - F: Parser, - G: Parser, - Error: ParseError, + I: Input + Offset, + ::Token: crate::input::AsChar, + F: Parser, + G: Parser, + Error: ParseError, { - use crate::input::AsChar; - - let mut i = input.clone(); - - while i.input_len() > 0 { - let current_len = i.input_len(); - - match normal.parse_next(i.clone()) { - Ok((i2, _)) => { - // return if we consumed everything or if the normal parser - // does not consume anything - if i2.input_len() == 0 { - return Ok(input.next_slice(input.input_len())); - } else if i2.input_len() == current_len { - let offset = input.offset_to(&i2); - return Ok(input.next_slice(offset)); - } else { - i = i2; - } - } - Err(ErrMode::Backtrack(_)) => { - if i.next_token().expect("input_len > 0").1.as_char() == control_char { - let next = control_char.len_utf8(); - if next >= i.input_len() { - return Err(ErrMode::from_error_kind(input, ErrorKind::Escaped)); - } else { - match escapable.parse_next(i.next_slice(next).0) { - Ok((i2, _)) => { + use crate::input::AsChar; + + let mut i = input.clone(); + + while i.input_len() > 0 { + let current_len = i.input_len(); + + match normal.parse_next(i.clone()) { + Ok((i2, _)) => { + // return if we consumed everything or if the normal parser + // does not consume anything if i2.input_len() == 0 { - return Ok(input.next_slice(input.input_len())); + return Ok(input.next_slice(input.input_len())); + } else if i2.input_len() == current_len { + let offset = input.offset_to(&i2); + return Ok(input.next_slice(offset)); } else { - i = i2; + i = i2; } - } - Err(e) => return Err(e), } - } - } else { - let offset = input.offset_to(&i); - if offset == 0 { - return Err(ErrMode::from_error_kind(input, ErrorKind::Escaped)); - } - return Ok(input.next_slice(offset)); + Err(ErrMode::Backtrack(_)) => { + if i.next_token().expect("input_len > 0").1.as_char() == control_char { + let next = control_char.len_utf8(); + if next >= i.input_len() { + return Err(ErrMode::from_error_kind(input, ErrorKind::Escaped)); + } else { + match escapable.parse_next(i.next_slice(next).0) { + Ok((i2, _)) => { + if i2.input_len() == 0 { + return Ok(input.next_slice(input.input_len())); + } else { + i = i2; + } + } + Err(e) => return Err(e), + } + } + } else { + let offset = input.offset_to(&i); + if offset == 0 { + return Err(ErrMode::from_error_kind(input, ErrorKind::Escaped)); + } + return Ok(input.next_slice(offset)); + } + } + Err(e) => { + return Err(e); + } } - } - Err(e) => { - return Err(e); - } } - } - Ok(input.next_slice(input.input_len())) + Ok(input.next_slice(input.input_len())) } /// Matches a byte string with escaped characters. @@ -789,371 +789,371 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::escaped_transform`][crate::character::escaped_transform] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::escaped_transform`" + since = "0.1.0", + note = "Replaced with `winnow::character::escaped_transform`" )] pub fn escaped_transform( - mut normal: F, - control_char: char, - mut transform: G, + mut normal: F, + control_char: char, + mut transform: G, ) -> impl FnMut(I) -> IResult where - I: Input + Offset, - ::Token: crate::input::AsChar, - Output: crate::input::Accumulate<::Slice>, - F: Parser::Slice, Error>, - G: Parser::Slice, Error>, - Error: ParseError, + I: Input + Offset, + ::Token: crate::input::AsChar, + Output: crate::input::Accumulate<::Slice>, + F: Parser::Slice, Error>, + G: Parser::Slice, Error>, + Error: ParseError, { - move |input: I| escaped_transform_internal(input, &mut normal, control_char, &mut transform) + move |input: I| escaped_transform_internal(input, &mut normal, control_char, &mut transform) } #[cfg(feature = "alloc")] pub(crate) fn escaped_transform_internal( - input: I, - normal: &mut F, - control_char: char, - transform: &mut G, + input: I, + normal: &mut F, + control_char: char, + transform: &mut G, ) -> IResult where - I: Input + Offset, - ::Token: crate::input::AsChar, - Output: crate::input::Accumulate<::Slice>, - F: Parser::Slice, Error>, - G: Parser::Slice, Error>, - Error: ParseError, + I: Input + Offset, + ::Token: crate::input::AsChar, + Output: crate::input::Accumulate<::Slice>, + F: Parser::Slice, Error>, + G: Parser::Slice, Error>, + Error: ParseError, { - use crate::input::AsChar; - - let mut offset = 0; - let mut res = Output::initial(Some(input.input_len())); - - let i = input.clone(); - - while offset < i.input_len() { - let current_len = i.input_len(); - let (remainder, _) = i.next_slice(offset); - match normal.parse_next(remainder.clone()) { - Ok((i2, o)) => { - res.accumulate(o); - if i2.input_len() == 0 { - return Ok((i.next_slice(i.input_len()).0, res)); - } else if i2.input_len() == current_len { - return Ok((remainder, res)); - } else { - offset = input.offset_to(&i2); - } - } - Err(ErrMode::Backtrack(_)) => { - if remainder.next_token().expect("input_len > 0").1.as_char() == control_char { - let next = offset + control_char.len_utf8(); - let input_len = input.input_len(); - - if next >= input_len { - return Err(ErrMode::from_error_kind( - remainder, - ErrorKind::EscapedTransform, - )); - } else { - match transform.parse_next(i.next_slice(next).0) { - Ok((i2, o)) => { + use crate::input::AsChar; + + let mut offset = 0; + let mut res = Output::initial(Some(input.input_len())); + + let i = input.clone(); + + while offset < i.input_len() { + let current_len = i.input_len(); + let (remainder, _) = i.next_slice(offset); + match normal.parse_next(remainder.clone()) { + Ok((i2, o)) => { res.accumulate(o); if i2.input_len() == 0 { - return Ok((i.next_slice(i.input_len()).0, res)); + return Ok((i.next_slice(i.input_len()).0, res)); + } else if i2.input_len() == current_len { + return Ok((remainder, res)); } else { - offset = input.offset_to(&i2); + offset = input.offset_to(&i2); } - } - Err(e) => return Err(e), } - } - } else { - if offset == 0 { - return Err(ErrMode::from_error_kind( - remainder, - ErrorKind::EscapedTransform, - )); - } - return Ok((remainder, res)); + Err(ErrMode::Backtrack(_)) => { + if remainder.next_token().expect("input_len > 0").1.as_char() == control_char { + let next = offset + control_char.len_utf8(); + let input_len = input.input_len(); + + if next >= input_len { + return Err(ErrMode::from_error_kind( + remainder, + ErrorKind::EscapedTransform, + )); + } else { + match transform.parse_next(i.next_slice(next).0) { + Ok((i2, o)) => { + res.accumulate(o); + if i2.input_len() == 0 { + return Ok((i.next_slice(i.input_len()).0, res)); + } else { + offset = input.offset_to(&i2); + } + } + Err(e) => return Err(e), + } + } + } else { + if offset == 0 { + return Err(ErrMode::from_error_kind( + remainder, + ErrorKind::EscapedTransform, + )); + } + return Ok((remainder, res)); + } + } + Err(e) => return Err(e), } - } - Err(e) => return Err(e), } - } - Ok((input.next_slice(offset).0, res)) + Ok((input.next_slice(offset).0, res)) } #[cfg(test)] mod tests { - use super::*; - #[cfg(feature = "alloc")] - use crate::{ - branch::alt, - combinator::{map, value}, - lib::std::string::String, - lib::std::vec::Vec, - }; - - #[test] - fn complete_take_while_m_n_utf8_all_matching() { - let result: IResult<&str, &str> = - super::take_while_m_n(1, 4, |c: char| c.is_alphabetic())("øn"); - assert_eq!(result, Ok(("", "øn"))); - } - - #[test] - fn complete_take_while_m_n_utf8_all_matching_substring() { - let result: IResult<&str, &str> = - super::take_while_m_n(1, 1, |c: char| c.is_alphabetic())("øn"); - assert_eq!(result, Ok(("n", "ø"))); - } - - // issue #1336 "escaped hangs if normal parser accepts empty" - fn escaped_string(input: &str) -> IResult<&str, &str> { - use crate::character::complete::{alpha0, one_of}; - escaped(alpha0, '\\', one_of("n"))(input) - } - - // issue #1336 "escaped hangs if normal parser accepts empty" - #[test] - fn escaped_hang() { - escaped_string("7").unwrap(); - escaped_string("a7").unwrap(); - } - - // issue ##1118 escaped does not work with empty string - fn unquote(input: &str) -> IResult<&str, &str> { - use crate::bytes::complete::*; - use crate::character::complete::*; - use crate::combinator::opt; - use crate::sequence::delimited; - - delimited( - char('"'), - escaped(opt(none_of(r#"\""#)), '\\', one_of(r#"\"rnt"#)), - char('"'), - )(input) - } - - #[test] - fn escaped_hang_1118() { - assert_eq!(unquote(r#""""#), Ok(("", ""))); - } - - #[cfg(feature = "alloc")] - #[allow(unused_variables)] - #[test] - fn escaping() { - use crate::character::complete::one_of; - use crate::character::complete::{alpha1 as alpha, digit1 as digit}; - - fn esc(i: &[u8]) -> IResult<&[u8], &[u8]> { - escaped(alpha, '\\', one_of("\"n\\"))(i) + use super::*; + #[cfg(feature = "alloc")] + use crate::{ + branch::alt, + combinator::{map, value}, + lib::std::string::String, + lib::std::vec::Vec, + }; + + #[test] + fn complete_take_while_m_n_utf8_all_matching() { + let result: IResult<&str, &str> = + super::take_while_m_n(1, 4, |c: char| c.is_alphabetic())("øn"); + assert_eq!(result, Ok(("", "øn"))); } - assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], &b"abcd"[..]))); - assert_eq!(esc(&b"ab\\\"cd;"[..]), Ok((&b";"[..], &b"ab\\\"cd"[..]))); - assert_eq!(esc(&b"\\\"abcd;"[..]), Ok((&b";"[..], &b"\\\"abcd"[..]))); - assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], &b"\\n"[..]))); - assert_eq!(esc(&b"ab\\\"12"[..]), Ok((&b"12"[..], &b"ab\\\""[..]))); - assert_eq!( - esc(&b"AB\\"[..]), - Err(ErrMode::Backtrack(error_position!( - &b"AB\\"[..], - ErrorKind::Escaped - ))) - ); - assert_eq!( - esc(&b"AB\\A"[..]), - Err(ErrMode::Backtrack(error_node_position!( - &b"AB\\A"[..], - ErrorKind::Escaped, - error_position!(&b"A"[..], ErrorKind::OneOf) - ))) - ); - - fn esc2(i: &[u8]) -> IResult<&[u8], &[u8]> { - escaped(digit, '\\', one_of("\"n\\"))(i) + + #[test] + fn complete_take_while_m_n_utf8_all_matching_substring() { + let result: IResult<&str, &str> = + super::take_while_m_n(1, 1, |c: char| c.is_alphabetic())("øn"); + assert_eq!(result, Ok(("n", "ø"))); } - assert_eq!(esc2(&b"12\\nnn34"[..]), Ok((&b"nn34"[..], &b"12\\n"[..]))); - } - #[cfg(feature = "alloc")] - #[test] - fn escaping_str() { - use crate::character::complete::one_of; - use crate::character::complete::{alpha1 as alpha, digit1 as digit}; + // issue #1336 "escaped hangs if normal parser accepts empty" + fn escaped_string(input: &str) -> IResult<&str, &str> { + use crate::character::complete::{alpha0, one_of}; + escaped(alpha0, '\\', one_of("n"))(input) + } - fn esc(i: &str) -> IResult<&str, &str> { - escaped(alpha, '\\', one_of("\"n\\"))(i) + // issue #1336 "escaped hangs if normal parser accepts empty" + #[test] + fn escaped_hang() { + escaped_string("7").unwrap(); + escaped_string("a7").unwrap(); } - assert_eq!(esc("abcd;"), Ok((";", "abcd"))); - assert_eq!(esc("ab\\\"cd;"), Ok((";", "ab\\\"cd"))); - assert_eq!(esc("\\\"abcd;"), Ok((";", "\\\"abcd"))); - assert_eq!(esc("\\n;"), Ok((";", "\\n"))); - assert_eq!(esc("ab\\\"12"), Ok(("12", "ab\\\""))); - assert_eq!( - esc("AB\\"), - Err(ErrMode::Backtrack(error_position!( - "AB\\", - ErrorKind::Escaped - ))) - ); - assert_eq!( - esc("AB\\A"), - Err(ErrMode::Backtrack(error_node_position!( - "AB\\A", - ErrorKind::Escaped, - error_position!("A", ErrorKind::OneOf) - ))) - ); - - fn esc2(i: &str) -> IResult<&str, &str> { - escaped(digit, '\\', one_of("\"n\\"))(i) + + // issue ##1118 escaped does not work with empty string + fn unquote(input: &str) -> IResult<&str, &str> { + use crate::bytes::complete::*; + use crate::character::complete::*; + use crate::combinator::opt; + use crate::sequence::delimited; + + delimited( + char('"'), + escaped(opt(none_of(r#"\""#)), '\\', one_of(r#"\"rnt"#)), + char('"'), + )(input) } - assert_eq!(esc2("12\\nnn34"), Ok(("nn34", "12\\n"))); - fn esc3(i: &str) -> IResult<&str, &str> { - escaped(alpha, '\u{241b}', one_of("\"n"))(i) + #[test] + fn escaped_hang_1118() { + assert_eq!(unquote(r#""""#), Ok(("", ""))); } - assert_eq!(esc3("ab␛ncd;"), Ok((";", "ab␛ncd"))); - } - - #[cfg(feature = "alloc")] - fn to_s(i: Vec) -> String { - String::from_utf8_lossy(&i).into_owned() - } - - #[cfg(feature = "alloc")] - #[test] - fn escape_transform() { - use crate::character::complete::alpha1 as alpha; - - fn esc(i: &[u8]) -> IResult<&[u8], String> { - map( - escaped_transform( - alpha, - '\\', - alt(( - value(&b"\\"[..], tag("\\")), - value(&b"\""[..], tag("\"")), - value(&b"\n"[..], tag("n")), - )), - ), - to_s, - )(i) + + #[cfg(feature = "alloc")] + #[allow(unused_variables)] + #[test] + fn escaping() { + use crate::character::complete::one_of; + use crate::character::complete::{alpha1 as alpha, digit1 as digit}; + + fn esc(i: &[u8]) -> IResult<&[u8], &[u8]> { + escaped(alpha, '\\', one_of("\"n\\"))(i) + } + assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], &b"abcd"[..]))); + assert_eq!(esc(&b"ab\\\"cd;"[..]), Ok((&b";"[..], &b"ab\\\"cd"[..]))); + assert_eq!(esc(&b"\\\"abcd;"[..]), Ok((&b";"[..], &b"\\\"abcd"[..]))); + assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], &b"\\n"[..]))); + assert_eq!(esc(&b"ab\\\"12"[..]), Ok((&b"12"[..], &b"ab\\\""[..]))); + assert_eq!( + esc(&b"AB\\"[..]), + Err(ErrMode::Backtrack(error_position!( + &b"AB\\"[..], + ErrorKind::Escaped + ))) + ); + assert_eq!( + esc(&b"AB\\A"[..]), + Err(ErrMode::Backtrack(error_node_position!( + &b"AB\\A"[..], + ErrorKind::Escaped, + error_position!(&b"A"[..], ErrorKind::OneOf) + ))) + ); + + fn esc2(i: &[u8]) -> IResult<&[u8], &[u8]> { + escaped(digit, '\\', one_of("\"n\\"))(i) + } + assert_eq!(esc2(&b"12\\nnn34"[..]), Ok((&b"nn34"[..], &b"12\\n"[..]))); } - assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], String::from("abcd")))); - assert_eq!( - esc(&b"ab\\\"cd;"[..]), - Ok((&b";"[..], String::from("ab\"cd"))) - ); - assert_eq!( - esc(&b"\\\"abcd;"[..]), - Ok((&b";"[..], String::from("\"abcd"))) - ); - assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], String::from("\n")))); - assert_eq!( - esc(&b"ab\\\"12"[..]), - Ok((&b"12"[..], String::from("ab\""))) - ); - assert_eq!( - esc(&b"AB\\"[..]), - Err(ErrMode::Backtrack(error_position!( - &b"\\"[..], - ErrorKind::EscapedTransform - ))) - ); - assert_eq!( - esc(&b"AB\\A"[..]), - Err(ErrMode::Backtrack(error_node_position!( - &b"AB\\A"[..], - ErrorKind::EscapedTransform, - error_position!(&b"A"[..], ErrorKind::Tag) - ))) - ); - - fn esc2(i: &[u8]) -> IResult<&[u8], String> { - map( - escaped_transform( - alpha, - '&', - alt(( - value("è".as_bytes(), tag("egrave;")), - value("à".as_bytes(), tag("agrave;")), - )), - ), - to_s, - )(i) + #[cfg(feature = "alloc")] + #[test] + fn escaping_str() { + use crate::character::complete::one_of; + use crate::character::complete::{alpha1 as alpha, digit1 as digit}; + + fn esc(i: &str) -> IResult<&str, &str> { + escaped(alpha, '\\', one_of("\"n\\"))(i) + } + assert_eq!(esc("abcd;"), Ok((";", "abcd"))); + assert_eq!(esc("ab\\\"cd;"), Ok((";", "ab\\\"cd"))); + assert_eq!(esc("\\\"abcd;"), Ok((";", "\\\"abcd"))); + assert_eq!(esc("\\n;"), Ok((";", "\\n"))); + assert_eq!(esc("ab\\\"12"), Ok(("12", "ab\\\""))); + assert_eq!( + esc("AB\\"), + Err(ErrMode::Backtrack(error_position!( + "AB\\", + ErrorKind::Escaped + ))) + ); + assert_eq!( + esc("AB\\A"), + Err(ErrMode::Backtrack(error_node_position!( + "AB\\A", + ErrorKind::Escaped, + error_position!("A", ErrorKind::OneOf) + ))) + ); + + fn esc2(i: &str) -> IResult<&str, &str> { + escaped(digit, '\\', one_of("\"n\\"))(i) + } + assert_eq!(esc2("12\\nnn34"), Ok(("nn34", "12\\n"))); + + fn esc3(i: &str) -> IResult<&str, &str> { + escaped(alpha, '\u{241b}', one_of("\"n"))(i) + } + assert_eq!(esc3("ab␛ncd;"), Ok((";", "ab␛ncd"))); } - assert_eq!( - esc2(&b"abèDEF;"[..]), - Ok((&b";"[..], String::from("abèDEF"))) - ); - assert_eq!( - esc2(&b"abèDàEF;"[..]), - Ok((&b";"[..], String::from("abèDàEF"))) - ); - } - - #[cfg(feature = "std")] - #[test] - fn escape_transform_str() { - use crate::character::complete::alpha1 as alpha; - - fn esc(i: &str) -> IResult<&str, String> { - escaped_transform( - alpha, - '\\', - alt(( - value("\\", tag("\\")), - value("\"", tag("\"")), - value("\n", tag("n")), - )), - )(i) + + #[cfg(feature = "alloc")] + fn to_s(i: Vec) -> String { + String::from_utf8_lossy(&i).into_owned() } - assert_eq!(esc("abcd;"), Ok((";", String::from("abcd")))); - assert_eq!(esc("ab\\\"cd;"), Ok((";", String::from("ab\"cd")))); - assert_eq!(esc("\\\"abcd;"), Ok((";", String::from("\"abcd")))); - assert_eq!(esc("\\n;"), Ok((";", String::from("\n")))); - assert_eq!(esc("ab\\\"12"), Ok(("12", String::from("ab\"")))); - assert_eq!( - esc("AB\\"), - Err(ErrMode::Backtrack(error_position!( - "\\", - ErrorKind::EscapedTransform - ))) - ); - assert_eq!( - esc("AB\\A"), - Err(ErrMode::Backtrack(error_node_position!( - "AB\\A", - ErrorKind::EscapedTransform, - error_position!("A", ErrorKind::Tag) - ))) - ); - - fn esc2(i: &str) -> IResult<&str, String> { - escaped_transform( - alpha, - '&', - alt((value("è", tag("egrave;")), value("à", tag("agrave;")))), - )(i) + #[cfg(feature = "alloc")] + #[test] + fn escape_transform() { + use crate::character::complete::alpha1 as alpha; + + fn esc(i: &[u8]) -> IResult<&[u8], String> { + map( + escaped_transform( + alpha, + '\\', + alt(( + value(&b"\\"[..], tag("\\")), + value(&b"\""[..], tag("\"")), + value(&b"\n"[..], tag("n")), + )), + ), + to_s, + )(i) + } + + assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], String::from("abcd")))); + assert_eq!( + esc(&b"ab\\\"cd;"[..]), + Ok((&b";"[..], String::from("ab\"cd"))) + ); + assert_eq!( + esc(&b"\\\"abcd;"[..]), + Ok((&b";"[..], String::from("\"abcd"))) + ); + assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], String::from("\n")))); + assert_eq!( + esc(&b"ab\\\"12"[..]), + Ok((&b"12"[..], String::from("ab\""))) + ); + assert_eq!( + esc(&b"AB\\"[..]), + Err(ErrMode::Backtrack(error_position!( + &b"\\"[..], + ErrorKind::EscapedTransform + ))) + ); + assert_eq!( + esc(&b"AB\\A"[..]), + Err(ErrMode::Backtrack(error_node_position!( + &b"AB\\A"[..], + ErrorKind::EscapedTransform, + error_position!(&b"A"[..], ErrorKind::Tag) + ))) + ); + + fn esc2(i: &[u8]) -> IResult<&[u8], String> { + map( + escaped_transform( + alpha, + '&', + alt(( + value("è".as_bytes(), tag("egrave;")), + value("à".as_bytes(), tag("agrave;")), + )), + ), + to_s, + )(i) + } + assert_eq!( + esc2(&b"abèDEF;"[..]), + Ok((&b";"[..], String::from("abèDEF"))) + ); + assert_eq!( + esc2(&b"abèDàEF;"[..]), + Ok((&b";"[..], String::from("abèDàEF"))) + ); } - assert_eq!(esc2("abèDEF;"), Ok((";", String::from("abèDEF")))); - assert_eq!( - esc2("abèDàEF;"), - Ok((";", String::from("abèDàEF"))) - ); - - fn esc3(i: &str) -> IResult<&str, String> { - escaped_transform( - alpha, - '␛', - alt((value("\0", tag("0")), value("\n", tag("n")))), - )(i) + + #[cfg(feature = "std")] + #[test] + fn escape_transform_str() { + use crate::character::complete::alpha1 as alpha; + + fn esc(i: &str) -> IResult<&str, String> { + escaped_transform( + alpha, + '\\', + alt(( + value("\\", tag("\\")), + value("\"", tag("\"")), + value("\n", tag("n")), + )), + )(i) + } + + assert_eq!(esc("abcd;"), Ok((";", String::from("abcd")))); + assert_eq!(esc("ab\\\"cd;"), Ok((";", String::from("ab\"cd")))); + assert_eq!(esc("\\\"abcd;"), Ok((";", String::from("\"abcd")))); + assert_eq!(esc("\\n;"), Ok((";", String::from("\n")))); + assert_eq!(esc("ab\\\"12"), Ok(("12", String::from("ab\"")))); + assert_eq!( + esc("AB\\"), + Err(ErrMode::Backtrack(error_position!( + "\\", + ErrorKind::EscapedTransform + ))) + ); + assert_eq!( + esc("AB\\A"), + Err(ErrMode::Backtrack(error_node_position!( + "AB\\A", + ErrorKind::EscapedTransform, + error_position!("A", ErrorKind::Tag) + ))) + ); + + fn esc2(i: &str) -> IResult<&str, String> { + escaped_transform( + alpha, + '&', + alt((value("è", tag("egrave;")), value("à", tag("agrave;")))), + )(i) + } + assert_eq!(esc2("abèDEF;"), Ok((";", String::from("abèDEF")))); + assert_eq!( + esc2("abèDàEF;"), + Ok((";", String::from("abèDàEF"))) + ); + + fn esc3(i: &str) -> IResult<&str, String> { + escaped_transform( + alpha, + '␛', + alt((value("\0", tag("0")), value("\n", tag("n")))), + )(i) + } + assert_eq!(esc3("a␛0bc␛n"), Ok(("", String::from("a\0bc\n")))); } - assert_eq!(esc3("a␛0bc␛n"), Ok(("", String::from("a\0bc\n")))); - } } diff --git a/src/bytes/mod.rs b/src/bytes/mod.rs index 038b4fd0..2784da00 100644 --- a/src/bytes/mod.rs +++ b/src/bytes/mod.rs @@ -35,17 +35,17 @@ use crate::IResult; /// ``` #[inline(always)] pub fn any, const STREAMING: bool>( - input: I, + input: I, ) -> IResult::Token, E> where - I: InputIsStreaming, - I: Input, + I: InputIsStreaming, + I: Input, { - if STREAMING { - streaming::any(input) - } else { - complete::any(input) - } + if STREAMING { + streaming::any(input) + } else { + complete::any(input) + } } /// Recognizes a literal @@ -89,21 +89,21 @@ where /// ``` #[inline(always)] pub fn tag, const STREAMING: bool>( - tag: T, + tag: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: InputIsStreaming, - I: Input + Compare, - T: SliceLen + Clone, + I: InputIsStreaming, + I: Input + Compare, + T: SliceLen + Clone, { - move |i: I| { - let t = tag.clone(); - if STREAMING { - streaming::tag_internal(i, t) - } else { - complete::tag_internal(i, t) + move |i: I| { + let t = tag.clone(); + if STREAMING { + streaming::tag_internal(i, t) + } else { + complete::tag_internal(i, t) + } } - } } /// Recognizes a case insensitive literal. @@ -145,21 +145,21 @@ where /// ``` #[inline(always)] pub fn tag_no_case, const STREAMING: bool>( - tag: T, + tag: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: InputIsStreaming, - I: Input + Compare, - T: SliceLen + Clone, + I: InputIsStreaming, + I: Input + Compare, + T: SliceLen + Clone, { - move |i: I| { - let t = tag.clone(); - if STREAMING { - streaming::tag_no_case_internal(i, t) - } else { - complete::tag_no_case_internal(i, t) + move |i: I| { + let t = tag.clone(); + if STREAMING { + streaming::tag_no_case_internal(i, t) + } else { + complete::tag_no_case_internal(i, t) + } } - } } /// Returns a token that matches the [pattern][ContainsToken] @@ -209,21 +209,21 @@ where /// ``` #[inline(always)] pub fn one_of, const STREAMING: bool>( - list: T, + list: T, ) -> impl Fn(I) -> IResult::Token, Error> where - I: InputIsStreaming, - I: Input, - ::Token: Copy, - T: ContainsToken<::Token>, + I: InputIsStreaming, + I: Input, + ::Token: Copy, + T: ContainsToken<::Token>, { - move |i: I| { - if STREAMING { - streaming::one_of_internal(i, &list) - } else { - complete::one_of_internal(i, &list) + move |i: I| { + if STREAMING { + streaming::one_of_internal(i, &list) + } else { + complete::one_of_internal(i, &list) + } } - } } /// Returns a token that does not match the [pattern][ContainsToken] @@ -252,21 +252,21 @@ where /// ``` #[inline(always)] pub fn none_of, const STREAMING: bool>( - list: T, + list: T, ) -> impl Fn(I) -> IResult::Token, Error> where - I: InputIsStreaming, - I: Input, - ::Token: Copy, - T: ContainsToken<::Token>, + I: InputIsStreaming, + I: Input, + ::Token: Copy, + T: ContainsToken<::Token>, { - move |i: I| { - if STREAMING { - streaming::none_of_internal(i, &list) - } else { - complete::none_of_internal(i, &list) + move |i: I| { + if STREAMING { + streaming::none_of_internal(i, &list) + } else { + complete::none_of_internal(i, &list) + } } - } } /// Returns the longest input slice (if any) that matches the [pattern][ContainsToken] @@ -305,20 +305,20 @@ where /// ``` #[inline(always)] pub fn take_while0, const STREAMING: bool>( - list: T, + list: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: InputIsStreaming, - I: Input, - T: ContainsToken<::Token>, + I: InputIsStreaming, + I: Input, + T: ContainsToken<::Token>, { - move |i: I| { - if STREAMING { - streaming::take_while_internal(i, &list) - } else { - complete::take_while_internal(i, &list) + move |i: I| { + if STREAMING { + streaming::take_while_internal(i, &list) + } else { + complete::take_while_internal(i, &list) + } } - } } /// Returns the longest (at least 1) input slice that matches the [pattern][ContainsToken] @@ -378,20 +378,20 @@ where /// ``` #[inline(always)] pub fn take_while1, const STREAMING: bool>( - list: T, + list: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: InputIsStreaming, - I: Input, - T: ContainsToken<::Token>, + I: InputIsStreaming, + I: Input, + T: ContainsToken<::Token>, { - move |i: I| { - if STREAMING { - streaming::take_while1_internal(i, &list) - } else { - complete::take_while1_internal(i, &list) + move |i: I| { + if STREAMING { + streaming::take_while1_internal(i, &list) + } else { + complete::take_while1_internal(i, &list) + } } - } } /// Returns the longest (m <= len <= n) input slice that matches the [pattern][ContainsToken] @@ -436,22 +436,22 @@ where /// ``` #[inline(always)] pub fn take_while_m_n, const STREAMING: bool>( - m: usize, - n: usize, - list: T, + m: usize, + n: usize, + list: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: InputIsStreaming, - I: Input, - T: ContainsToken<::Token>, + I: InputIsStreaming, + I: Input, + T: ContainsToken<::Token>, { - move |i: I| { - if STREAMING { - streaming::take_while_m_n_internal(i, m, n, &list) - } else { - complete::take_while_m_n_internal(i, m, n, &list) + move |i: I| { + if STREAMING { + streaming::take_while_m_n_internal(i, m, n, &list) + } else { + complete::take_while_m_n_internal(i, m, n, &list) + } } - } } /// Returns the longest input slice (if any) till a [pattern][ContainsToken] is met. @@ -490,20 +490,20 @@ where /// ``` #[inline(always)] pub fn take_till0, const STREAMING: bool>( - list: T, + list: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: InputIsStreaming, - I: Input, - T: ContainsToken<::Token>, + I: InputIsStreaming, + I: Input, + T: ContainsToken<::Token>, { - move |i: I| { - if STREAMING { - streaming::take_till_internal(i, &list) - } else { - complete::take_till_internal(i, &list) + move |i: I| { + if STREAMING { + streaming::take_till_internal(i, &list) + } else { + complete::take_till_internal(i, &list) + } } - } } /// Returns the longest (at least 1) input slice till a [pattern][ContainsToken] is met. @@ -563,20 +563,20 @@ where /// ``` #[inline(always)] pub fn take_till1, const STREAMING: bool>( - list: T, + list: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: InputIsStreaming, - I: Input, - T: ContainsToken<::Token>, + I: InputIsStreaming, + I: Input, + T: ContainsToken<::Token>, { - move |i: I| { - if STREAMING { - streaming::take_till1_internal(i, &list) - } else { - complete::take_till1_internal(i, &list) + move |i: I| { + if STREAMING { + streaming::take_till1_internal(i, &list) + } else { + complete::take_till1_internal(i, &list) + } } - } } /// Returns an input slice containing the first N input elements (I[..N]). @@ -633,21 +633,21 @@ where /// ``` #[inline(always)] pub fn take, const STREAMING: bool>( - count: C, + count: C, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: InputIsStreaming, - I: Input, - C: ToUsize, + I: InputIsStreaming, + I: Input, + C: ToUsize, { - let c = count.to_usize(); - move |i: I| { - if STREAMING { - streaming::take_internal(i, c) - } else { - complete::take_internal(i, c) + let c = count.to_usize(); + move |i: I| { + if STREAMING { + streaming::take_internal(i, c) + } else { + complete::take_internal(i, c) + } } - } } /// Returns the input slice up to the first occurrence of the literal. @@ -690,20 +690,20 @@ where /// ``` #[inline(always)] pub fn take_until0, const STREAMING: bool>( - tag: T, + tag: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: InputIsStreaming, - I: Input + FindSlice, - T: SliceLen + Clone, + I: InputIsStreaming, + I: Input + FindSlice, + T: SliceLen + Clone, { - move |i: I| { - if STREAMING { - streaming::take_until_internal(i, tag.clone()) - } else { - complete::take_until_internal(i, tag.clone()) + move |i: I| { + if STREAMING { + streaming::take_until_internal(i, tag.clone()) + } else { + complete::take_until_internal(i, tag.clone()) + } } - } } /// Returns the non empty input slice up to the first occurrence of the literal. @@ -749,18 +749,18 @@ where /// ``` #[inline(always)] pub fn take_until1, const STREAMING: bool>( - tag: T, + tag: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: InputIsStreaming, - I: Input + FindSlice, - T: SliceLen + Clone, + I: InputIsStreaming, + I: Input + FindSlice, + T: SliceLen + Clone, { - move |i: I| { - if STREAMING { - streaming::take_until1_internal(i, tag.clone()) - } else { - complete::take_until1_internal(i, tag.clone()) + move |i: I| { + if STREAMING { + streaming::take_until1_internal(i, tag.clone()) + } else { + complete::take_until1_internal(i, tag.clone()) + } } - } } diff --git a/src/bytes/streaming.rs b/src/bytes/streaming.rs index 8fd87a2b..87ca5eb1 100644 --- a/src/bytes/streaming.rs +++ b/src/bytes/streaming.rs @@ -7,19 +7,19 @@ use crate::error::ErrorKind; use crate::error::Needed; use crate::error::ParseError; use crate::input::{ - split_at_offset1_streaming, split_at_offset_streaming, Compare, CompareResult, ContainsToken, - FindSlice, Input, Offset, SliceLen, ToUsize, + split_at_offset1_streaming, split_at_offset_streaming, Compare, CompareResult, ContainsToken, + FindSlice, Input, Offset, SliceLen, ToUsize, }; use crate::lib::std::result::Result::Ok; use crate::{IResult, Parser}; pub(crate) fn any>(input: I) -> IResult::Token, E> where - I: Input, + I: Input, { - input - .next_token() - .ok_or_else(|| ErrMode::Incomplete(Needed::new(1))) + input + .next_token() + .ok_or_else(|| ErrMode::Incomplete(Needed::new(1))) } /// Recognizes a pattern. @@ -43,36 +43,36 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::bytes::tag`][crate::bytes::tag] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::bytes::tag` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::bytes::tag` with input wrapped in `winnow::input::Streaming`" )] pub fn tag>( - tag: T, + tag: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input + Compare, - T: SliceLen + Clone, + I: Input + Compare, + T: SliceLen + Clone, { - move |i: I| tag_internal(i, tag.clone()) + move |i: I| tag_internal(i, tag.clone()) } pub(crate) fn tag_internal>( - i: I, - t: T, + i: I, + t: T, ) -> IResult::Slice, Error> where - I: Input + Compare, - T: SliceLen, + I: Input + Compare, + T: SliceLen, { - let tag_len = t.slice_len(); - match i.compare(t) { - CompareResult::Ok => Ok(i.next_slice(tag_len)), - CompareResult::Incomplete => Err(ErrMode::Incomplete(Needed::new(tag_len - i.input_len()))), - CompareResult::Error => { - let e: ErrorKind = ErrorKind::Tag; - Err(ErrMode::from_error_kind(i, e)) + let tag_len = t.slice_len(); + match i.compare(t) { + CompareResult::Ok => Ok(i.next_slice(tag_len)), + CompareResult::Incomplete => Err(ErrMode::Incomplete(Needed::new(tag_len - i.input_len()))), + CompareResult::Error => { + let e: ErrorKind = ErrorKind::Tag; + Err(ErrMode::from_error_kind(i, e)) + } } - } } /// Recognizes a case insensitive pattern. @@ -97,75 +97,75 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::bytes::tag_no_case`][crate::bytes::tag_no_case] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::bytes::tag_no_case` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::bytes::tag_no_case` with input wrapped in `winnow::input::Streaming`" )] pub fn tag_no_case>( - tag: T, + tag: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input + Compare, - T: SliceLen + Clone, + I: Input + Compare, + T: SliceLen + Clone, { - move |i: I| tag_no_case_internal(i, tag.clone()) + move |i: I| tag_no_case_internal(i, tag.clone()) } pub(crate) fn tag_no_case_internal>( - i: I, - t: T, + i: I, + t: T, ) -> IResult::Slice, Error> where - I: Input + Compare, - T: SliceLen, + I: Input + Compare, + T: SliceLen, { - let tag_len = t.slice_len(); - - match (i).compare_no_case(t) { - CompareResult::Ok => Ok(i.next_slice(tag_len)), - CompareResult::Incomplete => Err(ErrMode::Incomplete(Needed::new(tag_len - i.input_len()))), - CompareResult::Error => { - let e: ErrorKind = ErrorKind::Tag; - Err(ErrMode::from_error_kind(i, e)) + let tag_len = t.slice_len(); + + match (i).compare_no_case(t) { + CompareResult::Ok => Ok(i.next_slice(tag_len)), + CompareResult::Incomplete => Err(ErrMode::Incomplete(Needed::new(tag_len - i.input_len()))), + CompareResult::Error => { + let e: ErrorKind = ErrorKind::Tag; + Err(ErrMode::from_error_kind(i, e)) + } } - } } pub(crate) fn one_of_internal>( - input: I, - list: &T, + input: I, + list: &T, ) -> IResult::Token, E> where - I: Input, - ::Token: Copy, - T: ContainsToken<::Token>, + I: Input, + ::Token: Copy, + T: ContainsToken<::Token>, { - let (new_input, token) = input - .next_token() - .ok_or_else(|| ErrMode::Incomplete(Needed::new(1)))?; - if list.contains_token(token) { - Ok((new_input, token)) - } else { - Err(ErrMode::from_error_kind(input, ErrorKind::OneOf)) - } + let (new_input, token) = input + .next_token() + .ok_or_else(|| ErrMode::Incomplete(Needed::new(1)))?; + if list.contains_token(token) { + Ok((new_input, token)) + } else { + Err(ErrMode::from_error_kind(input, ErrorKind::OneOf)) + } } pub(crate) fn none_of_internal>( - input: I, - list: &T, + input: I, + list: &T, ) -> IResult::Token, E> where - I: Input, - ::Token: Copy, - T: ContainsToken<::Token>, + I: Input, + ::Token: Copy, + T: ContainsToken<::Token>, { - let (new_input, token) = input - .next_token() - .ok_or_else(|| ErrMode::Incomplete(Needed::new(1)))?; - if !list.contains_token(token) { - Ok((new_input, token)) - } else { - Err(ErrMode::from_error_kind(input, ErrorKind::NoneOf)) - } + let (new_input, token) = input + .next_token() + .ok_or_else(|| ErrMode::Incomplete(Needed::new(1)))?; + if !list.contains_token(token) { + Ok((new_input, token)) + } else { + Err(ErrMode::from_error_kind(input, ErrorKind::NoneOf)) + } } /// Parse till certain characters are met. @@ -192,29 +192,29 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::bytes::take_till1`][crate::bytes::take_till1] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::bytes::take_till1` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::bytes::take_till1` with input wrapped in `winnow::input::Streaming`" )] pub fn is_not>( - arr: T, + arr: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - move |i: I| is_not_internal(i, &arr) + move |i: I| is_not_internal(i, &arr) } pub(crate) fn is_not_internal>( - i: I, - arr: &T, + i: I, + arr: &T, ) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - let e: ErrorKind = ErrorKind::IsNot; - split_at_offset1_streaming(&i, |c| arr.contains_token(c), e) + let e: ErrorKind = ErrorKind::IsNot; + split_at_offset1_streaming(&i, |c| arr.contains_token(c), e) } /// Returns the longest slice of the matches the pattern. @@ -243,29 +243,29 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::bytes::take_while1`][crate::bytes::take_while1] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::bytes::take_while1` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::bytes::take_while1` with input wrapped in `winnow::input::Streaming`" )] pub fn is_a>( - arr: T, + arr: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - move |i: I| is_a_internal(i, &arr) + move |i: I| is_a_internal(i, &arr) } pub(crate) fn is_a_internal>( - i: I, - arr: &T, + i: I, + arr: &T, ) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - let e: ErrorKind = ErrorKind::IsA; - split_at_offset1_streaming(&i, |c| !arr.contains_token(c), e) + let e: ErrorKind = ErrorKind::IsA; + split_at_offset1_streaming(&i, |c| !arr.contains_token(c), e) } /// Returns the longest input slice (if any) that matches the predicate. @@ -293,28 +293,28 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::bytes::take_while0`][crate::bytes::take_while0] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::bytes::take_while0` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::bytes::take_while0` with input wrapped in `winnow::input::Streaming`" )] pub fn take_while>( - list: T, + list: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - move |i: I| take_while_internal(i, &list) + move |i: I| take_while_internal(i, &list) } pub(crate) fn take_while_internal>( - i: I, - list: &T, + i: I, + list: &T, ) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - split_at_offset_streaming(&i, |c| !list.contains_token(c)) + split_at_offset_streaming(&i, |c| !list.contains_token(c)) } /// Returns the longest (at least 1) input slice that matches the predicate. @@ -344,29 +344,29 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::bytes::take_while1`][crate::bytes::take_while1] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::bytes::take_while1` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::bytes::take_while1` with input wrapped in `winnow::input::Streaming`" )] pub fn take_while1>( - list: T, + list: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - move |i: I| take_while1_internal(i, &list) + move |i: I| take_while1_internal(i, &list) } pub(crate) fn take_while1_internal>( - i: I, - list: &T, + i: I, + list: &T, ) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - let e: ErrorKind = ErrorKind::TakeWhile1; - split_at_offset1_streaming(&i, |c| !list.contains_token(c), e) + let e: ErrorKind = ErrorKind::TakeWhile1; + split_at_offset1_streaming(&i, |c| !list.contains_token(c), e) } /// Returns the longest (m <= len <= n) input slice that matches the predicate. @@ -397,61 +397,61 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::bytes::take_while_m_n`][crate::bytes::take_while_m_n] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::bytes::take_while_m_n` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::bytes::take_while_m_n` with input wrapped in `winnow::input::Streaming`" )] pub fn take_while_m_n>( - m: usize, - n: usize, - list: T, + m: usize, + n: usize, + list: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - move |i: I| take_while_m_n_internal(i, m, n, &list) + move |i: I| take_while_m_n_internal(i, m, n, &list) } pub(crate) fn take_while_m_n_internal>( - input: I, - m: usize, - n: usize, - list: &T, + input: I, + m: usize, + n: usize, + list: &T, ) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - if n < m { - return Err(ErrMode::from_error_kind(input, ErrorKind::TakeWhileMN)); - } - - let mut final_count = 0; - for (processed, (offset, token)) in input.iter_offsets().enumerate() { - if !list.contains_token(token) { - if processed < m { + if n < m { return Err(ErrMode::from_error_kind(input, ErrorKind::TakeWhileMN)); - } else { - return Ok(input.next_slice(offset)); - } - } else { - if processed == n { - return Ok(input.next_slice(offset)); - } - final_count = processed + 1; } - } - if final_count == n { - Ok(input.next_slice(input.input_len())) - } else { - let needed = if m > input.input_len() { - m - input.input_len() + let mut final_count = 0; + for (processed, (offset, token)) in input.iter_offsets().enumerate() { + if !list.contains_token(token) { + if processed < m { + return Err(ErrMode::from_error_kind(input, ErrorKind::TakeWhileMN)); + } else { + return Ok(input.next_slice(offset)); + } + } else { + if processed == n { + return Ok(input.next_slice(offset)); + } + final_count = processed + 1; + } + } + + if final_count == n { + Ok(input.next_slice(input.input_len())) } else { - 1 - }; - Err(ErrMode::Incomplete(Needed::new(needed))) - } + let needed = if m > input.input_len() { + m - input.input_len() + } else { + 1 + }; + Err(ErrMode::Incomplete(Needed::new(needed))) + } } /// Returns the longest input slice (if any) till a predicate is met. @@ -480,29 +480,29 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::bytes::take_till0`][crate::bytes::take_till0] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::bytes::take_till0` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::bytes::take_till0` with input wrapped in `winnow::input::Streaming`" )] #[allow(clippy::redundant_closure)] pub fn take_till>( - list: T, + list: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - move |i: I| take_till_internal(i, &list) + move |i: I| take_till_internal(i, &list) } pub(crate) fn take_till_internal>( - i: I, - list: &T, + i: I, + list: &T, ) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - split_at_offset_streaming(&i, |c| list.contains_token(c)) + split_at_offset_streaming(&i, |c| list.contains_token(c)) } /// Returns the longest (at least 1) input slice till a predicate is met. @@ -530,30 +530,30 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::bytes::take_till1`][crate::bytes::take_till1] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::bytes::take_till1` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::bytes::take_till1` with input wrapped in `winnow::input::Streaming`" )] #[allow(clippy::redundant_closure)] pub fn take_till1>( - list: T, + list: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - move |i: I| take_till1_internal(i, &list) + move |i: I| take_till1_internal(i, &list) } pub(crate) fn take_till1_internal>( - i: I, - list: &T, + i: I, + list: &T, ) -> IResult::Slice, Error> where - I: Input, - T: ContainsToken<::Token>, + I: Input, + T: ContainsToken<::Token>, { - let e: ErrorKind = ErrorKind::TakeTill1; - split_at_offset1_streaming(&i, |c| list.contains_token(c), e) + let e: ErrorKind = ErrorKind::TakeTill1; + split_at_offset1_streaming(&i, |c| list.contains_token(c), e) } /// Returns an input slice containing the first N input elements (I[..N]). @@ -582,31 +582,31 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::bytes::take`][crate::bytes::take] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::bytes::take` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::bytes::take` with input wrapped in `winnow::input::Streaming`" )] pub fn take>( - count: C, + count: C, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input, - C: ToUsize, + I: Input, + C: ToUsize, { - let c = count.to_usize(); - move |i: I| take_internal(i, c) + let c = count.to_usize(); + move |i: I| take_internal(i, c) } pub(crate) fn take_internal>( - i: I, - c: usize, + i: I, + c: usize, ) -> IResult::Slice, Error> where - I: Input, + I: Input, { - match i.offset_at(c) { - Ok(offset) => Ok(i.next_slice(offset)), - Err(i) => Err(ErrMode::Incomplete(i)), - } + match i.offset_at(c) { + Ok(offset) => Ok(i.next_slice(offset)), + Err(i) => Err(ErrMode::Incomplete(i)), + } } /// Returns the input slice up to the first occurrence of the pattern. @@ -633,31 +633,31 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::bytes::take_until0`][crate::bytes::take_until0] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::bytes::take_until0` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::bytes::take_until0` with input wrapped in `winnow::input::Streaming`" )] pub fn take_until>( - tag: T, + tag: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input + FindSlice, - T: SliceLen + Clone, + I: Input + FindSlice, + T: SliceLen + Clone, { - move |i: I| take_until_internal(i, tag.clone()) + move |i: I| take_until_internal(i, tag.clone()) } pub(crate) fn take_until_internal>( - i: I, - t: T, + i: I, + t: T, ) -> IResult::Slice, Error> where - I: Input + FindSlice, - T: SliceLen, + I: Input + FindSlice, + T: SliceLen, { - match i.find_slice(t) { - Some(offset) => Ok(i.next_slice(offset)), - None => Err(ErrMode::Incomplete(Needed::Unknown)), - } + match i.find_slice(t) { + Some(offset) => Ok(i.next_slice(offset)), + None => Err(ErrMode::Incomplete(Needed::Unknown)), + } } /// Returns the non empty input slice up to the first occurrence of the pattern. @@ -685,32 +685,32 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::bytes::take_until1`][crate::bytes::take_until1] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::bytes::take_until1` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::bytes::take_until1` with input wrapped in `winnow::input::Streaming`" )] pub fn take_until1>( - tag: T, + tag: T, ) -> impl Fn(I) -> IResult::Slice, Error> where - I: Input + FindSlice, - T: SliceLen + Clone, + I: Input + FindSlice, + T: SliceLen + Clone, { - move |i: I| take_until1_internal(i, tag.clone()) + move |i: I| take_until1_internal(i, tag.clone()) } pub(crate) fn take_until1_internal>( - i: I, - t: T, + i: I, + t: T, ) -> IResult::Slice, Error> where - I: Input + FindSlice, - T: SliceLen, + I: Input + FindSlice, + T: SliceLen, { - match i.find_slice(t) { - None => Err(ErrMode::Incomplete(Needed::Unknown)), - Some(0) => Err(ErrMode::from_error_kind(i, ErrorKind::TakeUntil)), - Some(offset) => Ok(i.next_slice(offset)), - } + match i.find_slice(t) { + None => Err(ErrMode::Incomplete(Needed::Unknown)), + Some(0) => Err(ErrMode::from_error_kind(i, ErrorKind::TakeUntil)), + Some(offset) => Ok(i.next_slice(offset)), + } } /// Matches a byte string with escaped characters. @@ -736,84 +736,84 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::escaped`][crate::character::escaped] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::escaped` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::escaped` with input wrapped in `winnow::input::Streaming`" )] pub fn escaped( - mut normal: F, - control_char: char, - mut escapable: G, + mut normal: F, + control_char: char, + mut escapable: G, ) -> impl FnMut(I) -> IResult::Slice, Error> where - I: Input + Offset, - ::Token: crate::input::AsChar, - F: Parser, - G: Parser, - Error: ParseError, + I: Input + Offset, + ::Token: crate::input::AsChar, + F: Parser, + G: Parser, + Error: ParseError, { - move |input: I| escaped_internal(input, &mut normal, control_char, &mut escapable) + move |input: I| escaped_internal(input, &mut normal, control_char, &mut escapable) } pub(crate) fn escaped_internal( - input: I, - normal: &mut F, - control_char: char, - escapable: &mut G, + input: I, + normal: &mut F, + control_char: char, + escapable: &mut G, ) -> IResult::Slice, Error> where - I: Input + Offset, - ::Token: crate::input::AsChar, - F: Parser, - G: Parser, - Error: ParseError, + I: Input + Offset, + ::Token: crate::input::AsChar, + F: Parser, + G: Parser, + Error: ParseError, { - use crate::input::AsChar; + use crate::input::AsChar; - let mut i = input.clone(); + let mut i = input.clone(); - while i.input_len() > 0 { - let current_len = i.input_len(); + while i.input_len() > 0 { + let current_len = i.input_len(); - match normal.parse_next(i.clone()) { - Ok((i2, _)) => { - if i2.input_len() == 0 { - return Err(ErrMode::Incomplete(Needed::Unknown)); - } else if i2.input_len() == current_len { - let offset = input.offset_to(&i2); - return Ok(input.next_slice(offset)); - } else { - i = i2; - } - } - Err(ErrMode::Backtrack(_)) => { - if i.next_token().expect("input_len > 0").1.as_char() == control_char { - let next = control_char.len_utf8(); - if next >= i.input_len() { - return Err(ErrMode::Incomplete(Needed::new(1))); - } else { - match escapable.parse_next(i.next_slice(next).0) { - Ok((i2, _)) => { + match normal.parse_next(i.clone()) { + Ok((i2, _)) => { if i2.input_len() == 0 { - return Err(ErrMode::Incomplete(Needed::Unknown)); + return Err(ErrMode::Incomplete(Needed::Unknown)); + } else if i2.input_len() == current_len { + let offset = input.offset_to(&i2); + return Ok(input.next_slice(offset)); } else { - i = i2; + i = i2; } - } - Err(e) => return Err(e), } - } - } else { - let offset = input.offset_to(&i); - return Ok(input.next_slice(offset)); + Err(ErrMode::Backtrack(_)) => { + if i.next_token().expect("input_len > 0").1.as_char() == control_char { + let next = control_char.len_utf8(); + if next >= i.input_len() { + return Err(ErrMode::Incomplete(Needed::new(1))); + } else { + match escapable.parse_next(i.next_slice(next).0) { + Ok((i2, _)) => { + if i2.input_len() == 0 { + return Err(ErrMode::Incomplete(Needed::Unknown)); + } else { + i = i2; + } + } + Err(e) => return Err(e), + } + } + } else { + let offset = input.offset_to(&i); + return Ok(input.next_slice(offset)); + } + } + Err(e) => { + return Err(e); + } } - } - Err(e) => { - return Err(e); - } } - } - Err(ErrMode::Incomplete(Needed::Unknown)) + Err(ErrMode::Incomplete(Needed::Unknown)) } /// Matches a byte string with escaped characters. @@ -850,551 +850,551 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::escaped_transform`][crate::character::escaped_transform] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::escaped_transform` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::escaped_transform` with input wrapped in `winnow::input::Streaming`" )] pub fn escaped_transform( - mut normal: F, - control_char: char, - mut transform: G, + mut normal: F, + control_char: char, + mut transform: G, ) -> impl FnMut(I) -> IResult where - I: Input + Offset, - ::Token: crate::input::AsChar, - Output: crate::input::Accumulate<::Slice>, - F: Parser::Slice, Error>, - G: Parser::Slice, Error>, - Error: ParseError, + I: Input + Offset, + ::Token: crate::input::AsChar, + Output: crate::input::Accumulate<::Slice>, + F: Parser::Slice, Error>, + G: Parser::Slice, Error>, + Error: ParseError, { - move |input: I| escaped_transform_internal(input, &mut normal, control_char, &mut transform) + move |input: I| escaped_transform_internal(input, &mut normal, control_char, &mut transform) } #[cfg(feature = "alloc")] pub(crate) fn escaped_transform_internal( - input: I, - normal: &mut F, - control_char: char, - transform: &mut G, + input: I, + normal: &mut F, + control_char: char, + transform: &mut G, ) -> IResult where - I: Input + Offset, - ::Token: crate::input::AsChar, - Output: crate::input::Accumulate<::Slice>, - F: Parser::Slice, Error>, - G: Parser::Slice, Error>, - Error: ParseError, + I: Input + Offset, + ::Token: crate::input::AsChar, + Output: crate::input::Accumulate<::Slice>, + F: Parser::Slice, Error>, + G: Parser::Slice, Error>, + Error: ParseError, { - use crate::input::AsChar; - - let mut offset = 0; - let mut res = Output::initial(Some(input.input_len())); - - let i = input.clone(); - - while offset < i.input_len() { - let current_len = i.input_len(); - let remainder = i.next_slice(offset).0; - match normal.parse_next(remainder.clone()) { - Ok((i2, o)) => { - res.accumulate(o); - if i2.input_len() == 0 { - return Err(ErrMode::Incomplete(Needed::Unknown)); - } else if i2.input_len() == current_len { - return Ok((remainder, res)); - } else { - offset = input.offset_to(&i2); - } - } - Err(ErrMode::Backtrack(_)) => { - if remainder.next_token().expect("input_len > 0").1.as_char() == control_char { - let next = offset + control_char.len_utf8(); - let input_len = input.input_len(); - - if next >= input_len { - return Err(ErrMode::Incomplete(Needed::Unknown)); - } else { - match transform.parse_next(i.next_slice(next).0) { - Ok((i2, o)) => { + use crate::input::AsChar; + + let mut offset = 0; + let mut res = Output::initial(Some(input.input_len())); + + let i = input.clone(); + + while offset < i.input_len() { + let current_len = i.input_len(); + let remainder = i.next_slice(offset).0; + match normal.parse_next(remainder.clone()) { + Ok((i2, o)) => { res.accumulate(o); if i2.input_len() == 0 { - return Err(ErrMode::Incomplete(Needed::Unknown)); + return Err(ErrMode::Incomplete(Needed::Unknown)); + } else if i2.input_len() == current_len { + return Ok((remainder, res)); } else { - offset = input.offset_to(&i2); + offset = input.offset_to(&i2); } - } - Err(e) => return Err(e), } - } - } else { - return Ok((remainder, res)); + Err(ErrMode::Backtrack(_)) => { + if remainder.next_token().expect("input_len > 0").1.as_char() == control_char { + let next = offset + control_char.len_utf8(); + let input_len = input.input_len(); + + if next >= input_len { + return Err(ErrMode::Incomplete(Needed::Unknown)); + } else { + match transform.parse_next(i.next_slice(next).0) { + Ok((i2, o)) => { + res.accumulate(o); + if i2.input_len() == 0 { + return Err(ErrMode::Incomplete(Needed::Unknown)); + } else { + offset = input.offset_to(&i2); + } + } + Err(e) => return Err(e), + } + } + } else { + return Ok((remainder, res)); + } + } + Err(e) => return Err(e), } - } - Err(e) => return Err(e), } - } - Err(ErrMode::Incomplete(Needed::Unknown)) + Err(ErrMode::Incomplete(Needed::Unknown)) } #[cfg(test)] mod tests { - use crate::character::streaming::{ - alpha1 as alpha, alphanumeric1 as alphanumeric, digit1 as digit, hex_digit1 as hex_digit, - multispace1 as multispace, oct_digit1 as oct_digit, space1 as space, - }; - use crate::error::ErrorKind; - use crate::error::{ErrMode, Needed}; - use crate::input::AsChar; - use crate::IResult; - - #[test] - fn is_a() { - use crate::bytes::streaming::is_a; - - fn a_or_b(i: &[u8]) -> IResult<&[u8], &[u8]> { - is_a("ab")(i) - } + use crate::character::streaming::{ + alpha1 as alpha, alphanumeric1 as alphanumeric, digit1 as digit, hex_digit1 as hex_digit, + multispace1 as multispace, oct_digit1 as oct_digit, space1 as space, + }; + use crate::error::ErrorKind; + use crate::error::{ErrMode, Needed}; + use crate::input::AsChar; + use crate::IResult; - let a = &b"abcd"[..]; - assert_eq!(a_or_b(a), Ok((&b"cd"[..], &b"ab"[..]))); + #[test] + fn is_a() { + use crate::bytes::streaming::is_a; - let b = &b"bcde"[..]; - assert_eq!(a_or_b(b), Ok((&b"cde"[..], &b"b"[..]))); + fn a_or_b(i: &[u8]) -> IResult<&[u8], &[u8]> { + is_a("ab")(i) + } - let c = &b"cdef"[..]; - assert_eq!( - a_or_b(c), - Err(ErrMode::Backtrack(error_position!(c, ErrorKind::IsA))) - ); + let a = &b"abcd"[..]; + assert_eq!(a_or_b(a), Ok((&b"cd"[..], &b"ab"[..]))); - let d = &b"bacdef"[..]; - assert_eq!(a_or_b(d), Ok((&b"cdef"[..], &b"ba"[..]))); - } + let b = &b"bcde"[..]; + assert_eq!(a_or_b(b), Ok((&b"cde"[..], &b"b"[..]))); - #[test] - fn is_not() { - use crate::bytes::streaming::is_not; + let c = &b"cdef"[..]; + assert_eq!( + a_or_b(c), + Err(ErrMode::Backtrack(error_position!(c, ErrorKind::IsA))) + ); - fn a_or_b(i: &[u8]) -> IResult<&[u8], &[u8]> { - is_not("ab")(i) + let d = &b"bacdef"[..]; + assert_eq!(a_or_b(d), Ok((&b"cdef"[..], &b"ba"[..]))); } - let a = &b"cdab"[..]; - assert_eq!(a_or_b(a), Ok((&b"ab"[..], &b"cd"[..]))); + #[test] + fn is_not() { + use crate::bytes::streaming::is_not; - let b = &b"cbde"[..]; - assert_eq!(a_or_b(b), Ok((&b"bde"[..], &b"c"[..]))); + fn a_or_b(i: &[u8]) -> IResult<&[u8], &[u8]> { + is_not("ab")(i) + } - let c = &b"abab"[..]; - assert_eq!( - a_or_b(c), - Err(ErrMode::Backtrack(error_position!(c, ErrorKind::IsNot))) - ); + let a = &b"cdab"[..]; + assert_eq!(a_or_b(a), Ok((&b"ab"[..], &b"cd"[..]))); - let d = &b"cdefba"[..]; - assert_eq!(a_or_b(d), Ok((&b"ba"[..], &b"cdef"[..]))); + let b = &b"cbde"[..]; + assert_eq!(a_or_b(b), Ok((&b"bde"[..], &b"c"[..]))); - let e = &b"e"[..]; - assert_eq!(a_or_b(e), Err(ErrMode::Incomplete(Needed::new(1)))); - } + let c = &b"abab"[..]; + assert_eq!( + a_or_b(c), + Err(ErrMode::Backtrack(error_position!(c, ErrorKind::IsNot))) + ); - #[test] - fn take_until_incomplete() { - use crate::bytes::streaming::take_until; - fn y(i: &[u8]) -> IResult<&[u8], &[u8]> { - take_until("end")(i) - } - assert_eq!(y(&b"nd"[..]), Err(ErrMode::Incomplete(Needed::Unknown))); - assert_eq!(y(&b"123"[..]), Err(ErrMode::Incomplete(Needed::Unknown))); - assert_eq!(y(&b"123en"[..]), Err(ErrMode::Incomplete(Needed::Unknown))); - } - - #[test] - fn take_until_incomplete_s() { - use crate::bytes::streaming::take_until; - fn ys(i: &str) -> IResult<&str, &str> { - take_until("end")(i) + let d = &b"cdefba"[..]; + assert_eq!(a_or_b(d), Ok((&b"ba"[..], &b"cdef"[..]))); + + let e = &b"e"[..]; + assert_eq!(a_or_b(e), Err(ErrMode::Incomplete(Needed::new(1)))); } - assert_eq!(ys("123en"), Err(ErrMode::Incomplete(Needed::Unknown))); - } - #[test] - fn recognize() { - use crate::bytes::streaming::{tag, take}; - use crate::combinator::recognize; - use crate::sequence::delimited; + #[test] + fn take_until_incomplete() { + use crate::bytes::streaming::take_until; + fn y(i: &[u8]) -> IResult<&[u8], &[u8]> { + take_until("end")(i) + } + assert_eq!(y(&b"nd"[..]), Err(ErrMode::Incomplete(Needed::Unknown))); + assert_eq!(y(&b"123"[..]), Err(ErrMode::Incomplete(Needed::Unknown))); + assert_eq!(y(&b"123en"[..]), Err(ErrMode::Incomplete(Needed::Unknown))); + } - fn x(i: &[u8]) -> IResult<&[u8], &[u8]> { - recognize(delimited(tag("")))(i) + #[test] + fn take_until_incomplete_s() { + use crate::bytes::streaming::take_until; + fn ys(i: &str) -> IResult<&str, &str> { + take_until("end")(i) + } + assert_eq!(ys("123en"), Err(ErrMode::Incomplete(Needed::Unknown))); } - let r = x(&b" aaa"[..]); - assert_eq!(r, Ok((&b" aaa"[..], &b""[..]))); - let semicolon = &b";"[..]; + #[test] + fn recognize() { + use crate::bytes::streaming::{tag, take}; + use crate::combinator::recognize; + use crate::sequence::delimited; - fn ya(i: &[u8]) -> IResult<&[u8], &[u8]> { - recognize(alpha)(i) - } - let ra = ya(&b"abc;"[..]); - assert_eq!(ra, Ok((semicolon, &b"abc"[..]))); + fn x(i: &[u8]) -> IResult<&[u8], &[u8]> { + recognize(delimited(tag("")))(i) + } + let r = x(&b" aaa"[..]); + assert_eq!(r, Ok((&b" aaa"[..], &b""[..]))); - fn yd(i: &[u8]) -> IResult<&[u8], &[u8]> { - recognize(digit)(i) - } - let rd = yd(&b"123;"[..]); - assert_eq!(rd, Ok((semicolon, &b"123"[..]))); + let semicolon = &b";"[..]; - fn yhd(i: &[u8]) -> IResult<&[u8], &[u8]> { - recognize(hex_digit)(i) - } - let rhd = yhd(&b"123abcDEF;"[..]); - assert_eq!(rhd, Ok((semicolon, &b"123abcDEF"[..]))); + fn ya(i: &[u8]) -> IResult<&[u8], &[u8]> { + recognize(alpha)(i) + } + let ra = ya(&b"abc;"[..]); + assert_eq!(ra, Ok((semicolon, &b"abc"[..]))); - fn yod(i: &[u8]) -> IResult<&[u8], &[u8]> { - recognize(oct_digit)(i) - } - let rod = yod(&b"1234567;"[..]); - assert_eq!(rod, Ok((semicolon, &b"1234567"[..]))); + fn yd(i: &[u8]) -> IResult<&[u8], &[u8]> { + recognize(digit)(i) + } + let rd = yd(&b"123;"[..]); + assert_eq!(rd, Ok((semicolon, &b"123"[..]))); - fn yan(i: &[u8]) -> IResult<&[u8], &[u8]> { - recognize(alphanumeric)(i) - } - let ran = yan(&b"123abc;"[..]); - assert_eq!(ran, Ok((semicolon, &b"123abc"[..]))); + fn yhd(i: &[u8]) -> IResult<&[u8], &[u8]> { + recognize(hex_digit)(i) + } + let rhd = yhd(&b"123abcDEF;"[..]); + assert_eq!(rhd, Ok((semicolon, &b"123abcDEF"[..]))); - fn ys(i: &[u8]) -> IResult<&[u8], &[u8]> { - recognize(space)(i) - } - let rs = ys(&b" \t;"[..]); - assert_eq!(rs, Ok((semicolon, &b" \t"[..]))); + fn yod(i: &[u8]) -> IResult<&[u8], &[u8]> { + recognize(oct_digit)(i) + } + let rod = yod(&b"1234567;"[..]); + assert_eq!(rod, Ok((semicolon, &b"1234567"[..]))); - fn yms(i: &[u8]) -> IResult<&[u8], &[u8]> { - recognize(multispace)(i) - } - let rms = yms(&b" \t\r\n;"[..]); - assert_eq!(rms, Ok((semicolon, &b" \t\r\n"[..]))); - } + fn yan(i: &[u8]) -> IResult<&[u8], &[u8]> { + recognize(alphanumeric)(i) + } + let ran = yan(&b"123abc;"[..]); + assert_eq!(ran, Ok((semicolon, &b"123abc"[..]))); - #[test] - fn take_while() { - use crate::bytes::streaming::take_while; + fn ys(i: &[u8]) -> IResult<&[u8], &[u8]> { + recognize(space)(i) + } + let rs = ys(&b" \t;"[..]); + assert_eq!(rs, Ok((semicolon, &b" \t"[..]))); - fn f(i: &[u8]) -> IResult<&[u8], &[u8]> { - take_while(AsChar::is_alpha)(i) - } - let a = b""; - let b = b"abcd"; - let c = b"abcd123"; - let d = b"123"; - - assert_eq!(f(&a[..]), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(f(&b[..]), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(f(&c[..]), Ok((&d[..], &b[..]))); - assert_eq!(f(&d[..]), Ok((&d[..], &a[..]))); - } - - #[test] - fn take_while1() { - use crate::bytes::streaming::take_while1; - - fn f(i: &[u8]) -> IResult<&[u8], &[u8]> { - take_while1(AsChar::is_alpha)(i) + fn yms(i: &[u8]) -> IResult<&[u8], &[u8]> { + recognize(multispace)(i) + } + let rms = yms(&b" \t\r\n;"[..]); + assert_eq!(rms, Ok((semicolon, &b" \t\r\n"[..]))); } - let a = b""; - let b = b"abcd"; - let c = b"abcd123"; - let d = b"123"; - - assert_eq!(f(&a[..]), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(f(&b[..]), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(f(&c[..]), Ok((&b"123"[..], &b[..]))); - assert_eq!( - f(&d[..]), - Err(ErrMode::Backtrack(error_position!( - &d[..], - ErrorKind::TakeWhile1 - ))) - ); - } - - #[test] - fn take_while_m_n() { - use crate::bytes::streaming::take_while_m_n; - - fn x(i: &[u8]) -> IResult<&[u8], &[u8]> { - take_while_m_n(2, 4, AsChar::is_alpha)(i) + + #[test] + fn take_while() { + use crate::bytes::streaming::take_while; + + fn f(i: &[u8]) -> IResult<&[u8], &[u8]> { + take_while(AsChar::is_alpha)(i) + } + let a = b""; + let b = b"abcd"; + let c = b"abcd123"; + let d = b"123"; + + assert_eq!(f(&a[..]), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(f(&b[..]), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(f(&c[..]), Ok((&d[..], &b[..]))); + assert_eq!(f(&d[..]), Ok((&d[..], &a[..]))); } - let a = b""; - let b = b"a"; - let c = b"abc"; - let d = b"abc123"; - let e = b"abcde"; - let f = b"123"; - - assert_eq!(x(&a[..]), Err(ErrMode::Incomplete(Needed::new(2)))); - assert_eq!(x(&b[..]), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(x(&c[..]), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(x(&d[..]), Ok((&b"123"[..], &c[..]))); - assert_eq!(x(&e[..]), Ok((&b"e"[..], &b"abcd"[..]))); - assert_eq!( - x(&f[..]), - Err(ErrMode::Backtrack(error_position!( - &f[..], - ErrorKind::TakeWhileMN - ))) - ); - } - - #[test] - fn take_till() { - use crate::bytes::streaming::take_till; - - fn f(i: &[u8]) -> IResult<&[u8], &[u8]> { - take_till(AsChar::is_alpha)(i) + + #[test] + fn take_while1() { + use crate::bytes::streaming::take_while1; + + fn f(i: &[u8]) -> IResult<&[u8], &[u8]> { + take_while1(AsChar::is_alpha)(i) + } + let a = b""; + let b = b"abcd"; + let c = b"abcd123"; + let d = b"123"; + + assert_eq!(f(&a[..]), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(f(&b[..]), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(f(&c[..]), Ok((&b"123"[..], &b[..]))); + assert_eq!( + f(&d[..]), + Err(ErrMode::Backtrack(error_position!( + &d[..], + ErrorKind::TakeWhile1 + ))) + ); } - let a = b""; - let b = b"abcd"; - let c = b"123abcd"; - let d = b"123"; - - assert_eq!(f(&a[..]), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(f(&b[..]), Ok((&b"abcd"[..], &b""[..]))); - assert_eq!(f(&c[..]), Ok((&b"abcd"[..], &b"123"[..]))); - assert_eq!(f(&d[..]), Err(ErrMode::Incomplete(Needed::new(1)))); - } - - #[test] - fn take_till1() { - use crate::bytes::streaming::take_till1; - - fn f(i: &[u8]) -> IResult<&[u8], &[u8]> { - take_till1(AsChar::is_alpha)(i) + + #[test] + fn take_while_m_n() { + use crate::bytes::streaming::take_while_m_n; + + fn x(i: &[u8]) -> IResult<&[u8], &[u8]> { + take_while_m_n(2, 4, AsChar::is_alpha)(i) + } + let a = b""; + let b = b"a"; + let c = b"abc"; + let d = b"abc123"; + let e = b"abcde"; + let f = b"123"; + + assert_eq!(x(&a[..]), Err(ErrMode::Incomplete(Needed::new(2)))); + assert_eq!(x(&b[..]), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(x(&c[..]), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(x(&d[..]), Ok((&b"123"[..], &c[..]))); + assert_eq!(x(&e[..]), Ok((&b"e"[..], &b"abcd"[..]))); + assert_eq!( + x(&f[..]), + Err(ErrMode::Backtrack(error_position!( + &f[..], + ErrorKind::TakeWhileMN + ))) + ); } - let a = b""; - let b = b"abcd"; - let c = b"123abcd"; - let d = b"123"; - - assert_eq!(f(&a[..]), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!( - f(&b[..]), - Err(ErrMode::Backtrack(error_position!( - &b[..], - ErrorKind::TakeTill1 - ))) - ); - assert_eq!(f(&c[..]), Ok((&b"abcd"[..], &b"123"[..]))); - assert_eq!(f(&d[..]), Err(ErrMode::Incomplete(Needed::new(1)))); - } - - #[test] - fn take_while_utf8() { - use crate::bytes::streaming::take_while; - - fn f(i: &str) -> IResult<&str, &str> { - take_while(|c| c != '點')(i) + + #[test] + fn take_till() { + use crate::bytes::streaming::take_till; + + fn f(i: &[u8]) -> IResult<&[u8], &[u8]> { + take_till(AsChar::is_alpha)(i) + } + let a = b""; + let b = b"abcd"; + let c = b"123abcd"; + let d = b"123"; + + assert_eq!(f(&a[..]), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(f(&b[..]), Ok((&b"abcd"[..], &b""[..]))); + assert_eq!(f(&c[..]), Ok((&b"abcd"[..], &b"123"[..]))); + assert_eq!(f(&d[..]), Err(ErrMode::Incomplete(Needed::new(1)))); } - assert_eq!(f(""), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(f("abcd"), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(f("abcd點"), Ok(("點", "abcd"))); - assert_eq!(f("abcd點a"), Ok(("點a", "abcd"))); + #[test] + fn take_till1() { + use crate::bytes::streaming::take_till1; - fn g(i: &str) -> IResult<&str, &str> { - take_while(|c| c == '點')(i) + fn f(i: &[u8]) -> IResult<&[u8], &[u8]> { + take_till1(AsChar::is_alpha)(i) + } + let a = b""; + let b = b"abcd"; + let c = b"123abcd"; + let d = b"123"; + + assert_eq!(f(&a[..]), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!( + f(&b[..]), + Err(ErrMode::Backtrack(error_position!( + &b[..], + ErrorKind::TakeTill1 + ))) + ); + assert_eq!(f(&c[..]), Ok((&b"abcd"[..], &b"123"[..]))); + assert_eq!(f(&d[..]), Err(ErrMode::Incomplete(Needed::new(1)))); } - assert_eq!(g(""), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(g("點abcd"), Ok(("abcd", "點"))); - assert_eq!(g("點點點a"), Ok(("a", "點點點"))); - } + #[test] + fn take_while_utf8() { + use crate::bytes::streaming::take_while; - #[test] - fn take_till_utf8() { - use crate::bytes::streaming::take_till; + fn f(i: &str) -> IResult<&str, &str> { + take_while(|c| c != '點')(i) + } - fn f(i: &str) -> IResult<&str, &str> { - take_till(|c| c == '點')(i) - } + assert_eq!(f(""), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(f("abcd"), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(f("abcd點"), Ok(("點", "abcd"))); + assert_eq!(f("abcd點a"), Ok(("點a", "abcd"))); - assert_eq!(f(""), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(f("abcd"), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(f("abcd點"), Ok(("點", "abcd"))); - assert_eq!(f("abcd點a"), Ok(("點a", "abcd"))); + fn g(i: &str) -> IResult<&str, &str> { + take_while(|c| c == '點')(i) + } - fn g(i: &str) -> IResult<&str, &str> { - take_till(|c| c != '點')(i) + assert_eq!(g(""), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(g("點abcd"), Ok(("abcd", "點"))); + assert_eq!(g("點點點a"), Ok(("a", "點點點"))); } - assert_eq!(g(""), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(g("點abcd"), Ok(("abcd", "點"))); - assert_eq!(g("點點點a"), Ok(("a", "點點點"))); - } + #[test] + fn take_till_utf8() { + use crate::bytes::streaming::take_till; - #[test] - fn take_utf8() { - use crate::bytes::streaming::{take, take_while}; + fn f(i: &str) -> IResult<&str, &str> { + take_till(|c| c == '點')(i) + } - fn f(i: &str) -> IResult<&str, &str> { - take(3_usize)(i) - } + assert_eq!(f(""), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(f("abcd"), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(f("abcd點"), Ok(("點", "abcd"))); + assert_eq!(f("abcd點a"), Ok(("點a", "abcd"))); - assert_eq!(f(""), Err(ErrMode::Incomplete(Needed::Unknown))); - assert_eq!(f("ab"), Err(ErrMode::Incomplete(Needed::Unknown))); - assert_eq!(f("點"), Err(ErrMode::Incomplete(Needed::Unknown))); - assert_eq!(f("ab點cd"), Ok(("cd", "ab點"))); - assert_eq!(f("a點bcd"), Ok(("cd", "a點b"))); - assert_eq!(f("a點b"), Ok(("", "a點b"))); + fn g(i: &str) -> IResult<&str, &str> { + take_till(|c| c != '點')(i) + } - fn g(i: &str) -> IResult<&str, &str> { - take_while(|c| c == '點')(i) + assert_eq!(g(""), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(g("點abcd"), Ok(("abcd", "點"))); + assert_eq!(g("點點點a"), Ok(("a", "點點點"))); } - assert_eq!(g(""), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(g("點abcd"), Ok(("abcd", "點"))); - assert_eq!(g("點點點a"), Ok(("a", "點點點"))); - } + #[test] + fn take_utf8() { + use crate::bytes::streaming::{take, take_while}; - #[test] - fn take_while_m_n_utf8() { - use crate::bytes::streaming::take_while_m_n; + fn f(i: &str) -> IResult<&str, &str> { + take(3_usize)(i) + } - fn parser(i: &str) -> IResult<&str, &str> { - take_while_m_n(1, 1, |c| c == 'A' || c == '😃')(i) - } - assert_eq!(parser("A!"), Ok(("!", "A"))); - assert_eq!(parser("😃!"), Ok(("!", "😃"))); - } + assert_eq!(f(""), Err(ErrMode::Incomplete(Needed::Unknown))); + assert_eq!(f("ab"), Err(ErrMode::Incomplete(Needed::Unknown))); + assert_eq!(f("點"), Err(ErrMode::Incomplete(Needed::Unknown))); + assert_eq!(f("ab點cd"), Ok(("cd", "ab點"))); + assert_eq!(f("a點bcd"), Ok(("cd", "a點b"))); + assert_eq!(f("a點b"), Ok(("", "a點b"))); - #[test] - fn take_while_m_n_utf8_full_match() { - use crate::bytes::streaming::take_while_m_n; + fn g(i: &str) -> IResult<&str, &str> { + take_while(|c| c == '點')(i) + } - fn parser(i: &str) -> IResult<&str, &str> { - take_while_m_n(1, 1, |c: char| c.is_alphabetic())(i) + assert_eq!(g(""), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(g("點abcd"), Ok(("abcd", "點"))); + assert_eq!(g("點點點a"), Ok(("a", "點點點"))); } - assert_eq!(parser("øn"), Ok(("n", "ø"))); - } - #[test] - #[cfg(feature = "std")] - fn recognize_take_while() { - use crate::bytes::streaming::take_while; - use crate::combinator::recognize; + #[test] + fn take_while_m_n_utf8() { + use crate::bytes::streaming::take_while_m_n; - fn x(i: &[u8]) -> IResult<&[u8], &[u8]> { - take_while(AsChar::is_alphanum)(i) - } - fn y(i: &[u8]) -> IResult<&[u8], &[u8]> { - recognize(x)(i) - } - assert_eq!(x(&b"ab."[..]), Ok((&b"."[..], &b"ab"[..]))); - println!("X: {:?}", x(&b"ab"[..])); - assert_eq!(y(&b"ab."[..]), Ok((&b"."[..], &b"ab"[..]))); - } - - #[test] - fn length_bytes() { - use crate::input::Streaming; - use crate::{bytes::streaming::tag, multi::length_data, number::streaming::le_u8}; - - fn x(i: Streaming<&[u8]>) -> IResult, &[u8]> { - length_data(le_u8)(i) + fn parser(i: &str) -> IResult<&str, &str> { + take_while_m_n(1, 1, |c| c == 'A' || c == '😃')(i) + } + assert_eq!(parser("A!"), Ok(("!", "A"))); + assert_eq!(parser("😃!"), Ok(("!", "😃"))); } - assert_eq!( - x(Streaming(b"\x02..>>")), - Ok((Streaming(&b">>"[..]), &b".."[..])) - ); - assert_eq!( - x(Streaming(b"\x02..")), - Ok((Streaming(&[][..]), &b".."[..])) - ); - assert_eq!( - x(Streaming(b"\x02.")), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - x(Streaming(b"\x02")), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - - fn y(i: Streaming<&[u8]>) -> IResult, &[u8]> { - let (i, _) = tag("magic")(i)?; - length_data(le_u8)(i) + + #[test] + fn take_while_m_n_utf8_full_match() { + use crate::bytes::streaming::take_while_m_n; + + fn parser(i: &str) -> IResult<&str, &str> { + take_while_m_n(1, 1, |c: char| c.is_alphabetic())(i) + } + assert_eq!(parser("øn"), Ok(("n", "ø"))); } - assert_eq!( - y(Streaming(b"magic\x02..>>")), - Ok((Streaming(&b">>"[..]), &b".."[..])) - ); - assert_eq!( - y(Streaming(b"magic\x02..")), - Ok((Streaming(&[][..]), &b".."[..])) - ); - assert_eq!( - y(Streaming(b"magic\x02.")), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - y(Streaming(b"magic\x02")), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - } - - #[cfg(feature = "alloc")] - #[test] - fn case_insensitive() { - use crate::bytes::streaming::tag_no_case; - - fn test(i: &[u8]) -> IResult<&[u8], &[u8]> { - tag_no_case("ABcd")(i) + + #[test] + #[cfg(feature = "std")] + fn recognize_take_while() { + use crate::bytes::streaming::take_while; + use crate::combinator::recognize; + + fn x(i: &[u8]) -> IResult<&[u8], &[u8]> { + take_while(AsChar::is_alphanum)(i) + } + fn y(i: &[u8]) -> IResult<&[u8], &[u8]> { + recognize(x)(i) + } + assert_eq!(x(&b"ab."[..]), Ok((&b"."[..], &b"ab"[..]))); + println!("X: {:?}", x(&b"ab"[..])); + assert_eq!(y(&b"ab."[..]), Ok((&b"."[..], &b"ab"[..]))); } - assert_eq!(test(&b"aBCdefgh"[..]), Ok((&b"efgh"[..], &b"aBCd"[..]))); - assert_eq!(test(&b"abcdefgh"[..]), Ok((&b"efgh"[..], &b"abcd"[..]))); - assert_eq!(test(&b"ABCDefgh"[..]), Ok((&b"efgh"[..], &b"ABCD"[..]))); - assert_eq!(test(&b"ab"[..]), Err(ErrMode::Incomplete(Needed::new(2)))); - assert_eq!( - test(&b"Hello"[..]), - Err(ErrMode::Backtrack(error_position!( - &b"Hello"[..], - ErrorKind::Tag - ))) - ); - assert_eq!( - test(&b"Hel"[..]), - Err(ErrMode::Backtrack(error_position!( - &b"Hel"[..], - ErrorKind::Tag - ))) - ); - - fn test2(i: &str) -> IResult<&str, &str> { - tag_no_case("ABcd")(i) + + #[test] + fn length_bytes() { + use crate::input::Streaming; + use crate::{bytes::streaming::tag, multi::length_data, number::streaming::le_u8}; + + fn x(i: Streaming<&[u8]>) -> IResult, &[u8]> { + length_data(le_u8)(i) + } + assert_eq!( + x(Streaming(b"\x02..>>")), + Ok((Streaming(&b">>"[..]), &b".."[..])) + ); + assert_eq!( + x(Streaming(b"\x02..")), + Ok((Streaming(&[][..]), &b".."[..])) + ); + assert_eq!( + x(Streaming(b"\x02.")), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + x(Streaming(b"\x02")), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + + fn y(i: Streaming<&[u8]>) -> IResult, &[u8]> { + let (i, _) = tag("magic")(i)?; + length_data(le_u8)(i) + } + assert_eq!( + y(Streaming(b"magic\x02..>>")), + Ok((Streaming(&b">>"[..]), &b".."[..])) + ); + assert_eq!( + y(Streaming(b"magic\x02..")), + Ok((Streaming(&[][..]), &b".."[..])) + ); + assert_eq!( + y(Streaming(b"magic\x02.")), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + y(Streaming(b"magic\x02")), + Err(ErrMode::Incomplete(Needed::new(2))) + ); } - assert_eq!(test2("aBCdefgh"), Ok(("efgh", "aBCd"))); - assert_eq!(test2("abcdefgh"), Ok(("efgh", "abcd"))); - assert_eq!(test2("ABCDefgh"), Ok(("efgh", "ABCD"))); - assert_eq!(test2("ab"), Err(ErrMode::Incomplete(Needed::new(2)))); - assert_eq!( - test2("Hello"), - Err(ErrMode::Backtrack(error_position!("Hello", ErrorKind::Tag))) - ); - assert_eq!( - test2("Hel"), - Err(ErrMode::Backtrack(error_position!("Hel", ErrorKind::Tag))) - ); - } - - #[test] - fn tag_fixed_size_array() { - use crate::bytes::streaming::tag; - - fn test(i: &[u8]) -> IResult<&[u8], &[u8]> { - tag([0x42])(i) + + #[cfg(feature = "alloc")] + #[test] + fn case_insensitive() { + use crate::bytes::streaming::tag_no_case; + + fn test(i: &[u8]) -> IResult<&[u8], &[u8]> { + tag_no_case("ABcd")(i) + } + assert_eq!(test(&b"aBCdefgh"[..]), Ok((&b"efgh"[..], &b"aBCd"[..]))); + assert_eq!(test(&b"abcdefgh"[..]), Ok((&b"efgh"[..], &b"abcd"[..]))); + assert_eq!(test(&b"ABCDefgh"[..]), Ok((&b"efgh"[..], &b"ABCD"[..]))); + assert_eq!(test(&b"ab"[..]), Err(ErrMode::Incomplete(Needed::new(2)))); + assert_eq!( + test(&b"Hello"[..]), + Err(ErrMode::Backtrack(error_position!( + &b"Hello"[..], + ErrorKind::Tag + ))) + ); + assert_eq!( + test(&b"Hel"[..]), + Err(ErrMode::Backtrack(error_position!( + &b"Hel"[..], + ErrorKind::Tag + ))) + ); + + fn test2(i: &str) -> IResult<&str, &str> { + tag_no_case("ABcd")(i) + } + assert_eq!(test2("aBCdefgh"), Ok(("efgh", "aBCd"))); + assert_eq!(test2("abcdefgh"), Ok(("efgh", "abcd"))); + assert_eq!(test2("ABCDefgh"), Ok(("efgh", "ABCD"))); + assert_eq!(test2("ab"), Err(ErrMode::Incomplete(Needed::new(2)))); + assert_eq!( + test2("Hello"), + Err(ErrMode::Backtrack(error_position!("Hello", ErrorKind::Tag))) + ); + assert_eq!( + test2("Hel"), + Err(ErrMode::Backtrack(error_position!("Hel", ErrorKind::Tag))) + ); } - fn test2(i: &[u8]) -> IResult<&[u8], &[u8]> { - tag(&[0x42])(i) + + #[test] + fn tag_fixed_size_array() { + use crate::bytes::streaming::tag; + + fn test(i: &[u8]) -> IResult<&[u8], &[u8]> { + tag([0x42])(i) + } + fn test2(i: &[u8]) -> IResult<&[u8], &[u8]> { + tag(&[0x42])(i) + } + let input = [0x42, 0x00]; + assert_eq!(test(&input), Ok((&b"\x00"[..], &b"\x42"[..]))); + assert_eq!(test2(&input), Ok((&b"\x00"[..], &b"\x42"[..]))); } - let input = [0x42, 0x00]; - assert_eq!(test(&input), Ok((&b"\x00"[..], &b"\x42"[..]))); - assert_eq!(test2(&input), Ok((&b"\x00"[..], &b"\x42"[..]))); - } } diff --git a/src/bytes/tests.rs b/src/bytes/tests.rs index 44368663..8a822d0b 100644 --- a/src/bytes/tests.rs +++ b/src/bytes/tests.rs @@ -17,37 +17,37 @@ use crate::Parser; #[test] fn complete_take_while_m_n_utf8_all_matching() { - let result: IResult<&str, &str> = take_while_m_n(1, 4, |c: char| c.is_alphabetic())("øn"); - assert_eq!(result, Ok(("", "øn"))); + let result: IResult<&str, &str> = take_while_m_n(1, 4, |c: char| c.is_alphabetic())("øn"); + assert_eq!(result, Ok(("", "øn"))); } #[test] fn complete_take_while_m_n_utf8_all_matching_substring() { - let result: IResult<&str, &str> = take_while_m_n(1, 1, |c: char| c.is_alphabetic())("øn"); - assert_eq!(result, Ok(("n", "ø"))); + let result: IResult<&str, &str> = take_while_m_n(1, 1, |c: char| c.is_alphabetic())("øn"); + assert_eq!(result, Ok(("n", "ø"))); } #[cfg(feature = "std")] fn model_complete_take_while_m_n( - m: usize, - n: usize, - valid: usize, - input: &str, + m: usize, + n: usize, + valid: usize, + input: &str, ) -> IResult<&str, &str> { - if n < m { - Err(crate::error::ErrMode::from_error_kind( - input, - crate::error::ErrorKind::TakeWhileMN, - )) - } else if m <= valid { - let offset = n.min(valid); - Ok((&input[offset..], &input[0..offset])) - } else { - Err(crate::error::ErrMode::from_error_kind( - input, - crate::error::ErrorKind::TakeWhileMN, - )) - } + if n < m { + Err(crate::error::ErrMode::from_error_kind( + input, + crate::error::ErrorKind::TakeWhileMN, + )) + } else if m <= valid { + let offset = n.min(valid); + Ok((&input[offset..], &input[0..offset])) + } else { + Err(crate::error::ErrMode::from_error_kind( + input, + crate::error::ErrorKind::TakeWhileMN, + )) + } } #[cfg(feature = "std")] @@ -63,592 +63,592 @@ proptest! { #[test] fn streaming_any_str() { - use super::any; - assert_eq!( - any::<_, Error>, true>(Streaming("Ә")), - Ok((Streaming(""), 'Ә')) - ); + use super::any; + assert_eq!( + any::<_, Error>, true>(Streaming("Ә")), + Ok((Streaming(""), 'Ә')) + ); } #[test] fn streaming_one_of_test() { - fn f(i: Streaming<&[u8]>) -> IResult, u8> { - one_of("ab")(i) - } - - let a = &b"abcd"[..]; - assert_eq!(f(Streaming(a)), Ok((Streaming(&b"bcd"[..]), b'a'))); - - let b = &b"cde"[..]; - assert_eq!( - f(Streaming(b)), - Err(ErrMode::Backtrack(error_position!( - Streaming(b), - ErrorKind::OneOf - ))) - ); - - fn utf8(i: Streaming<&str>) -> IResult, char> { - one_of("+\u{FF0B}")(i) - } - - assert!(utf8(Streaming("+")).is_ok()); - assert!(utf8(Streaming("\u{FF0B}")).is_ok()); + fn f(i: Streaming<&[u8]>) -> IResult, u8> { + one_of("ab")(i) + } + + let a = &b"abcd"[..]; + assert_eq!(f(Streaming(a)), Ok((Streaming(&b"bcd"[..]), b'a'))); + + let b = &b"cde"[..]; + assert_eq!( + f(Streaming(b)), + Err(ErrMode::Backtrack(error_position!( + Streaming(b), + ErrorKind::OneOf + ))) + ); + + fn utf8(i: Streaming<&str>) -> IResult, char> { + one_of("+\u{FF0B}")(i) + } + + assert!(utf8(Streaming("+")).is_ok()); + assert!(utf8(Streaming("\u{FF0B}")).is_ok()); } #[test] fn char_byteslice() { - fn f(i: Streaming<&[u8]>) -> IResult, u8> { - one_of('c')(i) - } - - let a = &b"abcd"[..]; - assert_eq!( - f(Streaming(a)), - Err(ErrMode::Backtrack(error_position!( - Streaming(a), - ErrorKind::OneOf - ))) - ); - - let b = &b"cde"[..]; - assert_eq!(f(Streaming(b)), Ok((Streaming(&b"de"[..]), b'c'))); + fn f(i: Streaming<&[u8]>) -> IResult, u8> { + one_of('c')(i) + } + + let a = &b"abcd"[..]; + assert_eq!( + f(Streaming(a)), + Err(ErrMode::Backtrack(error_position!( + Streaming(a), + ErrorKind::OneOf + ))) + ); + + let b = &b"cde"[..]; + assert_eq!(f(Streaming(b)), Ok((Streaming(&b"de"[..]), b'c'))); } #[test] fn char_str() { - fn f(i: Streaming<&str>) -> IResult, char> { - one_of('c')(i) - } - - let a = "abcd"; - assert_eq!( - f(Streaming(a)), - Err(ErrMode::Backtrack(error_position!( - Streaming(a), - ErrorKind::OneOf - ))) - ); - - let b = "cde"; - assert_eq!(f(Streaming(b)), Ok((Streaming("de"), 'c'))); + fn f(i: Streaming<&str>) -> IResult, char> { + one_of('c')(i) + } + + let a = "abcd"; + assert_eq!( + f(Streaming(a)), + Err(ErrMode::Backtrack(error_position!( + Streaming(a), + ErrorKind::OneOf + ))) + ); + + let b = "cde"; + assert_eq!(f(Streaming(b)), Ok((Streaming("de"), 'c'))); } #[test] fn streaming_none_of_test() { - fn f(i: Streaming<&[u8]>) -> IResult, u8> { - none_of("ab")(i) - } - - let a = &b"abcd"[..]; - assert_eq!( - f(Streaming(a)), - Err(ErrMode::Backtrack(error_position!( - Streaming(a), - ErrorKind::NoneOf - ))) - ); - - let b = &b"cde"[..]; - assert_eq!(f(Streaming(b)), Ok((Streaming(&b"de"[..]), b'c'))); + fn f(i: Streaming<&[u8]>) -> IResult, u8> { + none_of("ab")(i) + } + + let a = &b"abcd"[..]; + assert_eq!( + f(Streaming(a)), + Err(ErrMode::Backtrack(error_position!( + Streaming(a), + ErrorKind::NoneOf + ))) + ); + + let b = &b"cde"[..]; + assert_eq!(f(Streaming(b)), Ok((Streaming(&b"de"[..]), b'c'))); } #[test] fn streaming_is_a() { - fn a_or_b(i: Streaming<&[u8]>) -> IResult, &[u8]> { - take_while1("ab")(i) - } - - let a = Streaming(&b"abcd"[..]); - assert_eq!(a_or_b(a), Ok((Streaming(&b"cd"[..]), &b"ab"[..]))); - - let b = Streaming(&b"bcde"[..]); - assert_eq!(a_or_b(b), Ok((Streaming(&b"cde"[..]), &b"b"[..]))); - - let c = Streaming(&b"cdef"[..]); - assert_eq!( - a_or_b(c), - Err(ErrMode::Backtrack(error_position!( - c, - ErrorKind::TakeWhile1 - ))) - ); - - let d = Streaming(&b"bacdef"[..]); - assert_eq!(a_or_b(d), Ok((Streaming(&b"cdef"[..]), &b"ba"[..]))); + fn a_or_b(i: Streaming<&[u8]>) -> IResult, &[u8]> { + take_while1("ab")(i) + } + + let a = Streaming(&b"abcd"[..]); + assert_eq!(a_or_b(a), Ok((Streaming(&b"cd"[..]), &b"ab"[..]))); + + let b = Streaming(&b"bcde"[..]); + assert_eq!(a_or_b(b), Ok((Streaming(&b"cde"[..]), &b"b"[..]))); + + let c = Streaming(&b"cdef"[..]); + assert_eq!( + a_or_b(c), + Err(ErrMode::Backtrack(error_position!( + c, + ErrorKind::TakeWhile1 + ))) + ); + + let d = Streaming(&b"bacdef"[..]); + assert_eq!(a_or_b(d), Ok((Streaming(&b"cdef"[..]), &b"ba"[..]))); } #[test] fn streaming_is_not() { - fn a_or_b(i: Streaming<&[u8]>) -> IResult, &[u8]> { - take_till1("ab")(i) - } + fn a_or_b(i: Streaming<&[u8]>) -> IResult, &[u8]> { + take_till1("ab")(i) + } - let a = Streaming(&b"cdab"[..]); - assert_eq!(a_or_b(a), Ok((Streaming(&b"ab"[..]), &b"cd"[..]))); + let a = Streaming(&b"cdab"[..]); + assert_eq!(a_or_b(a), Ok((Streaming(&b"ab"[..]), &b"cd"[..]))); - let b = Streaming(&b"cbde"[..]); - assert_eq!(a_or_b(b), Ok((Streaming(&b"bde"[..]), &b"c"[..]))); + let b = Streaming(&b"cbde"[..]); + assert_eq!(a_or_b(b), Ok((Streaming(&b"bde"[..]), &b"c"[..]))); - let c = Streaming(&b"abab"[..]); - assert_eq!( - a_or_b(c), - Err(ErrMode::Backtrack(error_position!(c, ErrorKind::TakeTill1))) - ); + let c = Streaming(&b"abab"[..]); + assert_eq!( + a_or_b(c), + Err(ErrMode::Backtrack(error_position!(c, ErrorKind::TakeTill1))) + ); - let d = Streaming(&b"cdefba"[..]); - assert_eq!(a_or_b(d), Ok((Streaming(&b"ba"[..]), &b"cdef"[..]))); + let d = Streaming(&b"cdefba"[..]); + assert_eq!(a_or_b(d), Ok((Streaming(&b"ba"[..]), &b"cdef"[..]))); - let e = Streaming(&b"e"[..]); - assert_eq!(a_or_b(e), Err(ErrMode::Incomplete(Needed::new(1)))); + let e = Streaming(&b"e"[..]); + assert_eq!(a_or_b(e), Err(ErrMode::Incomplete(Needed::new(1)))); } #[test] fn streaming_take_until_incomplete() { - fn y(i: Streaming<&[u8]>) -> IResult, &[u8]> { - take_until0("end")(i) - } - assert_eq!( - y(Streaming(&b"nd"[..])), - Err(ErrMode::Incomplete(Needed::Unknown)) - ); - assert_eq!( - y(Streaming(&b"123"[..])), - Err(ErrMode::Incomplete(Needed::Unknown)) - ); - assert_eq!( - y(Streaming(&b"123en"[..])), - Err(ErrMode::Incomplete(Needed::Unknown)) - ); + fn y(i: Streaming<&[u8]>) -> IResult, &[u8]> { + take_until0("end")(i) + } + assert_eq!( + y(Streaming(&b"nd"[..])), + Err(ErrMode::Incomplete(Needed::Unknown)) + ); + assert_eq!( + y(Streaming(&b"123"[..])), + Err(ErrMode::Incomplete(Needed::Unknown)) + ); + assert_eq!( + y(Streaming(&b"123en"[..])), + Err(ErrMode::Incomplete(Needed::Unknown)) + ); } #[test] fn streaming_take_until_incomplete_s() { - fn ys(i: Streaming<&str>) -> IResult, &str> { - take_until0("end")(i) - } - assert_eq!( - ys(Streaming("123en")), - Err(ErrMode::Incomplete(Needed::Unknown)) - ); + fn ys(i: Streaming<&str>) -> IResult, &str> { + take_until0("end")(i) + } + assert_eq!( + ys(Streaming("123en")), + Err(ErrMode::Incomplete(Needed::Unknown)) + ); } #[test] fn streaming_recognize() { - use crate::character::{ - alpha1 as alpha, alphanumeric1 as alphanumeric, digit1 as digit, hex_digit1 as hex_digit, - multispace1 as multispace, oct_digit1 as oct_digit, space1 as space, - }; - - fn x(i: Streaming<&[u8]>) -> IResult, &[u8]> { - delimited(tag("")) - .recognize() - .parse_next(i) - } - let r = x(Streaming(&b" aaa"[..])); - assert_eq!(r, Ok((Streaming(&b" aaa"[..]), &b""[..]))); - - let semicolon = &b";"[..]; - - fn ya(i: Streaming<&[u8]>) -> IResult, &[u8]> { - alpha.recognize().parse_next(i) - } - let ra = ya(Streaming(&b"abc;"[..])); - assert_eq!(ra, Ok((Streaming(semicolon), &b"abc"[..]))); - - fn yd(i: Streaming<&[u8]>) -> IResult, &[u8]> { - digit.recognize().parse_next(i) - } - let rd = yd(Streaming(&b"123;"[..])); - assert_eq!(rd, Ok((Streaming(semicolon), &b"123"[..]))); - - fn yhd(i: Streaming<&[u8]>) -> IResult, &[u8]> { - hex_digit.recognize().parse_next(i) - } - let rhd = yhd(Streaming(&b"123abcDEF;"[..])); - assert_eq!(rhd, Ok((Streaming(semicolon), &b"123abcDEF"[..]))); - - fn yod(i: Streaming<&[u8]>) -> IResult, &[u8]> { - oct_digit.recognize().parse_next(i) - } - let rod = yod(Streaming(&b"1234567;"[..])); - assert_eq!(rod, Ok((Streaming(semicolon), &b"1234567"[..]))); - - fn yan(i: Streaming<&[u8]>) -> IResult, &[u8]> { - alphanumeric.recognize().parse_next(i) - } - let ran = yan(Streaming(&b"123abc;"[..])); - assert_eq!(ran, Ok((Streaming(semicolon), &b"123abc"[..]))); - - fn ys(i: Streaming<&[u8]>) -> IResult, &[u8]> { - space.recognize().parse_next(i) - } - let rs = ys(Streaming(&b" \t;"[..])); - assert_eq!(rs, Ok((Streaming(semicolon), &b" \t"[..]))); - - fn yms(i: Streaming<&[u8]>) -> IResult, &[u8]> { - multispace.recognize().parse_next(i) - } - let rms = yms(Streaming(&b" \t\r\n;"[..])); - assert_eq!(rms, Ok((Streaming(semicolon), &b" \t\r\n"[..]))); + use crate::character::{ + alpha1 as alpha, alphanumeric1 as alphanumeric, digit1 as digit, hex_digit1 as hex_digit, + multispace1 as multispace, oct_digit1 as oct_digit, space1 as space, + }; + + fn x(i: Streaming<&[u8]>) -> IResult, &[u8]> { + delimited(tag("")) + .recognize() + .parse_next(i) + } + let r = x(Streaming(&b" aaa"[..])); + assert_eq!(r, Ok((Streaming(&b" aaa"[..]), &b""[..]))); + + let semicolon = &b";"[..]; + + fn ya(i: Streaming<&[u8]>) -> IResult, &[u8]> { + alpha.recognize().parse_next(i) + } + let ra = ya(Streaming(&b"abc;"[..])); + assert_eq!(ra, Ok((Streaming(semicolon), &b"abc"[..]))); + + fn yd(i: Streaming<&[u8]>) -> IResult, &[u8]> { + digit.recognize().parse_next(i) + } + let rd = yd(Streaming(&b"123;"[..])); + assert_eq!(rd, Ok((Streaming(semicolon), &b"123"[..]))); + + fn yhd(i: Streaming<&[u8]>) -> IResult, &[u8]> { + hex_digit.recognize().parse_next(i) + } + let rhd = yhd(Streaming(&b"123abcDEF;"[..])); + assert_eq!(rhd, Ok((Streaming(semicolon), &b"123abcDEF"[..]))); + + fn yod(i: Streaming<&[u8]>) -> IResult, &[u8]> { + oct_digit.recognize().parse_next(i) + } + let rod = yod(Streaming(&b"1234567;"[..])); + assert_eq!(rod, Ok((Streaming(semicolon), &b"1234567"[..]))); + + fn yan(i: Streaming<&[u8]>) -> IResult, &[u8]> { + alphanumeric.recognize().parse_next(i) + } + let ran = yan(Streaming(&b"123abc;"[..])); + assert_eq!(ran, Ok((Streaming(semicolon), &b"123abc"[..]))); + + fn ys(i: Streaming<&[u8]>) -> IResult, &[u8]> { + space.recognize().parse_next(i) + } + let rs = ys(Streaming(&b" \t;"[..])); + assert_eq!(rs, Ok((Streaming(semicolon), &b" \t"[..]))); + + fn yms(i: Streaming<&[u8]>) -> IResult, &[u8]> { + multispace.recognize().parse_next(i) + } + let rms = yms(Streaming(&b" \t\r\n;"[..])); + assert_eq!(rms, Ok((Streaming(semicolon), &b" \t\r\n"[..]))); } #[test] fn streaming_take_while0() { - fn f(i: Streaming<&[u8]>) -> IResult, &[u8]> { - take_while0(AsChar::is_alpha)(i) - } - let a = &b""[..]; - let b = &b"abcd"[..]; - let c = &b"abcd123"[..]; - let d = &b"123"[..]; - - assert_eq!(f(Streaming(a)), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(f(Streaming(b)), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(f(Streaming(c)), Ok((Streaming(d), b))); - assert_eq!(f(Streaming(d)), Ok((Streaming(d), a))); + fn f(i: Streaming<&[u8]>) -> IResult, &[u8]> { + take_while0(AsChar::is_alpha)(i) + } + let a = &b""[..]; + let b = &b"abcd"[..]; + let c = &b"abcd123"[..]; + let d = &b"123"[..]; + + assert_eq!(f(Streaming(a)), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(f(Streaming(b)), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(f(Streaming(c)), Ok((Streaming(d), b))); + assert_eq!(f(Streaming(d)), Ok((Streaming(d), a))); } #[test] fn streaming_take_while1() { - fn f(i: Streaming<&[u8]>) -> IResult, &[u8]> { - take_while1(AsChar::is_alpha)(i) - } - let a = &b""[..]; - let b = &b"abcd"[..]; - let c = &b"abcd123"[..]; - let d = &b"123"[..]; - - assert_eq!(f(Streaming(a)), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(f(Streaming(b)), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(f(Streaming(c)), Ok((Streaming(&b"123"[..]), b))); - assert_eq!( - f(Streaming(d)), - Err(ErrMode::Backtrack(error_position!( - Streaming(d), - ErrorKind::TakeWhile1 - ))) - ); + fn f(i: Streaming<&[u8]>) -> IResult, &[u8]> { + take_while1(AsChar::is_alpha)(i) + } + let a = &b""[..]; + let b = &b"abcd"[..]; + let c = &b"abcd123"[..]; + let d = &b"123"[..]; + + assert_eq!(f(Streaming(a)), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(f(Streaming(b)), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(f(Streaming(c)), Ok((Streaming(&b"123"[..]), b))); + assert_eq!( + f(Streaming(d)), + Err(ErrMode::Backtrack(error_position!( + Streaming(d), + ErrorKind::TakeWhile1 + ))) + ); } #[test] fn streaming_take_while_m_n() { - fn x(i: Streaming<&[u8]>) -> IResult, &[u8]> { - take_while_m_n(2, 4, AsChar::is_alpha)(i) - } - let a = &b""[..]; - let b = &b"a"[..]; - let c = &b"abc"[..]; - let d = &b"abc123"[..]; - let e = &b"abcde"[..]; - let f = &b"123"[..]; - - assert_eq!(x(Streaming(a)), Err(ErrMode::Incomplete(Needed::new(2)))); - assert_eq!(x(Streaming(b)), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(x(Streaming(c)), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(x(Streaming(d)), Ok((Streaming(&b"123"[..]), c))); - assert_eq!(x(Streaming(e)), Ok((Streaming(&b"e"[..]), &b"abcd"[..]))); - assert_eq!( - x(Streaming(f)), - Err(ErrMode::Backtrack(error_position!( - Streaming(f), - ErrorKind::TakeWhileMN - ))) - ); + fn x(i: Streaming<&[u8]>) -> IResult, &[u8]> { + take_while_m_n(2, 4, AsChar::is_alpha)(i) + } + let a = &b""[..]; + let b = &b"a"[..]; + let c = &b"abc"[..]; + let d = &b"abc123"[..]; + let e = &b"abcde"[..]; + let f = &b"123"[..]; + + assert_eq!(x(Streaming(a)), Err(ErrMode::Incomplete(Needed::new(2)))); + assert_eq!(x(Streaming(b)), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(x(Streaming(c)), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(x(Streaming(d)), Ok((Streaming(&b"123"[..]), c))); + assert_eq!(x(Streaming(e)), Ok((Streaming(&b"e"[..]), &b"abcd"[..]))); + assert_eq!( + x(Streaming(f)), + Err(ErrMode::Backtrack(error_position!( + Streaming(f), + ErrorKind::TakeWhileMN + ))) + ); } #[test] fn streaming_take_till0() { - fn f(i: Streaming<&[u8]>) -> IResult, &[u8]> { - take_till0(AsChar::is_alpha)(i) - } - let a = &b""[..]; - let b = &b"abcd"[..]; - let c = &b"123abcd"[..]; - let d = &b"123"[..]; - - assert_eq!(f(Streaming(a)), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(f(Streaming(b)), Ok((Streaming(&b"abcd"[..]), &b""[..]))); - assert_eq!(f(Streaming(c)), Ok((Streaming(&b"abcd"[..]), &b"123"[..]))); - assert_eq!(f(Streaming(d)), Err(ErrMode::Incomplete(Needed::new(1)))); + fn f(i: Streaming<&[u8]>) -> IResult, &[u8]> { + take_till0(AsChar::is_alpha)(i) + } + let a = &b""[..]; + let b = &b"abcd"[..]; + let c = &b"123abcd"[..]; + let d = &b"123"[..]; + + assert_eq!(f(Streaming(a)), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(f(Streaming(b)), Ok((Streaming(&b"abcd"[..]), &b""[..]))); + assert_eq!(f(Streaming(c)), Ok((Streaming(&b"abcd"[..]), &b"123"[..]))); + assert_eq!(f(Streaming(d)), Err(ErrMode::Incomplete(Needed::new(1)))); } #[test] fn streaming_take_till1() { - fn f(i: Streaming<&[u8]>) -> IResult, &[u8]> { - take_till1(AsChar::is_alpha)(i) - } - let a = &b""[..]; - let b = &b"abcd"[..]; - let c = &b"123abcd"[..]; - let d = &b"123"[..]; - - assert_eq!(f(Streaming(a)), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!( - f(Streaming(b)), - Err(ErrMode::Backtrack(error_position!( - Streaming(b), - ErrorKind::TakeTill1 - ))) - ); - assert_eq!(f(Streaming(c)), Ok((Streaming(&b"abcd"[..]), &b"123"[..]))); - assert_eq!(f(Streaming(d)), Err(ErrMode::Incomplete(Needed::new(1)))); + fn f(i: Streaming<&[u8]>) -> IResult, &[u8]> { + take_till1(AsChar::is_alpha)(i) + } + let a = &b""[..]; + let b = &b"abcd"[..]; + let c = &b"123abcd"[..]; + let d = &b"123"[..]; + + assert_eq!(f(Streaming(a)), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!( + f(Streaming(b)), + Err(ErrMode::Backtrack(error_position!( + Streaming(b), + ErrorKind::TakeTill1 + ))) + ); + assert_eq!(f(Streaming(c)), Ok((Streaming(&b"abcd"[..]), &b"123"[..]))); + assert_eq!(f(Streaming(d)), Err(ErrMode::Incomplete(Needed::new(1)))); } #[test] fn streaming_take_while_utf8() { - fn f(i: Streaming<&str>) -> IResult, &str> { - take_while0(|c| c != '點')(i) - } - - assert_eq!(f(Streaming("")), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!( - f(Streaming("abcd")), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!(f(Streaming("abcd點")), Ok((Streaming("點"), "abcd"))); - assert_eq!(f(Streaming("abcd點a")), Ok((Streaming("點a"), "abcd"))); - - fn g(i: Streaming<&str>) -> IResult, &str> { - take_while0(|c| c == '點')(i) - } - - assert_eq!(g(Streaming("")), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(g(Streaming("點abcd")), Ok((Streaming("abcd"), "點"))); - assert_eq!(g(Streaming("點點點a")), Ok((Streaming("a"), "點點點"))); + fn f(i: Streaming<&str>) -> IResult, &str> { + take_while0(|c| c != '點')(i) + } + + assert_eq!(f(Streaming("")), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!( + f(Streaming("abcd")), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!(f(Streaming("abcd點")), Ok((Streaming("點"), "abcd"))); + assert_eq!(f(Streaming("abcd點a")), Ok((Streaming("點a"), "abcd"))); + + fn g(i: Streaming<&str>) -> IResult, &str> { + take_while0(|c| c == '點')(i) + } + + assert_eq!(g(Streaming("")), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(g(Streaming("點abcd")), Ok((Streaming("abcd"), "點"))); + assert_eq!(g(Streaming("點點點a")), Ok((Streaming("a"), "點點點"))); } #[test] fn streaming_take_till0_utf8() { - fn f(i: Streaming<&str>) -> IResult, &str> { - take_till0(|c| c == '點')(i) - } - - assert_eq!(f(Streaming("")), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!( - f(Streaming("abcd")), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!(f(Streaming("abcd點")), Ok((Streaming("點"), "abcd"))); - assert_eq!(f(Streaming("abcd點a")), Ok((Streaming("點a"), "abcd"))); - - fn g(i: Streaming<&str>) -> IResult, &str> { - take_till0(|c| c != '點')(i) - } - - assert_eq!(g(Streaming("")), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(g(Streaming("點abcd")), Ok((Streaming("abcd"), "點"))); - assert_eq!(g(Streaming("點點點a")), Ok((Streaming("a"), "點點點"))); + fn f(i: Streaming<&str>) -> IResult, &str> { + take_till0(|c| c == '點')(i) + } + + assert_eq!(f(Streaming("")), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!( + f(Streaming("abcd")), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!(f(Streaming("abcd點")), Ok((Streaming("點"), "abcd"))); + assert_eq!(f(Streaming("abcd點a")), Ok((Streaming("點a"), "abcd"))); + + fn g(i: Streaming<&str>) -> IResult, &str> { + take_till0(|c| c != '點')(i) + } + + assert_eq!(g(Streaming("")), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(g(Streaming("點abcd")), Ok((Streaming("abcd"), "點"))); + assert_eq!(g(Streaming("點點點a")), Ok((Streaming("a"), "點點點"))); } #[test] fn streaming_take_utf8() { - fn f(i: Streaming<&str>) -> IResult, &str> { - take(3_usize)(i) - } - - assert_eq!(f(Streaming("")), Err(ErrMode::Incomplete(Needed::Unknown))); - assert_eq!( - f(Streaming("ab")), - Err(ErrMode::Incomplete(Needed::Unknown)) - ); - assert_eq!( - f(Streaming("點")), - Err(ErrMode::Incomplete(Needed::Unknown)) - ); - assert_eq!(f(Streaming("ab點cd")), Ok((Streaming("cd"), "ab點"))); - assert_eq!(f(Streaming("a點bcd")), Ok((Streaming("cd"), "a點b"))); - assert_eq!(f(Streaming("a點b")), Ok((Streaming(""), "a點b"))); - - fn g(i: Streaming<&str>) -> IResult, &str> { - take_while0(|c| c == '點')(i) - } - - assert_eq!(g(Streaming("")), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(g(Streaming("點abcd")), Ok((Streaming("abcd"), "點"))); - assert_eq!(g(Streaming("點點點a")), Ok((Streaming("a"), "點點點"))); + fn f(i: Streaming<&str>) -> IResult, &str> { + take(3_usize)(i) + } + + assert_eq!(f(Streaming("")), Err(ErrMode::Incomplete(Needed::Unknown))); + assert_eq!( + f(Streaming("ab")), + Err(ErrMode::Incomplete(Needed::Unknown)) + ); + assert_eq!( + f(Streaming("點")), + Err(ErrMode::Incomplete(Needed::Unknown)) + ); + assert_eq!(f(Streaming("ab點cd")), Ok((Streaming("cd"), "ab點"))); + assert_eq!(f(Streaming("a點bcd")), Ok((Streaming("cd"), "a點b"))); + assert_eq!(f(Streaming("a點b")), Ok((Streaming(""), "a點b"))); + + fn g(i: Streaming<&str>) -> IResult, &str> { + take_while0(|c| c == '點')(i) + } + + assert_eq!(g(Streaming("")), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(g(Streaming("點abcd")), Ok((Streaming("abcd"), "點"))); + assert_eq!(g(Streaming("點點點a")), Ok((Streaming("a"), "點點點"))); } #[test] fn streaming_take_while_m_n_utf8_fixed() { - fn parser(i: Streaming<&str>) -> IResult, &str> { - take_while_m_n(1, 1, |c| c == 'A' || c == '😃')(i) - } - assert_eq!(parser(Streaming("A!")), Ok((Streaming("!"), "A"))); - assert_eq!(parser(Streaming("😃!")), Ok((Streaming("!"), "😃"))); + fn parser(i: Streaming<&str>) -> IResult, &str> { + take_while_m_n(1, 1, |c| c == 'A' || c == '😃')(i) + } + assert_eq!(parser(Streaming("A!")), Ok((Streaming("!"), "A"))); + assert_eq!(parser(Streaming("😃!")), Ok((Streaming("!"), "😃"))); } #[test] fn streaming_take_while_m_n_utf8_range() { - fn parser(i: Streaming<&str>) -> IResult, &str> { - take_while_m_n(1, 2, |c| c == 'A' || c == '😃')(i) - } - assert_eq!(parser(Streaming("A!")), Ok((Streaming("!"), "A"))); - assert_eq!(parser(Streaming("😃!")), Ok((Streaming("!"), "😃"))); + fn parser(i: Streaming<&str>) -> IResult, &str> { + take_while_m_n(1, 2, |c| c == 'A' || c == '😃')(i) + } + assert_eq!(parser(Streaming("A!")), Ok((Streaming("!"), "A"))); + assert_eq!(parser(Streaming("😃!")), Ok((Streaming("!"), "😃"))); } #[test] fn streaming_take_while_m_n_utf8_full_match_fixed() { - fn parser(i: Streaming<&str>) -> IResult, &str> { - take_while_m_n(1, 1, |c: char| c.is_alphabetic())(i) - } - assert_eq!(parser(Streaming("øn")), Ok((Streaming("n"), "ø"))); + fn parser(i: Streaming<&str>) -> IResult, &str> { + take_while_m_n(1, 1, |c: char| c.is_alphabetic())(i) + } + assert_eq!(parser(Streaming("øn")), Ok((Streaming("n"), "ø"))); } #[test] fn streaming_take_while_m_n_utf8_full_match_range() { - fn parser(i: Streaming<&str>) -> IResult, &str> { - take_while_m_n(1, 2, |c: char| c.is_alphabetic())(i) - } - assert_eq!(parser(Streaming("øn")), Ok((Streaming(""), "øn"))); + fn parser(i: Streaming<&str>) -> IResult, &str> { + take_while_m_n(1, 2, |c: char| c.is_alphabetic())(i) + } + assert_eq!(parser(Streaming("øn")), Ok((Streaming(""), "øn"))); } #[test] #[cfg(feature = "std")] fn streaming_recognize_take_while0() { - fn x(i: Streaming<&[u8]>) -> IResult, &[u8]> { - take_while0(AsChar::is_alphanum)(i) - } - fn y(i: Streaming<&[u8]>) -> IResult, &[u8]> { - x.recognize().parse_next(i) - } - assert_eq!( - x(Streaming(&b"ab."[..])), - Ok((Streaming(&b"."[..]), &b"ab"[..])) - ); - assert_eq!( - y(Streaming(&b"ab."[..])), - Ok((Streaming(&b"."[..]), &b"ab"[..])) - ); + fn x(i: Streaming<&[u8]>) -> IResult, &[u8]> { + take_while0(AsChar::is_alphanum)(i) + } + fn y(i: Streaming<&[u8]>) -> IResult, &[u8]> { + x.recognize().parse_next(i) + } + assert_eq!( + x(Streaming(&b"ab."[..])), + Ok((Streaming(&b"."[..]), &b"ab"[..])) + ); + assert_eq!( + y(Streaming(&b"ab."[..])), + Ok((Streaming(&b"."[..]), &b"ab"[..])) + ); } #[test] fn streaming_length_bytes() { - use crate::number::le_u8; - - fn x(i: Streaming<&[u8]>) -> IResult, &[u8]> { - length_data(le_u8)(i) - } - assert_eq!( - x(Streaming(b"\x02..>>")), - Ok((Streaming(&b">>"[..]), &b".."[..])) - ); - assert_eq!( - x(Streaming(b"\x02..")), - Ok((Streaming(&[][..]), &b".."[..])) - ); - assert_eq!( - x(Streaming(b"\x02.")), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - x(Streaming(b"\x02")), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - - fn y(i: Streaming<&[u8]>) -> IResult, &[u8]> { - let (i, _) = tag("magic")(i)?; - length_data(le_u8)(i) - } - assert_eq!( - y(Streaming(b"magic\x02..>>")), - Ok((Streaming(&b">>"[..]), &b".."[..])) - ); - assert_eq!( - y(Streaming(b"magic\x02..")), - Ok((Streaming(&[][..]), &b".."[..])) - ); - assert_eq!( - y(Streaming(b"magic\x02.")), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - y(Streaming(b"magic\x02")), - Err(ErrMode::Incomplete(Needed::new(2))) - ); + use crate::number::le_u8; + + fn x(i: Streaming<&[u8]>) -> IResult, &[u8]> { + length_data(le_u8)(i) + } + assert_eq!( + x(Streaming(b"\x02..>>")), + Ok((Streaming(&b">>"[..]), &b".."[..])) + ); + assert_eq!( + x(Streaming(b"\x02..")), + Ok((Streaming(&[][..]), &b".."[..])) + ); + assert_eq!( + x(Streaming(b"\x02.")), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + x(Streaming(b"\x02")), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + + fn y(i: Streaming<&[u8]>) -> IResult, &[u8]> { + let (i, _) = tag("magic")(i)?; + length_data(le_u8)(i) + } + assert_eq!( + y(Streaming(b"magic\x02..>>")), + Ok((Streaming(&b">>"[..]), &b".."[..])) + ); + assert_eq!( + y(Streaming(b"magic\x02..")), + Ok((Streaming(&[][..]), &b".."[..])) + ); + assert_eq!( + y(Streaming(b"magic\x02.")), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + y(Streaming(b"magic\x02")), + Err(ErrMode::Incomplete(Needed::new(2))) + ); } #[cfg(feature = "alloc")] #[test] fn streaming_case_insensitive() { - fn test(i: Streaming<&[u8]>) -> IResult, &[u8]> { - tag_no_case("ABcd")(i) - } - assert_eq!( - test(Streaming(&b"aBCdefgh"[..])), - Ok((Streaming(&b"efgh"[..]), &b"aBCd"[..])) - ); - assert_eq!( - test(Streaming(&b"abcdefgh"[..])), - Ok((Streaming(&b"efgh"[..]), &b"abcd"[..])) - ); - assert_eq!( - test(Streaming(&b"ABCDefgh"[..])), - Ok((Streaming(&b"efgh"[..]), &b"ABCD"[..])) - ); - assert_eq!( - test(Streaming(&b"ab"[..])), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_eq!( - test(Streaming(&b"Hello"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"Hello"[..]), - ErrorKind::Tag - ))) - ); - assert_eq!( - test(Streaming(&b"Hel"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"Hel"[..]), - ErrorKind::Tag - ))) - ); - - fn test2(i: Streaming<&str>) -> IResult, &str> { - tag_no_case("ABcd")(i) - } - assert_eq!( - test2(Streaming("aBCdefgh")), - Ok((Streaming("efgh"), "aBCd")) - ); - assert_eq!( - test2(Streaming("abcdefgh")), - Ok((Streaming("efgh"), "abcd")) - ); - assert_eq!( - test2(Streaming("ABCDefgh")), - Ok((Streaming("efgh"), "ABCD")) - ); - assert_eq!( - test2(Streaming("ab")), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_eq!( - test2(Streaming("Hello")), - Err(ErrMode::Backtrack(error_position!( - Streaming("Hello"), - ErrorKind::Tag - ))) - ); - assert_eq!( - test2(Streaming("Hel")), - Err(ErrMode::Backtrack(error_position!( - Streaming("Hel"), - ErrorKind::Tag - ))) - ); + fn test(i: Streaming<&[u8]>) -> IResult, &[u8]> { + tag_no_case("ABcd")(i) + } + assert_eq!( + test(Streaming(&b"aBCdefgh"[..])), + Ok((Streaming(&b"efgh"[..]), &b"aBCd"[..])) + ); + assert_eq!( + test(Streaming(&b"abcdefgh"[..])), + Ok((Streaming(&b"efgh"[..]), &b"abcd"[..])) + ); + assert_eq!( + test(Streaming(&b"ABCDefgh"[..])), + Ok((Streaming(&b"efgh"[..]), &b"ABCD"[..])) + ); + assert_eq!( + test(Streaming(&b"ab"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_eq!( + test(Streaming(&b"Hello"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"Hello"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + test(Streaming(&b"Hel"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"Hel"[..]), + ErrorKind::Tag + ))) + ); + + fn test2(i: Streaming<&str>) -> IResult, &str> { + tag_no_case("ABcd")(i) + } + assert_eq!( + test2(Streaming("aBCdefgh")), + Ok((Streaming("efgh"), "aBCd")) + ); + assert_eq!( + test2(Streaming("abcdefgh")), + Ok((Streaming("efgh"), "abcd")) + ); + assert_eq!( + test2(Streaming("ABCDefgh")), + Ok((Streaming("efgh"), "ABCD")) + ); + assert_eq!( + test2(Streaming("ab")), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_eq!( + test2(Streaming("Hello")), + Err(ErrMode::Backtrack(error_position!( + Streaming("Hello"), + ErrorKind::Tag + ))) + ); + assert_eq!( + test2(Streaming("Hel")), + Err(ErrMode::Backtrack(error_position!( + Streaming("Hel"), + ErrorKind::Tag + ))) + ); } #[test] fn streaming_tag_fixed_size_array() { - fn test(i: Streaming<&[u8]>) -> IResult, &[u8]> { - tag([0x42])(i) - } - fn test2(i: Streaming<&[u8]>) -> IResult, &[u8]> { - tag(&[0x42])(i) - } - let input = Streaming(&[0x42, 0x00][..]); - assert_eq!(test(input), Ok((Streaming(&b"\x00"[..]), &b"\x42"[..]))); - assert_eq!(test2(input), Ok((Streaming(&b"\x00"[..]), &b"\x42"[..]))); + fn test(i: Streaming<&[u8]>) -> IResult, &[u8]> { + tag([0x42])(i) + } + fn test2(i: Streaming<&[u8]>) -> IResult, &[u8]> { + tag(&[0x42])(i) + } + let input = Streaming(&[0x42, 0x00][..]); + assert_eq!(test(input), Ok((Streaming(&b"\x00"[..]), &b"\x42"[..]))); + assert_eq!(test2(input), Ok((Streaming(&b"\x00"[..]), &b"\x42"[..]))); } diff --git a/src/character/complete.rs b/src/character/complete.rs index 6822c748..1e30d5e6 100644 --- a/src/character/complete.rs +++ b/src/character/complete.rs @@ -9,7 +9,7 @@ use crate::error::ErrMode; use crate::error::ErrorKind; use crate::error::ParseError; use crate::input::{ - split_at_offset1_complete, split_at_offset_complete, AsBStr, AsChar, ContainsToken, Input, + split_at_offset1_complete, split_at_offset_complete, AsBStr, AsChar, ContainsToken, Input, }; use crate::input::{Compare, CompareResult}; use crate::IResult; @@ -35,21 +35,21 @@ use crate::IResult; #[deprecated(since = "0.1.0", note = "Replaced with `winnow::bytes::one_of`")] pub fn char>(c: char) -> impl Fn(I) -> IResult where - I: Input, - ::Token: AsChar, + I: Input, + ::Token: AsChar, { - move |i: I| char_internal(i, c) + move |i: I| char_internal(i, c) } pub(crate) fn char_internal>(i: I, c: char) -> IResult where - I: Input, - ::Token: AsChar, + I: Input, + ::Token: AsChar, { - i.next_token() - .map(|(i, t)| (i, t.as_char())) - .filter(|(_, t)| *t == c) - .ok_or_else(|| ErrMode::Backtrack(Error::from_char(i, c))) + i.next_token() + .map(|(i, t)| (i, t.as_char())) + .filter(|(_, t)| *t == c) + .ok_or_else(|| ErrMode::Backtrack(Error::from_char(i, c))) } /// Recognizes one character and checks that it satisfies a predicate @@ -72,26 +72,26 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::bytes::one_of`")] pub fn satisfy>(cond: F) -> impl Fn(I) -> IResult where - I: Input, - ::Token: AsChar, - F: Fn(char) -> bool, + I: Input, + ::Token: AsChar, + F: Fn(char) -> bool, { - move |i: I| satisfy_internal(i, &cond) + move |i: I| satisfy_internal(i, &cond) } pub(crate) fn satisfy_internal>( - i: I, - cond: &F, + i: I, + cond: &F, ) -> IResult where - I: Input, - ::Token: AsChar, - F: Fn(char) -> bool, + I: Input, + ::Token: AsChar, + F: Fn(char) -> bool, { - i.next_token() - .map(|(i, t)| (i, t.as_char())) - .filter(|(_, t)| cond(*t)) - .ok_or_else(|| ErrMode::from_error_kind(i, ErrorKind::Satisfy)) + i.next_token() + .map(|(i, t)| (i, t.as_char())) + .filter(|(_, t)| cond(*t)) + .ok_or_else(|| ErrMode::from_error_kind(i, ErrorKind::Satisfy)) } /// Recognizes one of the provided characters. @@ -111,11 +111,11 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::bytes::one_of`")] pub fn one_of>(list: T) -> impl Fn(I) -> IResult where - I: Input, - ::Token: AsChar + Copy, - T: ContainsToken<::Token>, + I: Input, + ::Token: AsChar + Copy, + T: ContainsToken<::Token>, { - move |i: I| crate::bytes::complete::one_of_internal(i, &list).map(|(i, c)| (i, c.as_char())) + move |i: I| crate::bytes::complete::one_of_internal(i, &list).map(|(i, c)| (i, c.as_char())) } /// Recognizes a character that is not in the provided characters. @@ -135,11 +135,11 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::bytes::none_of`")] pub fn none_of>(list: T) -> impl Fn(I) -> IResult where - I: Input, - ::Token: AsChar + Copy, - T: ContainsToken<::Token>, + I: Input, + ::Token: AsChar + Copy, + T: ContainsToken<::Token>, { - move |i: I| crate::bytes::complete::none_of_internal(i, &list).map(|(i, c)| (i, c.as_char())) + move |i: I| crate::bytes::complete::none_of_internal(i, &list).map(|(i, c)| (i, c.as_char())) } /// Recognizes the string "\r\n". @@ -163,17 +163,17 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::character::crlf`")] pub fn crlf>(input: T) -> IResult::Slice, E> where - T: Input, - T: Compare<&'static str>, + T: Input, + T: Compare<&'static str>, { - const CRLF: &str = "\r\n"; - match input.compare(CRLF) { - CompareResult::Ok => Ok(input.next_slice(CRLF.len())), - CompareResult::Incomplete | CompareResult::Error => { - let e: ErrorKind = ErrorKind::CrLf; - Err(ErrMode::from_error_kind(input, e)) + const CRLF: &str = "\r\n"; + match input.compare(CRLF) { + CompareResult::Ok => Ok(input.next_slice(CRLF.len())), + CompareResult::Incomplete | CompareResult::Error => { + let e: ErrorKind = ErrorKind::CrLf; + Err(ErrMode::from_error_kind(input, e)) + } } - } } //FIXME: there's still an incomplete @@ -199,38 +199,38 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::not_line_ending`][crate::character::not_line_ending] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::not_line_ending`" + since = "0.1.0", + note = "Replaced with `winnow::character::not_line_ending`" )] pub fn not_line_ending>(input: T) -> IResult::Slice, E> where - T: Input + AsBStr, - T: Compare<&'static str>, - ::Token: AsChar, + T: Input + AsBStr, + T: Compare<&'static str>, + ::Token: AsChar, { - match input.offset_for(|item| { - let c = item.as_char(); - c == '\r' || c == '\n' - }) { - None => Ok(input.next_slice(input.input_len())), - Some(offset) => { - let (new_input, res) = input.next_slice(offset); - let bytes = new_input.as_bstr(); - let nth = bytes[0]; - if nth == b'\r' { - let comp = new_input.compare("\r\n"); - match comp { - //FIXME: calculate the right index - CompareResult::Ok => {} - CompareResult::Incomplete | CompareResult::Error => { - let e: ErrorKind = ErrorKind::Tag; - return Err(ErrMode::from_error_kind(input, e)); - } + match input.offset_for(|item| { + let c = item.as_char(); + c == '\r' || c == '\n' + }) { + None => Ok(input.next_slice(input.input_len())), + Some(offset) => { + let (new_input, res) = input.next_slice(offset); + let bytes = new_input.as_bstr(); + let nth = bytes[0]; + if nth == b'\r' { + let comp = new_input.compare("\r\n"); + match comp { + //FIXME: calculate the right index + CompareResult::Ok => {} + CompareResult::Incomplete | CompareResult::Error => { + let e: ErrorKind = ErrorKind::Tag; + return Err(ErrMode::from_error_kind(input, e)); + } + } + } + Ok((new_input, res)) } - } - Ok((new_input, res)) } - } } /// Recognizes an end of line (both '\n' and '\r\n'). @@ -252,26 +252,26 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::line_ending`][crate::character::line_ending] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::line_ending`" + since = "0.1.0", + note = "Replaced with `winnow::character::line_ending`" )] pub fn line_ending>(input: T) -> IResult::Slice, E> where - T: Input, - T: Compare<&'static str>, + T: Input, + T: Compare<&'static str>, { - const LF: &str = "\n"; - const CRLF: &str = "\r\n"; - match input.compare(LF) { - CompareResult::Ok => Ok(input.next_slice(LF.len())), - CompareResult::Incomplete => Err(ErrMode::from_error_kind(input, ErrorKind::CrLf)), - CompareResult::Error => match input.compare("\r\n") { - CompareResult::Ok => Ok(input.next_slice(CRLF.len())), - CompareResult::Incomplete | CompareResult::Error => Err(ErrMode::Backtrack( - E::from_error_kind(input, ErrorKind::CrLf), - )), - }, - } + const LF: &str = "\n"; + const CRLF: &str = "\r\n"; + match input.compare(LF) { + CompareResult::Ok => Ok(input.next_slice(LF.len())), + CompareResult::Incomplete => Err(ErrMode::from_error_kind(input, ErrorKind::CrLf)), + CompareResult::Error => match input.compare("\r\n") { + CompareResult::Ok => Ok(input.next_slice(CRLF.len())), + CompareResult::Incomplete | CompareResult::Error => Err(ErrMode::Backtrack( + E::from_error_kind(input, ErrorKind::CrLf), + )), + }, + } } /// Matches a newline character '\n'. @@ -295,10 +295,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::character::newline`")] pub fn newline>(input: I) -> IResult where - I: Input, - ::Token: AsChar, + I: Input, + ::Token: AsChar, { - char('\n')(input) + char('\n')(input) } /// Matches a tab character '\t'. @@ -322,10 +322,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::character::tab`")] pub fn tab>(input: I) -> IResult where - I: Input, - ::Token: AsChar, + I: Input, + ::Token: AsChar, { - char('\t')(input) + char('\t')(input) } /// Matches one byte as a character. Note that the input type will @@ -348,10 +348,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::bytes::any`")] pub fn anychar>(input: T) -> IResult where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - crate::bytes::complete::any(input).map(|(i, c)| (i, c.as_char())) + crate::bytes::complete::any(input).map(|(i, c)| (i, c.as_char())) } /// Recognizes zero or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z @@ -376,10 +376,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::character::alpha0`")] pub fn alpha0>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset_complete(&input, |item| !item.is_alpha()) + split_at_offset_complete(&input, |item| !item.is_alpha()) } /// Recognizes one or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z @@ -404,10 +404,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::character::alpha1`")] pub fn alpha1>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset1_complete(&input, |item| !item.is_alpha(), ErrorKind::Alpha) + split_at_offset1_complete(&input, |item| !item.is_alpha(), ErrorKind::Alpha) } /// Recognizes zero or more ASCII numerical characters: 0-9 @@ -433,10 +433,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::character::digit0`")] pub fn digit0>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset_complete(&input, |item| !item.is_dec_digit()) + split_at_offset_complete(&input, |item| !item.is_dec_digit()) } /// Recognizes one or more ASCII numerical characters: 0-9 @@ -479,10 +479,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::character::digit1`")] pub fn digit1>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset1_complete(&input, |item| !item.is_dec_digit(), ErrorKind::Digit) + split_at_offset1_complete(&input, |item| !item.is_dec_digit(), ErrorKind::Digit) } /// Recognizes zero or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f @@ -504,15 +504,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::hex_digit0`][crate::character::hex_digit0] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::hex_digit0`" + since = "0.1.0", + note = "Replaced with `winnow::character::hex_digit0`" )] pub fn hex_digit0>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset_complete(&input, |item| !item.is_hex_digit()) + split_at_offset_complete(&input, |item| !item.is_hex_digit()) } /// Recognizes one or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f @@ -535,15 +535,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::hex_digit1`][crate::character::hex_digit1] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::hex_digit1`" + since = "0.1.0", + note = "Replaced with `winnow::character::hex_digit1`" )] pub fn hex_digit1>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset1_complete(&input, |item| !item.is_hex_digit(), ErrorKind::HexDigit) + split_at_offset1_complete(&input, |item| !item.is_hex_digit(), ErrorKind::HexDigit) } /// Recognizes zero or more octal characters: 0-7 @@ -566,15 +566,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::oct_digit0`][crate::character::oct_digit0] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::oct_digit0`" + since = "0.1.0", + note = "Replaced with `winnow::character::oct_digit0`" )] pub fn oct_digit0>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset_complete(&input, |item| !item.is_oct_digit()) + split_at_offset_complete(&input, |item| !item.is_oct_digit()) } /// Recognizes one or more octal characters: 0-7 @@ -597,15 +597,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::oct_digit1`][crate::character::oct_digit1] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::oct_digit1`" + since = "0.1.0", + note = "Replaced with `winnow::character::oct_digit1`" )] pub fn oct_digit1>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset1_complete(&input, |item| !item.is_oct_digit(), ErrorKind::OctDigit) + split_at_offset1_complete(&input, |item| !item.is_oct_digit(), ErrorKind::OctDigit) } /// Recognizes zero or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z @@ -628,15 +628,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::alphanumeric0`][crate::character::alphanumeric0] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::alphanumeric0`" + since = "0.1.0", + note = "Replaced with `winnow::character::alphanumeric0`" )] pub fn alphanumeric0>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset_complete(&input, |item| !item.is_alphanum()) + split_at_offset_complete(&input, |item| !item.is_alphanum()) } /// Recognizes one or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z @@ -659,15 +659,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::alphanumeric1`][crate::character::alphanumeric1] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::alphanumeric1`" + since = "0.1.0", + note = "Replaced with `winnow::character::alphanumeric1`" )] pub fn alphanumeric1>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset1_complete(&input, |item| !item.is_alphanum(), ErrorKind::AlphaNumeric) + split_at_offset1_complete(&input, |item| !item.is_alphanum(), ErrorKind::AlphaNumeric) } /// Recognizes zero or more spaces and tabs. @@ -692,13 +692,13 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::character::space0`")] pub fn space0>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset_complete(&input, |item| { - let c = item.as_char(); - !(c == ' ' || c == '\t') - }) + split_at_offset_complete(&input, |item| { + let c = item.as_char(); + !(c == ' ' || c == '\t') + }) } /// Recognizes one or more spaces and tabs. @@ -723,17 +723,17 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::character::space1`")] pub fn space1>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset1_complete( - &input, - |item| { - let c = item.as_char(); - !(c == ' ' || c == '\t') - }, - ErrorKind::Space, - ) + split_at_offset1_complete( + &input, + |item| { + let c = item.as_char(); + !(c == ' ' || c == '\t') + }, + ErrorKind::Space, + ) } /// Recognizes zero or more spaces, tabs, carriage returns and line feeds. @@ -756,18 +756,18 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::multispace0`][crate::character::multispace0] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::multispace0`" + since = "0.1.0", + note = "Replaced with `winnow::character::multispace0`" )] pub fn multispace0>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset_complete(&input, |item| { - let c = item.as_char(); - !(c == ' ' || c == '\t' || c == '\r' || c == '\n') - }) + split_at_offset_complete(&input, |item| { + let c = item.as_char(); + !(c == ' ' || c == '\t' || c == '\r' || c == '\n') + }) } /// Recognizes one or more spaces, tabs, carriage returns and line feeds. @@ -790,38 +790,38 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::multispace1`][crate::character::multispace1] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::multispace1`" + since = "0.1.0", + note = "Replaced with `winnow::character::multispace1`" )] pub fn multispace1>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset1_complete( - &input, - |item| { - let c = item.as_char(); - !(c == ' ' || c == '\t' || c == '\r' || c == '\n') - }, - ErrorKind::MultiSpace, - ) + split_at_offset1_complete( + &input, + |item| { + let c = item.as_char(); + !(c == ' ' || c == '\t' || c == '\r' || c == '\n') + }, + ErrorKind::MultiSpace, + ) } pub(crate) fn sign>(input: T) -> IResult where - T: Input, - ::Token: AsChar + Copy, + T: Input, + ::Token: AsChar + Copy, { - fn sign(token: impl AsChar) -> bool { - let token = token.as_char(); - token == '+' || token == '-' - } + fn sign(token: impl AsChar) -> bool { + let token = token.as_char(); + token == '+' || token == '-' + } - let (i, sign) = opt(|input| crate::bytes::complete::one_of_internal(input, &sign))(input)?; - let sign = sign.map(AsChar::as_char) != Some('-'); + let (i, sign) = opt(|input| crate::bytes::complete::one_of_internal(input, &sign))(input)?; + let sign = sign.map(AsChar::as_char) != Some('-'); - Ok((i, sign)) + Ok((i, sign)) } #[doc(hidden)] @@ -932,497 +932,497 @@ uints! { u8 u16 u32 u64 u128 } #[cfg(test)] mod tests { - use super::*; - use crate::branch::alt; - use crate::error::ErrMode; - use crate::error::Error; - use crate::input::ParseSlice; - use proptest::prelude::*; - - macro_rules! assert_parse( + use super::*; + use crate::branch::alt; + use crate::error::ErrMode; + use crate::error::Error; + use crate::input::ParseSlice; + use proptest::prelude::*; + + macro_rules! assert_parse( ($left: expr, $right: expr) => { let res: $crate::IResult<_, _> = $left; assert_eq!(res, $right); }; ); - #[test] - fn character() { - let empty: &[u8] = b""; - let a: &[u8] = b"abcd"; - let b: &[u8] = b"1234"; - let c: &[u8] = b"a123"; - let d: &[u8] = "azé12".as_bstr(); - let e: &[u8] = b" "; - let f: &[u8] = b" ;"; - //assert_eq!(alpha1::<_, Error<_>>(a), Err(ErrMode::Incomplete(Needed::Size(1)))); - assert_parse!(alpha1(a), Ok((empty, a))); - assert_eq!( - alpha1(b), - Err(ErrMode::Backtrack(Error { - input: b, - kind: ErrorKind::Alpha - })) - ); - assert_eq!(alpha1::<_, Error<_>>(c), Ok((&c[1..], &b"a"[..]))); - assert_eq!(alpha1::<_, Error<_>>(d), Ok(("é12".as_bstr(), &b"az"[..]))); - assert_eq!( - digit1(a), - Err(ErrMode::Backtrack(Error { - input: a, - kind: ErrorKind::Digit - })) - ); - assert_eq!(digit1::<_, Error<_>>(b), Ok((empty, b))); - assert_eq!( - digit1(c), - Err(ErrMode::Backtrack(Error { - input: c, - kind: ErrorKind::Digit - })) - ); - assert_eq!( - digit1(d), - Err(ErrMode::Backtrack(Error { - input: d, - kind: ErrorKind::Digit - })) - ); - assert_eq!(hex_digit1::<_, Error<_>>(a), Ok((empty, a))); - assert_eq!(hex_digit1::<_, Error<_>>(b), Ok((empty, b))); - assert_eq!(hex_digit1::<_, Error<_>>(c), Ok((empty, c))); - assert_eq!( - hex_digit1::<_, Error<_>>(d), - Ok(("zé12".as_bstr(), &b"a"[..])) - ); - assert_eq!( - hex_digit1(e), - Err(ErrMode::Backtrack(Error { - input: e, - kind: ErrorKind::HexDigit - })) - ); - assert_eq!( - oct_digit1(a), - Err(ErrMode::Backtrack(Error { - input: a, - kind: ErrorKind::OctDigit - })) - ); - assert_eq!(oct_digit1::<_, Error<_>>(b), Ok((empty, b))); - assert_eq!( - oct_digit1(c), - Err(ErrMode::Backtrack(Error { - input: c, - kind: ErrorKind::OctDigit - })) - ); - assert_eq!( - oct_digit1(d), - Err(ErrMode::Backtrack(Error { - input: d, - kind: ErrorKind::OctDigit - })) - ); - assert_eq!(alphanumeric1::<_, Error<_>>(a), Ok((empty, a))); - //assert_eq!(fix_error!(b,(), alphanumeric), Ok((empty, b))); - assert_eq!(alphanumeric1::<_, Error<_>>(c), Ok((empty, c))); - assert_eq!( - alphanumeric1::<_, Error<_>>(d), - Ok(("é12".as_bstr(), &b"az"[..])) - ); - assert_eq!(space1::<_, Error<_>>(e), Ok((empty, e))); - assert_eq!(space1::<_, Error<_>>(f), Ok((&b";"[..], &b" "[..]))); - } - - #[cfg(feature = "alloc")] - #[test] - fn character_s() { - let empty = ""; - let a = "abcd"; - let b = "1234"; - let c = "a123"; - let d = "azé12"; - let e = " "; - assert_eq!(alpha1::<_, Error<_>>(a), Ok((empty, a))); - assert_eq!( - alpha1(b), - Err(ErrMode::Backtrack(Error { - input: b, - kind: ErrorKind::Alpha - })) - ); - assert_eq!(alpha1::<_, Error<_>>(c), Ok((&c[1..], "a"))); - assert_eq!(alpha1::<_, Error<_>>(d), Ok(("é12", "az"))); - assert_eq!( - digit1(a), - Err(ErrMode::Backtrack(Error { - input: a, - kind: ErrorKind::Digit - })) - ); - assert_eq!(digit1::<_, Error<_>>(b), Ok((empty, b))); - assert_eq!( - digit1(c), - Err(ErrMode::Backtrack(Error { - input: c, - kind: ErrorKind::Digit - })) - ); - assert_eq!( - digit1(d), - Err(ErrMode::Backtrack(Error { - input: d, - kind: ErrorKind::Digit - })) - ); - assert_eq!(hex_digit1::<_, Error<_>>(a), Ok((empty, a))); - assert_eq!(hex_digit1::<_, Error<_>>(b), Ok((empty, b))); - assert_eq!(hex_digit1::<_, Error<_>>(c), Ok((empty, c))); - assert_eq!(hex_digit1::<_, Error<_>>(d), Ok(("zé12", "a"))); - assert_eq!( - hex_digit1(e), - Err(ErrMode::Backtrack(Error { - input: e, - kind: ErrorKind::HexDigit - })) - ); - assert_eq!( - oct_digit1(a), - Err(ErrMode::Backtrack(Error { - input: a, - kind: ErrorKind::OctDigit - })) - ); - assert_eq!(oct_digit1::<_, Error<_>>(b), Ok((empty, b))); - assert_eq!( - oct_digit1(c), - Err(ErrMode::Backtrack(Error { - input: c, - kind: ErrorKind::OctDigit - })) - ); - assert_eq!( - oct_digit1(d), - Err(ErrMode::Backtrack(Error { - input: d, - kind: ErrorKind::OctDigit - })) - ); - assert_eq!(alphanumeric1::<_, Error<_>>(a), Ok((empty, a))); - //assert_eq!(fix_error!(b,(), alphanumeric), Ok((empty, b))); - assert_eq!(alphanumeric1::<_, Error<_>>(c), Ok((empty, c))); - assert_eq!(alphanumeric1::<_, Error<_>>(d), Ok(("é12", "az"))); - assert_eq!(space1::<_, Error<_>>(e), Ok((empty, e))); - } - - use crate::input::Offset; - #[test] - fn offset() { - let a = &b"abcd;"[..]; - let b = &b"1234;"[..]; - let c = &b"a123;"[..]; - let d = &b" \t;"[..]; - let e = &b" \t\r\n;"[..]; - let f = &b"123abcDEF;"[..]; - - match alpha1::<_, Error<_>>(a) { - Ok((i, _)) => { - assert_eq!(a.offset_to(i) + i.len(), a.len()); - } - _ => panic!("wrong return type in offset test for alpha"), - } - match digit1::<_, Error<_>>(b) { - Ok((i, _)) => { - assert_eq!(b.offset_to(i) + i.len(), b.len()); - } - _ => panic!("wrong return type in offset test for digit"), - } - match alphanumeric1::<_, Error<_>>(c) { - Ok((i, _)) => { - assert_eq!(c.offset_to(i) + i.len(), c.len()); - } - _ => panic!("wrong return type in offset test for alphanumeric"), + #[test] + fn character() { + let empty: &[u8] = b""; + let a: &[u8] = b"abcd"; + let b: &[u8] = b"1234"; + let c: &[u8] = b"a123"; + let d: &[u8] = "azé12".as_bstr(); + let e: &[u8] = b" "; + let f: &[u8] = b" ;"; + //assert_eq!(alpha1::<_, Error<_>>(a), Err(ErrMode::Incomplete(Needed::Size(1)))); + assert_parse!(alpha1(a), Ok((empty, a))); + assert_eq!( + alpha1(b), + Err(ErrMode::Backtrack(Error { + input: b, + kind: ErrorKind::Alpha + })) + ); + assert_eq!(alpha1::<_, Error<_>>(c), Ok((&c[1..], &b"a"[..]))); + assert_eq!(alpha1::<_, Error<_>>(d), Ok(("é12".as_bstr(), &b"az"[..]))); + assert_eq!( + digit1(a), + Err(ErrMode::Backtrack(Error { + input: a, + kind: ErrorKind::Digit + })) + ); + assert_eq!(digit1::<_, Error<_>>(b), Ok((empty, b))); + assert_eq!( + digit1(c), + Err(ErrMode::Backtrack(Error { + input: c, + kind: ErrorKind::Digit + })) + ); + assert_eq!( + digit1(d), + Err(ErrMode::Backtrack(Error { + input: d, + kind: ErrorKind::Digit + })) + ); + assert_eq!(hex_digit1::<_, Error<_>>(a), Ok((empty, a))); + assert_eq!(hex_digit1::<_, Error<_>>(b), Ok((empty, b))); + assert_eq!(hex_digit1::<_, Error<_>>(c), Ok((empty, c))); + assert_eq!( + hex_digit1::<_, Error<_>>(d), + Ok(("zé12".as_bstr(), &b"a"[..])) + ); + assert_eq!( + hex_digit1(e), + Err(ErrMode::Backtrack(Error { + input: e, + kind: ErrorKind::HexDigit + })) + ); + assert_eq!( + oct_digit1(a), + Err(ErrMode::Backtrack(Error { + input: a, + kind: ErrorKind::OctDigit + })) + ); + assert_eq!(oct_digit1::<_, Error<_>>(b), Ok((empty, b))); + assert_eq!( + oct_digit1(c), + Err(ErrMode::Backtrack(Error { + input: c, + kind: ErrorKind::OctDigit + })) + ); + assert_eq!( + oct_digit1(d), + Err(ErrMode::Backtrack(Error { + input: d, + kind: ErrorKind::OctDigit + })) + ); + assert_eq!(alphanumeric1::<_, Error<_>>(a), Ok((empty, a))); + //assert_eq!(fix_error!(b,(), alphanumeric), Ok((empty, b))); + assert_eq!(alphanumeric1::<_, Error<_>>(c), Ok((empty, c))); + assert_eq!( + alphanumeric1::<_, Error<_>>(d), + Ok(("é12".as_bstr(), &b"az"[..])) + ); + assert_eq!(space1::<_, Error<_>>(e), Ok((empty, e))); + assert_eq!(space1::<_, Error<_>>(f), Ok((&b";"[..], &b" "[..]))); } - match space1::<_, Error<_>>(d) { - Ok((i, _)) => { - assert_eq!(d.offset_to(i) + i.len(), d.len()); - } - _ => panic!("wrong return type in offset test for space"), + + #[cfg(feature = "alloc")] + #[test] + fn character_s() { + let empty = ""; + let a = "abcd"; + let b = "1234"; + let c = "a123"; + let d = "azé12"; + let e = " "; + assert_eq!(alpha1::<_, Error<_>>(a), Ok((empty, a))); + assert_eq!( + alpha1(b), + Err(ErrMode::Backtrack(Error { + input: b, + kind: ErrorKind::Alpha + })) + ); + assert_eq!(alpha1::<_, Error<_>>(c), Ok((&c[1..], "a"))); + assert_eq!(alpha1::<_, Error<_>>(d), Ok(("é12", "az"))); + assert_eq!( + digit1(a), + Err(ErrMode::Backtrack(Error { + input: a, + kind: ErrorKind::Digit + })) + ); + assert_eq!(digit1::<_, Error<_>>(b), Ok((empty, b))); + assert_eq!( + digit1(c), + Err(ErrMode::Backtrack(Error { + input: c, + kind: ErrorKind::Digit + })) + ); + assert_eq!( + digit1(d), + Err(ErrMode::Backtrack(Error { + input: d, + kind: ErrorKind::Digit + })) + ); + assert_eq!(hex_digit1::<_, Error<_>>(a), Ok((empty, a))); + assert_eq!(hex_digit1::<_, Error<_>>(b), Ok((empty, b))); + assert_eq!(hex_digit1::<_, Error<_>>(c), Ok((empty, c))); + assert_eq!(hex_digit1::<_, Error<_>>(d), Ok(("zé12", "a"))); + assert_eq!( + hex_digit1(e), + Err(ErrMode::Backtrack(Error { + input: e, + kind: ErrorKind::HexDigit + })) + ); + assert_eq!( + oct_digit1(a), + Err(ErrMode::Backtrack(Error { + input: a, + kind: ErrorKind::OctDigit + })) + ); + assert_eq!(oct_digit1::<_, Error<_>>(b), Ok((empty, b))); + assert_eq!( + oct_digit1(c), + Err(ErrMode::Backtrack(Error { + input: c, + kind: ErrorKind::OctDigit + })) + ); + assert_eq!( + oct_digit1(d), + Err(ErrMode::Backtrack(Error { + input: d, + kind: ErrorKind::OctDigit + })) + ); + assert_eq!(alphanumeric1::<_, Error<_>>(a), Ok((empty, a))); + //assert_eq!(fix_error!(b,(), alphanumeric), Ok((empty, b))); + assert_eq!(alphanumeric1::<_, Error<_>>(c), Ok((empty, c))); + assert_eq!(alphanumeric1::<_, Error<_>>(d), Ok(("é12", "az"))); + assert_eq!(space1::<_, Error<_>>(e), Ok((empty, e))); } - match multispace1::<_, Error<_>>(e) { - Ok((i, _)) => { - assert_eq!(e.offset_to(i) + i.len(), e.len()); - } - _ => panic!("wrong return type in offset test for multispace"), + + use crate::input::Offset; + #[test] + fn offset() { + let a = &b"abcd;"[..]; + let b = &b"1234;"[..]; + let c = &b"a123;"[..]; + let d = &b" \t;"[..]; + let e = &b" \t\r\n;"[..]; + let f = &b"123abcDEF;"[..]; + + match alpha1::<_, Error<_>>(a) { + Ok((i, _)) => { + assert_eq!(a.offset_to(i) + i.len(), a.len()); + } + _ => panic!("wrong return type in offset test for alpha"), + } + match digit1::<_, Error<_>>(b) { + Ok((i, _)) => { + assert_eq!(b.offset_to(i) + i.len(), b.len()); + } + _ => panic!("wrong return type in offset test for digit"), + } + match alphanumeric1::<_, Error<_>>(c) { + Ok((i, _)) => { + assert_eq!(c.offset_to(i) + i.len(), c.len()); + } + _ => panic!("wrong return type in offset test for alphanumeric"), + } + match space1::<_, Error<_>>(d) { + Ok((i, _)) => { + assert_eq!(d.offset_to(i) + i.len(), d.len()); + } + _ => panic!("wrong return type in offset test for space"), + } + match multispace1::<_, Error<_>>(e) { + Ok((i, _)) => { + assert_eq!(e.offset_to(i) + i.len(), e.len()); + } + _ => panic!("wrong return type in offset test for multispace"), + } + match hex_digit1::<_, Error<_>>(f) { + Ok((i, _)) => { + assert_eq!(f.offset_to(i) + i.len(), f.len()); + } + _ => panic!("wrong return type in offset test for hex_digit"), + } + match oct_digit1::<_, Error<_>>(f) { + Ok((i, _)) => { + assert_eq!(f.offset_to(i) + i.len(), f.len()); + } + _ => panic!("wrong return type in offset test for oct_digit"), + } } - match hex_digit1::<_, Error<_>>(f) { - Ok((i, _)) => { - assert_eq!(f.offset_to(i) + i.len(), f.len()); - } - _ => panic!("wrong return type in offset test for hex_digit"), + + #[test] + fn is_not_line_ending_bytes() { + let a: &[u8] = b"ab12cd\nefgh"; + assert_eq!( + not_line_ending::<_, Error<_>>(a), + Ok((&b"\nefgh"[..], &b"ab12cd"[..])) + ); + + let b: &[u8] = b"ab12cd\nefgh\nijkl"; + assert_eq!( + not_line_ending::<_, Error<_>>(b), + Ok((&b"\nefgh\nijkl"[..], &b"ab12cd"[..])) + ); + + let c: &[u8] = b"ab12cd\r\nefgh\nijkl"; + assert_eq!( + not_line_ending::<_, Error<_>>(c), + Ok((&b"\r\nefgh\nijkl"[..], &b"ab12cd"[..])) + ); + + let d: &[u8] = b"ab12cd"; + assert_eq!(not_line_ending::<_, Error<_>>(d), Ok((&[][..], d))); } - match oct_digit1::<_, Error<_>>(f) { - Ok((i, _)) => { - assert_eq!(f.offset_to(i) + i.len(), f.len()); - } - _ => panic!("wrong return type in offset test for oct_digit"), + + #[test] + fn is_not_line_ending_str() { + /* + let a: &str = "ab12cd\nefgh"; + assert_eq!(not_line_ending(a), Ok((&"\nefgh"[..], &"ab12cd"[..]))); + + let b: &str = "ab12cd\nefgh\nijkl"; + assert_eq!(not_line_ending(b), Ok((&"\nefgh\nijkl"[..], &"ab12cd"[..]))); + + let c: &str = "ab12cd\r\nefgh\nijkl"; + assert_eq!(not_line_ending(c), Ok((&"\r\nefgh\nijkl"[..], &"ab12cd"[..]))); + + let d = "βèƒôřè\nÂßÇáƒƭèř"; + assert_eq!(not_line_ending(d), Ok((&"\nÂßÇáƒƭèř"[..], &"βèƒôřè"[..]))); + + let e = "βèƒôřè\r\nÂßÇáƒƭèř"; + assert_eq!(not_line_ending(e), Ok((&"\r\nÂßÇáƒƭèř"[..], &"βèƒôřè"[..]))); + */ + + let f = "βèƒôřè\rÂßÇáƒƭèř"; + assert_eq!( + not_line_ending(f), + Err(ErrMode::Backtrack(Error { + input: f, + kind: ErrorKind::Tag + })) + ); + + let g2: &str = "ab12cd"; + assert_eq!(not_line_ending::<_, Error<_>>(g2), Ok(("", g2))); } - } - - #[test] - fn is_not_line_ending_bytes() { - let a: &[u8] = b"ab12cd\nefgh"; - assert_eq!( - not_line_ending::<_, Error<_>>(a), - Ok((&b"\nefgh"[..], &b"ab12cd"[..])) - ); - - let b: &[u8] = b"ab12cd\nefgh\nijkl"; - assert_eq!( - not_line_ending::<_, Error<_>>(b), - Ok((&b"\nefgh\nijkl"[..], &b"ab12cd"[..])) - ); - - let c: &[u8] = b"ab12cd\r\nefgh\nijkl"; - assert_eq!( - not_line_ending::<_, Error<_>>(c), - Ok((&b"\r\nefgh\nijkl"[..], &b"ab12cd"[..])) - ); - - let d: &[u8] = b"ab12cd"; - assert_eq!(not_line_ending::<_, Error<_>>(d), Ok((&[][..], d))); - } - - #[test] - fn is_not_line_ending_str() { - /* - let a: &str = "ab12cd\nefgh"; - assert_eq!(not_line_ending(a), Ok((&"\nefgh"[..], &"ab12cd"[..]))); - - let b: &str = "ab12cd\nefgh\nijkl"; - assert_eq!(not_line_ending(b), Ok((&"\nefgh\nijkl"[..], &"ab12cd"[..]))); - - let c: &str = "ab12cd\r\nefgh\nijkl"; - assert_eq!(not_line_ending(c), Ok((&"\r\nefgh\nijkl"[..], &"ab12cd"[..]))); - - let d = "βèƒôřè\nÂßÇáƒƭèř"; - assert_eq!(not_line_ending(d), Ok((&"\nÂßÇáƒƭèř"[..], &"βèƒôřè"[..]))); - - let e = "βèƒôřè\r\nÂßÇáƒƭèř"; - assert_eq!(not_line_ending(e), Ok((&"\r\nÂßÇáƒƭèř"[..], &"βèƒôřè"[..]))); - */ - - let f = "βèƒôřè\rÂßÇáƒƭèř"; - assert_eq!( - not_line_ending(f), - Err(ErrMode::Backtrack(Error { - input: f, - kind: ErrorKind::Tag - })) - ); - - let g2: &str = "ab12cd"; - assert_eq!(not_line_ending::<_, Error<_>>(g2), Ok(("", g2))); - } - - #[test] - fn hex_digit_test() { - let i = &b"0123456789abcdefABCDEF;"[..]; - assert_parse!(hex_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); - - let i = &b"g"[..]; - assert_parse!( - hex_digit1(i), - Err(ErrMode::Backtrack(error_position!(i, ErrorKind::HexDigit))) - ); - - let i = &b"G"[..]; - assert_parse!( - hex_digit1(i), - Err(ErrMode::Backtrack(error_position!(i, ErrorKind::HexDigit))) - ); - - assert!(AsChar::is_hex_digit(b'0')); - assert!(AsChar::is_hex_digit(b'9')); - assert!(AsChar::is_hex_digit(b'a')); - assert!(AsChar::is_hex_digit(b'f')); - assert!(AsChar::is_hex_digit(b'A')); - assert!(AsChar::is_hex_digit(b'F')); - assert!(!AsChar::is_hex_digit(b'g')); - assert!(!AsChar::is_hex_digit(b'G')); - assert!(!AsChar::is_hex_digit(b'/')); - assert!(!AsChar::is_hex_digit(b':')); - assert!(!AsChar::is_hex_digit(b'@')); - assert!(!AsChar::is_hex_digit(b'\x60')); - } - - #[test] - fn oct_digit_test() { - let i = &b"01234567;"[..]; - assert_parse!(oct_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); - - let i = &b"8"[..]; - assert_parse!( - oct_digit1(i), - Err(ErrMode::Backtrack(error_position!(i, ErrorKind::OctDigit))) - ); - - assert!(AsChar::is_oct_digit(b'0')); - assert!(AsChar::is_oct_digit(b'7')); - assert!(!AsChar::is_oct_digit(b'8')); - assert!(!AsChar::is_oct_digit(b'9')); - assert!(!AsChar::is_oct_digit(b'a')); - assert!(!AsChar::is_oct_digit(b'A')); - assert!(!AsChar::is_oct_digit(b'/')); - assert!(!AsChar::is_oct_digit(b':')); - assert!(!AsChar::is_oct_digit(b'@')); - assert!(!AsChar::is_oct_digit(b'\x60')); - } - - #[test] - fn full_line_windows() { - use crate::sequence::pair; - fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { - pair(not_line_ending, line_ending)(i) + + #[test] + fn hex_digit_test() { + let i = &b"0123456789abcdefABCDEF;"[..]; + assert_parse!(hex_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); + + let i = &b"g"[..]; + assert_parse!( + hex_digit1(i), + Err(ErrMode::Backtrack(error_position!(i, ErrorKind::HexDigit))) + ); + + let i = &b"G"[..]; + assert_parse!( + hex_digit1(i), + Err(ErrMode::Backtrack(error_position!(i, ErrorKind::HexDigit))) + ); + + assert!(AsChar::is_hex_digit(b'0')); + assert!(AsChar::is_hex_digit(b'9')); + assert!(AsChar::is_hex_digit(b'a')); + assert!(AsChar::is_hex_digit(b'f')); + assert!(AsChar::is_hex_digit(b'A')); + assert!(AsChar::is_hex_digit(b'F')); + assert!(!AsChar::is_hex_digit(b'g')); + assert!(!AsChar::is_hex_digit(b'G')); + assert!(!AsChar::is_hex_digit(b'/')); + assert!(!AsChar::is_hex_digit(b':')); + assert!(!AsChar::is_hex_digit(b'@')); + assert!(!AsChar::is_hex_digit(b'\x60')); } - let input = b"abc\r\n"; - let output = take_full_line(input); - assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\r\n"[..])))); - } - - #[test] - fn full_line_unix() { - use crate::sequence::pair; - fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { - pair(not_line_ending, line_ending)(i) + + #[test] + fn oct_digit_test() { + let i = &b"01234567;"[..]; + assert_parse!(oct_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); + + let i = &b"8"[..]; + assert_parse!( + oct_digit1(i), + Err(ErrMode::Backtrack(error_position!(i, ErrorKind::OctDigit))) + ); + + assert!(AsChar::is_oct_digit(b'0')); + assert!(AsChar::is_oct_digit(b'7')); + assert!(!AsChar::is_oct_digit(b'8')); + assert!(!AsChar::is_oct_digit(b'9')); + assert!(!AsChar::is_oct_digit(b'a')); + assert!(!AsChar::is_oct_digit(b'A')); + assert!(!AsChar::is_oct_digit(b'/')); + assert!(!AsChar::is_oct_digit(b':')); + assert!(!AsChar::is_oct_digit(b'@')); + assert!(!AsChar::is_oct_digit(b'\x60')); } - let input = b"abc\n"; - let output = take_full_line(input); - assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\n"[..])))); - } - - #[test] - fn check_windows_lineending() { - let input = b"\r\n"; - let output = line_ending(&input[..]); - assert_parse!(output, Ok((&b""[..], &b"\r\n"[..]))); - } - - #[test] - fn check_unix_lineending() { - let input = b"\n"; - let output = line_ending(&input[..]); - assert_parse!(output, Ok((&b""[..], &b"\n"[..]))); - } - - #[test] - fn cr_lf() { - assert_parse!(crlf(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..]))); - assert_parse!( - crlf(&b"\r"[..]), - Err(ErrMode::Backtrack(error_position!( - &b"\r"[..], - ErrorKind::CrLf - ))) - ); - assert_parse!( - crlf(&b"\ra"[..]), - Err(ErrMode::Backtrack(error_position!( - &b"\ra"[..], - ErrorKind::CrLf - ))) - ); - - assert_parse!(crlf("\r\na"), Ok(("a", "\r\n"))); - assert_parse!( - crlf("\r"), - Err(ErrMode::Backtrack(error_position!("\r", ErrorKind::CrLf))) - ); - assert_parse!( - crlf("\ra"), - Err(ErrMode::Backtrack(error_position!("\ra", ErrorKind::CrLf))) - ); - } - - #[test] - fn end_of_line() { - assert_parse!(line_ending(&b"\na"[..]), Ok((&b"a"[..], &b"\n"[..]))); - assert_parse!(line_ending(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..]))); - assert_parse!( - line_ending(&b"\r"[..]), - Err(ErrMode::Backtrack(error_position!( - &b"\r"[..], - ErrorKind::CrLf - ))) - ); - assert_parse!( - line_ending(&b"\ra"[..]), - Err(ErrMode::Backtrack(error_position!( - &b"\ra"[..], - ErrorKind::CrLf - ))) - ); - - assert_parse!(line_ending("\na"), Ok(("a", "\n"))); - assert_parse!(line_ending("\r\na"), Ok(("a", "\r\n"))); - assert_parse!( - line_ending("\r"), - Err(ErrMode::Backtrack(error_position!("\r", ErrorKind::CrLf))) - ); - assert_parse!( - line_ending("\ra"), - Err(ErrMode::Backtrack(error_position!("\ra", ErrorKind::CrLf))) - ); - } - - fn digit_to_i16(input: &str) -> IResult<&str, i16> { - let i = input; - let (i, opt_sign) = opt(alt((char('+'), char('-'))))(i)?; - let sign = match opt_sign { - Some('+') | None => true, - Some('-') => false, - _ => unreachable!(), - }; - let (i, s) = match digit1::<_, crate::error::Error<_>>(i) { - Ok((i, s)) => (i, s), - Err(_) => return Err(ErrMode::from_error_kind(input, ErrorKind::Digit)), - }; + #[test] + fn full_line_windows() { + use crate::sequence::pair; + fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { + pair(not_line_ending, line_ending)(i) + } + let input = b"abc\r\n"; + let output = take_full_line(input); + assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\r\n"[..])))); + } - match s.parse_slice() { - Some(n) => { - if sign { - Ok((i, n)) - } else { - Ok((i, -n)) + #[test] + fn full_line_unix() { + use crate::sequence::pair; + fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { + pair(not_line_ending, line_ending)(i) } - } - None => Err(ErrMode::from_error_kind(i, ErrorKind::Digit)), + let input = b"abc\n"; + let output = take_full_line(input); + assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\n"[..])))); } - } - fn digit_to_u32(i: &str) -> IResult<&str, u32> { - let (i, s) = digit1(i)?; - match s.parse_slice() { - Some(n) => Ok((i, n)), - None => Err(ErrMode::from_error_kind(i, ErrorKind::Digit)), + #[test] + fn check_windows_lineending() { + let input = b"\r\n"; + let output = line_ending(&input[..]); + assert_parse!(output, Ok((&b""[..], &b"\r\n"[..]))); } - } - proptest! { #[test] - fn ints(s in "\\PC*") { - let res1 = digit_to_i16(&s); - let res2 = i16(s.as_str()); - assert_eq!(res1, res2); + fn check_unix_lineending() { + let input = b"\n"; + let output = line_ending(&input[..]); + assert_parse!(output, Ok((&b""[..], &b"\n"[..]))); } #[test] - fn uints(s in "\\PC*") { - let res1 = digit_to_u32(&s); - let res2 = u32(s.as_str()); - assert_eq!(res1, res2); + fn cr_lf() { + assert_parse!(crlf(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..]))); + assert_parse!( + crlf(&b"\r"[..]), + Err(ErrMode::Backtrack(error_position!( + &b"\r"[..], + ErrorKind::CrLf + ))) + ); + assert_parse!( + crlf(&b"\ra"[..]), + Err(ErrMode::Backtrack(error_position!( + &b"\ra"[..], + ErrorKind::CrLf + ))) + ); + + assert_parse!(crlf("\r\na"), Ok(("a", "\r\n"))); + assert_parse!( + crlf("\r"), + Err(ErrMode::Backtrack(error_position!("\r", ErrorKind::CrLf))) + ); + assert_parse!( + crlf("\ra"), + Err(ErrMode::Backtrack(error_position!("\ra", ErrorKind::CrLf))) + ); + } + + #[test] + fn end_of_line() { + assert_parse!(line_ending(&b"\na"[..]), Ok((&b"a"[..], &b"\n"[..]))); + assert_parse!(line_ending(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..]))); + assert_parse!( + line_ending(&b"\r"[..]), + Err(ErrMode::Backtrack(error_position!( + &b"\r"[..], + ErrorKind::CrLf + ))) + ); + assert_parse!( + line_ending(&b"\ra"[..]), + Err(ErrMode::Backtrack(error_position!( + &b"\ra"[..], + ErrorKind::CrLf + ))) + ); + + assert_parse!(line_ending("\na"), Ok(("a", "\n"))); + assert_parse!(line_ending("\r\na"), Ok(("a", "\r\n"))); + assert_parse!( + line_ending("\r"), + Err(ErrMode::Backtrack(error_position!("\r", ErrorKind::CrLf))) + ); + assert_parse!( + line_ending("\ra"), + Err(ErrMode::Backtrack(error_position!("\ra", ErrorKind::CrLf))) + ); + } + + fn digit_to_i16(input: &str) -> IResult<&str, i16> { + let i = input; + let (i, opt_sign) = opt(alt((char('+'), char('-'))))(i)?; + let sign = match opt_sign { + Some('+') | None => true, + Some('-') => false, + _ => unreachable!(), + }; + + let (i, s) = match digit1::<_, crate::error::Error<_>>(i) { + Ok((i, s)) => (i, s), + Err(_) => return Err(ErrMode::from_error_kind(input, ErrorKind::Digit)), + }; + + match s.parse_slice() { + Some(n) => { + if sign { + Ok((i, n)) + } else { + Ok((i, -n)) + } + } + None => Err(ErrMode::from_error_kind(i, ErrorKind::Digit)), + } + } + + fn digit_to_u32(i: &str) -> IResult<&str, u32> { + let (i, s) = digit1(i)?; + match s.parse_slice() { + Some(n) => Ok((i, n)), + None => Err(ErrMode::from_error_kind(i, ErrorKind::Digit)), + } + } + + proptest! { + #[test] + fn ints(s in "\\PC*") { + let res1 = digit_to_i16(&s); + let res2 = i16(s.as_str()); + assert_eq!(res1, res2); + } + + #[test] + fn uints(s in "\\PC*") { + let res1 = digit_to_u32(&s); + let res2 = u32(s.as_str()); + assert_eq!(res1, res2); + } } - } } diff --git a/src/character/mod.rs b/src/character/mod.rs index 3fd9a67d..68a50274 100644 --- a/src/character/mod.rs +++ b/src/character/mod.rs @@ -49,18 +49,18 @@ use crate::Parser; /// ``` #[inline(always)] pub fn crlf, const STREAMING: bool>( - input: I, + input: I, ) -> IResult::Slice, E> where - I: InputIsStreaming, - I: Input, - I: Compare<&'static str>, + I: InputIsStreaming, + I: Input, + I: Compare<&'static str>, { - if STREAMING { - streaming::crlf(input) - } else { - complete::crlf(input) - } + if STREAMING { + streaming::crlf(input) + } else { + complete::crlf(input) + } } /// Recognizes a string of any char except '\r\n' or '\n'. @@ -98,19 +98,19 @@ where /// ``` #[inline(always)] pub fn not_line_ending, const STREAMING: bool>( - input: I, + input: I, ) -> IResult::Slice, E> where - I: InputIsStreaming, - I: Input + AsBStr, - I: Compare<&'static str>, - ::Token: AsChar, + I: InputIsStreaming, + I: Input + AsBStr, + I: Compare<&'static str>, + ::Token: AsChar, { - if STREAMING { - streaming::not_line_ending(input) - } else { - complete::not_line_ending(input) - } + if STREAMING { + streaming::not_line_ending(input) + } else { + complete::not_line_ending(input) + } } /// Recognizes an end of line (both '\n' and '\r\n'). @@ -143,18 +143,18 @@ where /// ``` #[inline(always)] pub fn line_ending, const STREAMING: bool>( - input: I, + input: I, ) -> IResult::Slice, E> where - I: InputIsStreaming, - I: Input, - I: Compare<&'static str>, + I: InputIsStreaming, + I: Input, + I: Compare<&'static str>, { - if STREAMING { - streaming::line_ending(input) - } else { - complete::line_ending(input) - } + if STREAMING { + streaming::line_ending(input) + } else { + complete::line_ending(input) + } } /// Matches a newline character '\n'. @@ -188,15 +188,15 @@ where #[inline(always)] pub fn newline, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Token: AsChar, + I: InputIsStreaming, + I: Input, + ::Token: AsChar, { - if STREAMING { - streaming::newline(input) - } else { - complete::newline(input) - } + if STREAMING { + streaming::newline(input) + } else { + complete::newline(input) + } } /// Matches a tab character '\t'. @@ -230,15 +230,15 @@ where #[inline(always)] pub fn tab, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Token: AsChar, + I: InputIsStreaming, + I: Input, + ::Token: AsChar, { - if STREAMING { - streaming::tab(input) - } else { - complete::tab(input) - } + if STREAMING { + streaming::tab(input) + } else { + complete::tab(input) + } } /// Recognizes zero or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z @@ -273,18 +273,18 @@ where /// ``` #[inline(always)] pub fn alpha0, const STREAMING: bool>( - input: I, + input: I, ) -> IResult::Slice, E> where - I: InputIsStreaming, - I: Input, - ::Token: AsChar, + I: InputIsStreaming, + I: Input, + ::Token: AsChar, { - if STREAMING { - streaming::alpha0(input) - } else { - complete::alpha0(input) - } + if STREAMING { + streaming::alpha0(input) + } else { + complete::alpha0(input) + } } /// Recognizes one or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z @@ -319,18 +319,18 @@ where /// ``` #[inline(always)] pub fn alpha1, const STREAMING: bool>( - input: I, + input: I, ) -> IResult::Slice, E> where - I: InputIsStreaming, - I: Input, - ::Token: AsChar, + I: InputIsStreaming, + I: Input, + ::Token: AsChar, { - if STREAMING { - streaming::alpha1(input) - } else { - complete::alpha1(input) - } + if STREAMING { + streaming::alpha1(input) + } else { + complete::alpha1(input) + } } /// Recognizes zero or more ASCII numerical characters: 0-9 @@ -366,18 +366,18 @@ where /// ``` #[inline(always)] pub fn digit0, const STREAMING: bool>( - input: I, + input: I, ) -> IResult::Slice, E> where - I: InputIsStreaming, - I: Input, - ::Token: AsChar, + I: InputIsStreaming, + I: Input, + ::Token: AsChar, { - if STREAMING { - streaming::digit0(input) - } else { - complete::digit0(input) - } + if STREAMING { + streaming::digit0(input) + } else { + complete::digit0(input) + } } /// Recognizes one or more ASCII numerical characters: 0-9 @@ -428,18 +428,18 @@ where /// ``` #[inline(always)] pub fn digit1, const STREAMING: bool>( - input: I, + input: I, ) -> IResult::Slice, E> where - I: InputIsStreaming, - I: Input, - ::Token: AsChar, + I: InputIsStreaming, + I: Input, + ::Token: AsChar, { - if STREAMING { - streaming::digit1(input) - } else { - complete::digit1(input) - } + if STREAMING { + streaming::digit1(input) + } else { + complete::digit1(input) + } } /// Recognizes zero or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f @@ -473,18 +473,18 @@ where /// ``` #[inline(always)] pub fn hex_digit0, const STREAMING: bool>( - input: I, + input: I, ) -> IResult::Slice, E> where - I: InputIsStreaming, - I: Input, - ::Token: AsChar, + I: InputIsStreaming, + I: Input, + ::Token: AsChar, { - if STREAMING { - streaming::hex_digit0(input) - } else { - complete::hex_digit0(input) - } + if STREAMING { + streaming::hex_digit0(input) + } else { + complete::hex_digit0(input) + } } /// Recognizes one or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f @@ -519,18 +519,18 @@ where /// ``` #[inline(always)] pub fn hex_digit1, const STREAMING: bool>( - input: I, + input: I, ) -> IResult::Slice, E> where - I: InputIsStreaming, - I: Input, - ::Token: AsChar, + I: InputIsStreaming, + I: Input, + ::Token: AsChar, { - if STREAMING { - streaming::hex_digit1(input) - } else { - complete::hex_digit1(input) - } + if STREAMING { + streaming::hex_digit1(input) + } else { + complete::hex_digit1(input) + } } /// Recognizes zero or more octal characters: 0-7 @@ -565,18 +565,18 @@ where /// ``` #[inline(always)] pub fn oct_digit0, const STREAMING: bool>( - input: I, + input: I, ) -> IResult::Slice, E> where - I: InputIsStreaming, - I: Input, - ::Token: AsChar, + I: InputIsStreaming, + I: Input, + ::Token: AsChar, { - if STREAMING { - streaming::oct_digit0(input) - } else { - complete::oct_digit0(input) - } + if STREAMING { + streaming::oct_digit0(input) + } else { + complete::oct_digit0(input) + } } /// Recognizes one or more octal characters: 0-7 @@ -611,18 +611,18 @@ where /// ``` #[inline(always)] pub fn oct_digit1, const STREAMING: bool>( - input: I, + input: I, ) -> IResult::Slice, E> where - I: InputIsStreaming, - I: Input, - ::Token: AsChar, + I: InputIsStreaming, + I: Input, + ::Token: AsChar, { - if STREAMING { - streaming::oct_digit1(input) - } else { - complete::oct_digit1(input) - } + if STREAMING { + streaming::oct_digit1(input) + } else { + complete::oct_digit1(input) + } } /// Recognizes zero or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z @@ -657,18 +657,18 @@ where /// ``` #[inline(always)] pub fn alphanumeric0, const STREAMING: bool>( - input: I, + input: I, ) -> IResult::Slice, E> where - I: InputIsStreaming, - I: Input, - ::Token: AsChar, + I: InputIsStreaming, + I: Input, + ::Token: AsChar, { - if STREAMING { - streaming::alphanumeric0(input) - } else { - complete::alphanumeric0(input) - } + if STREAMING { + streaming::alphanumeric0(input) + } else { + complete::alphanumeric0(input) + } } /// Recognizes one or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z @@ -703,18 +703,18 @@ where /// ``` #[inline(always)] pub fn alphanumeric1, const STREAMING: bool>( - input: I, + input: I, ) -> IResult::Slice, E> where - I: InputIsStreaming, - I: Input, - ::Token: AsChar, + I: InputIsStreaming, + I: Input, + ::Token: AsChar, { - if STREAMING { - streaming::alphanumeric1(input) - } else { - complete::alphanumeric1(input) - } + if STREAMING { + streaming::alphanumeric1(input) + } else { + complete::alphanumeric1(input) + } } /// Recognizes zero or more spaces and tabs. @@ -737,18 +737,18 @@ where /// ``` #[inline(always)] pub fn space0, const STREAMING: bool>( - input: I, + input: I, ) -> IResult::Slice, E> where - I: InputIsStreaming, - I: Input, - ::Token: AsChar, + I: InputIsStreaming, + I: Input, + ::Token: AsChar, { - if STREAMING { - streaming::space0(input) - } else { - complete::space0(input) - } + if STREAMING { + streaming::space0(input) + } else { + complete::space0(input) + } } /// Recognizes one or more spaces and tabs. @@ -783,18 +783,18 @@ where /// ``` #[inline(always)] pub fn space1, const STREAMING: bool>( - input: I, + input: I, ) -> IResult::Slice, E> where - I: InputIsStreaming, - I: Input, - ::Token: AsChar, + I: InputIsStreaming, + I: Input, + ::Token: AsChar, { - if STREAMING { - streaming::space1(input) - } else { - complete::space1(input) - } + if STREAMING { + streaming::space1(input) + } else { + complete::space1(input) + } } /// Recognizes zero or more spaces, tabs, carriage returns and line feeds. @@ -829,18 +829,18 @@ where /// ``` #[inline(always)] pub fn multispace0, const STREAMING: bool>( - input: I, + input: I, ) -> IResult::Slice, E> where - I: InputIsStreaming, - I: Input, - ::Token: AsChar, + I: InputIsStreaming, + I: Input, + ::Token: AsChar, { - if STREAMING { - streaming::multispace0(input) - } else { - complete::multispace0(input) - } + if STREAMING { + streaming::multispace0(input) + } else { + complete::multispace0(input) + } } /// Recognizes one or more spaces, tabs, carriage returns and line feeds. @@ -875,18 +875,18 @@ where /// ``` #[inline(always)] pub fn multispace1, const STREAMING: bool>( - input: I, + input: I, ) -> IResult::Slice, E> where - I: InputIsStreaming, - I: Input, - ::Token: AsChar, + I: InputIsStreaming, + I: Input, + ::Token: AsChar, { - if STREAMING { - streaming::multispace1(input) - } else { - complete::multispace1(input) - } + if STREAMING { + streaming::multispace1(input) + } else { + complete::multispace1(input) + } } /// Decode a decimal unsigned integer @@ -896,144 +896,144 @@ where /// *Streaming version*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data. pub fn dec_uint, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Token: AsChar + Copy, - O: Uint, + I: InputIsStreaming, + I: Input, + ::Token: AsChar + Copy, + O: Uint, { - let i = input.clone(); + let i = input.clone(); - if i.input_len() == 0 { - if STREAMING { - return Err(ErrMode::Incomplete(Needed::new(1))); - } else { - return Err(ErrMode::from_error_kind(input, ErrorKind::Digit)); - } - } - - let mut value = O::default(); - for (offset, c) in i.iter_offsets() { - match c.as_char().to_digit(10) { - Some(d) => match value.checked_mul(10, sealed::SealedMarker).and_then(|v| { - let d = d as u8; - v.checked_add(d, sealed::SealedMarker) - }) { - None => return Err(ErrMode::from_error_kind(input, ErrorKind::Digit)), - Some(v) => value = v, - }, - None => { - if offset == 0 { - return Err(ErrMode::from_error_kind(input, ErrorKind::Digit)); + if i.input_len() == 0 { + if STREAMING { + return Err(ErrMode::Incomplete(Needed::new(1))); } else { - return Ok((i.next_slice(offset).0, value)); + return Err(ErrMode::from_error_kind(input, ErrorKind::Digit)); } - } } - } - if STREAMING { - Err(ErrMode::Incomplete(Needed::new(1))) - } else { - Ok((i.next_slice(i.input_len()).0, value)) - } + let mut value = O::default(); + for (offset, c) in i.iter_offsets() { + match c.as_char().to_digit(10) { + Some(d) => match value.checked_mul(10, sealed::SealedMarker).and_then(|v| { + let d = d as u8; + v.checked_add(d, sealed::SealedMarker) + }) { + None => return Err(ErrMode::from_error_kind(input, ErrorKind::Digit)), + Some(v) => value = v, + }, + None => { + if offset == 0 { + return Err(ErrMode::from_error_kind(input, ErrorKind::Digit)); + } else { + return Ok((i.next_slice(offset).0, value)); + } + } + } + } + + if STREAMING { + Err(ErrMode::Incomplete(Needed::new(1))) + } else { + Ok((i.next_slice(i.input_len()).0, value)) + } } /// Metadata for parsing unsigned integers pub trait Uint: Default { - #[doc(hidden)] - fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option; - #[doc(hidden)] - fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option; + #[doc(hidden)] + fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option; + #[doc(hidden)] + fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option; } impl Uint for u8 { - fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_mul(by as Self) - } - fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_add(by as Self) - } + fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_mul(by as Self) + } + fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_add(by as Self) + } } impl Uint for u16 { - fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_mul(by as Self) - } - fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_add(by as Self) - } + fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_mul(by as Self) + } + fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_add(by as Self) + } } impl Uint for u32 { - fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_mul(by as Self) - } - fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_add(by as Self) - } + fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_mul(by as Self) + } + fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_add(by as Self) + } } impl Uint for u64 { - fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_mul(by as Self) - } - fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_add(by as Self) - } + fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_mul(by as Self) + } + fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_add(by as Self) + } } impl Uint for u128 { - fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_mul(by as Self) - } - fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_add(by as Self) - } + fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_mul(by as Self) + } + fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_add(by as Self) + } } impl Uint for i8 { - fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_mul(by as Self) - } - fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_add(by as Self) - } + fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_mul(by as Self) + } + fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_add(by as Self) + } } impl Uint for i16 { - fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_mul(by as Self) - } - fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_add(by as Self) - } + fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_mul(by as Self) + } + fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_add(by as Self) + } } impl Uint for i32 { - fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_mul(by as Self) - } - fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_add(by as Self) - } + fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_mul(by as Self) + } + fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_add(by as Self) + } } impl Uint for i64 { - fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_mul(by as Self) - } - fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_add(by as Self) - } + fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_mul(by as Self) + } + fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_add(by as Self) + } } impl Uint for i128 { - fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_mul(by as Self) - } - fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_add(by as Self) - } + fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_mul(by as Self) + } + fn checked_add(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_add(by as Self) + } } /// Decode a decimal signed integer @@ -1043,94 +1043,94 @@ impl Uint for i128 { /// *Streaming version*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data. pub fn dec_int, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Token: AsChar + Copy, - O: Int, + I: InputIsStreaming, + I: Input, + ::Token: AsChar + Copy, + O: Int, { - let i = input.clone(); - - fn sign(token: impl AsChar) -> bool { - let token = token.as_char(); - token == '+' || token == '-' - } - let (i, sign) = opt(crate::bytes::one_of(sign).map(AsChar::as_char)) - .map(|c| c != Some('-')) - .parse_next(i)?; + let i = input.clone(); - if i.input_len() == 0 { - if STREAMING { - return Err(ErrMode::Incomplete(Needed::new(1))); - } else { - return Err(ErrMode::from_error_kind(input, ErrorKind::Digit)); + fn sign(token: impl AsChar) -> bool { + let token = token.as_char(); + token == '+' || token == '-' } - } - - let mut value = O::default(); - for (offset, c) in i.iter_offsets() { - match c.as_char().to_digit(10) { - Some(d) => match value.checked_mul(10, sealed::SealedMarker).and_then(|v| { - let d = d as u8; - if sign { - v.checked_add(d, sealed::SealedMarker) + let (i, sign) = opt(crate::bytes::one_of(sign).map(AsChar::as_char)) + .map(|c| c != Some('-')) + .parse_next(i)?; + + if i.input_len() == 0 { + if STREAMING { + return Err(ErrMode::Incomplete(Needed::new(1))); } else { - v.checked_sub(d, sealed::SealedMarker) + return Err(ErrMode::from_error_kind(input, ErrorKind::Digit)); } - }) { - None => return Err(ErrMode::from_error_kind(input, ErrorKind::Digit)), - Some(v) => value = v, - }, - None => { - if offset == 0 { - return Err(ErrMode::from_error_kind(input, ErrorKind::Digit)); - } else { - return Ok((i.next_slice(offset).0, value)); + } + + let mut value = O::default(); + for (offset, c) in i.iter_offsets() { + match c.as_char().to_digit(10) { + Some(d) => match value.checked_mul(10, sealed::SealedMarker).and_then(|v| { + let d = d as u8; + if sign { + v.checked_add(d, sealed::SealedMarker) + } else { + v.checked_sub(d, sealed::SealedMarker) + } + }) { + None => return Err(ErrMode::from_error_kind(input, ErrorKind::Digit)), + Some(v) => value = v, + }, + None => { + if offset == 0 { + return Err(ErrMode::from_error_kind(input, ErrorKind::Digit)); + } else { + return Ok((i.next_slice(offset).0, value)); + } + } } - } } - } - if STREAMING { - Err(ErrMode::Incomplete(Needed::new(1))) - } else { - Ok((i.next_slice(i.input_len()).0, value)) - } + if STREAMING { + Err(ErrMode::Incomplete(Needed::new(1))) + } else { + Ok((i.next_slice(i.input_len()).0, value)) + } } /// Metadata for parsing signed integers pub trait Int: Uint { - #[doc(hidden)] - fn checked_sub(self, by: u8, _: sealed::SealedMarker) -> Option; + #[doc(hidden)] + fn checked_sub(self, by: u8, _: sealed::SealedMarker) -> Option; } impl Int for i8 { - fn checked_sub(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_sub(by as Self) - } + fn checked_sub(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_sub(by as Self) + } } impl Int for i16 { - fn checked_sub(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_sub(by as Self) - } + fn checked_sub(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_sub(by as Self) + } } impl Int for i32 { - fn checked_sub(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_sub(by as Self) - } + fn checked_sub(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_sub(by as Self) + } } impl Int for i64 { - fn checked_sub(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_sub(by as Self) - } + fn checked_sub(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_sub(by as Self) + } } impl Int for i128 { - fn checked_sub(self, by: u8, _: sealed::SealedMarker) -> Option { - self.checked_sub(by as Self) - } + fn checked_sub(self, by: u8, _: sealed::SealedMarker) -> Option { + self.checked_sub(by as Self) + } } /// Decode a variable-width hexadecimal integer. @@ -1174,96 +1174,96 @@ impl Int for i128 { #[inline] pub fn hex_uint, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - O: HexUint, - ::Token: AsChar, - ::Slice: AsBStr, + I: InputIsStreaming, + I: Input, + O: HexUint, + ::Token: AsChar, + ::Slice: AsBStr, { - let invalid_offset = input - .offset_for(|c| { - let c = c.as_char(); - !"0123456789abcdefABCDEF".contains(c) - }) - .unwrap_or_else(|| input.input_len()); - let max_nibbles = O::max_nibbles(sealed::SealedMarker); - let max_offset = input.offset_at(max_nibbles); - let offset = match max_offset { - Ok(max_offset) => { - if max_offset < invalid_offset { - // Overflow + let invalid_offset = input + .offset_for(|c| { + let c = c.as_char(); + !"0123456789abcdefABCDEF".contains(c) + }) + .unwrap_or_else(|| input.input_len()); + let max_nibbles = O::max_nibbles(sealed::SealedMarker); + let max_offset = input.offset_at(max_nibbles); + let offset = match max_offset { + Ok(max_offset) => { + if max_offset < invalid_offset { + // Overflow + return Err(ErrMode::from_error_kind(input, ErrorKind::IsA)); + } else { + invalid_offset + } + } + Err(_) => { + if STREAMING && invalid_offset == input.input_len() { + // Only the next byte is guaranteed required + return Err(ErrMode::Incomplete(Needed::new(1))); + } else { + invalid_offset + } + } + }; + if offset == 0 { + // Must be at least one digit return Err(ErrMode::from_error_kind(input, ErrorKind::IsA)); - } else { - invalid_offset - } } - Err(_) => { - if STREAMING && invalid_offset == input.input_len() { - // Only the next byte is guaranteed required - return Err(ErrMode::Incomplete(Needed::new(1))); - } else { - invalid_offset - } + let (remaining, parsed) = input.next_slice(offset); + + let mut res = O::default(); + for c in parsed.as_bstr() { + let nibble = *c as char; + let nibble = nibble.to_digit(16).unwrap_or(0) as u8; + let nibble = O::from(nibble); + res = (res << O::from(4)) + nibble; } - }; - if offset == 0 { - // Must be at least one digit - return Err(ErrMode::from_error_kind(input, ErrorKind::IsA)); - } - let (remaining, parsed) = input.next_slice(offset); - - let mut res = O::default(); - for c in parsed.as_bstr() { - let nibble = *c as char; - let nibble = nibble.to_digit(16).unwrap_or(0) as u8; - let nibble = O::from(nibble); - res = (res << O::from(4)) + nibble; - } - - Ok((remaining, res)) + + Ok((remaining, res)) } /// Metadata for parsing hex numbers pub trait HexUint: - Default + Shl + Add + From + Default + Shl + Add + From { - #[doc(hidden)] - fn max_nibbles(_: sealed::SealedMarker) -> usize; + #[doc(hidden)] + fn max_nibbles(_: sealed::SealedMarker) -> usize; } impl HexUint for u8 { - #[inline(always)] - fn max_nibbles(_: sealed::SealedMarker) -> usize { - 2 - } + #[inline(always)] + fn max_nibbles(_: sealed::SealedMarker) -> usize { + 2 + } } impl HexUint for u16 { - #[inline(always)] - fn max_nibbles(_: sealed::SealedMarker) -> usize { - 4 - } + #[inline(always)] + fn max_nibbles(_: sealed::SealedMarker) -> usize { + 4 + } } impl HexUint for u32 { - #[inline(always)] - fn max_nibbles(_: sealed::SealedMarker) -> usize { - 8 - } + #[inline(always)] + fn max_nibbles(_: sealed::SealedMarker) -> usize { + 8 + } } impl HexUint for u64 { - #[inline(always)] - fn max_nibbles(_: sealed::SealedMarker) -> usize { - 16 - } + #[inline(always)] + fn max_nibbles(_: sealed::SealedMarker) -> usize { + 16 + } } impl HexUint for u128 { - #[inline(always)] - fn max_nibbles(_: sealed::SealedMarker) -> usize { - 32 - } + #[inline(always)] + fn max_nibbles(_: sealed::SealedMarker) -> usize { + 32 + } } /// Recognizes floating point number in text format and returns a f32. @@ -1310,23 +1310,23 @@ impl HexUint for u128 { #[inline(always)] pub fn float, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - I: Offset + Compare<&'static str>, - ::Slice: ParseSlice, - ::Token: AsChar + Copy, - ::IterOffsets: Clone, - I: AsBStr, + I: InputIsStreaming, + I: Input, + I: Offset + Compare<&'static str>, + ::Slice: ParseSlice, + ::Token: AsChar + Copy, + ::IterOffsets: Clone, + I: AsBStr, { - let (i, s) = if STREAMING { - crate::number::streaming::recognize_float_or_exceptions(input)? - } else { - crate::number::complete::recognize_float_or_exceptions(input)? - }; - match s.parse_slice() { - Some(f) => Ok((i, f)), - None => Err(ErrMode::from_error_kind(i, ErrorKind::Float)), - } + let (i, s) = if STREAMING { + crate::number::streaming::recognize_float_or_exceptions(input)? + } else { + crate::number::complete::recognize_float_or_exceptions(input)? + }; + match s.parse_slice() { + Some(f) => Ok((i, f)), + None => Err(ErrMode::from_error_kind(i, ErrorKind::Float)), + } } /// Matches a byte string with escaped characters. @@ -1365,25 +1365,35 @@ where /// ``` #[inline(always)] pub fn escaped<'a, I: 'a, Error, F, G, O1, O2, const STREAMING: bool>( - mut normal: F, - control_char: char, - mut escapable: G, + mut normal: F, + control_char: char, + mut escapable: G, ) -> impl FnMut(I) -> IResult::Slice, Error> where - I: InputIsStreaming, - I: Input + Offset, - ::Token: crate::input::AsChar, - F: Parser, - G: Parser, - Error: ParseError, + I: InputIsStreaming, + I: Input + Offset, + ::Token: crate::input::AsChar, + F: Parser, + G: Parser, + Error: ParseError, { - move |input: I| { - if STREAMING { - crate::bytes::streaming::escaped_internal(input, &mut normal, control_char, &mut escapable) - } else { - crate::bytes::complete::escaped_internal(input, &mut normal, control_char, &mut escapable) + move |input: I| { + if STREAMING { + crate::bytes::streaming::escaped_internal( + input, + &mut normal, + control_char, + &mut escapable, + ) + } else { + crate::bytes::complete::escaped_internal( + input, + &mut normal, + control_char, + &mut escapable, + ) + } } - } } /// Matches a byte string with escaped characters. @@ -1448,88 +1458,88 @@ where #[cfg(feature = "alloc")] #[inline(always)] pub fn escaped_transform( - mut normal: F, - control_char: char, - mut transform: G, + mut normal: F, + control_char: char, + mut transform: G, ) -> impl FnMut(I) -> IResult where - I: InputIsStreaming, - I: Input + Offset, - ::Token: crate::input::AsChar, - Output: crate::input::Accumulate<::Slice>, - F: Parser::Slice, Error>, - G: Parser::Slice, Error>, - Error: ParseError, + I: InputIsStreaming, + I: Input + Offset, + ::Token: crate::input::AsChar, + Output: crate::input::Accumulate<::Slice>, + F: Parser::Slice, Error>, + G: Parser::Slice, Error>, + Error: ParseError, { - move |input: I| { - if STREAMING { - crate::bytes::streaming::escaped_transform_internal( - input, - &mut normal, - control_char, - &mut transform, - ) - } else { - crate::bytes::complete::escaped_transform_internal( - input, - &mut normal, - control_char, - &mut transform, - ) + move |input: I| { + if STREAMING { + crate::bytes::streaming::escaped_transform_internal( + input, + &mut normal, + control_char, + &mut transform, + ) + } else { + crate::bytes::complete::escaped_transform_internal( + input, + &mut normal, + control_char, + &mut transform, + ) + } } - } } #[inline] #[doc(hidden)] #[deprecated(since = "0.1.0", note = "Replaced with `AsChar::is_alpha`")] pub fn is_alphabetic(chr: u8) -> bool { - matches!(chr, 0x41..=0x5A | 0x61..=0x7A) + matches!(chr, 0x41..=0x5A | 0x61..=0x7A) } #[inline] #[doc(hidden)] #[deprecated(since = "0.1.0", note = "Replaced with `AsChar::is_dec_digit`")] pub fn is_digit(chr: u8) -> bool { - matches!(chr, 0x30..=0x39) + matches!(chr, 0x30..=0x39) } #[inline] #[doc(hidden)] #[deprecated(since = "0.1.0", note = "Replaced with `AsChar::is_hex_digit`")] pub fn is_hex_digit(chr: u8) -> bool { - matches!(chr, 0x30..=0x39 | 0x41..=0x46 | 0x61..=0x66) + matches!(chr, 0x30..=0x39 | 0x41..=0x46 | 0x61..=0x66) } #[inline] #[doc(hidden)] #[deprecated(since = "0.1.0", note = "Replaced with `AsChar::is_oct_digit`")] pub fn is_oct_digit(chr: u8) -> bool { - matches!(chr, 0x30..=0x37) + matches!(chr, 0x30..=0x37) } #[inline] #[doc(hidden)] #[deprecated(since = "0.1.0", note = "Replaced with `AsChar::is_alphanum`")] pub fn is_alphanumeric(chr: u8) -> bool { - #![allow(deprecated)] - is_alphabetic(chr) || is_digit(chr) + #![allow(deprecated)] + is_alphabetic(chr) || is_digit(chr) } #[inline] #[doc(hidden)] #[deprecated(since = "0.1.0", note = "Replaced with `AsChar::is_space`")] pub fn is_space(chr: u8) -> bool { - chr == b' ' || chr == b'\t' + chr == b' ' || chr == b'\t' } #[inline] #[doc(hidden)] #[deprecated(since = "0.1.0", note = "Replaced with `AsChar::is_newline`")] pub fn is_newline(chr: u8) -> bool { - chr == b'\n' + chr == b'\n' } mod sealed { - pub struct SealedMarker; + pub struct SealedMarker; } diff --git a/src/character/streaming.rs b/src/character/streaming.rs index 6535bb00..010d926e 100644 --- a/src/character/streaming.rs +++ b/src/character/streaming.rs @@ -10,7 +10,7 @@ use crate::error::ErrorKind; use crate::error::Needed; use crate::error::ParseError; use crate::input::{ - split_at_offset1_streaming, split_at_offset_streaming, AsBStr, AsChar, ContainsToken, Input, + split_at_offset1_streaming, split_at_offset_streaming, AsBStr, AsChar, ContainsToken, Input, }; use crate::input::{Compare, CompareResult}; use crate::IResult; @@ -33,31 +33,31 @@ use crate::IResult; /// /// **WARNING:** Deprecated, replaced with [`winnow::bytes::one_of`][crate::bytes::one_of] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::bytes::one_of` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::bytes::one_of` with input wrapped in `winnow::input::Streaming`" )] pub fn char>(c: char) -> impl Fn(I) -> IResult where - I: Input, - ::Token: AsChar, + I: Input, + ::Token: AsChar, { - move |i: I| char_internal(i, c) + move |i: I| char_internal(i, c) } pub(crate) fn char_internal>(i: I, c: char) -> IResult where - I: Input, - ::Token: AsChar, + I: Input, + ::Token: AsChar, { - let (input, token) = i - .next_token() - .map(|(i, t)| (i, t.as_char())) - .ok_or_else(|| ErrMode::Incomplete(Needed::new(1)))?; - if c == token { - Ok((input, token)) - } else { - Err(ErrMode::Backtrack(Error::from_char(i, c))) - } + let (input, token) = i + .next_token() + .map(|(i, t)| (i, t.as_char())) + .ok_or_else(|| ErrMode::Incomplete(Needed::new(1)))?; + if c == token { + Ok((input, token)) + } else { + Err(ErrMode::Backtrack(Error::from_char(i, c))) + } } /// Recognizes one character and checks that it satisfies a predicate @@ -78,36 +78,36 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::bytes::one_of`][crate::bytes::one_of] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::bytes::one_of` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::bytes::one_of` with input wrapped in `winnow::input::Streaming`" )] pub fn satisfy>(cond: F) -> impl Fn(I) -> IResult where - I: Input, - ::Token: AsChar, - F: Fn(char) -> bool, + I: Input, + ::Token: AsChar, + F: Fn(char) -> bool, { - move |i: I| satisfy_internal(i, &cond) + move |i: I| satisfy_internal(i, &cond) } pub(crate) fn satisfy_internal>( - i: I, - cond: &F, + i: I, + cond: &F, ) -> IResult where - I: Input, - ::Token: AsChar, - F: Fn(char) -> bool, + I: Input, + ::Token: AsChar, + F: Fn(char) -> bool, { - let (input, token) = i - .next_token() - .map(|(i, t)| (i, t.as_char())) - .ok_or(ErrMode::Incomplete(Needed::Unknown))?; - if cond(token) { - Ok((input, token)) - } else { - Err(ErrMode::from_error_kind(i, ErrorKind::Satisfy)) - } + let (input, token) = i + .next_token() + .map(|(i, t)| (i, t.as_char())) + .ok_or(ErrMode::Incomplete(Needed::Unknown))?; + if cond(token) { + Ok((input, token)) + } else { + Err(ErrMode::from_error_kind(i, ErrorKind::Satisfy)) + } } /// Recognizes one of the provided characters. @@ -125,16 +125,16 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::bytes::one_of`][crate::bytes::one_of] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::bytes::one_of` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::bytes::one_of` with input wrapped in `winnow::input::Streaming`" )] pub fn one_of>(list: T) -> impl Fn(I) -> IResult where - I: Input, - ::Token: Copy + AsChar, - T: ContainsToken<::Token>, + I: Input, + ::Token: Copy + AsChar, + T: ContainsToken<::Token>, { - move |i: I| crate::bytes::streaming::one_of_internal(i, &list).map(|(i, c)| (i, c.as_char())) + move |i: I| crate::bytes::streaming::one_of_internal(i, &list).map(|(i, c)| (i, c.as_char())) } /// Recognizes a character that is not in the provided characters. @@ -152,16 +152,16 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::bytes::none_of`][crate::bytes::none_of] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::bytes::none_of` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::bytes::none_of` with input wrapped in `winnow::input::Streaming`" )] pub fn none_of>(list: T) -> impl Fn(I) -> IResult where - I: Input, - ::Token: Copy + AsChar, - T: ContainsToken<::Token>, + I: Input, + ::Token: Copy + AsChar, + T: ContainsToken<::Token>, { - move |i: I| crate::bytes::streaming::none_of_internal(i, &list).map(|(i, c)| (i, c.as_char())) + move |i: I| crate::bytes::streaming::none_of_internal(i, &list).map(|(i, c)| (i, c.as_char())) } /// Recognizes the string "\r\n". @@ -179,23 +179,23 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::crlf`][crate::character::crlf] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::crlf` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::crlf` with input wrapped in `winnow::input::Streaming`" )] pub fn crlf>(input: T) -> IResult::Slice, E> where - T: Input, - T: Compare<&'static str>, + T: Input, + T: Compare<&'static str>, { - const CRLF: &str = "\r\n"; - match input.compare(CRLF) { - CompareResult::Ok => Ok(input.next_slice(CRLF.len())), - CompareResult::Incomplete => Err(ErrMode::Incomplete(Needed::new(CRLF.len()))), - CompareResult::Error => { - let e: ErrorKind = ErrorKind::CrLf; - Err(ErrMode::from_error_kind(input, e)) + const CRLF: &str = "\r\n"; + match input.compare(CRLF) { + CompareResult::Ok => Ok(input.next_slice(CRLF.len())), + CompareResult::Incomplete => Err(ErrMode::Incomplete(Needed::new(CRLF.len()))), + CompareResult::Error => { + let e: ErrorKind = ErrorKind::CrLf; + Err(ErrMode::from_error_kind(input, e)) + } } - } } /// Recognizes a string of any char except '\r\n' or '\n'. @@ -215,41 +215,41 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::not_line_ending`][crate::character::not_line_ending] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::not_line_ending` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::not_line_ending` with input wrapped in `winnow::input::Streaming`" )] pub fn not_line_ending>(input: T) -> IResult::Slice, E> where - T: Input + AsBStr, - T: Compare<&'static str>, - ::Token: AsChar, + T: Input + AsBStr, + T: Compare<&'static str>, + ::Token: AsChar, { - match input.offset_for(|item| { - let c = item.as_char(); - c == '\r' || c == '\n' - }) { - None => Err(ErrMode::Incomplete(Needed::Unknown)), - Some(offset) => { - let (new_input, res) = input.next_slice(offset); - let bytes = new_input.as_bstr(); - let nth = bytes[0]; - if nth == b'\r' { - let comp = new_input.compare("\r\n"); - match comp { - //FIXME: calculate the right index - CompareResult::Ok => {} - CompareResult::Incomplete => { - return Err(ErrMode::Incomplete(Needed::Unknown)); - } - CompareResult::Error => { - let e: ErrorKind = ErrorKind::Tag; - return Err(ErrMode::from_error_kind(input, e)); - } + match input.offset_for(|item| { + let c = item.as_char(); + c == '\r' || c == '\n' + }) { + None => Err(ErrMode::Incomplete(Needed::Unknown)), + Some(offset) => { + let (new_input, res) = input.next_slice(offset); + let bytes = new_input.as_bstr(); + let nth = bytes[0]; + if nth == b'\r' { + let comp = new_input.compare("\r\n"); + match comp { + //FIXME: calculate the right index + CompareResult::Ok => {} + CompareResult::Incomplete => { + return Err(ErrMode::Incomplete(Needed::Unknown)); + } + CompareResult::Error => { + let e: ErrorKind = ErrorKind::Tag; + return Err(ErrMode::from_error_kind(input, e)); + } + } + } + Ok((new_input, res)) } - } - Ok((new_input, res)) } - } } /// Recognizes an end of line (both '\n' and '\r\n'). @@ -267,25 +267,25 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::line_ending`][crate::character::line_ending] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::line_ending` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::line_ending` with input wrapped in `winnow::input::Streaming`" )] pub fn line_ending>(input: T) -> IResult::Slice, E> where - T: Input, - T: Compare<&'static str>, + T: Input, + T: Compare<&'static str>, { - const LF: &str = "\n"; - const CRLF: &str = "\r\n"; - match input.compare(LF) { - CompareResult::Ok => Ok(input.next_slice(LF.len())), - CompareResult::Incomplete => Err(ErrMode::Incomplete(Needed::new(1))), - CompareResult::Error => match input.compare("\r\n") { - CompareResult::Ok => Ok(input.next_slice(CRLF.len())), - CompareResult::Incomplete => Err(ErrMode::Incomplete(Needed::new(2))), - CompareResult::Error => Err(ErrMode::from_error_kind(input, ErrorKind::CrLf)), - }, - } + const LF: &str = "\n"; + const CRLF: &str = "\r\n"; + match input.compare(LF) { + CompareResult::Ok => Ok(input.next_slice(LF.len())), + CompareResult::Incomplete => Err(ErrMode::Incomplete(Needed::new(1))), + CompareResult::Error => match input.compare("\r\n") { + CompareResult::Ok => Ok(input.next_slice(CRLF.len())), + CompareResult::Incomplete => Err(ErrMode::Incomplete(Needed::new(2))), + CompareResult::Error => Err(ErrMode::from_error_kind(input, ErrorKind::CrLf)), + }, + } } /// Matches a newline character '\\n'. @@ -303,15 +303,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::newline`][crate::character::newline] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::newline` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::newline` with input wrapped in `winnow::input::Streaming`" )] pub fn newline>(input: I) -> IResult where - I: Input, - ::Token: AsChar, + I: Input, + ::Token: AsChar, { - char('\n')(input) + char('\n')(input) } /// Matches a tab character '\t'. @@ -329,15 +329,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::tab`][crate::character::tab] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::tab` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::tab` with input wrapped in `winnow::input::Streaming`" )] pub fn tab>(input: I) -> IResult where - I: Input, - ::Token: AsChar, + I: Input, + ::Token: AsChar, { - char('\t')(input) + char('\t')(input) } /// Matches one byte as a character. Note that the input type will @@ -354,15 +354,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::bytes::any`][crate::bytes::any] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::bytes::any` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::bytes::any` with input wrapped in `winnow::input::Streaming`" )] pub fn anychar>(input: T) -> IResult where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - crate::bytes::streaming::any(input).map(|(i, c)| (i, c.as_char())) + crate::bytes::streaming::any(input).map(|(i, c)| (i, c.as_char())) } /// Recognizes zero or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z @@ -381,15 +381,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::alpha0`][crate::character::alpha0] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::alpha0` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::alpha0` with input wrapped in `winnow::input::Streaming`" )] pub fn alpha0>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset_streaming(&input, |item| !item.is_alpha()) + split_at_offset_streaming(&input, |item| !item.is_alpha()) } /// Recognizes one or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z @@ -408,15 +408,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::alpha1`][crate::character::alpha1] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::alpha1` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::alpha1` with input wrapped in `winnow::input::Streaming`" )] pub fn alpha1>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset1_streaming(&input, |item| !item.is_alpha(), ErrorKind::Alpha) + split_at_offset1_streaming(&input, |item| !item.is_alpha(), ErrorKind::Alpha) } /// Recognizes zero or more ASCII numerical characters: 0-9 @@ -435,15 +435,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::digit0`][crate::character::digit0] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::digit0` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::digit0` with input wrapped in `winnow::input::Streaming`" )] pub fn digit0>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset_streaming(&input, |item| !item.is_dec_digit()) + split_at_offset_streaming(&input, |item| !item.is_dec_digit()) } /// Recognizes one or more ASCII numerical characters: 0-9 @@ -462,15 +462,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::digit1`][crate::character::digit1] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::digit1` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::digit1` with input wrapped in `winnow::input::Streaming`" )] pub fn digit1>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset1_streaming(&input, |item| !item.is_dec_digit(), ErrorKind::Digit) + split_at_offset1_streaming(&input, |item| !item.is_dec_digit(), ErrorKind::Digit) } /// Recognizes zero or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f @@ -489,15 +489,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::hex_digit0`][crate::character::hex_digit0] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::hex_digit0` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::hex_digit0` with input wrapped in `winnow::input::Streaming`" )] pub fn hex_digit0>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset_streaming(&input, |item| !item.is_hex_digit()) + split_at_offset_streaming(&input, |item| !item.is_hex_digit()) } /// Recognizes one or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f @@ -516,15 +516,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::hex_digit1`][crate::character::hex_digit1] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::hex_digit1` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::hex_digit1` with input wrapped in `winnow::input::Streaming`" )] pub fn hex_digit1>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset1_streaming(&input, |item| !item.is_hex_digit(), ErrorKind::HexDigit) + split_at_offset1_streaming(&input, |item| !item.is_hex_digit(), ErrorKind::HexDigit) } /// Recognizes zero or more octal characters: 0-7 @@ -543,15 +543,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::oct_digit0`][crate::character::oct_digit0] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::oct_digit0` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::oct_digit0` with input wrapped in `winnow::input::Streaming`" )] pub fn oct_digit0>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset_streaming(&input, |item| !item.is_oct_digit()) + split_at_offset_streaming(&input, |item| !item.is_oct_digit()) } /// Recognizes one or more octal characters: 0-7 @@ -570,15 +570,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::oct_digit1`][crate::character::oct_digit1] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::oct_digit1` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::oct_digit1` with input wrapped in `winnow::input::Streaming`" )] pub fn oct_digit1>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset1_streaming(&input, |item| !item.is_oct_digit(), ErrorKind::OctDigit) + split_at_offset1_streaming(&input, |item| !item.is_oct_digit(), ErrorKind::OctDigit) } /// Recognizes zero or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z @@ -597,15 +597,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::alphanumeric0`][crate::character::alphanumeric0] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::alphanumeric0` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::alphanumeric0` with input wrapped in `winnow::input::Streaming`" )] pub fn alphanumeric0>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset_streaming(&input, |item| !item.is_alphanum()) + split_at_offset_streaming(&input, |item| !item.is_alphanum()) } /// Recognizes one or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z @@ -624,15 +624,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::alphanumeric1`][crate::character::alphanumeric1] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::alphanumeric1` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::alphanumeric1` with input wrapped in `winnow::input::Streaming`" )] pub fn alphanumeric1>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset1_streaming(&input, |item| !item.is_alphanum(), ErrorKind::AlphaNumeric) + split_at_offset1_streaming(&input, |item| !item.is_alphanum(), ErrorKind::AlphaNumeric) } /// Recognizes zero or more spaces and tabs. @@ -651,18 +651,18 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::space0`][crate::character::space0] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::space0` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::space0` with input wrapped in `winnow::input::Streaming`" )] pub fn space0>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset_streaming(&input, |item| { - let c = item.as_char(); - !(c == ' ' || c == '\t') - }) + split_at_offset_streaming(&input, |item| { + let c = item.as_char(); + !(c == ' ' || c == '\t') + }) } /// Recognizes one or more spaces and tabs. /// @@ -680,22 +680,22 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::space1`][crate::character::space1] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::space1` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::space1` with input wrapped in `winnow::input::Streaming`" )] pub fn space1>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset1_streaming( - &input, - |item| { - let c = item.as_char(); - !(c == ' ' || c == '\t') - }, - ErrorKind::Space, - ) + split_at_offset1_streaming( + &input, + |item| { + let c = item.as_char(); + !(c == ' ' || c == '\t') + }, + ErrorKind::Space, + ) } /// Recognizes zero or more spaces, tabs, carriage returns and line feeds. @@ -714,18 +714,18 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::multispace0`][crate::character::multispace0] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::multispace0` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::multispace0` with input wrapped in `winnow::input::Streaming`" )] pub fn multispace0>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset_streaming(&input, |item| { - let c = item.as_char(); - !(c == ' ' || c == '\t' || c == '\r' || c == '\n') - }) + split_at_offset_streaming(&input, |item| { + let c = item.as_char(); + !(c == ' ' || c == '\t' || c == '\r' || c == '\n') + }) } /// Recognizes one or more spaces, tabs, carriage returns and line feeds. @@ -744,38 +744,38 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::multispace1`][crate::character::multispace1] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::multispace1` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::multispace1` with input wrapped in `winnow::input::Streaming`" )] pub fn multispace1>(input: T) -> IResult::Slice, E> where - T: Input, - ::Token: AsChar, + T: Input, + ::Token: AsChar, { - split_at_offset1_streaming( - &input, - |item| { - let c = item.as_char(); - !(c == ' ' || c == '\t' || c == '\r' || c == '\n') - }, - ErrorKind::MultiSpace, - ) + split_at_offset1_streaming( + &input, + |item| { + let c = item.as_char(); + !(c == ' ' || c == '\t' || c == '\r' || c == '\n') + }, + ErrorKind::MultiSpace, + ) } pub(crate) fn sign>(input: T) -> IResult where - T: Input, - ::Token: AsChar + Copy, + T: Input, + ::Token: AsChar + Copy, { - fn sign(token: impl AsChar) -> bool { - let token = token.as_char(); - token == '+' || token == '-' - } + fn sign(token: impl AsChar) -> bool { + let token = token.as_char(); + token == '+' || token == '-' + } - let (i, sign) = opt(|input| crate::bytes::streaming::one_of_internal(input, &sign))(input)?; - let sign = sign.map(AsChar::as_char) != Some('-'); + let (i, sign) = opt(|input| crate::bytes::streaming::one_of_internal(input, &sign))(input)?; + let sign = sign.map(AsChar::as_char) != Some('-'); - Ok((i, sign)) + Ok((i, sign)) } #[doc(hidden)] @@ -872,564 +872,564 @@ uints! { u8 u16 u32 u64 u128 } #[cfg(test)] mod tests { - use super::*; - use crate::branch::alt; - use crate::error::Error; - use crate::error::ErrorKind; - use crate::error::{ErrMode, Needed}; - use crate::input::ParseSlice; - use crate::sequence::pair; - use crate::IResult; - use proptest::prelude::*; - - macro_rules! assert_parse( + use super::*; + use crate::branch::alt; + use crate::error::Error; + use crate::error::ErrorKind; + use crate::error::{ErrMode, Needed}; + use crate::input::ParseSlice; + use crate::sequence::pair; + use crate::IResult; + use proptest::prelude::*; + + macro_rules! assert_parse( ($left: expr, $right: expr) => { let res: $crate::IResult<_, _, Error<_>> = $left; assert_eq!(res, $right); }; ); - #[test] - fn anychar_str() { - use super::anychar; - assert_eq!(anychar::<_, Error<_>>("Ә"), Ok(("", 'Ә'))); - } - - #[test] - fn character() { - let a: &[u8] = b"abcd"; - let b: &[u8] = b"1234"; - let c: &[u8] = b"a123"; - let d: &[u8] = "azé12".as_bstr(); - let e: &[u8] = b" "; - let f: &[u8] = b" ;"; - //assert_eq!(alpha1::<_, Error<_>>(a), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_parse!(alpha1(a), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!( - alpha1(b), - Err(ErrMode::Backtrack(Error::new(b, ErrorKind::Alpha))) - ); - assert_eq!(alpha1::<_, Error<_>>(c), Ok((&c[1..], &b"a"[..]))); - assert_eq!(alpha1::<_, Error<_>>(d), Ok(("é12".as_bstr(), &b"az"[..]))); - assert_eq!( - digit1(a), - Err(ErrMode::Backtrack(Error::new(a, ErrorKind::Digit))) - ); - assert_eq!( - digit1::<_, Error<_>>(b), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - digit1(c), - Err(ErrMode::Backtrack(Error::new(c, ErrorKind::Digit))) - ); - assert_eq!( - digit1(d), - Err(ErrMode::Backtrack(Error::new(d, ErrorKind::Digit))) - ); - assert_eq!( - hex_digit1::<_, Error<_>>(a), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - hex_digit1::<_, Error<_>>(b), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - hex_digit1::<_, Error<_>>(c), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - hex_digit1::<_, Error<_>>(d), - Ok(("zé12".as_bstr(), &b"a"[..])) - ); - assert_eq!( - hex_digit1(e), - Err(ErrMode::Backtrack(Error::new(e, ErrorKind::HexDigit))) - ); - assert_eq!( - oct_digit1(a), - Err(ErrMode::Backtrack(Error::new(a, ErrorKind::OctDigit))) - ); - assert_eq!( - oct_digit1::<_, Error<_>>(b), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - oct_digit1(c), - Err(ErrMode::Backtrack(Error::new(c, ErrorKind::OctDigit))) - ); - assert_eq!( - oct_digit1(d), - Err(ErrMode::Backtrack(Error::new(d, ErrorKind::OctDigit))) - ); - assert_eq!( - alphanumeric1::<_, Error<_>>(a), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - //assert_eq!(fix_error!(b,(), alphanumeric1), Ok((empty, b))); - assert_eq!( - alphanumeric1::<_, Error<_>>(c), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - alphanumeric1::<_, Error<_>>(d), - Ok(("é12".as_bstr(), &b"az"[..])) - ); - assert_eq!( - space1::<_, Error<_>>(e), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!(space1::<_, Error<_>>(f), Ok((&b";"[..], &b" "[..]))); - } - - #[cfg(feature = "alloc")] - #[test] - fn character_s() { - let a = "abcd"; - let b = "1234"; - let c = "a123"; - let d = "azé12"; - let e = " "; - assert_eq!( - alpha1::<_, Error<_>>(a), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - alpha1(b), - Err(ErrMode::Backtrack(Error::new(b, ErrorKind::Alpha))) - ); - assert_eq!(alpha1::<_, Error<_>>(c), Ok((&c[1..], "a"))); - assert_eq!(alpha1::<_, Error<_>>(d), Ok(("é12", "az"))); - assert_eq!( - digit1(a), - Err(ErrMode::Backtrack(Error::new(a, ErrorKind::Digit))) - ); - assert_eq!( - digit1::<_, Error<_>>(b), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - digit1(c), - Err(ErrMode::Backtrack(Error::new(c, ErrorKind::Digit))) - ); - assert_eq!( - digit1(d), - Err(ErrMode::Backtrack(Error::new(d, ErrorKind::Digit))) - ); - assert_eq!( - hex_digit1::<_, Error<_>>(a), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - hex_digit1::<_, Error<_>>(b), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - hex_digit1::<_, Error<_>>(c), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!(hex_digit1::<_, Error<_>>(d), Ok(("zé12", "a"))); - assert_eq!( - hex_digit1(e), - Err(ErrMode::Backtrack(Error::new(e, ErrorKind::HexDigit))) - ); - assert_eq!( - oct_digit1(a), - Err(ErrMode::Backtrack(Error::new(a, ErrorKind::OctDigit))) - ); - assert_eq!( - oct_digit1::<_, Error<_>>(b), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - oct_digit1(c), - Err(ErrMode::Backtrack(Error::new(c, ErrorKind::OctDigit))) - ); - assert_eq!( - oct_digit1(d), - Err(ErrMode::Backtrack(Error::new(d, ErrorKind::OctDigit))) - ); - assert_eq!( - alphanumeric1::<_, Error<_>>(a), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - //assert_eq!(fix_error!(b,(), alphanumeric1), Ok((empty, b))); - assert_eq!( - alphanumeric1::<_, Error<_>>(c), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!(alphanumeric1::<_, Error<_>>(d), Ok(("é12", "az"))); - assert_eq!( - space1::<_, Error<_>>(e), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - } - - use crate::input::Offset; - #[test] - fn offset() { - let a = &b"abcd;"[..]; - let b = &b"1234;"[..]; - let c = &b"a123;"[..]; - let d = &b" \t;"[..]; - let e = &b" \t\r\n;"[..]; - let f = &b"123abcDEF;"[..]; - - match alpha1::<_, Error<_>>(a) { - Ok((i, _)) => { - assert_eq!(a.offset_to(i) + i.len(), a.len()); - } - _ => panic!("wrong return type in offset test for alpha"), - } - match digit1::<_, Error<_>>(b) { - Ok((i, _)) => { - assert_eq!(b.offset_to(i) + i.len(), b.len()); - } - _ => panic!("wrong return type in offset test for digit"), + #[test] + fn anychar_str() { + use super::anychar; + assert_eq!(anychar::<_, Error<_>>("Ә"), Ok(("", 'Ә'))); } - match alphanumeric1::<_, Error<_>>(c) { - Ok((i, _)) => { - assert_eq!(c.offset_to(i) + i.len(), c.len()); - } - _ => panic!("wrong return type in offset test for alphanumeric"), + + #[test] + fn character() { + let a: &[u8] = b"abcd"; + let b: &[u8] = b"1234"; + let c: &[u8] = b"a123"; + let d: &[u8] = "azé12".as_bstr(); + let e: &[u8] = b" "; + let f: &[u8] = b" ;"; + //assert_eq!(alpha1::<_, Error<_>>(a), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_parse!(alpha1(a), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!( + alpha1(b), + Err(ErrMode::Backtrack(Error::new(b, ErrorKind::Alpha))) + ); + assert_eq!(alpha1::<_, Error<_>>(c), Ok((&c[1..], &b"a"[..]))); + assert_eq!(alpha1::<_, Error<_>>(d), Ok(("é12".as_bstr(), &b"az"[..]))); + assert_eq!( + digit1(a), + Err(ErrMode::Backtrack(Error::new(a, ErrorKind::Digit))) + ); + assert_eq!( + digit1::<_, Error<_>>(b), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + digit1(c), + Err(ErrMode::Backtrack(Error::new(c, ErrorKind::Digit))) + ); + assert_eq!( + digit1(d), + Err(ErrMode::Backtrack(Error::new(d, ErrorKind::Digit))) + ); + assert_eq!( + hex_digit1::<_, Error<_>>(a), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + hex_digit1::<_, Error<_>>(b), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + hex_digit1::<_, Error<_>>(c), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + hex_digit1::<_, Error<_>>(d), + Ok(("zé12".as_bstr(), &b"a"[..])) + ); + assert_eq!( + hex_digit1(e), + Err(ErrMode::Backtrack(Error::new(e, ErrorKind::HexDigit))) + ); + assert_eq!( + oct_digit1(a), + Err(ErrMode::Backtrack(Error::new(a, ErrorKind::OctDigit))) + ); + assert_eq!( + oct_digit1::<_, Error<_>>(b), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + oct_digit1(c), + Err(ErrMode::Backtrack(Error::new(c, ErrorKind::OctDigit))) + ); + assert_eq!( + oct_digit1(d), + Err(ErrMode::Backtrack(Error::new(d, ErrorKind::OctDigit))) + ); + assert_eq!( + alphanumeric1::<_, Error<_>>(a), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + //assert_eq!(fix_error!(b,(), alphanumeric1), Ok((empty, b))); + assert_eq!( + alphanumeric1::<_, Error<_>>(c), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + alphanumeric1::<_, Error<_>>(d), + Ok(("é12".as_bstr(), &b"az"[..])) + ); + assert_eq!( + space1::<_, Error<_>>(e), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!(space1::<_, Error<_>>(f), Ok((&b";"[..], &b" "[..]))); } - match space1::<_, Error<_>>(d) { - Ok((i, _)) => { - assert_eq!(d.offset_to(i) + i.len(), d.len()); - } - _ => panic!("wrong return type in offset test for space"), + + #[cfg(feature = "alloc")] + #[test] + fn character_s() { + let a = "abcd"; + let b = "1234"; + let c = "a123"; + let d = "azé12"; + let e = " "; + assert_eq!( + alpha1::<_, Error<_>>(a), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + alpha1(b), + Err(ErrMode::Backtrack(Error::new(b, ErrorKind::Alpha))) + ); + assert_eq!(alpha1::<_, Error<_>>(c), Ok((&c[1..], "a"))); + assert_eq!(alpha1::<_, Error<_>>(d), Ok(("é12", "az"))); + assert_eq!( + digit1(a), + Err(ErrMode::Backtrack(Error::new(a, ErrorKind::Digit))) + ); + assert_eq!( + digit1::<_, Error<_>>(b), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + digit1(c), + Err(ErrMode::Backtrack(Error::new(c, ErrorKind::Digit))) + ); + assert_eq!( + digit1(d), + Err(ErrMode::Backtrack(Error::new(d, ErrorKind::Digit))) + ); + assert_eq!( + hex_digit1::<_, Error<_>>(a), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + hex_digit1::<_, Error<_>>(b), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + hex_digit1::<_, Error<_>>(c), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!(hex_digit1::<_, Error<_>>(d), Ok(("zé12", "a"))); + assert_eq!( + hex_digit1(e), + Err(ErrMode::Backtrack(Error::new(e, ErrorKind::HexDigit))) + ); + assert_eq!( + oct_digit1(a), + Err(ErrMode::Backtrack(Error::new(a, ErrorKind::OctDigit))) + ); + assert_eq!( + oct_digit1::<_, Error<_>>(b), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + oct_digit1(c), + Err(ErrMode::Backtrack(Error::new(c, ErrorKind::OctDigit))) + ); + assert_eq!( + oct_digit1(d), + Err(ErrMode::Backtrack(Error::new(d, ErrorKind::OctDigit))) + ); + assert_eq!( + alphanumeric1::<_, Error<_>>(a), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + //assert_eq!(fix_error!(b,(), alphanumeric1), Ok((empty, b))); + assert_eq!( + alphanumeric1::<_, Error<_>>(c), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!(alphanumeric1::<_, Error<_>>(d), Ok(("é12", "az"))); + assert_eq!( + space1::<_, Error<_>>(e), + Err(ErrMode::Incomplete(Needed::new(1))) + ); } - match multispace1::<_, Error<_>>(e) { - Ok((i, _)) => { - assert_eq!(e.offset_to(i) + i.len(), e.len()); - } - _ => panic!("wrong return type in offset test for multispace"), + + use crate::input::Offset; + #[test] + fn offset() { + let a = &b"abcd;"[..]; + let b = &b"1234;"[..]; + let c = &b"a123;"[..]; + let d = &b" \t;"[..]; + let e = &b" \t\r\n;"[..]; + let f = &b"123abcDEF;"[..]; + + match alpha1::<_, Error<_>>(a) { + Ok((i, _)) => { + assert_eq!(a.offset_to(i) + i.len(), a.len()); + } + _ => panic!("wrong return type in offset test for alpha"), + } + match digit1::<_, Error<_>>(b) { + Ok((i, _)) => { + assert_eq!(b.offset_to(i) + i.len(), b.len()); + } + _ => panic!("wrong return type in offset test for digit"), + } + match alphanumeric1::<_, Error<_>>(c) { + Ok((i, _)) => { + assert_eq!(c.offset_to(i) + i.len(), c.len()); + } + _ => panic!("wrong return type in offset test for alphanumeric"), + } + match space1::<_, Error<_>>(d) { + Ok((i, _)) => { + assert_eq!(d.offset_to(i) + i.len(), d.len()); + } + _ => panic!("wrong return type in offset test for space"), + } + match multispace1::<_, Error<_>>(e) { + Ok((i, _)) => { + assert_eq!(e.offset_to(i) + i.len(), e.len()); + } + _ => panic!("wrong return type in offset test for multispace"), + } + match hex_digit1::<_, Error<_>>(f) { + Ok((i, _)) => { + assert_eq!(f.offset_to(i) + i.len(), f.len()); + } + _ => panic!("wrong return type in offset test for hex_digit"), + } + match oct_digit1::<_, Error<_>>(f) { + Ok((i, _)) => { + assert_eq!(f.offset_to(i) + i.len(), f.len()); + } + _ => panic!("wrong return type in offset test for oct_digit"), + } } - match hex_digit1::<_, Error<_>>(f) { - Ok((i, _)) => { - assert_eq!(f.offset_to(i) + i.len(), f.len()); - } - _ => panic!("wrong return type in offset test for hex_digit"), + + #[test] + fn is_not_line_ending_bytes() { + let a: &[u8] = b"ab12cd\nefgh"; + assert_eq!( + not_line_ending::<_, Error<_>>(a), + Ok((&b"\nefgh"[..], &b"ab12cd"[..])) + ); + + let b: &[u8] = b"ab12cd\nefgh\nijkl"; + assert_eq!( + not_line_ending::<_, Error<_>>(b), + Ok((&b"\nefgh\nijkl"[..], &b"ab12cd"[..])) + ); + + let c: &[u8] = b"ab12cd\r\nefgh\nijkl"; + assert_eq!( + not_line_ending::<_, Error<_>>(c), + Ok((&b"\r\nefgh\nijkl"[..], &b"ab12cd"[..])) + ); + + let d: &[u8] = b"ab12cd"; + assert_eq!( + not_line_ending::<_, Error<_>>(d), + Err(ErrMode::Incomplete(Needed::Unknown)) + ); } - match oct_digit1::<_, Error<_>>(f) { - Ok((i, _)) => { - assert_eq!(f.offset_to(i) + i.len(), f.len()); - } - _ => panic!("wrong return type in offset test for oct_digit"), + + #[test] + fn is_not_line_ending_str() { + /* + let a: &str = "ab12cd\nefgh"; + assert_eq!(not_line_ending(a), Ok((&"\nefgh"[..], &"ab12cd"[..]))); + + let b: &str = "ab12cd\nefgh\nijkl"; + assert_eq!(not_line_ending(b), Ok((&"\nefgh\nijkl"[..], &"ab12cd"[..]))); + + let c: &str = "ab12cd\r\nefgh\nijkl"; + assert_eq!(not_line_ending(c), Ok((&"\r\nefgh\nijkl"[..], &"ab12cd"[..]))); + + let d = "βèƒôřè\nÂßÇáƒƭèř"; + assert_eq!(not_line_ending(d), Ok((&"\nÂßÇáƒƭèř"[..], &"βèƒôřè"[..]))); + + let e = "βèƒôřè\r\nÂßÇáƒƭèř"; + assert_eq!(not_line_ending(e), Ok((&"\r\nÂßÇáƒƭèř"[..], &"βèƒôřè"[..]))); + */ + + let f = "βèƒôřè\rÂßÇáƒƭèř"; + assert_eq!( + not_line_ending(f), + Err(ErrMode::Backtrack(Error::new(f, ErrorKind::Tag))) + ); + + let g2: &str = "ab12cd"; + assert_eq!( + not_line_ending::<_, Error<_>>(g2), + Err(ErrMode::Incomplete(Needed::Unknown)) + ); } - } - - #[test] - fn is_not_line_ending_bytes() { - let a: &[u8] = b"ab12cd\nefgh"; - assert_eq!( - not_line_ending::<_, Error<_>>(a), - Ok((&b"\nefgh"[..], &b"ab12cd"[..])) - ); - - let b: &[u8] = b"ab12cd\nefgh\nijkl"; - assert_eq!( - not_line_ending::<_, Error<_>>(b), - Ok((&b"\nefgh\nijkl"[..], &b"ab12cd"[..])) - ); - - let c: &[u8] = b"ab12cd\r\nefgh\nijkl"; - assert_eq!( - not_line_ending::<_, Error<_>>(c), - Ok((&b"\r\nefgh\nijkl"[..], &b"ab12cd"[..])) - ); - - let d: &[u8] = b"ab12cd"; - assert_eq!( - not_line_ending::<_, Error<_>>(d), - Err(ErrMode::Incomplete(Needed::Unknown)) - ); - } - - #[test] - fn is_not_line_ending_str() { - /* - let a: &str = "ab12cd\nefgh"; - assert_eq!(not_line_ending(a), Ok((&"\nefgh"[..], &"ab12cd"[..]))); - - let b: &str = "ab12cd\nefgh\nijkl"; - assert_eq!(not_line_ending(b), Ok((&"\nefgh\nijkl"[..], &"ab12cd"[..]))); - - let c: &str = "ab12cd\r\nefgh\nijkl"; - assert_eq!(not_line_ending(c), Ok((&"\r\nefgh\nijkl"[..], &"ab12cd"[..]))); - - let d = "βèƒôřè\nÂßÇáƒƭèř"; - assert_eq!(not_line_ending(d), Ok((&"\nÂßÇáƒƭèř"[..], &"βèƒôřè"[..]))); - - let e = "βèƒôřè\r\nÂßÇáƒƭèř"; - assert_eq!(not_line_ending(e), Ok((&"\r\nÂßÇáƒƭèř"[..], &"βèƒôřè"[..]))); - */ - - let f = "βèƒôřè\rÂßÇáƒƭèř"; - assert_eq!( - not_line_ending(f), - Err(ErrMode::Backtrack(Error::new(f, ErrorKind::Tag))) - ); - - let g2: &str = "ab12cd"; - assert_eq!( - not_line_ending::<_, Error<_>>(g2), - Err(ErrMode::Incomplete(Needed::Unknown)) - ); - } - - #[test] - fn hex_digit_test() { - let i = &b"0123456789abcdefABCDEF;"[..]; - assert_parse!(hex_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); - - let i = &b"g"[..]; - assert_parse!( - hex_digit1(i), - Err(ErrMode::Backtrack(error_position!(i, ErrorKind::HexDigit))) - ); - - let i = &b"G"[..]; - assert_parse!( - hex_digit1(i), - Err(ErrMode::Backtrack(error_position!(i, ErrorKind::HexDigit))) - ); - - assert!(AsChar::is_hex_digit(b'0')); - assert!(AsChar::is_hex_digit(b'9')); - assert!(AsChar::is_hex_digit(b'a')); - assert!(AsChar::is_hex_digit(b'f')); - assert!(AsChar::is_hex_digit(b'A')); - assert!(AsChar::is_hex_digit(b'F')); - assert!(!AsChar::is_hex_digit(b'g')); - assert!(!AsChar::is_hex_digit(b'G')); - assert!(!AsChar::is_hex_digit(b'/')); - assert!(!AsChar::is_hex_digit(b':')); - assert!(!AsChar::is_hex_digit(b'@')); - assert!(!AsChar::is_hex_digit(b'\x60')); - } - - #[test] - fn oct_digit_test() { - let i = &b"01234567;"[..]; - assert_parse!(oct_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); - - let i = &b"8"[..]; - assert_parse!( - oct_digit1(i), - Err(ErrMode::Backtrack(error_position!(i, ErrorKind::OctDigit))) - ); - - assert!(AsChar::is_oct_digit(b'0')); - assert!(AsChar::is_oct_digit(b'7')); - assert!(!AsChar::is_oct_digit(b'8')); - assert!(!AsChar::is_oct_digit(b'9')); - assert!(!AsChar::is_oct_digit(b'a')); - assert!(!AsChar::is_oct_digit(b'A')); - assert!(!AsChar::is_oct_digit(b'/')); - assert!(!AsChar::is_oct_digit(b':')); - assert!(!AsChar::is_oct_digit(b'@')); - assert!(!AsChar::is_oct_digit(b'\x60')); - } - - #[test] - fn full_line_windows() { - fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { - pair(not_line_ending, line_ending)(i) + + #[test] + fn hex_digit_test() { + let i = &b"0123456789abcdefABCDEF;"[..]; + assert_parse!(hex_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); + + let i = &b"g"[..]; + assert_parse!( + hex_digit1(i), + Err(ErrMode::Backtrack(error_position!(i, ErrorKind::HexDigit))) + ); + + let i = &b"G"[..]; + assert_parse!( + hex_digit1(i), + Err(ErrMode::Backtrack(error_position!(i, ErrorKind::HexDigit))) + ); + + assert!(AsChar::is_hex_digit(b'0')); + assert!(AsChar::is_hex_digit(b'9')); + assert!(AsChar::is_hex_digit(b'a')); + assert!(AsChar::is_hex_digit(b'f')); + assert!(AsChar::is_hex_digit(b'A')); + assert!(AsChar::is_hex_digit(b'F')); + assert!(!AsChar::is_hex_digit(b'g')); + assert!(!AsChar::is_hex_digit(b'G')); + assert!(!AsChar::is_hex_digit(b'/')); + assert!(!AsChar::is_hex_digit(b':')); + assert!(!AsChar::is_hex_digit(b'@')); + assert!(!AsChar::is_hex_digit(b'\x60')); } - let input = b"abc\r\n"; - let output = take_full_line(input); - assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\r\n"[..])))); - } - - #[test] - fn full_line_unix() { - fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { - pair(not_line_ending, line_ending)(i) + + #[test] + fn oct_digit_test() { + let i = &b"01234567;"[..]; + assert_parse!(oct_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); + + let i = &b"8"[..]; + assert_parse!( + oct_digit1(i), + Err(ErrMode::Backtrack(error_position!(i, ErrorKind::OctDigit))) + ); + + assert!(AsChar::is_oct_digit(b'0')); + assert!(AsChar::is_oct_digit(b'7')); + assert!(!AsChar::is_oct_digit(b'8')); + assert!(!AsChar::is_oct_digit(b'9')); + assert!(!AsChar::is_oct_digit(b'a')); + assert!(!AsChar::is_oct_digit(b'A')); + assert!(!AsChar::is_oct_digit(b'/')); + assert!(!AsChar::is_oct_digit(b':')); + assert!(!AsChar::is_oct_digit(b'@')); + assert!(!AsChar::is_oct_digit(b'\x60')); } - let input = b"abc\n"; - let output = take_full_line(input); - assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\n"[..])))); - } - - #[test] - fn check_windows_lineending() { - let input = b"\r\n"; - let output = line_ending(&input[..]); - assert_parse!(output, Ok((&b""[..], &b"\r\n"[..]))); - } - - #[test] - fn check_unix_lineending() { - let input = b"\n"; - let output = line_ending(&input[..]); - assert_parse!(output, Ok((&b""[..], &b"\n"[..]))); - } - - #[test] - fn cr_lf() { - assert_parse!(crlf(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..]))); - assert_parse!(crlf(&b"\r"[..]), Err(ErrMode::Incomplete(Needed::new(2)))); - assert_parse!( - crlf(&b"\ra"[..]), - Err(ErrMode::Backtrack(error_position!( - &b"\ra"[..], - ErrorKind::CrLf - ))) - ); - - assert_parse!(crlf("\r\na"), Ok(("a", "\r\n"))); - assert_parse!(crlf("\r"), Err(ErrMode::Incomplete(Needed::new(2)))); - assert_parse!( - crlf("\ra"), - Err(ErrMode::Backtrack(error_position!("\ra", ErrorKind::CrLf))) - ); - } - - #[test] - fn end_of_line() { - assert_parse!(line_ending(&b"\na"[..]), Ok((&b"a"[..], &b"\n"[..]))); - assert_parse!(line_ending(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..]))); - assert_parse!( - line_ending(&b"\r"[..]), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_parse!( - line_ending(&b"\ra"[..]), - Err(ErrMode::Backtrack(error_position!( - &b"\ra"[..], - ErrorKind::CrLf - ))) - ); - - assert_parse!(line_ending("\na"), Ok(("a", "\n"))); - assert_parse!(line_ending("\r\na"), Ok(("a", "\r\n"))); - assert_parse!(line_ending("\r"), Err(ErrMode::Incomplete(Needed::new(2)))); - assert_parse!( - line_ending("\ra"), - Err(ErrMode::Backtrack(error_position!("\ra", ErrorKind::CrLf))) - ); - } - - fn digit_to_i16(input: &str) -> IResult<&str, i16> { - let i = input; - let (i, opt_sign) = opt(alt((char('+'), char('-'))))(i)?; - let sign = match opt_sign { - Some('+') | None => true, - Some('-') => false, - _ => unreachable!(), - }; - let (i, s) = match digit1::<_, crate::error::Error<_>>(i) { - Ok((i, s)) => (i, s), - Err(ErrMode::Incomplete(i)) => return Err(ErrMode::Incomplete(i)), - Err(_) => return Err(ErrMode::from_error_kind(input, ErrorKind::Digit)), - }; - match s.parse_slice() { - Some(n) => { - if sign { - Ok((i, n)) - } else { - Ok((i, -n)) + #[test] + fn full_line_windows() { + fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { + pair(not_line_ending, line_ending)(i) } - } - None => Err(ErrMode::from_error_kind(i, ErrorKind::Digit)), + let input = b"abc\r\n"; + let output = take_full_line(input); + assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\r\n"[..])))); } - } - fn digit_to_u32(i: &str) -> IResult<&str, u32> { - let (i, s) = digit1(i)?; - match s.parse_slice() { - Some(n) => Ok((i, n)), - None => Err(ErrMode::from_error_kind(i, ErrorKind::Digit)), + #[test] + fn full_line_unix() { + fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { + pair(not_line_ending, line_ending)(i) + } + let input = b"abc\n"; + let output = take_full_line(input); + assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\n"[..])))); } - } - #[test] - fn one_of_test() { - fn f(i: &[u8]) -> IResult<&[u8], char> { - one_of("ab")(i) + #[test] + fn check_windows_lineending() { + let input = b"\r\n"; + let output = line_ending(&input[..]); + assert_parse!(output, Ok((&b""[..], &b"\r\n"[..]))); } - let a = &b"abcd"[..]; - assert_eq!(f(a), Ok((&b"bcd"[..], 'a'))); + #[test] + fn check_unix_lineending() { + let input = b"\n"; + let output = line_ending(&input[..]); + assert_parse!(output, Ok((&b""[..], &b"\n"[..]))); + } - let b = &b"cde"[..]; - assert_eq!( - f(b), - Err(ErrMode::Backtrack(error_position!(b, ErrorKind::OneOf))) - ); + #[test] + fn cr_lf() { + assert_parse!(crlf(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..]))); + assert_parse!(crlf(&b"\r"[..]), Err(ErrMode::Incomplete(Needed::new(2)))); + assert_parse!( + crlf(&b"\ra"[..]), + Err(ErrMode::Backtrack(error_position!( + &b"\ra"[..], + ErrorKind::CrLf + ))) + ); + + assert_parse!(crlf("\r\na"), Ok(("a", "\r\n"))); + assert_parse!(crlf("\r"), Err(ErrMode::Incomplete(Needed::new(2)))); + assert_parse!( + crlf("\ra"), + Err(ErrMode::Backtrack(error_position!("\ra", ErrorKind::CrLf))) + ); + } - fn utf8(i: &str) -> IResult<&str, char> { - one_of("+\u{FF0B}")(i) + #[test] + fn end_of_line() { + assert_parse!(line_ending(&b"\na"[..]), Ok((&b"a"[..], &b"\n"[..]))); + assert_parse!(line_ending(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..]))); + assert_parse!( + line_ending(&b"\r"[..]), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_parse!( + line_ending(&b"\ra"[..]), + Err(ErrMode::Backtrack(error_position!( + &b"\ra"[..], + ErrorKind::CrLf + ))) + ); + + assert_parse!(line_ending("\na"), Ok(("a", "\n"))); + assert_parse!(line_ending("\r\na"), Ok(("a", "\r\n"))); + assert_parse!(line_ending("\r"), Err(ErrMode::Incomplete(Needed::new(2)))); + assert_parse!( + line_ending("\ra"), + Err(ErrMode::Backtrack(error_position!("\ra", ErrorKind::CrLf))) + ); } - assert!(utf8("+").is_ok()); - assert!(utf8("\u{FF0B}").is_ok()); - } + fn digit_to_i16(input: &str) -> IResult<&str, i16> { + let i = input; + let (i, opt_sign) = opt(alt((char('+'), char('-'))))(i)?; + let sign = match opt_sign { + Some('+') | None => true, + Some('-') => false, + _ => unreachable!(), + }; + + let (i, s) = match digit1::<_, crate::error::Error<_>>(i) { + Ok((i, s)) => (i, s), + Err(ErrMode::Incomplete(i)) => return Err(ErrMode::Incomplete(i)), + Err(_) => return Err(ErrMode::from_error_kind(input, ErrorKind::Digit)), + }; + match s.parse_slice() { + Some(n) => { + if sign { + Ok((i, n)) + } else { + Ok((i, -n)) + } + } + None => Err(ErrMode::from_error_kind(i, ErrorKind::Digit)), + } + } - #[test] - fn none_of_test() { - fn f(i: &[u8]) -> IResult<&[u8], char> { - none_of("ab")(i) + fn digit_to_u32(i: &str) -> IResult<&str, u32> { + let (i, s) = digit1(i)?; + match s.parse_slice() { + Some(n) => Ok((i, n)), + None => Err(ErrMode::from_error_kind(i, ErrorKind::Digit)), + } } - let a = &b"abcd"[..]; - assert_eq!( - f(a), - Err(ErrMode::Backtrack(error_position!(a, ErrorKind::NoneOf))) - ); + #[test] + fn one_of_test() { + fn f(i: &[u8]) -> IResult<&[u8], char> { + one_of("ab")(i) + } + + let a = &b"abcd"[..]; + assert_eq!(f(a), Ok((&b"bcd"[..], 'a'))); - let b = &b"cde"[..]; - assert_eq!(f(b), Ok((&b"de"[..], 'c'))); - } + let b = &b"cde"[..]; + assert_eq!( + f(b), + Err(ErrMode::Backtrack(error_position!(b, ErrorKind::OneOf))) + ); - #[test] - fn char_byteslice() { - fn f(i: &[u8]) -> IResult<&[u8], char> { - char('c')(i) + fn utf8(i: &str) -> IResult<&str, char> { + one_of("+\u{FF0B}")(i) + } + + assert!(utf8("+").is_ok()); + assert!(utf8("\u{FF0B}").is_ok()); } - let a = &b"abcd"[..]; - assert_eq!( - f(a), - Err(ErrMode::Backtrack(error_position!(a, ErrorKind::Char))) - ); + #[test] + fn none_of_test() { + fn f(i: &[u8]) -> IResult<&[u8], char> { + none_of("ab")(i) + } - let b = &b"cde"[..]; - assert_eq!(f(b), Ok((&b"de"[..], 'c'))); - } + let a = &b"abcd"[..]; + assert_eq!( + f(a), + Err(ErrMode::Backtrack(error_position!(a, ErrorKind::NoneOf))) + ); - #[test] - fn char_str() { - fn f(i: &str) -> IResult<&str, char> { - char('c')(i) + let b = &b"cde"[..]; + assert_eq!(f(b), Ok((&b"de"[..], 'c'))); } - let a = "abcd"; - assert_eq!( - f(a), - Err(ErrMode::Backtrack(error_position!(a, ErrorKind::Char))) - ); + #[test] + fn char_byteslice() { + fn f(i: &[u8]) -> IResult<&[u8], char> { + char('c')(i) + } + + let a = &b"abcd"[..]; + assert_eq!( + f(a), + Err(ErrMode::Backtrack(error_position!(a, ErrorKind::Char))) + ); - let b = "cde"; - assert_eq!(f(b), Ok(("de", 'c'))); - } + let b = &b"cde"[..]; + assert_eq!(f(b), Ok((&b"de"[..], 'c'))); + } - proptest! { #[test] - fn ints(s in "\\PC*") { - let res1 = digit_to_i16(&s); - let res2 = i16(s.as_str()); - assert_eq!(res1, res2); + fn char_str() { + fn f(i: &str) -> IResult<&str, char> { + char('c')(i) + } + + let a = "abcd"; + assert_eq!( + f(a), + Err(ErrMode::Backtrack(error_position!(a, ErrorKind::Char))) + ); + + let b = "cde"; + assert_eq!(f(b), Ok(("de", 'c'))); } - #[test] - fn uints(s in "\\PC*") { - let res1 = digit_to_u32(&s); - let res2 = u32(s.as_str()); - assert_eq!(res1, res2); + proptest! { + #[test] + fn ints(s in "\\PC*") { + let res1 = digit_to_i16(&s); + let res2 = i16(s.as_str()); + assert_eq!(res1, res2); + } + + #[test] + fn uints(s in "\\PC*") { + let res1 = digit_to_u32(&s); + let res2 = u32(s.as_str()); + assert_eq!(res1, res2); + } } - } } diff --git a/src/character/tests.rs b/src/character/tests.rs index 323aa89e..6f147c7c 100644 --- a/src/character/tests.rs +++ b/src/character/tests.rs @@ -1,1516 +1,1516 @@ use super::*; mod complete { - use super::*; - use crate::branch::alt; - use crate::bytes::none_of; - use crate::bytes::one_of; - use crate::combinator::opt; - use crate::error::ErrMode; - use crate::error::Error; - use crate::error::ErrorKind; - use crate::input::ParseSlice; - #[cfg(feature = "alloc")] - use crate::{lib::std::string::String, lib::std::vec::Vec}; - use proptest::prelude::*; - - macro_rules! assert_parse( + use super::*; + use crate::branch::alt; + use crate::bytes::none_of; + use crate::bytes::one_of; + use crate::combinator::opt; + use crate::error::ErrMode; + use crate::error::Error; + use crate::error::ErrorKind; + use crate::input::ParseSlice; + #[cfg(feature = "alloc")] + use crate::{lib::std::string::String, lib::std::vec::Vec}; + use proptest::prelude::*; + + macro_rules! assert_parse( ($left: expr, $right: expr) => { let res: $crate::IResult<_, _, Error<_>> = $left; assert_eq!(res, $right); }; ); - #[test] - fn character() { - let empty: &[u8] = b""; - let a: &[u8] = b"abcd"; - let b: &[u8] = b"1234"; - let c: &[u8] = b"a123"; - let d: &[u8] = "azé12".as_bytes(); - let e: &[u8] = b" "; - let f: &[u8] = b" ;"; - //assert_eq!(alpha1::<_, Error>(a), Err(ErrMode::Incomplete(Needed::Size(1)))); - assert_parse!(alpha1(a), Ok((empty, a))); - assert_eq!( - alpha1(b), - Err(ErrMode::Backtrack(Error::new(b, ErrorKind::Alpha))) - ); - assert_eq!(alpha1::<_, Error<_>, false>(c), Ok((&c[1..], &b"a"[..]))); - assert_eq!( - alpha1::<_, Error<_>, false>(d), - Ok(("é12".as_bytes(), &b"az"[..])) - ); - assert_eq!( - digit1(a), - Err(ErrMode::Backtrack(Error::new(a, ErrorKind::Digit))) - ); - assert_eq!(digit1::<_, Error<_>, false>(b), Ok((empty, b))); - assert_eq!( - digit1(c), - Err(ErrMode::Backtrack(Error::new(c, ErrorKind::Digit))) - ); - assert_eq!( - digit1(d), - Err(ErrMode::Backtrack(Error::new(d, ErrorKind::Digit))) - ); - assert_eq!(hex_digit1::<_, Error<_>, false>(a), Ok((empty, a))); - assert_eq!(hex_digit1::<_, Error<_>, false>(b), Ok((empty, b))); - assert_eq!(hex_digit1::<_, Error<_>, false>(c), Ok((empty, c))); - assert_eq!( - hex_digit1::<_, Error<_>, false>(d), - Ok(("zé12".as_bytes(), &b"a"[..])) - ); - assert_eq!( - hex_digit1(e), - Err(ErrMode::Backtrack(Error::new(e, ErrorKind::HexDigit))) - ); - assert_eq!( - oct_digit1(a), - Err(ErrMode::Backtrack(Error::new(a, ErrorKind::OctDigit))) - ); - assert_eq!(oct_digit1::<_, Error<_>, false>(b), Ok((empty, b))); - assert_eq!( - oct_digit1(c), - Err(ErrMode::Backtrack(Error::new(c, ErrorKind::OctDigit))) - ); - assert_eq!( - oct_digit1(d), - Err(ErrMode::Backtrack(Error::new(d, ErrorKind::OctDigit))) - ); - assert_eq!(alphanumeric1::<_, Error<_>, false>(a), Ok((empty, a))); - //assert_eq!(fix_error!(b,(), alphanumeric), Ok((empty, b))); - assert_eq!(alphanumeric1::<_, Error<_>, false>(c), Ok((empty, c))); - assert_eq!( - alphanumeric1::<_, Error<_>, false>(d), - Ok(("é12".as_bytes(), &b"az"[..])) - ); - assert_eq!(space1::<_, Error<_>, false>(e), Ok((empty, e))); - assert_eq!(space1::<_, Error<_>, false>(f), Ok((&b";"[..], &b" "[..]))); - } - - #[cfg(feature = "alloc")] - #[test] - fn character_s() { - let empty = ""; - let a = "abcd"; - let b = "1234"; - let c = "a123"; - let d = "azé12"; - let e = " "; - assert_eq!(alpha1::<_, Error<_>, false>(a), Ok((empty, a))); - assert_eq!( - alpha1(b), - Err(ErrMode::Backtrack(Error::new(b, ErrorKind::Alpha))) - ); - assert_eq!(alpha1::<_, Error<_>, false>(c), Ok((&c[1..], "a"))); - assert_eq!(alpha1::<_, Error<_>, false>(d), Ok(("é12", "az"))); - assert_eq!( - digit1(a), - Err(ErrMode::Backtrack(Error::new(a, ErrorKind::Digit))) - ); - assert_eq!(digit1::<_, Error<_>, false>(b), Ok((empty, b))); - assert_eq!( - digit1(c), - Err(ErrMode::Backtrack(Error::new(c, ErrorKind::Digit))) - ); - assert_eq!( - digit1(d), - Err(ErrMode::Backtrack(Error::new(d, ErrorKind::Digit))) - ); - assert_eq!(hex_digit1::<_, Error<_>, false>(a), Ok((empty, a))); - assert_eq!(hex_digit1::<_, Error<_>, false>(b), Ok((empty, b))); - assert_eq!(hex_digit1::<_, Error<_>, false>(c), Ok((empty, c))); - assert_eq!(hex_digit1::<_, Error<_>, false>(d), Ok(("zé12", "a"))); - assert_eq!( - hex_digit1(e), - Err(ErrMode::Backtrack(Error::new(e, ErrorKind::HexDigit))) - ); - assert_eq!( - oct_digit1(a), - Err(ErrMode::Backtrack(Error::new(a, ErrorKind::OctDigit))) - ); - assert_eq!(oct_digit1::<_, Error<_>, false>(b), Ok((empty, b))); - assert_eq!( - oct_digit1(c), - Err(ErrMode::Backtrack(Error::new(c, ErrorKind::OctDigit))) - ); - assert_eq!( - oct_digit1(d), - Err(ErrMode::Backtrack(Error::new(d, ErrorKind::OctDigit))) - ); - assert_eq!(alphanumeric1::<_, Error<_>, false>(a), Ok((empty, a))); - //assert_eq!(fix_error!(b,(), alphanumeric), Ok((empty, b))); - assert_eq!(alphanumeric1::<_, Error<_>, false>(c), Ok((empty, c))); - assert_eq!(alphanumeric1::<_, Error<_>, false>(d), Ok(("é12", "az"))); - assert_eq!(space1::<_, Error<_>, false>(e), Ok((empty, e))); - } - - use crate::input::Offset; - #[test] - fn offset() { - let a = &b"abcd;"[..]; - let b = &b"1234;"[..]; - let c = &b"a123;"[..]; - let d = &b" \t;"[..]; - let e = &b" \t\r\n;"[..]; - let f = &b"123abcDEF;"[..]; - - match alpha1::<_, Error<_>, false>(a) { - Ok((i, _)) => { - assert_eq!(a.offset_to(i) + i.len(), a.len()); - } - _ => panic!("wrong return type in offset test for alpha"), - } - match digit1::<_, Error<_>, false>(b) { - Ok((i, _)) => { - assert_eq!(b.offset_to(i) + i.len(), b.len()); - } - _ => panic!("wrong return type in offset test for digit"), - } - match alphanumeric1::<_, Error<_>, false>(c) { - Ok((i, _)) => { - assert_eq!(c.offset_to(i) + i.len(), c.len()); - } - _ => panic!("wrong return type in offset test for alphanumeric"), - } - match space1::<_, Error<_>, false>(d) { - Ok((i, _)) => { - assert_eq!(d.offset_to(i) + i.len(), d.len()); - } - _ => panic!("wrong return type in offset test for space"), + #[test] + fn character() { + let empty: &[u8] = b""; + let a: &[u8] = b"abcd"; + let b: &[u8] = b"1234"; + let c: &[u8] = b"a123"; + let d: &[u8] = "azé12".as_bytes(); + let e: &[u8] = b" "; + let f: &[u8] = b" ;"; + //assert_eq!(alpha1::<_, Error>(a), Err(ErrMode::Incomplete(Needed::Size(1)))); + assert_parse!(alpha1(a), Ok((empty, a))); + assert_eq!( + alpha1(b), + Err(ErrMode::Backtrack(Error::new(b, ErrorKind::Alpha))) + ); + assert_eq!(alpha1::<_, Error<_>, false>(c), Ok((&c[1..], &b"a"[..]))); + assert_eq!( + alpha1::<_, Error<_>, false>(d), + Ok(("é12".as_bytes(), &b"az"[..])) + ); + assert_eq!( + digit1(a), + Err(ErrMode::Backtrack(Error::new(a, ErrorKind::Digit))) + ); + assert_eq!(digit1::<_, Error<_>, false>(b), Ok((empty, b))); + assert_eq!( + digit1(c), + Err(ErrMode::Backtrack(Error::new(c, ErrorKind::Digit))) + ); + assert_eq!( + digit1(d), + Err(ErrMode::Backtrack(Error::new(d, ErrorKind::Digit))) + ); + assert_eq!(hex_digit1::<_, Error<_>, false>(a), Ok((empty, a))); + assert_eq!(hex_digit1::<_, Error<_>, false>(b), Ok((empty, b))); + assert_eq!(hex_digit1::<_, Error<_>, false>(c), Ok((empty, c))); + assert_eq!( + hex_digit1::<_, Error<_>, false>(d), + Ok(("zé12".as_bytes(), &b"a"[..])) + ); + assert_eq!( + hex_digit1(e), + Err(ErrMode::Backtrack(Error::new(e, ErrorKind::HexDigit))) + ); + assert_eq!( + oct_digit1(a), + Err(ErrMode::Backtrack(Error::new(a, ErrorKind::OctDigit))) + ); + assert_eq!(oct_digit1::<_, Error<_>, false>(b), Ok((empty, b))); + assert_eq!( + oct_digit1(c), + Err(ErrMode::Backtrack(Error::new(c, ErrorKind::OctDigit))) + ); + assert_eq!( + oct_digit1(d), + Err(ErrMode::Backtrack(Error::new(d, ErrorKind::OctDigit))) + ); + assert_eq!(alphanumeric1::<_, Error<_>, false>(a), Ok((empty, a))); + //assert_eq!(fix_error!(b,(), alphanumeric), Ok((empty, b))); + assert_eq!(alphanumeric1::<_, Error<_>, false>(c), Ok((empty, c))); + assert_eq!( + alphanumeric1::<_, Error<_>, false>(d), + Ok(("é12".as_bytes(), &b"az"[..])) + ); + assert_eq!(space1::<_, Error<_>, false>(e), Ok((empty, e))); + assert_eq!(space1::<_, Error<_>, false>(f), Ok((&b";"[..], &b" "[..]))); } - match multispace1::<_, Error<_>, false>(e) { - Ok((i, _)) => { - assert_eq!(e.offset_to(i) + i.len(), e.len()); - } - _ => panic!("wrong return type in offset test for multispace"), + + #[cfg(feature = "alloc")] + #[test] + fn character_s() { + let empty = ""; + let a = "abcd"; + let b = "1234"; + let c = "a123"; + let d = "azé12"; + let e = " "; + assert_eq!(alpha1::<_, Error<_>, false>(a), Ok((empty, a))); + assert_eq!( + alpha1(b), + Err(ErrMode::Backtrack(Error::new(b, ErrorKind::Alpha))) + ); + assert_eq!(alpha1::<_, Error<_>, false>(c), Ok((&c[1..], "a"))); + assert_eq!(alpha1::<_, Error<_>, false>(d), Ok(("é12", "az"))); + assert_eq!( + digit1(a), + Err(ErrMode::Backtrack(Error::new(a, ErrorKind::Digit))) + ); + assert_eq!(digit1::<_, Error<_>, false>(b), Ok((empty, b))); + assert_eq!( + digit1(c), + Err(ErrMode::Backtrack(Error::new(c, ErrorKind::Digit))) + ); + assert_eq!( + digit1(d), + Err(ErrMode::Backtrack(Error::new(d, ErrorKind::Digit))) + ); + assert_eq!(hex_digit1::<_, Error<_>, false>(a), Ok((empty, a))); + assert_eq!(hex_digit1::<_, Error<_>, false>(b), Ok((empty, b))); + assert_eq!(hex_digit1::<_, Error<_>, false>(c), Ok((empty, c))); + assert_eq!(hex_digit1::<_, Error<_>, false>(d), Ok(("zé12", "a"))); + assert_eq!( + hex_digit1(e), + Err(ErrMode::Backtrack(Error::new(e, ErrorKind::HexDigit))) + ); + assert_eq!( + oct_digit1(a), + Err(ErrMode::Backtrack(Error::new(a, ErrorKind::OctDigit))) + ); + assert_eq!(oct_digit1::<_, Error<_>, false>(b), Ok((empty, b))); + assert_eq!( + oct_digit1(c), + Err(ErrMode::Backtrack(Error::new(c, ErrorKind::OctDigit))) + ); + assert_eq!( + oct_digit1(d), + Err(ErrMode::Backtrack(Error::new(d, ErrorKind::OctDigit))) + ); + assert_eq!(alphanumeric1::<_, Error<_>, false>(a), Ok((empty, a))); + //assert_eq!(fix_error!(b,(), alphanumeric), Ok((empty, b))); + assert_eq!(alphanumeric1::<_, Error<_>, false>(c), Ok((empty, c))); + assert_eq!(alphanumeric1::<_, Error<_>, false>(d), Ok(("é12", "az"))); + assert_eq!(space1::<_, Error<_>, false>(e), Ok((empty, e))); } - match hex_digit1::<_, Error<_>, false>(f) { - Ok((i, _)) => { - assert_eq!(f.offset_to(i) + i.len(), f.len()); - } - _ => panic!("wrong return type in offset test for hex_digit"), + + use crate::input::Offset; + #[test] + fn offset() { + let a = &b"abcd;"[..]; + let b = &b"1234;"[..]; + let c = &b"a123;"[..]; + let d = &b" \t;"[..]; + let e = &b" \t\r\n;"[..]; + let f = &b"123abcDEF;"[..]; + + match alpha1::<_, Error<_>, false>(a) { + Ok((i, _)) => { + assert_eq!(a.offset_to(i) + i.len(), a.len()); + } + _ => panic!("wrong return type in offset test for alpha"), + } + match digit1::<_, Error<_>, false>(b) { + Ok((i, _)) => { + assert_eq!(b.offset_to(i) + i.len(), b.len()); + } + _ => panic!("wrong return type in offset test for digit"), + } + match alphanumeric1::<_, Error<_>, false>(c) { + Ok((i, _)) => { + assert_eq!(c.offset_to(i) + i.len(), c.len()); + } + _ => panic!("wrong return type in offset test for alphanumeric"), + } + match space1::<_, Error<_>, false>(d) { + Ok((i, _)) => { + assert_eq!(d.offset_to(i) + i.len(), d.len()); + } + _ => panic!("wrong return type in offset test for space"), + } + match multispace1::<_, Error<_>, false>(e) { + Ok((i, _)) => { + assert_eq!(e.offset_to(i) + i.len(), e.len()); + } + _ => panic!("wrong return type in offset test for multispace"), + } + match hex_digit1::<_, Error<_>, false>(f) { + Ok((i, _)) => { + assert_eq!(f.offset_to(i) + i.len(), f.len()); + } + _ => panic!("wrong return type in offset test for hex_digit"), + } + match oct_digit1::<_, Error<_>, false>(f) { + Ok((i, _)) => { + assert_eq!(f.offset_to(i) + i.len(), f.len()); + } + _ => panic!("wrong return type in offset test for oct_digit"), + } } - match oct_digit1::<_, Error<_>, false>(f) { - Ok((i, _)) => { - assert_eq!(f.offset_to(i) + i.len(), f.len()); - } - _ => panic!("wrong return type in offset test for oct_digit"), + + #[test] + fn is_not_line_ending_bytes() { + let a: &[u8] = b"ab12cd\nefgh"; + assert_eq!( + not_line_ending::<_, Error<_>, false>(a), + Ok((&b"\nefgh"[..], &b"ab12cd"[..])) + ); + + let b: &[u8] = b"ab12cd\nefgh\nijkl"; + assert_eq!( + not_line_ending::<_, Error<_>, false>(b), + Ok((&b"\nefgh\nijkl"[..], &b"ab12cd"[..])) + ); + + let c: &[u8] = b"ab12cd\r\nefgh\nijkl"; + assert_eq!( + not_line_ending::<_, Error<_>, false>(c), + Ok((&b"\r\nefgh\nijkl"[..], &b"ab12cd"[..])) + ); + + let d: &[u8] = b"ab12cd"; + assert_eq!(not_line_ending::<_, Error<_>, false>(d), Ok((&[][..], d))); } - } - - #[test] - fn is_not_line_ending_bytes() { - let a: &[u8] = b"ab12cd\nefgh"; - assert_eq!( - not_line_ending::<_, Error<_>, false>(a), - Ok((&b"\nefgh"[..], &b"ab12cd"[..])) - ); - - let b: &[u8] = b"ab12cd\nefgh\nijkl"; - assert_eq!( - not_line_ending::<_, Error<_>, false>(b), - Ok((&b"\nefgh\nijkl"[..], &b"ab12cd"[..])) - ); - - let c: &[u8] = b"ab12cd\r\nefgh\nijkl"; - assert_eq!( - not_line_ending::<_, Error<_>, false>(c), - Ok((&b"\r\nefgh\nijkl"[..], &b"ab12cd"[..])) - ); - - let d: &[u8] = b"ab12cd"; - assert_eq!(not_line_ending::<_, Error<_>, false>(d), Ok((&[][..], d))); - } - - #[test] - fn is_not_line_ending_str() { - let f = "βèƒôřè\rÂßÇáƒƭèř"; - assert_eq!( - not_line_ending(f), - Err(ErrMode::Backtrack(Error::new(f, ErrorKind::Tag))) - ); - - let g2: &str = "ab12cd"; - assert_eq!(not_line_ending::<_, Error<_>, false>(g2), Ok(("", g2))); - } - - #[test] - fn hex_digit_test() { - let i = &b"0123456789abcdefABCDEF;"[..]; - assert_parse!(hex_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); - - let i = &b"g"[..]; - assert_parse!( - hex_digit1(i), - Err(ErrMode::Backtrack(error_position!(i, ErrorKind::HexDigit))) - ); - - let i = &b"G"[..]; - assert_parse!( - hex_digit1(i), - Err(ErrMode::Backtrack(error_position!(i, ErrorKind::HexDigit))) - ); - - assert!(AsChar::is_hex_digit(b'0')); - assert!(AsChar::is_hex_digit(b'9')); - assert!(AsChar::is_hex_digit(b'a')); - assert!(AsChar::is_hex_digit(b'f')); - assert!(AsChar::is_hex_digit(b'A')); - assert!(AsChar::is_hex_digit(b'F')); - assert!(!AsChar::is_hex_digit(b'g')); - assert!(!AsChar::is_hex_digit(b'G')); - assert!(!AsChar::is_hex_digit(b'/')); - assert!(!AsChar::is_hex_digit(b':')); - assert!(!AsChar::is_hex_digit(b'@')); - assert!(!AsChar::is_hex_digit(b'\x60')); - } - - #[test] - fn oct_digit_test() { - let i = &b"01234567;"[..]; - assert_parse!(oct_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); - - let i = &b"8"[..]; - assert_parse!( - oct_digit1(i), - Err(ErrMode::Backtrack(error_position!(i, ErrorKind::OctDigit))) - ); - - assert!(AsChar::is_oct_digit(b'0')); - assert!(AsChar::is_oct_digit(b'7')); - assert!(!AsChar::is_oct_digit(b'8')); - assert!(!AsChar::is_oct_digit(b'9')); - assert!(!AsChar::is_oct_digit(b'a')); - assert!(!AsChar::is_oct_digit(b'A')); - assert!(!AsChar::is_oct_digit(b'/')); - assert!(!AsChar::is_oct_digit(b':')); - assert!(!AsChar::is_oct_digit(b'@')); - assert!(!AsChar::is_oct_digit(b'\x60')); - } - - #[test] - fn full_line_windows() { - use crate::sequence::pair; - fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { - pair(not_line_ending, line_ending)(i) + + #[test] + fn is_not_line_ending_str() { + let f = "βèƒôřè\rÂßÇáƒƭèř"; + assert_eq!( + not_line_ending(f), + Err(ErrMode::Backtrack(Error::new(f, ErrorKind::Tag))) + ); + + let g2: &str = "ab12cd"; + assert_eq!(not_line_ending::<_, Error<_>, false>(g2), Ok(("", g2))); } - let input = b"abc\r\n"; - let output = take_full_line(input); - assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\r\n"[..])))); - } - #[test] - fn full_line_unix() { - use crate::sequence::pair; - fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { - pair(not_line_ending, line_ending)(i) + #[test] + fn hex_digit_test() { + let i = &b"0123456789abcdefABCDEF;"[..]; + assert_parse!(hex_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); + + let i = &b"g"[..]; + assert_parse!( + hex_digit1(i), + Err(ErrMode::Backtrack(error_position!(i, ErrorKind::HexDigit))) + ); + + let i = &b"G"[..]; + assert_parse!( + hex_digit1(i), + Err(ErrMode::Backtrack(error_position!(i, ErrorKind::HexDigit))) + ); + + assert!(AsChar::is_hex_digit(b'0')); + assert!(AsChar::is_hex_digit(b'9')); + assert!(AsChar::is_hex_digit(b'a')); + assert!(AsChar::is_hex_digit(b'f')); + assert!(AsChar::is_hex_digit(b'A')); + assert!(AsChar::is_hex_digit(b'F')); + assert!(!AsChar::is_hex_digit(b'g')); + assert!(!AsChar::is_hex_digit(b'G')); + assert!(!AsChar::is_hex_digit(b'/')); + assert!(!AsChar::is_hex_digit(b':')); + assert!(!AsChar::is_hex_digit(b'@')); + assert!(!AsChar::is_hex_digit(b'\x60')); } - let input = b"abc\n"; - let output = take_full_line(input); - assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\n"[..])))); - } - - #[test] - fn check_windows_lineending() { - let input = b"\r\n"; - let output = line_ending(&input[..]); - assert_parse!(output, Ok((&b""[..], &b"\r\n"[..]))); - } - - #[test] - fn check_unix_lineending() { - let input = b"\n"; - let output = line_ending(&input[..]); - assert_parse!(output, Ok((&b""[..], &b"\n"[..]))); - } - - #[test] - fn cr_lf() { - assert_parse!(crlf(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..]))); - assert_parse!( - crlf(&b"\r"[..]), - Err(ErrMode::Backtrack(error_position!( - &b"\r"[..], - ErrorKind::CrLf - ))) - ); - assert_parse!( - crlf(&b"\ra"[..]), - Err(ErrMode::Backtrack(error_position!( - &b"\ra"[..], - ErrorKind::CrLf - ))) - ); - - assert_parse!(crlf("\r\na"), Ok(("a", "\r\n"))); - assert_parse!( - crlf("\r"), - Err(ErrMode::Backtrack(error_position!("\r", ErrorKind::CrLf))) - ); - assert_parse!( - crlf("\ra"), - Err(ErrMode::Backtrack(error_position!("\ra", ErrorKind::CrLf))) - ); - } - - #[test] - fn end_of_line() { - assert_parse!(line_ending(&b"\na"[..]), Ok((&b"a"[..], &b"\n"[..]))); - assert_parse!(line_ending(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..]))); - assert_parse!( - line_ending(&b"\r"[..]), - Err(ErrMode::Backtrack(error_position!( - &b"\r"[..], - ErrorKind::CrLf - ))) - ); - assert_parse!( - line_ending(&b"\ra"[..]), - Err(ErrMode::Backtrack(error_position!( - &b"\ra"[..], - ErrorKind::CrLf - ))) - ); - - assert_parse!(line_ending("\na"), Ok(("a", "\n"))); - assert_parse!(line_ending("\r\na"), Ok(("a", "\r\n"))); - assert_parse!( - line_ending("\r"), - Err(ErrMode::Backtrack(error_position!("\r", ErrorKind::CrLf))) - ); - assert_parse!( - line_ending("\ra"), - Err(ErrMode::Backtrack(error_position!("\ra", ErrorKind::CrLf))) - ); - } - - fn digit_to_i16(input: &str) -> IResult<&str, i16> { - let i = input; - let (i, opt_sign) = opt(alt(('+', '-')))(i)?; - let sign = match opt_sign { - Some('+') | None => true, - Some('-') => false, - _ => unreachable!(), - }; - let (i, s) = match digit1::<_, crate::error::Error<_>, false>(i) { - Ok((i, s)) => (i, s), - Err(_) => return Err(ErrMode::from_error_kind(input, ErrorKind::Digit)), - }; + #[test] + fn oct_digit_test() { + let i = &b"01234567;"[..]; + assert_parse!(oct_digit1(i), Ok((&b";"[..], &i[..i.len() - 1]))); + + let i = &b"8"[..]; + assert_parse!( + oct_digit1(i), + Err(ErrMode::Backtrack(error_position!(i, ErrorKind::OctDigit))) + ); + + assert!(AsChar::is_oct_digit(b'0')); + assert!(AsChar::is_oct_digit(b'7')); + assert!(!AsChar::is_oct_digit(b'8')); + assert!(!AsChar::is_oct_digit(b'9')); + assert!(!AsChar::is_oct_digit(b'a')); + assert!(!AsChar::is_oct_digit(b'A')); + assert!(!AsChar::is_oct_digit(b'/')); + assert!(!AsChar::is_oct_digit(b':')); + assert!(!AsChar::is_oct_digit(b'@')); + assert!(!AsChar::is_oct_digit(b'\x60')); + } - match s.parse_slice() { - Some(n) => { - if sign { - Ok((i, n)) - } else { - Ok((i, -n)) + #[test] + fn full_line_windows() { + use crate::sequence::pair; + fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { + pair(not_line_ending, line_ending)(i) } - } - None => Err(ErrMode::from_error_kind(i, ErrorKind::Digit)), + let input = b"abc\r\n"; + let output = take_full_line(input); + assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\r\n"[..])))); } - } - fn digit_to_u32(i: &str) -> IResult<&str, u32> { - let (i, s) = digit1(i)?; - match s.parse_slice() { - Some(n) => Ok((i, n)), - None => Err(ErrMode::from_error_kind(i, ErrorKind::Digit)), + #[test] + fn full_line_unix() { + use crate::sequence::pair; + fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> { + pair(not_line_ending, line_ending)(i) + } + let input = b"abc\n"; + let output = take_full_line(input); + assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\n"[..])))); } - } - proptest! { #[test] - fn ints(s in "\\PC*") { - let res1 = digit_to_i16(&s); - let res2 = dec_int(s.as_str()); - assert_eq!(res1, res2); + fn check_windows_lineending() { + let input = b"\r\n"; + let output = line_ending(&input[..]); + assert_parse!(output, Ok((&b""[..], &b"\r\n"[..]))); } #[test] - fn uints(s in "\\PC*") { - let res1 = digit_to_u32(&s); - let res2 = dec_uint(s.as_str()); - assert_eq!(res1, res2); + fn check_unix_lineending() { + let input = b"\n"; + let output = line_ending(&input[..]); + assert_parse!(output, Ok((&b""[..], &b"\n"[..]))); } - } - #[test] - fn hex_uint_tests() { - fn hex_u32(input: &[u8]) -> IResult<&[u8], u32> { - hex_uint(input) + #[test] + fn cr_lf() { + assert_parse!(crlf(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..]))); + assert_parse!( + crlf(&b"\r"[..]), + Err(ErrMode::Backtrack(error_position!( + &b"\r"[..], + ErrorKind::CrLf + ))) + ); + assert_parse!( + crlf(&b"\ra"[..]), + Err(ErrMode::Backtrack(error_position!( + &b"\ra"[..], + ErrorKind::CrLf + ))) + ); + + assert_parse!(crlf("\r\na"), Ok(("a", "\r\n"))); + assert_parse!( + crlf("\r"), + Err(ErrMode::Backtrack(error_position!("\r", ErrorKind::CrLf))) + ); + assert_parse!( + crlf("\ra"), + Err(ErrMode::Backtrack(error_position!("\ra", ErrorKind::CrLf))) + ); } - assert_parse!( - hex_u32(&b";"[..]), - Err(ErrMode::Backtrack(error_position!( - &b";"[..], - ErrorKind::IsA - ))) - ); - assert_parse!(hex_u32(&b"ff;"[..]), Ok((&b";"[..], 255))); - assert_parse!(hex_u32(&b"1be2;"[..]), Ok((&b";"[..], 7138))); - assert_parse!(hex_u32(&b"c5a31be2;"[..]), Ok((&b";"[..], 3_315_801_058))); - assert_parse!(hex_u32(&b"C5A31be2;"[..]), Ok((&b";"[..], 3_315_801_058))); - assert_parse!( - hex_u32(&b"00c5a31be2;"[..]), // overflow - Err(ErrMode::Backtrack(error_position!( - &b"00c5a31be2;"[..], - ErrorKind::IsA - ))) - ); - assert_parse!( - hex_u32(&b"c5a31be201;"[..]), // overflow - Err(ErrMode::Backtrack(error_position!( - &b"c5a31be201;"[..], - ErrorKind::IsA - ))) - ); - assert_parse!(hex_u32(&b"ffffffff;"[..]), Ok((&b";"[..], 4_294_967_295))); - assert_parse!( - hex_u32(&b"ffffffffffffffff;"[..]), // overflow - Err(ErrMode::Backtrack(error_position!( - &b"ffffffffffffffff;"[..], - ErrorKind::IsA - ))) - ); - assert_parse!( - hex_u32(&b"ffffffffffffffff"[..]), // overflow - Err(ErrMode::Backtrack(error_position!( - &b"ffffffffffffffff"[..], - ErrorKind::IsA - ))) - ); - assert_parse!(hex_u32(&b"0x1be2;"[..]), Ok((&b"x1be2;"[..], 0))); - assert_parse!(hex_u32(&b"12af"[..]), Ok((&b""[..], 0x12af))); - } - - #[test] - #[cfg(feature = "std")] - fn float_test() { - let mut test_cases = vec![ - "+3.14", - "3.14", - "-3.14", - "0", - "0.0", - "1.", - ".789", - "-.5", - "1e7", - "-1E-7", - ".3e-2", - "1.e4", - "1.2e4", - "12.34", - "-1.234E-12", - "-1.234e-12", - "0.00000000000000000087", - ]; - - for test in test_cases.drain(..) { - let expected32 = str::parse::(test).unwrap(); - let expected64 = str::parse::(test).unwrap(); - - println!("now parsing: {} -> {}", test, expected32); - - let larger = test.to_string(); - - assert_parse!(float(larger.as_bytes()), Ok((&b""[..], expected32))); - assert_parse!(float(&larger[..]), Ok(("", expected32))); - - assert_parse!(float(larger.as_bytes()), Ok((&b""[..], expected64))); - assert_parse!(float(&larger[..]), Ok(("", expected64))); + #[test] + fn end_of_line() { + assert_parse!(line_ending(&b"\na"[..]), Ok((&b"a"[..], &b"\n"[..]))); + assert_parse!(line_ending(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..]))); + assert_parse!( + line_ending(&b"\r"[..]), + Err(ErrMode::Backtrack(error_position!( + &b"\r"[..], + ErrorKind::CrLf + ))) + ); + assert_parse!( + line_ending(&b"\ra"[..]), + Err(ErrMode::Backtrack(error_position!( + &b"\ra"[..], + ErrorKind::CrLf + ))) + ); + + assert_parse!(line_ending("\na"), Ok(("a", "\n"))); + assert_parse!(line_ending("\r\na"), Ok(("a", "\r\n"))); + assert_parse!( + line_ending("\r"), + Err(ErrMode::Backtrack(error_position!("\r", ErrorKind::CrLf))) + ); + assert_parse!( + line_ending("\ra"), + Err(ErrMode::Backtrack(error_position!("\ra", ErrorKind::CrLf))) + ); } - let remaining_exponent = "-1.234E-"; - assert_parse!( - float::<_, f64, _, false>(remaining_exponent), - Err(ErrMode::Cut(Error { - input: "-1.234E-", - kind: ErrorKind::Float - })) - ); - - let (_i, nan) = float::<_, f32, (), false>("NaN").unwrap(); - assert!(nan.is_nan()); - - let (_i, inf) = float::<_, f32, (), false>("inf").unwrap(); - assert!(inf.is_infinite()); - let (_i, inf) = float::<_, f32, (), false>("infinite").unwrap(); - assert!(inf.is_infinite()); - } - - #[cfg(feature = "std")] - fn parse_f64(i: &str) -> IResult<&str, f64, ()> { - #[allow(deprecated)] // will just become `pub(crate)` later - match crate::number::complete::recognize_float_or_exceptions(i) { - Err(e) => Err(e), - Ok((i, s)) => { - if s.is_empty() { - return Err(ErrMode::Backtrack(())); + fn digit_to_i16(input: &str) -> IResult<&str, i16> { + let i = input; + let (i, opt_sign) = opt(alt(('+', '-')))(i)?; + let sign = match opt_sign { + Some('+') | None => true, + Some('-') => false, + _ => unreachable!(), + }; + + let (i, s) = match digit1::<_, crate::error::Error<_>, false>(i) { + Ok((i, s)) => (i, s), + Err(_) => return Err(ErrMode::from_error_kind(input, ErrorKind::Digit)), + }; + + match s.parse_slice() { + Some(n) => { + if sign { + Ok((i, n)) + } else { + Ok((i, -n)) + } + } + None => Err(ErrMode::from_error_kind(i, ErrorKind::Digit)), } + } + + fn digit_to_u32(i: &str) -> IResult<&str, u32> { + let (i, s) = digit1(i)?; match s.parse_slice() { - Some(n) => Ok((i, n)), - None => Err(ErrMode::Backtrack(())), + Some(n) => Ok((i, n)), + None => Err(ErrMode::from_error_kind(i, ErrorKind::Digit)), } + } + + proptest! { + #[test] + fn ints(s in "\\PC*") { + let res1 = digit_to_i16(&s); + let res2 = dec_int(s.as_str()); + assert_eq!(res1, res2); + } + + #[test] + fn uints(s in "\\PC*") { + let res1 = digit_to_u32(&s); + let res2 = dec_uint(s.as_str()); + assert_eq!(res1, res2); } } - } - proptest! { #[test] - #[cfg(feature = "std")] - fn floats(s in "\\PC*") { - println!("testing {}", s); - let res1 = parse_f64(&s); - let res2 = float::<_, f64, (), false>(s.as_str()); - assert_eq!(res1, res2); + fn hex_uint_tests() { + fn hex_u32(input: &[u8]) -> IResult<&[u8], u32> { + hex_uint(input) + } + + assert_parse!( + hex_u32(&b";"[..]), + Err(ErrMode::Backtrack(error_position!( + &b";"[..], + ErrorKind::IsA + ))) + ); + assert_parse!(hex_u32(&b"ff;"[..]), Ok((&b";"[..], 255))); + assert_parse!(hex_u32(&b"1be2;"[..]), Ok((&b";"[..], 7138))); + assert_parse!(hex_u32(&b"c5a31be2;"[..]), Ok((&b";"[..], 3_315_801_058))); + assert_parse!(hex_u32(&b"C5A31be2;"[..]), Ok((&b";"[..], 3_315_801_058))); + assert_parse!( + hex_u32(&b"00c5a31be2;"[..]), // overflow + Err(ErrMode::Backtrack(error_position!( + &b"00c5a31be2;"[..], + ErrorKind::IsA + ))) + ); + assert_parse!( + hex_u32(&b"c5a31be201;"[..]), // overflow + Err(ErrMode::Backtrack(error_position!( + &b"c5a31be201;"[..], + ErrorKind::IsA + ))) + ); + assert_parse!(hex_u32(&b"ffffffff;"[..]), Ok((&b";"[..], 4_294_967_295))); + assert_parse!( + hex_u32(&b"ffffffffffffffff;"[..]), // overflow + Err(ErrMode::Backtrack(error_position!( + &b"ffffffffffffffff;"[..], + ErrorKind::IsA + ))) + ); + assert_parse!( + hex_u32(&b"ffffffffffffffff"[..]), // overflow + Err(ErrMode::Backtrack(error_position!( + &b"ffffffffffffffff"[..], + ErrorKind::IsA + ))) + ); + assert_parse!(hex_u32(&b"0x1be2;"[..]), Ok((&b"x1be2;"[..], 0))); + assert_parse!(hex_u32(&b"12af"[..]), Ok((&b""[..], 0x12af))); } - } - // issue #1336 "escaped hangs if normal parser accepts empty" - #[test] - fn complete_escaped_hang() { - // issue #1336 "escaped hangs if normal parser accepts empty" - fn escaped_string(input: &str) -> IResult<&str, &str> { - use crate::bytes::one_of; - use crate::character::alpha0; - escaped(alpha0, '\\', one_of("n"))(input) + #[test] + #[cfg(feature = "std")] + fn float_test() { + let mut test_cases = vec![ + "+3.14", + "3.14", + "-3.14", + "0", + "0.0", + "1.", + ".789", + "-.5", + "1e7", + "-1E-7", + ".3e-2", + "1.e4", + "1.2e4", + "12.34", + "-1.234E-12", + "-1.234e-12", + "0.00000000000000000087", + ]; + + for test in test_cases.drain(..) { + let expected32 = str::parse::(test).unwrap(); + let expected64 = str::parse::(test).unwrap(); + + println!("now parsing: {} -> {}", test, expected32); + + let larger = test.to_string(); + + assert_parse!(float(larger.as_bytes()), Ok((&b""[..], expected32))); + assert_parse!(float(&larger[..]), Ok(("", expected32))); + + assert_parse!(float(larger.as_bytes()), Ok((&b""[..], expected64))); + assert_parse!(float(&larger[..]), Ok(("", expected64))); + } + + let remaining_exponent = "-1.234E-"; + assert_parse!( + float::<_, f64, _, false>(remaining_exponent), + Err(ErrMode::Cut(Error { + input: "-1.234E-", + kind: ErrorKind::Float + })) + ); + + let (_i, nan) = float::<_, f32, (), false>("NaN").unwrap(); + assert!(nan.is_nan()); + + let (_i, inf) = float::<_, f32, (), false>("inf").unwrap(); + assert!(inf.is_infinite()); + let (_i, inf) = float::<_, f32, (), false>("infinite").unwrap(); + assert!(inf.is_infinite()); } - escaped_string("7").unwrap(); - escaped_string("a7").unwrap(); - } - - #[test] - fn complete_escaped_hang_1118() { - // issue ##1118 escaped does not work with empty string - fn unquote(input: &str) -> IResult<&str, &str> { - use crate::bytes::one_of; - use crate::combinator::opt; - use crate::sequence::delimited; - - delimited( - '"', - escaped(opt(none_of(r#"\""#)), '\\', one_of(r#"\"rnt"#)), - '"', - )(input) + #[cfg(feature = "std")] + fn parse_f64(i: &str) -> IResult<&str, f64, ()> { + #[allow(deprecated)] // will just become `pub(crate)` later + match crate::number::complete::recognize_float_or_exceptions(i) { + Err(e) => Err(e), + Ok((i, s)) => { + if s.is_empty() { + return Err(ErrMode::Backtrack(())); + } + match s.parse_slice() { + Some(n) => Ok((i, n)), + None => Err(ErrMode::Backtrack(())), + } + } + } } - assert_eq!(unquote(r#""""#), Ok(("", ""))); - } + proptest! { + #[test] + #[cfg(feature = "std")] + fn floats(s in "\\PC*") { + println!("testing {}", s); + let res1 = parse_f64(&s); + let res2 = float::<_, f64, (), false>(s.as_str()); + assert_eq!(res1, res2); + } + } - #[cfg(feature = "alloc")] - #[allow(unused_variables)] - #[test] - fn complete_escaping() { - use crate::bytes::one_of; - use crate::character::{alpha1 as alpha, digit1 as digit}; + // issue #1336 "escaped hangs if normal parser accepts empty" + #[test] + fn complete_escaped_hang() { + // issue #1336 "escaped hangs if normal parser accepts empty" + fn escaped_string(input: &str) -> IResult<&str, &str> { + use crate::bytes::one_of; + use crate::character::alpha0; + escaped(alpha0, '\\', one_of("n"))(input) + } - fn esc(i: &[u8]) -> IResult<&[u8], &[u8]> { - escaped(alpha, '\\', one_of("\"n\\"))(i) - } - assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], &b"abcd"[..]))); - assert_eq!(esc(&b"ab\\\"cd;"[..]), Ok((&b";"[..], &b"ab\\\"cd"[..]))); - assert_eq!(esc(&b"\\\"abcd;"[..]), Ok((&b";"[..], &b"\\\"abcd"[..]))); - assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], &b"\\n"[..]))); - assert_eq!(esc(&b"ab\\\"12"[..]), Ok((&b"12"[..], &b"ab\\\""[..]))); - assert_eq!( - esc(&b"AB\\"[..]), - Err(ErrMode::Backtrack(error_position!( - &b"AB\\"[..], - ErrorKind::Escaped - ))) - ); - assert_eq!( - esc(&b"AB\\A"[..]), - Err(ErrMode::Backtrack(error_node_position!( - &b"AB\\A"[..], - ErrorKind::Escaped, - error_position!(&b"A"[..], ErrorKind::OneOf) - ))) - ); - - fn esc2(i: &[u8]) -> IResult<&[u8], &[u8]> { - escaped(digit, '\\', one_of("\"n\\"))(i) + escaped_string("7").unwrap(); + escaped_string("a7").unwrap(); } - assert_eq!(esc2(&b"12\\nnn34"[..]), Ok((&b"nn34"[..], &b"12\\n"[..]))); - } - #[cfg(feature = "alloc")] - #[test] - fn complete_escaping_str() { - use crate::bytes::one_of; - use crate::character::{alpha1 as alpha, digit1 as digit}; + #[test] + fn complete_escaped_hang_1118() { + // issue ##1118 escaped does not work with empty string + fn unquote(input: &str) -> IResult<&str, &str> { + use crate::bytes::one_of; + use crate::combinator::opt; + use crate::sequence::delimited; + + delimited( + '"', + escaped(opt(none_of(r#"\""#)), '\\', one_of(r#"\"rnt"#)), + '"', + )(input) + } - fn esc(i: &str) -> IResult<&str, &str> { - escaped(alpha, '\\', one_of("\"n\\"))(i) - } - assert_eq!(esc("abcd;"), Ok((";", "abcd"))); - assert_eq!(esc("ab\\\"cd;"), Ok((";", "ab\\\"cd"))); - assert_eq!(esc("\\\"abcd;"), Ok((";", "\\\"abcd"))); - assert_eq!(esc("\\n;"), Ok((";", "\\n"))); - assert_eq!(esc("ab\\\"12"), Ok(("12", "ab\\\""))); - assert_eq!( - esc("AB\\"), - Err(ErrMode::Backtrack(error_position!( - "AB\\", - ErrorKind::Escaped - ))) - ); - assert_eq!( - esc("AB\\A"), - Err(ErrMode::Backtrack(error_node_position!( - "AB\\A", - ErrorKind::Escaped, - error_position!("A", ErrorKind::OneOf) - ))) - ); - - fn esc2(i: &str) -> IResult<&str, &str> { - escaped(digit, '\\', one_of("\"n\\"))(i) + assert_eq!(unquote(r#""""#), Ok(("", ""))); } - assert_eq!(esc2("12\\nnn34"), Ok(("nn34", "12\\n"))); - fn esc3(i: &str) -> IResult<&str, &str> { - escaped(alpha, '\u{241b}', one_of("\"n"))(i) - } - assert_eq!(esc3("ab␛ncd;"), Ok((";", "ab␛ncd"))); - } - - #[test] - fn test_escaped_error() { - fn esc(s: &str) -> IResult<&str, &str> { - use crate::character::digit1; - escaped(digit1, '\\', one_of("\"n\\"))(s) - } + #[cfg(feature = "alloc")] + #[allow(unused_variables)] + #[test] + fn complete_escaping() { + use crate::bytes::one_of; + use crate::character::{alpha1 as alpha, digit1 as digit}; - assert_eq!( - esc("abcd"), - Err(ErrMode::Backtrack(Error { - input: "abcd", - kind: ErrorKind::Escaped - })) - ); - } - - #[cfg(feature = "alloc")] - #[test] - fn complete_escape_transform() { - use crate::bytes::tag; - use crate::character::alpha1 as alpha; + fn esc(i: &[u8]) -> IResult<&[u8], &[u8]> { + escaped(alpha, '\\', one_of("\"n\\"))(i) + } + assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], &b"abcd"[..]))); + assert_eq!(esc(&b"ab\\\"cd;"[..]), Ok((&b";"[..], &b"ab\\\"cd"[..]))); + assert_eq!(esc(&b"\\\"abcd;"[..]), Ok((&b";"[..], &b"\\\"abcd"[..]))); + assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], &b"\\n"[..]))); + assert_eq!(esc(&b"ab\\\"12"[..]), Ok((&b"12"[..], &b"ab\\\""[..]))); + assert_eq!( + esc(&b"AB\\"[..]), + Err(ErrMode::Backtrack(error_position!( + &b"AB\\"[..], + ErrorKind::Escaped + ))) + ); + assert_eq!( + esc(&b"AB\\A"[..]), + Err(ErrMode::Backtrack(error_node_position!( + &b"AB\\A"[..], + ErrorKind::Escaped, + error_position!(&b"A"[..], ErrorKind::OneOf) + ))) + ); + + fn esc2(i: &[u8]) -> IResult<&[u8], &[u8]> { + escaped(digit, '\\', one_of("\"n\\"))(i) + } + assert_eq!(esc2(&b"12\\nnn34"[..]), Ok((&b"nn34"[..], &b"12\\n"[..]))); + } #[cfg(feature = "alloc")] - fn to_s(i: Vec) -> String { - String::from_utf8_lossy(&i).into_owned() - } + #[test] + fn complete_escaping_str() { + use crate::bytes::one_of; + use crate::character::{alpha1 as alpha, digit1 as digit}; - fn esc(i: &[u8]) -> IResult<&[u8], String> { - escaped_transform( - alpha, - '\\', - alt(( - tag("\\").value(&b"\\"[..]), - tag("\"").value(&b"\""[..]), - tag("n").value(&b"\n"[..]), - )), - ) - .map(to_s) - .parse_next(i) - } + fn esc(i: &str) -> IResult<&str, &str> { + escaped(alpha, '\\', one_of("\"n\\"))(i) + } + assert_eq!(esc("abcd;"), Ok((";", "abcd"))); + assert_eq!(esc("ab\\\"cd;"), Ok((";", "ab\\\"cd"))); + assert_eq!(esc("\\\"abcd;"), Ok((";", "\\\"abcd"))); + assert_eq!(esc("\\n;"), Ok((";", "\\n"))); + assert_eq!(esc("ab\\\"12"), Ok(("12", "ab\\\""))); + assert_eq!( + esc("AB\\"), + Err(ErrMode::Backtrack(error_position!( + "AB\\", + ErrorKind::Escaped + ))) + ); + assert_eq!( + esc("AB\\A"), + Err(ErrMode::Backtrack(error_node_position!( + "AB\\A", + ErrorKind::Escaped, + error_position!("A", ErrorKind::OneOf) + ))) + ); + + fn esc2(i: &str) -> IResult<&str, &str> { + escaped(digit, '\\', one_of("\"n\\"))(i) + } + assert_eq!(esc2("12\\nnn34"), Ok(("nn34", "12\\n"))); - assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], String::from("abcd")))); - assert_eq!( - esc(&b"ab\\\"cd;"[..]), - Ok((&b";"[..], String::from("ab\"cd"))) - ); - assert_eq!( - esc(&b"\\\"abcd;"[..]), - Ok((&b";"[..], String::from("\"abcd"))) - ); - assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], String::from("\n")))); - assert_eq!( - esc(&b"ab\\\"12"[..]), - Ok((&b"12"[..], String::from("ab\""))) - ); - assert_eq!( - esc(&b"AB\\"[..]), - Err(ErrMode::Backtrack(error_position!( - &b"\\"[..], - ErrorKind::EscapedTransform - ))) - ); - assert_eq!( - esc(&b"AB\\A"[..]), - Err(ErrMode::Backtrack(error_node_position!( - &b"AB\\A"[..], - ErrorKind::EscapedTransform, - error_position!(&b"A"[..], ErrorKind::Tag) - ))) - ); - - fn esc2(i: &[u8]) -> IResult<&[u8], String> { - escaped_transform( - alpha, - '&', - alt(( - tag("egrave;").value("è".as_bytes()), - tag("agrave;").value("à".as_bytes()), - )), - ) - .map(to_s) - .parse_next(i) - } - assert_eq!( - esc2(&b"abèDEF;"[..]), - Ok((&b";"[..], String::from("abèDEF"))) - ); - assert_eq!( - esc2(&b"abèDàEF;"[..]), - Ok((&b";"[..], String::from("abèDàEF"))) - ); - } - - #[cfg(feature = "std")] - #[test] - fn complete_escape_transform_str() { - use crate::bytes::tag; - use crate::character::alpha1 as alpha; - - fn esc(i: &str) -> IResult<&str, String> { - escaped_transform( - alpha, - '\\', - alt(( - tag("\\").value("\\"), - tag("\"").value("\""), - tag("n").value("\n"), - )), - )(i) + fn esc3(i: &str) -> IResult<&str, &str> { + escaped(alpha, '\u{241b}', one_of("\"n"))(i) + } + assert_eq!(esc3("ab␛ncd;"), Ok((";", "ab␛ncd"))); } - assert_eq!(esc("abcd;"), Ok((";", String::from("abcd")))); - assert_eq!(esc("ab\\\"cd;"), Ok((";", String::from("ab\"cd")))); - assert_eq!(esc("\\\"abcd;"), Ok((";", String::from("\"abcd")))); - assert_eq!(esc("\\n;"), Ok((";", String::from("\n")))); - assert_eq!(esc("ab\\\"12"), Ok(("12", String::from("ab\"")))); - assert_eq!( - esc("AB\\"), - Err(ErrMode::Backtrack(error_position!( - "\\", - ErrorKind::EscapedTransform - ))) - ); - assert_eq!( - esc("AB\\A"), - Err(ErrMode::Backtrack(error_node_position!( - "AB\\A", - ErrorKind::EscapedTransform, - error_position!("A", ErrorKind::Tag) - ))) - ); - - fn esc2(i: &str) -> IResult<&str, String> { - escaped_transform( - alpha, - '&', - alt((tag("egrave;").value("è"), tag("agrave;").value("à"))), - )(i) + #[test] + fn test_escaped_error() { + fn esc(s: &str) -> IResult<&str, &str> { + use crate::character::digit1; + escaped(digit1, '\\', one_of("\"n\\"))(s) + } + + assert_eq!( + esc("abcd"), + Err(ErrMode::Backtrack(Error { + input: "abcd", + kind: ErrorKind::Escaped + })) + ); } - assert_eq!(esc2("abèDEF;"), Ok((";", String::from("abèDEF")))); - assert_eq!( - esc2("abèDàEF;"), - Ok((";", String::from("abèDàEF"))) - ); - - fn esc3(i: &str) -> IResult<&str, String> { - escaped_transform( - alpha, - '␛', - alt((tag("0").value("\0"), tag("n").value("\n"))), - )(i) + + #[cfg(feature = "alloc")] + #[test] + fn complete_escape_transform() { + use crate::bytes::tag; + use crate::character::alpha1 as alpha; + + #[cfg(feature = "alloc")] + fn to_s(i: Vec) -> String { + String::from_utf8_lossy(&i).into_owned() + } + + fn esc(i: &[u8]) -> IResult<&[u8], String> { + escaped_transform( + alpha, + '\\', + alt(( + tag("\\").value(&b"\\"[..]), + tag("\"").value(&b"\""[..]), + tag("n").value(&b"\n"[..]), + )), + ) + .map(to_s) + .parse_next(i) + } + + assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], String::from("abcd")))); + assert_eq!( + esc(&b"ab\\\"cd;"[..]), + Ok((&b";"[..], String::from("ab\"cd"))) + ); + assert_eq!( + esc(&b"\\\"abcd;"[..]), + Ok((&b";"[..], String::from("\"abcd"))) + ); + assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], String::from("\n")))); + assert_eq!( + esc(&b"ab\\\"12"[..]), + Ok((&b"12"[..], String::from("ab\""))) + ); + assert_eq!( + esc(&b"AB\\"[..]), + Err(ErrMode::Backtrack(error_position!( + &b"\\"[..], + ErrorKind::EscapedTransform + ))) + ); + assert_eq!( + esc(&b"AB\\A"[..]), + Err(ErrMode::Backtrack(error_node_position!( + &b"AB\\A"[..], + ErrorKind::EscapedTransform, + error_position!(&b"A"[..], ErrorKind::Tag) + ))) + ); + + fn esc2(i: &[u8]) -> IResult<&[u8], String> { + escaped_transform( + alpha, + '&', + alt(( + tag("egrave;").value("è".as_bytes()), + tag("agrave;").value("à".as_bytes()), + )), + ) + .map(to_s) + .parse_next(i) + } + assert_eq!( + esc2(&b"abèDEF;"[..]), + Ok((&b";"[..], String::from("abèDEF"))) + ); + assert_eq!( + esc2(&b"abèDàEF;"[..]), + Ok((&b";"[..], String::from("abèDàEF"))) + ); } - assert_eq!(esc3("a␛0bc␛n"), Ok(("", String::from("a\0bc\n")))); - } - - #[test] - #[cfg(feature = "alloc")] - fn test_escaped_transform_error() { - fn esc_trans(s: &str) -> IResult<&str, String> { - use crate::character::digit1; - escaped_transform(digit1, '\\', "n")(s) + + #[cfg(feature = "std")] + #[test] + fn complete_escape_transform_str() { + use crate::bytes::tag; + use crate::character::alpha1 as alpha; + + fn esc(i: &str) -> IResult<&str, String> { + escaped_transform( + alpha, + '\\', + alt(( + tag("\\").value("\\"), + tag("\"").value("\""), + tag("n").value("\n"), + )), + )(i) + } + + assert_eq!(esc("abcd;"), Ok((";", String::from("abcd")))); + assert_eq!(esc("ab\\\"cd;"), Ok((";", String::from("ab\"cd")))); + assert_eq!(esc("\\\"abcd;"), Ok((";", String::from("\"abcd")))); + assert_eq!(esc("\\n;"), Ok((";", String::from("\n")))); + assert_eq!(esc("ab\\\"12"), Ok(("12", String::from("ab\"")))); + assert_eq!( + esc("AB\\"), + Err(ErrMode::Backtrack(error_position!( + "\\", + ErrorKind::EscapedTransform + ))) + ); + assert_eq!( + esc("AB\\A"), + Err(ErrMode::Backtrack(error_node_position!( + "AB\\A", + ErrorKind::EscapedTransform, + error_position!("A", ErrorKind::Tag) + ))) + ); + + fn esc2(i: &str) -> IResult<&str, String> { + escaped_transform( + alpha, + '&', + alt((tag("egrave;").value("è"), tag("agrave;").value("à"))), + )(i) + } + assert_eq!(esc2("abèDEF;"), Ok((";", String::from("abèDEF")))); + assert_eq!( + esc2("abèDàEF;"), + Ok((";", String::from("abèDàEF"))) + ); + + fn esc3(i: &str) -> IResult<&str, String> { + escaped_transform( + alpha, + '␛', + alt((tag("0").value("\0"), tag("n").value("\n"))), + )(i) + } + assert_eq!(esc3("a␛0bc␛n"), Ok(("", String::from("a\0bc\n")))); } - assert_eq!( - esc_trans("abcd"), - Err(ErrMode::Backtrack(Error { - input: "abcd", - kind: ErrorKind::EscapedTransform - })) - ); - } + #[test] + #[cfg(feature = "alloc")] + fn test_escaped_transform_error() { + fn esc_trans(s: &str) -> IResult<&str, String> { + use crate::character::digit1; + escaped_transform(digit1, '\\', "n")(s) + } + + assert_eq!( + esc_trans("abcd"), + Err(ErrMode::Backtrack(Error { + input: "abcd", + kind: ErrorKind::EscapedTransform + })) + ); + } } mod streaming { - use super::*; - use crate::combinator::opt; - use crate::error::Error; - use crate::error::ErrorKind; - use crate::error::{ErrMode, Needed}; - use crate::input::ParseSlice; - use crate::input::Streaming; - use crate::sequence::pair; - use crate::IResult; - use proptest::prelude::*; - - macro_rules! assert_parse( + use super::*; + use crate::combinator::opt; + use crate::error::Error; + use crate::error::ErrorKind; + use crate::error::{ErrMode, Needed}; + use crate::input::ParseSlice; + use crate::input::Streaming; + use crate::sequence::pair; + use crate::IResult; + use proptest::prelude::*; + + macro_rules! assert_parse( ($left: expr, $right: expr) => { let res: $crate::IResult<_, _, Error<_>> = $left; assert_eq!(res, $right); }; ); - #[test] - fn character() { - let a: &[u8] = b"abcd"; - let b: &[u8] = b"1234"; - let c: &[u8] = b"a123"; - let d: &[u8] = "azé12".as_bytes(); - let e: &[u8] = b" "; - let f: &[u8] = b" ;"; - //assert_eq!(alpha1::<_, Error<_>, true>(a), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_parse!( - alpha1(Streaming(a)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - alpha1(Streaming(b)), - Err(ErrMode::Backtrack(Error::new( - Streaming(b), - ErrorKind::Alpha - ))) - ); - assert_eq!( - alpha1::<_, Error<_>, true>(Streaming(c)), - Ok((Streaming(&c[1..]), &b"a"[..])) - ); - assert_eq!( - alpha1::<_, Error<_>, true>(Streaming(d)), - Ok((Streaming("é12".as_bytes()), &b"az"[..])) - ); - assert_eq!( - digit1(Streaming(a)), - Err(ErrMode::Backtrack(Error::new( - Streaming(a), - ErrorKind::Digit - ))) - ); - assert_eq!( - digit1::<_, Error<_>, true>(Streaming(b)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - digit1(Streaming(c)), - Err(ErrMode::Backtrack(Error::new( - Streaming(c), - ErrorKind::Digit - ))) - ); - assert_eq!( - digit1(Streaming(d)), - Err(ErrMode::Backtrack(Error::new( - Streaming(d), - ErrorKind::Digit - ))) - ); - assert_eq!( - hex_digit1::<_, Error<_>, true>(Streaming(a)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - hex_digit1::<_, Error<_>, true>(Streaming(b)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - hex_digit1::<_, Error<_>, true>(Streaming(c)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - hex_digit1::<_, Error<_>, true>(Streaming(d)), - Ok((Streaming("zé12".as_bytes()), &b"a"[..])) - ); - assert_eq!( - hex_digit1(Streaming(e)), - Err(ErrMode::Backtrack(Error::new( - Streaming(e), - ErrorKind::HexDigit - ))) - ); - assert_eq!( - oct_digit1(Streaming(a)), - Err(ErrMode::Backtrack(Error::new( - Streaming(a), - ErrorKind::OctDigit - ))) - ); - assert_eq!( - oct_digit1::<_, Error<_>, true>(Streaming(b)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - oct_digit1(Streaming(c)), - Err(ErrMode::Backtrack(Error::new( - Streaming(c), - ErrorKind::OctDigit - ))) - ); - assert_eq!( - oct_digit1(Streaming(d)), - Err(ErrMode::Backtrack(Error::new( - Streaming(d), - ErrorKind::OctDigit - ))) - ); - assert_eq!( - alphanumeric1::<_, Error<_>, true>(Streaming(a)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - //assert_eq!(fix_error!(b,(), alphanumeric1), Ok((empty, b))); - assert_eq!( - alphanumeric1::<_, Error<_>, true>(Streaming(c)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - alphanumeric1::<_, Error<_>, true>(Streaming(d)), - Ok((Streaming("é12".as_bytes()), &b"az"[..])) - ); - assert_eq!( - space1::<_, Error<_>, true>(Streaming(e)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - space1::<_, Error<_>, true>(Streaming(f)), - Ok((Streaming(&b";"[..]), &b" "[..])) - ); - } - - #[cfg(feature = "alloc")] - #[test] - fn character_s() { - let a = "abcd"; - let b = "1234"; - let c = "a123"; - let d = "azé12"; - let e = " "; - assert_eq!( - alpha1::<_, Error<_>, true>(Streaming(a)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - alpha1(Streaming(b)), - Err(ErrMode::Backtrack(Error::new( - Streaming(b), - ErrorKind::Alpha - ))) - ); - assert_eq!( - alpha1::<_, Error<_>, true>(Streaming(c)), - Ok((Streaming(&c[1..]), "a")) - ); - assert_eq!( - alpha1::<_, Error<_>, true>(Streaming(d)), - Ok((Streaming("é12"), "az")) - ); - assert_eq!( - digit1(Streaming(a)), - Err(ErrMode::Backtrack(Error::new( - Streaming(a), - ErrorKind::Digit - ))) - ); - assert_eq!( - digit1::<_, Error<_>, true>(Streaming(b)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - digit1(Streaming(c)), - Err(ErrMode::Backtrack(Error::new( - Streaming(c), - ErrorKind::Digit - ))) - ); - assert_eq!( - digit1(Streaming(d)), - Err(ErrMode::Backtrack(Error::new( - Streaming(d), - ErrorKind::Digit - ))) - ); - assert_eq!( - hex_digit1::<_, Error<_>, true>(Streaming(a)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - hex_digit1::<_, Error<_>, true>(Streaming(b)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - hex_digit1::<_, Error<_>, true>(Streaming(c)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - hex_digit1::<_, Error<_>, true>(Streaming(d)), - Ok((Streaming("zé12"), "a")) - ); - assert_eq!( - hex_digit1(Streaming(e)), - Err(ErrMode::Backtrack(Error::new( - Streaming(e), - ErrorKind::HexDigit - ))) - ); - assert_eq!( - oct_digit1(Streaming(a)), - Err(ErrMode::Backtrack(Error::new( - Streaming(a), - ErrorKind::OctDigit - ))) - ); - assert_eq!( - oct_digit1::<_, Error<_>, true>(Streaming(b)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - oct_digit1(Streaming(c)), - Err(ErrMode::Backtrack(Error::new( - Streaming(c), - ErrorKind::OctDigit - ))) - ); - assert_eq!( - oct_digit1(Streaming(d)), - Err(ErrMode::Backtrack(Error::new( - Streaming(d), - ErrorKind::OctDigit - ))) - ); - assert_eq!( - alphanumeric1::<_, Error<_>, true>(Streaming(a)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - //assert_eq!(fix_error!(b,(), alphanumeric1), Ok((empty, b))); - assert_eq!( - alphanumeric1::<_, Error<_>, true>(Streaming(c)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - alphanumeric1::<_, Error<_>, true>(Streaming(d)), - Ok((Streaming("é12"), "az")) - ); - assert_eq!( - space1::<_, Error<_>, true>(Streaming(e)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - } - - use crate::input::Offset; - #[test] - fn offset() { - let a = &b"abcd;"[..]; - let b = &b"1234;"[..]; - let c = &b"a123;"[..]; - let d = &b" \t;"[..]; - let e = &b" \t\r\n;"[..]; - let f = &b"123abcDEF;"[..]; - - match alpha1::<_, Error<_>, true>(Streaming(a)) { - Ok((Streaming(i), _)) => { - assert_eq!(a.offset_to(i) + i.len(), a.len()); - } - _ => panic!("wrong return type in offset test for alpha"), - } - match digit1::<_, Error<_>, true>(Streaming(b)) { - Ok((Streaming(i), _)) => { - assert_eq!(b.offset_to(i) + i.len(), b.len()); - } - _ => panic!("wrong return type in offset test for digit"), - } - match alphanumeric1::<_, Error<_>, true>(Streaming(c)) { - Ok((Streaming(i), _)) => { - assert_eq!(c.offset_to(i) + i.len(), c.len()); - } - _ => panic!("wrong return type in offset test for alphanumeric"), + #[test] + fn character() { + let a: &[u8] = b"abcd"; + let b: &[u8] = b"1234"; + let c: &[u8] = b"a123"; + let d: &[u8] = "azé12".as_bytes(); + let e: &[u8] = b" "; + let f: &[u8] = b" ;"; + //assert_eq!(alpha1::<_, Error<_>, true>(a), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_parse!( + alpha1(Streaming(a)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + alpha1(Streaming(b)), + Err(ErrMode::Backtrack(Error::new( + Streaming(b), + ErrorKind::Alpha + ))) + ); + assert_eq!( + alpha1::<_, Error<_>, true>(Streaming(c)), + Ok((Streaming(&c[1..]), &b"a"[..])) + ); + assert_eq!( + alpha1::<_, Error<_>, true>(Streaming(d)), + Ok((Streaming("é12".as_bytes()), &b"az"[..])) + ); + assert_eq!( + digit1(Streaming(a)), + Err(ErrMode::Backtrack(Error::new( + Streaming(a), + ErrorKind::Digit + ))) + ); + assert_eq!( + digit1::<_, Error<_>, true>(Streaming(b)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + digit1(Streaming(c)), + Err(ErrMode::Backtrack(Error::new( + Streaming(c), + ErrorKind::Digit + ))) + ); + assert_eq!( + digit1(Streaming(d)), + Err(ErrMode::Backtrack(Error::new( + Streaming(d), + ErrorKind::Digit + ))) + ); + assert_eq!( + hex_digit1::<_, Error<_>, true>(Streaming(a)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + hex_digit1::<_, Error<_>, true>(Streaming(b)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + hex_digit1::<_, Error<_>, true>(Streaming(c)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + hex_digit1::<_, Error<_>, true>(Streaming(d)), + Ok((Streaming("zé12".as_bytes()), &b"a"[..])) + ); + assert_eq!( + hex_digit1(Streaming(e)), + Err(ErrMode::Backtrack(Error::new( + Streaming(e), + ErrorKind::HexDigit + ))) + ); + assert_eq!( + oct_digit1(Streaming(a)), + Err(ErrMode::Backtrack(Error::new( + Streaming(a), + ErrorKind::OctDigit + ))) + ); + assert_eq!( + oct_digit1::<_, Error<_>, true>(Streaming(b)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + oct_digit1(Streaming(c)), + Err(ErrMode::Backtrack(Error::new( + Streaming(c), + ErrorKind::OctDigit + ))) + ); + assert_eq!( + oct_digit1(Streaming(d)), + Err(ErrMode::Backtrack(Error::new( + Streaming(d), + ErrorKind::OctDigit + ))) + ); + assert_eq!( + alphanumeric1::<_, Error<_>, true>(Streaming(a)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + //assert_eq!(fix_error!(b,(), alphanumeric1), Ok((empty, b))); + assert_eq!( + alphanumeric1::<_, Error<_>, true>(Streaming(c)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + alphanumeric1::<_, Error<_>, true>(Streaming(d)), + Ok((Streaming("é12".as_bytes()), &b"az"[..])) + ); + assert_eq!( + space1::<_, Error<_>, true>(Streaming(e)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + space1::<_, Error<_>, true>(Streaming(f)), + Ok((Streaming(&b";"[..]), &b" "[..])) + ); } - match space1::<_, Error<_>, true>(Streaming(d)) { - Ok((Streaming(i), _)) => { - assert_eq!(d.offset_to(i) + i.len(), d.len()); - } - _ => panic!("wrong return type in offset test for space"), + + #[cfg(feature = "alloc")] + #[test] + fn character_s() { + let a = "abcd"; + let b = "1234"; + let c = "a123"; + let d = "azé12"; + let e = " "; + assert_eq!( + alpha1::<_, Error<_>, true>(Streaming(a)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + alpha1(Streaming(b)), + Err(ErrMode::Backtrack(Error::new( + Streaming(b), + ErrorKind::Alpha + ))) + ); + assert_eq!( + alpha1::<_, Error<_>, true>(Streaming(c)), + Ok((Streaming(&c[1..]), "a")) + ); + assert_eq!( + alpha1::<_, Error<_>, true>(Streaming(d)), + Ok((Streaming("é12"), "az")) + ); + assert_eq!( + digit1(Streaming(a)), + Err(ErrMode::Backtrack(Error::new( + Streaming(a), + ErrorKind::Digit + ))) + ); + assert_eq!( + digit1::<_, Error<_>, true>(Streaming(b)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + digit1(Streaming(c)), + Err(ErrMode::Backtrack(Error::new( + Streaming(c), + ErrorKind::Digit + ))) + ); + assert_eq!( + digit1(Streaming(d)), + Err(ErrMode::Backtrack(Error::new( + Streaming(d), + ErrorKind::Digit + ))) + ); + assert_eq!( + hex_digit1::<_, Error<_>, true>(Streaming(a)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + hex_digit1::<_, Error<_>, true>(Streaming(b)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + hex_digit1::<_, Error<_>, true>(Streaming(c)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + hex_digit1::<_, Error<_>, true>(Streaming(d)), + Ok((Streaming("zé12"), "a")) + ); + assert_eq!( + hex_digit1(Streaming(e)), + Err(ErrMode::Backtrack(Error::new( + Streaming(e), + ErrorKind::HexDigit + ))) + ); + assert_eq!( + oct_digit1(Streaming(a)), + Err(ErrMode::Backtrack(Error::new( + Streaming(a), + ErrorKind::OctDigit + ))) + ); + assert_eq!( + oct_digit1::<_, Error<_>, true>(Streaming(b)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + oct_digit1(Streaming(c)), + Err(ErrMode::Backtrack(Error::new( + Streaming(c), + ErrorKind::OctDigit + ))) + ); + assert_eq!( + oct_digit1(Streaming(d)), + Err(ErrMode::Backtrack(Error::new( + Streaming(d), + ErrorKind::OctDigit + ))) + ); + assert_eq!( + alphanumeric1::<_, Error<_>, true>(Streaming(a)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + //assert_eq!(fix_error!(b,(), alphanumeric1), Ok((empty, b))); + assert_eq!( + alphanumeric1::<_, Error<_>, true>(Streaming(c)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + alphanumeric1::<_, Error<_>, true>(Streaming(d)), + Ok((Streaming("é12"), "az")) + ); + assert_eq!( + space1::<_, Error<_>, true>(Streaming(e)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); } - match multispace1::<_, Error<_>, true>(Streaming(e)) { - Ok((Streaming(i), _)) => { - assert_eq!(e.offset_to(i) + i.len(), e.len()); - } - _ => panic!("wrong return type in offset test for multispace"), + + use crate::input::Offset; + #[test] + fn offset() { + let a = &b"abcd;"[..]; + let b = &b"1234;"[..]; + let c = &b"a123;"[..]; + let d = &b" \t;"[..]; + let e = &b" \t\r\n;"[..]; + let f = &b"123abcDEF;"[..]; + + match alpha1::<_, Error<_>, true>(Streaming(a)) { + Ok((Streaming(i), _)) => { + assert_eq!(a.offset_to(i) + i.len(), a.len()); + } + _ => panic!("wrong return type in offset test for alpha"), + } + match digit1::<_, Error<_>, true>(Streaming(b)) { + Ok((Streaming(i), _)) => { + assert_eq!(b.offset_to(i) + i.len(), b.len()); + } + _ => panic!("wrong return type in offset test for digit"), + } + match alphanumeric1::<_, Error<_>, true>(Streaming(c)) { + Ok((Streaming(i), _)) => { + assert_eq!(c.offset_to(i) + i.len(), c.len()); + } + _ => panic!("wrong return type in offset test for alphanumeric"), + } + match space1::<_, Error<_>, true>(Streaming(d)) { + Ok((Streaming(i), _)) => { + assert_eq!(d.offset_to(i) + i.len(), d.len()); + } + _ => panic!("wrong return type in offset test for space"), + } + match multispace1::<_, Error<_>, true>(Streaming(e)) { + Ok((Streaming(i), _)) => { + assert_eq!(e.offset_to(i) + i.len(), e.len()); + } + _ => panic!("wrong return type in offset test for multispace"), + } + match hex_digit1::<_, Error<_>, true>(Streaming(f)) { + Ok((Streaming(i), _)) => { + assert_eq!(f.offset_to(i) + i.len(), f.len()); + } + _ => panic!("wrong return type in offset test for hex_digit"), + } + match oct_digit1::<_, Error<_>, true>(Streaming(f)) { + Ok((Streaming(i), _)) => { + assert_eq!(f.offset_to(i) + i.len(), f.len()); + } + _ => panic!("wrong return type in offset test for oct_digit"), + } } - match hex_digit1::<_, Error<_>, true>(Streaming(f)) { - Ok((Streaming(i), _)) => { - assert_eq!(f.offset_to(i) + i.len(), f.len()); - } - _ => panic!("wrong return type in offset test for hex_digit"), + + #[test] + fn is_not_line_ending_bytes() { + let a: &[u8] = b"ab12cd\nefgh"; + assert_eq!( + not_line_ending::<_, Error<_>, true>(Streaming(a)), + Ok((Streaming(&b"\nefgh"[..]), &b"ab12cd"[..])) + ); + + let b: &[u8] = b"ab12cd\nefgh\nijkl"; + assert_eq!( + not_line_ending::<_, Error<_>, true>(Streaming(b)), + Ok((Streaming(&b"\nefgh\nijkl"[..]), &b"ab12cd"[..])) + ); + + let c: &[u8] = b"ab12cd\r\nefgh\nijkl"; + assert_eq!( + not_line_ending::<_, Error<_>, true>(Streaming(c)), + Ok((Streaming(&b"\r\nefgh\nijkl"[..]), &b"ab12cd"[..])) + ); + + let d: &[u8] = b"ab12cd"; + assert_eq!( + not_line_ending::<_, Error<_>, true>(Streaming(d)), + Err(ErrMode::Incomplete(Needed::Unknown)) + ); } - match oct_digit1::<_, Error<_>, true>(Streaming(f)) { - Ok((Streaming(i), _)) => { - assert_eq!(f.offset_to(i) + i.len(), f.len()); - } - _ => panic!("wrong return type in offset test for oct_digit"), + + #[test] + fn is_not_line_ending_str() { + let f = "βèƒôřè\rÂßÇáƒƭèř"; + assert_eq!( + not_line_ending(Streaming(f)), + Err(ErrMode::Backtrack(Error::new(Streaming(f), ErrorKind::Tag))) + ); + + let g2: &str = "ab12cd"; + assert_eq!( + not_line_ending::<_, Error<_>, true>(Streaming(g2)), + Err(ErrMode::Incomplete(Needed::Unknown)) + ); } - } - - #[test] - fn is_not_line_ending_bytes() { - let a: &[u8] = b"ab12cd\nefgh"; - assert_eq!( - not_line_ending::<_, Error<_>, true>(Streaming(a)), - Ok((Streaming(&b"\nefgh"[..]), &b"ab12cd"[..])) - ); - - let b: &[u8] = b"ab12cd\nefgh\nijkl"; - assert_eq!( - not_line_ending::<_, Error<_>, true>(Streaming(b)), - Ok((Streaming(&b"\nefgh\nijkl"[..]), &b"ab12cd"[..])) - ); - - let c: &[u8] = b"ab12cd\r\nefgh\nijkl"; - assert_eq!( - not_line_ending::<_, Error<_>, true>(Streaming(c)), - Ok((Streaming(&b"\r\nefgh\nijkl"[..]), &b"ab12cd"[..])) - ); - - let d: &[u8] = b"ab12cd"; - assert_eq!( - not_line_ending::<_, Error<_>, true>(Streaming(d)), - Err(ErrMode::Incomplete(Needed::Unknown)) - ); - } - - #[test] - fn is_not_line_ending_str() { - let f = "βèƒôřè\rÂßÇáƒƭèř"; - assert_eq!( - not_line_ending(Streaming(f)), - Err(ErrMode::Backtrack(Error::new(Streaming(f), ErrorKind::Tag))) - ); - - let g2: &str = "ab12cd"; - assert_eq!( - not_line_ending::<_, Error<_>, true>(Streaming(g2)), - Err(ErrMode::Incomplete(Needed::Unknown)) - ); - } - - #[test] - fn hex_digit_test() { - let i = &b"0123456789abcdefABCDEF;"[..]; - assert_parse!( - hex_digit1(Streaming(i)), - Ok((Streaming(&b";"[..]), &i[..i.len() - 1])) - ); - - let i = &b"g"[..]; - assert_parse!( - hex_digit1(Streaming(i)), - Err(ErrMode::Backtrack(error_position!( - Streaming(i), - ErrorKind::HexDigit - ))) - ); - - let i = &b"G"[..]; - assert_parse!( - hex_digit1(Streaming(i)), - Err(ErrMode::Backtrack(error_position!( - Streaming(i), - ErrorKind::HexDigit - ))) - ); - - assert!(AsChar::is_hex_digit(b'0')); - assert!(AsChar::is_hex_digit(b'9')); - assert!(AsChar::is_hex_digit(b'a')); - assert!(AsChar::is_hex_digit(b'f')); - assert!(AsChar::is_hex_digit(b'A')); - assert!(AsChar::is_hex_digit(b'F')); - assert!(!AsChar::is_hex_digit(b'g')); - assert!(!AsChar::is_hex_digit(b'G')); - assert!(!AsChar::is_hex_digit(b'/')); - assert!(!AsChar::is_hex_digit(b':')); - assert!(!AsChar::is_hex_digit(b'@')); - assert!(!AsChar::is_hex_digit(b'\x60')); - } - - #[test] - fn oct_digit_test() { - let i = &b"01234567;"[..]; - assert_parse!( - oct_digit1(Streaming(i)), - Ok((Streaming(&b";"[..]), &i[..i.len() - 1])) - ); - - let i = &b"8"[..]; - assert_parse!( - oct_digit1(Streaming(i)), - Err(ErrMode::Backtrack(error_position!( - Streaming(i), - ErrorKind::OctDigit - ))) - ); - - assert!(AsChar::is_oct_digit(b'0')); - assert!(AsChar::is_oct_digit(b'7')); - assert!(!AsChar::is_oct_digit(b'8')); - assert!(!AsChar::is_oct_digit(b'9')); - assert!(!AsChar::is_oct_digit(b'a')); - assert!(!AsChar::is_oct_digit(b'A')); - assert!(!AsChar::is_oct_digit(b'/')); - assert!(!AsChar::is_oct_digit(b':')); - assert!(!AsChar::is_oct_digit(b'@')); - assert!(!AsChar::is_oct_digit(b'\x60')); - } - - #[test] - fn full_line_windows() { - #[allow(clippy::type_complexity)] - fn take_full_line(i: Streaming<&[u8]>) -> IResult, (&[u8], &[u8])> { - pair(not_line_ending, line_ending)(i) + + #[test] + fn hex_digit_test() { + let i = &b"0123456789abcdefABCDEF;"[..]; + assert_parse!( + hex_digit1(Streaming(i)), + Ok((Streaming(&b";"[..]), &i[..i.len() - 1])) + ); + + let i = &b"g"[..]; + assert_parse!( + hex_digit1(Streaming(i)), + Err(ErrMode::Backtrack(error_position!( + Streaming(i), + ErrorKind::HexDigit + ))) + ); + + let i = &b"G"[..]; + assert_parse!( + hex_digit1(Streaming(i)), + Err(ErrMode::Backtrack(error_position!( + Streaming(i), + ErrorKind::HexDigit + ))) + ); + + assert!(AsChar::is_hex_digit(b'0')); + assert!(AsChar::is_hex_digit(b'9')); + assert!(AsChar::is_hex_digit(b'a')); + assert!(AsChar::is_hex_digit(b'f')); + assert!(AsChar::is_hex_digit(b'A')); + assert!(AsChar::is_hex_digit(b'F')); + assert!(!AsChar::is_hex_digit(b'g')); + assert!(!AsChar::is_hex_digit(b'G')); + assert!(!AsChar::is_hex_digit(b'/')); + assert!(!AsChar::is_hex_digit(b':')); + assert!(!AsChar::is_hex_digit(b'@')); + assert!(!AsChar::is_hex_digit(b'\x60')); } - let input = b"abc\r\n"; - let output = take_full_line(Streaming(input)); - assert_eq!( - output, - Ok((Streaming(&b""[..]), (&b"abc"[..], &b"\r\n"[..]))) - ); - } - - #[test] - fn full_line_unix() { - #[allow(clippy::type_complexity)] - fn take_full_line(i: Streaming<&[u8]>) -> IResult, (&[u8], &[u8])> { - pair(not_line_ending, line_ending)(i) + + #[test] + fn oct_digit_test() { + let i = &b"01234567;"[..]; + assert_parse!( + oct_digit1(Streaming(i)), + Ok((Streaming(&b";"[..]), &i[..i.len() - 1])) + ); + + let i = &b"8"[..]; + assert_parse!( + oct_digit1(Streaming(i)), + Err(ErrMode::Backtrack(error_position!( + Streaming(i), + ErrorKind::OctDigit + ))) + ); + + assert!(AsChar::is_oct_digit(b'0')); + assert!(AsChar::is_oct_digit(b'7')); + assert!(!AsChar::is_oct_digit(b'8')); + assert!(!AsChar::is_oct_digit(b'9')); + assert!(!AsChar::is_oct_digit(b'a')); + assert!(!AsChar::is_oct_digit(b'A')); + assert!(!AsChar::is_oct_digit(b'/')); + assert!(!AsChar::is_oct_digit(b':')); + assert!(!AsChar::is_oct_digit(b'@')); + assert!(!AsChar::is_oct_digit(b'\x60')); } - let input = b"abc\n"; - let output = take_full_line(Streaming(input)); - assert_eq!(output, Ok((Streaming(&b""[..]), (&b"abc"[..], &b"\n"[..])))); - } - - #[test] - fn check_windows_lineending() { - let input = b"\r\n"; - let output = line_ending(Streaming(&input[..])); - assert_parse!(output, Ok((Streaming(&b""[..]), &b"\r\n"[..]))); - } - - #[test] - fn check_unix_lineending() { - let input = b"\n"; - let output = line_ending(Streaming(&input[..])); - assert_parse!(output, Ok((Streaming(&b""[..]), &b"\n"[..]))); - } - - #[test] - fn cr_lf() { - assert_parse!( - crlf(Streaming(&b"\r\na"[..])), - Ok((Streaming(&b"a"[..]), &b"\r\n"[..])) - ); - assert_parse!( - crlf(Streaming(&b"\r"[..])), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_parse!( - crlf(Streaming(&b"\ra"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"\ra"[..]), - ErrorKind::CrLf - ))) - ); - - assert_parse!(crlf(Streaming("\r\na")), Ok((Streaming("a"), "\r\n"))); - assert_parse!( - crlf(Streaming("\r")), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_parse!( - crlf(Streaming("\ra")), - Err(ErrMode::Backtrack(error_position!( - Streaming("\ra"), - ErrorKind::CrLf - ))) - ); - } - - #[test] - fn end_of_line() { - assert_parse!( - line_ending(Streaming(&b"\na"[..])), - Ok((Streaming(&b"a"[..]), &b"\n"[..])) - ); - assert_parse!( - line_ending(Streaming(&b"\r\na"[..])), - Ok((Streaming(&b"a"[..]), &b"\r\n"[..])) - ); - assert_parse!( - line_ending(Streaming(&b"\r"[..])), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_parse!( - line_ending(Streaming(&b"\ra"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"\ra"[..]), - ErrorKind::CrLf - ))) - ); - - assert_parse!(line_ending(Streaming("\na")), Ok((Streaming("a"), "\n"))); - assert_parse!( - line_ending(Streaming("\r\na")), - Ok((Streaming("a"), "\r\n")) - ); - assert_parse!( - line_ending(Streaming("\r")), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_parse!( - line_ending(Streaming("\ra")), - Err(ErrMode::Backtrack(error_position!( - Streaming("\ra"), - ErrorKind::CrLf - ))) - ); - } - - fn digit_to_i16(input: Streaming<&str>) -> IResult, i16> { - use crate::bytes::one_of; - let i = input; - let (i, opt_sign) = opt(one_of("+-"))(i)?; - let sign = match opt_sign { - Some('+') | None => true, - Some('-') => false, - _ => unreachable!(), - }; + #[test] + fn full_line_windows() { + #[allow(clippy::type_complexity)] + fn take_full_line(i: Streaming<&[u8]>) -> IResult, (&[u8], &[u8])> { + pair(not_line_ending, line_ending)(i) + } + let input = b"abc\r\n"; + let output = take_full_line(Streaming(input)); + assert_eq!( + output, + Ok((Streaming(&b""[..]), (&b"abc"[..], &b"\r\n"[..]))) + ); + } - let (i, s) = match digit1::<_, crate::error::Error<_>, true>(i) { - Ok((i, s)) => (i, s), - Err(ErrMode::Incomplete(i)) => return Err(ErrMode::Incomplete(i)), - Err(_) => return Err(ErrMode::from_error_kind(input, ErrorKind::Digit)), - }; - match s.parse_slice() { - Some(n) => { - if sign { - Ok((i, n)) - } else { - Ok((i, -n)) + #[test] + fn full_line_unix() { + #[allow(clippy::type_complexity)] + fn take_full_line(i: Streaming<&[u8]>) -> IResult, (&[u8], &[u8])> { + pair(not_line_ending, line_ending)(i) } - } - None => Err(ErrMode::from_error_kind(i, ErrorKind::Digit)), + let input = b"abc\n"; + let output = take_full_line(Streaming(input)); + assert_eq!(output, Ok((Streaming(&b""[..]), (&b"abc"[..], &b"\n"[..])))); } - } - fn digit_to_u32(i: Streaming<&str>) -> IResult, u32> { - let (i, s) = digit1(i)?; - match s.parse_slice() { - Some(n) => Ok((i, n)), - None => Err(ErrMode::from_error_kind(i, ErrorKind::Digit)), + #[test] + fn check_windows_lineending() { + let input = b"\r\n"; + let output = line_ending(Streaming(&input[..])); + assert_parse!(output, Ok((Streaming(&b""[..]), &b"\r\n"[..]))); } - } - proptest! { #[test] - fn ints(s in "\\PC*") { - let res1 = digit_to_i16(Streaming(&s)); - let res2 = dec_int(Streaming(s.as_str())); - assert_eq!(res1, res2); + fn check_unix_lineending() { + let input = b"\n"; + let output = line_ending(Streaming(&input[..])); + assert_parse!(output, Ok((Streaming(&b""[..]), &b"\n"[..]))); } #[test] - fn uints(s in "\\PC*") { - let res1 = digit_to_u32(Streaming(&s)); - let res2 = dec_uint(Streaming(s.as_str())); - assert_eq!(res1, res2); + fn cr_lf() { + assert_parse!( + crlf(Streaming(&b"\r\na"[..])), + Ok((Streaming(&b"a"[..]), &b"\r\n"[..])) + ); + assert_parse!( + crlf(Streaming(&b"\r"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_parse!( + crlf(Streaming(&b"\ra"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"\ra"[..]), + ErrorKind::CrLf + ))) + ); + + assert_parse!(crlf(Streaming("\r\na")), Ok((Streaming("a"), "\r\n"))); + assert_parse!( + crlf(Streaming("\r")), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_parse!( + crlf(Streaming("\ra")), + Err(ErrMode::Backtrack(error_position!( + Streaming("\ra"), + ErrorKind::CrLf + ))) + ); } - } - #[test] - fn hex_uint_tests() { - fn hex_u32(input: Streaming<&[u8]>) -> IResult, u32> { - hex_uint(input) + #[test] + fn end_of_line() { + assert_parse!( + line_ending(Streaming(&b"\na"[..])), + Ok((Streaming(&b"a"[..]), &b"\n"[..])) + ); + assert_parse!( + line_ending(Streaming(&b"\r\na"[..])), + Ok((Streaming(&b"a"[..]), &b"\r\n"[..])) + ); + assert_parse!( + line_ending(Streaming(&b"\r"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_parse!( + line_ending(Streaming(&b"\ra"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"\ra"[..]), + ErrorKind::CrLf + ))) + ); + + assert_parse!(line_ending(Streaming("\na")), Ok((Streaming("a"), "\n"))); + assert_parse!( + line_ending(Streaming("\r\na")), + Ok((Streaming("a"), "\r\n")) + ); + assert_parse!( + line_ending(Streaming("\r")), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_parse!( + line_ending(Streaming("\ra")), + Err(ErrMode::Backtrack(error_position!( + Streaming("\ra"), + ErrorKind::CrLf + ))) + ); } - assert_parse!( - hex_u32(Streaming(&b";"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b";"[..]), - ErrorKind::IsA - ))) - ); - assert_parse!( - hex_u32(Streaming(&b"ff;"[..])), - Ok((Streaming(&b";"[..]), 255)) - ); - assert_parse!( - hex_u32(Streaming(&b"1be2;"[..])), - Ok((Streaming(&b";"[..]), 7138)) - ); - assert_parse!( - hex_u32(Streaming(&b"c5a31be2;"[..])), - Ok((Streaming(&b";"[..]), 3_315_801_058)) - ); - assert_parse!( - hex_u32(Streaming(&b"C5A31be2;"[..])), - Ok((Streaming(&b";"[..]), 3_315_801_058)) - ); - assert_parse!( - hex_u32(Streaming(&b"00c5a31be2;"[..])), // overflow - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"00c5a31be2;"[..]), - ErrorKind::IsA - ))) - ); - assert_parse!( - hex_u32(Streaming(&b"c5a31be201;"[..])), // overflow - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"c5a31be201;"[..]), - ErrorKind::IsA - ))) - ); - assert_parse!( - hex_u32(Streaming(&b"ffffffff;"[..])), - Ok((Streaming(&b";"[..]), 4_294_967_295)) - ); - assert_parse!( - hex_u32(Streaming(&b"ffffffffffffffff;"[..])), // overflow - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"ffffffffffffffff;"[..]), - ErrorKind::IsA - ))) - ); - assert_parse!( - hex_u32(Streaming(&b"ffffffffffffffff"[..])), // overflow - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"ffffffffffffffff"[..]), - ErrorKind::IsA - ))) - ); - assert_parse!( - hex_u32(Streaming(&b"0x1be2;"[..])), - Ok((Streaming(&b"x1be2;"[..]), 0)) - ); - assert_parse!( - hex_u32(Streaming(&b"12af"[..])), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - } + fn digit_to_i16(input: Streaming<&str>) -> IResult, i16> { + use crate::bytes::one_of; + + let i = input; + let (i, opt_sign) = opt(one_of("+-"))(i)?; + let sign = match opt_sign { + Some('+') | None => true, + Some('-') => false, + _ => unreachable!(), + }; + + let (i, s) = match digit1::<_, crate::error::Error<_>, true>(i) { + Ok((i, s)) => (i, s), + Err(ErrMode::Incomplete(i)) => return Err(ErrMode::Incomplete(i)), + Err(_) => return Err(ErrMode::from_error_kind(input, ErrorKind::Digit)), + }; + match s.parse_slice() { + Some(n) => { + if sign { + Ok((i, n)) + } else { + Ok((i, -n)) + } + } + None => Err(ErrMode::from_error_kind(i, ErrorKind::Digit)), + } + } + + fn digit_to_u32(i: Streaming<&str>) -> IResult, u32> { + let (i, s) = digit1(i)?; + match s.parse_slice() { + Some(n) => Ok((i, n)), + None => Err(ErrMode::from_error_kind(i, ErrorKind::Digit)), + } + } + + proptest! { + #[test] + fn ints(s in "\\PC*") { + let res1 = digit_to_i16(Streaming(&s)); + let res2 = dec_int(Streaming(s.as_str())); + assert_eq!(res1, res2); + } + + #[test] + fn uints(s in "\\PC*") { + let res1 = digit_to_u32(Streaming(&s)); + let res2 = dec_uint(Streaming(s.as_str())); + assert_eq!(res1, res2); + } + } + + #[test] + fn hex_uint_tests() { + fn hex_u32(input: Streaming<&[u8]>) -> IResult, u32> { + hex_uint(input) + } + + assert_parse!( + hex_u32(Streaming(&b";"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b";"[..]), + ErrorKind::IsA + ))) + ); + assert_parse!( + hex_u32(Streaming(&b"ff;"[..])), + Ok((Streaming(&b";"[..]), 255)) + ); + assert_parse!( + hex_u32(Streaming(&b"1be2;"[..])), + Ok((Streaming(&b";"[..]), 7138)) + ); + assert_parse!( + hex_u32(Streaming(&b"c5a31be2;"[..])), + Ok((Streaming(&b";"[..]), 3_315_801_058)) + ); + assert_parse!( + hex_u32(Streaming(&b"C5A31be2;"[..])), + Ok((Streaming(&b";"[..]), 3_315_801_058)) + ); + assert_parse!( + hex_u32(Streaming(&b"00c5a31be2;"[..])), // overflow + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"00c5a31be2;"[..]), + ErrorKind::IsA + ))) + ); + assert_parse!( + hex_u32(Streaming(&b"c5a31be201;"[..])), // overflow + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"c5a31be201;"[..]), + ErrorKind::IsA + ))) + ); + assert_parse!( + hex_u32(Streaming(&b"ffffffff;"[..])), + Ok((Streaming(&b";"[..]), 4_294_967_295)) + ); + assert_parse!( + hex_u32(Streaming(&b"ffffffffffffffff;"[..])), // overflow + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"ffffffffffffffff;"[..]), + ErrorKind::IsA + ))) + ); + assert_parse!( + hex_u32(Streaming(&b"ffffffffffffffff"[..])), // overflow + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"ffffffffffffffff"[..]), + ErrorKind::IsA + ))) + ); + assert_parse!( + hex_u32(Streaming(&b"0x1be2;"[..])), + Ok((Streaming(&b"x1be2;"[..]), 0)) + ); + assert_parse!( + hex_u32(Streaming(&b"12af"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + } } diff --git a/src/combinator/mod.rs b/src/combinator/mod.rs index ec526e7f..e784f602 100644 --- a/src/combinator/mod.rs +++ b/src/combinator/mod.rs @@ -181,9 +181,9 @@ mod tests; #[inline] pub fn rest>(input: I) -> IResult::Slice, E> where - I: Input, + I: Input, { - Ok(input.next_slice(input.input_len())) + Ok(input.next_slice(input.input_len())) } /// Return the length of the remaining input. @@ -198,28 +198,28 @@ where #[inline] pub fn rest_len>(input: I) -> IResult where - I: Input, + I: Input, { - let len = input.input_len(); - Ok((input, len)) + let len = input.input_len(); + Ok((input, len)) } /// Implementation of [`Parser::by_ref`][Parser::by_ref] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct ByRef<'p, P> { - p: &'p mut P, + p: &'p mut P, } impl<'p, P> ByRef<'p, P> { - pub(crate) fn new(p: &'p mut P) -> Self { - Self { p } - } + pub(crate) fn new(p: &'p mut P) -> Self { + Self { p } + } } impl<'p, I, O, E, P: Parser> Parser for ByRef<'p, P> { - fn parse_next(&mut self, i: I) -> IResult { - self.p.parse_next(i) - } + fn parse_next(&mut self, i: I) -> IResult { + self.p.parse_next(i) + } } /// Maps a function on the result of a parser. @@ -244,40 +244,40 @@ impl<'p, I, O, E, P: Parser> Parser for ByRef<'p, P> { #[deprecated(since = "0.1.0", note = "Replaced with `Parser::map")] pub fn map(mut parser: F, mut f: G) -> impl FnMut(I) -> IResult where - F: Parser, - G: FnMut(O1) -> O2, + F: Parser, + G: FnMut(O1) -> O2, { - move |input: I| { - let (input, o1) = parser.parse_next(input)?; - Ok((input, f(o1))) - } + move |input: I| { + let (input, o1) = parser.parse_next(input)?; + Ok((input, f(o1))) + } } /// Implementation of [`Parser::map`] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct Map { - f: F, - g: G, - phantom: core::marker::PhantomData, + f: F, + g: G, + phantom: core::marker::PhantomData, } impl Map { - pub(crate) fn new(f: F, g: G) -> Self { - Self { - f, - g, - phantom: Default::default(), + pub(crate) fn new(f: F, g: G) -> Self { + Self { + f, + g, + phantom: Default::default(), + } } - } } impl, G: Fn(O1) -> O2> Parser for Map { - fn parse_next(&mut self, i: I) -> IResult { - match self.f.parse_next(i) { - Err(e) => Err(e), - Ok((i, o)) => Ok((i, (self.g)(o))), + fn parse_next(&mut self, i: I) -> IResult { + match self.f.parse_next(i) { + Err(e) => Err(e), + Ok((i, o)) => Ok((i, (self.g)(o))), + } } - } } /// Applies a function returning a `Result` over the result of a parser. @@ -304,56 +304,56 @@ impl, G: Fn(O1) -> O2> Parser for Ma /// ``` #[deprecated(since = "0.1.0", note = "Replaced with `Parser::map_res")] pub fn map_res, E2, F, G>( - mut parser: F, - mut f: G, + mut parser: F, + mut f: G, ) -> impl FnMut(I) -> IResult where - F: Parser, - G: FnMut(O1) -> Result, + F: Parser, + G: FnMut(O1) -> Result, { - move |input: I| { - let i = input.clone(); - let (input, o1) = parser.parse_next(input)?; - match f(o1) { - Ok(o2) => Ok((input, o2)), - Err(e) => Err(ErrMode::from_external_error(i, ErrorKind::MapRes, e)), + move |input: I| { + let i = input.clone(); + let (input, o1) = parser.parse_next(input)?; + match f(o1) { + Ok(o2) => Ok((input, o2)), + Err(e) => Err(ErrMode::from_external_error(i, ErrorKind::MapRes, e)), + } } - } } /// Implementation of [`Parser::map_res`] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct MapRes { - f: F, - g: G, - phantom: core::marker::PhantomData, + f: F, + g: G, + phantom: core::marker::PhantomData, } impl MapRes { - pub(crate) fn new(f: F, g: G) -> Self { - Self { - f, - g, - phantom: Default::default(), + pub(crate) fn new(f: F, g: G) -> Self { + Self { + f, + g, + phantom: Default::default(), + } } - } } impl Parser for MapRes where - I: Clone, - F: Parser, - G: FnMut(O1) -> Result, - E: FromExternalError, + I: Clone, + F: Parser, + G: FnMut(O1) -> Result, + E: FromExternalError, { - fn parse_next(&mut self, input: I) -> IResult { - let i = input.clone(); - let (input, o1) = self.f.parse_next(input)?; - match (self.g)(o1) { - Ok(o2) => Ok((input, o2)), - Err(e) => Err(ErrMode::from_external_error(i, ErrorKind::MapRes, e)), + fn parse_next(&mut self, input: I) -> IResult { + let i = input.clone(); + let (input, o1) = self.f.parse_next(input)?; + match (self.g)(o1) { + Ok(o2) => Ok((input, o2)), + Err(e) => Err(ErrMode::from_external_error(i, ErrorKind::MapRes, e)), + } } - } } /// Applies a function returning an `Option` over the result of a parser. @@ -380,56 +380,56 @@ where /// ``` #[deprecated(since = "0.1.0", note = "Replaced with `Parser::map_res")] pub fn map_opt, F, G>( - mut parser: F, - mut f: G, + mut parser: F, + mut f: G, ) -> impl FnMut(I) -> IResult where - F: Parser, - G: FnMut(O1) -> Option, + F: Parser, + G: FnMut(O1) -> Option, { - move |input: I| { - let i = input.clone(); - let (input, o1) = parser.parse_next(input)?; - match f(o1) { - Some(o2) => Ok((input, o2)), - None => Err(ErrMode::from_error_kind(i, ErrorKind::MapOpt)), + move |input: I| { + let i = input.clone(); + let (input, o1) = parser.parse_next(input)?; + match f(o1) { + Some(o2) => Ok((input, o2)), + None => Err(ErrMode::from_error_kind(i, ErrorKind::MapOpt)), + } } - } } /// Implementation of [`Parser::map_opt`] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct MapOpt { - f: F, - g: G, - phantom: core::marker::PhantomData, + f: F, + g: G, + phantom: core::marker::PhantomData, } impl MapOpt { - pub(crate) fn new(f: F, g: G) -> Self { - Self { - f, - g, - phantom: Default::default(), + pub(crate) fn new(f: F, g: G) -> Self { + Self { + f, + g, + phantom: Default::default(), + } } - } } impl Parser for MapOpt where - I: Clone, - F: Parser, - G: FnMut(O1) -> Option, - E: ParseError, + I: Clone, + F: Parser, + G: FnMut(O1) -> Option, + E: ParseError, { - fn parse_next(&mut self, input: I) -> IResult { - let i = input.clone(); - let (input, o1) = self.f.parse_next(input)?; - match (self.g)(o1) { - Some(o2) => Ok((input, o2)), - None => Err(ErrMode::from_error_kind(i, ErrorKind::MapOpt)), + fn parse_next(&mut self, input: I) -> IResult { + let i = input.clone(); + let (input, o1) = self.f.parse_next(input)?; + match (self.g)(o1) { + Some(o2) => Ok((input, o2)), + None => Err(ErrMode::from_error_kind(i, ErrorKind::MapOpt)), + } } - } } /// Applies a parser over the result of another one. @@ -452,82 +452,82 @@ where /// ``` #[deprecated(since = "0.1.0", note = "Replaced with `Parser::and_then")] pub fn map_parser, F, G>( - mut parser: F, - mut applied_parser: G, + mut parser: F, + mut applied_parser: G, ) -> impl FnMut(I) -> IResult where - F: Parser, - G: Parser, + F: Parser, + G: Parser, { - move |input: I| { - let (input, o1) = parser.parse_next(input)?; - let (_, o2) = applied_parser.parse_next(o1)?; - Ok((input, o2)) - } + move |input: I| { + let (input, o1) = parser.parse_next(input)?; + let (_, o2) = applied_parser.parse_next(o1)?; + Ok((input, o2)) + } } /// Implementation of [`Parser::and_then`] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct AndThen { - f: F, - g: G, - phantom: core::marker::PhantomData, + f: F, + g: G, + phantom: core::marker::PhantomData, } impl AndThen { - pub(crate) fn new(f: F, g: G) -> Self { - Self { - f, - g, - phantom: Default::default(), + pub(crate) fn new(f: F, g: G) -> Self { + Self { + f, + g, + phantom: Default::default(), + } } - } } impl, G: Parser> Parser - for AndThen + for AndThen { - fn parse_next(&mut self, i: I) -> IResult { - let (i, o1) = self.f.parse_next(i)?; - let (_, o2) = self.g.parse_next(o1)?; - Ok((i, o2)) - } + fn parse_next(&mut self, i: I) -> IResult { + let (i, o1) = self.f.parse_next(i)?; + let (_, o2) = self.g.parse_next(o1)?; + Ok((i, o2)) + } } /// Implementation of [`Parser::parse_to`] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct ParseTo { - p: P, - o1: core::marker::PhantomData, - o2: core::marker::PhantomData, + p: P, + o1: core::marker::PhantomData, + o2: core::marker::PhantomData, } impl ParseTo { - pub(crate) fn new(p: P) -> Self { - Self { - p, - o1: Default::default(), - o2: Default::default(), + pub(crate) fn new(p: P) -> Self { + Self { + p, + o1: Default::default(), + o2: Default::default(), + } } - } } impl Parser for ParseTo where - I: Input, - O1: crate::input::ParseSlice, - E: ParseError, - P: Parser, + I: Input, + O1: crate::input::ParseSlice, + E: ParseError, + P: Parser, { - fn parse_next(&mut self, i: I) -> IResult { - let input = i.clone(); - let (i, o) = self.p.parse_next(i)?; - - let o = o - .parse_slice() - .ok_or_else(|| ErrMode::from_error_kind(input, ErrorKind::Verify))?; - Ok((i, o)) - } + fn parse_next(&mut self, i: I) -> IResult { + let input = i.clone(); + let (i, o) = self.p.parse_next(i)?; + + let o = o + .parse_slice() + .ok_or_else(|| ErrMode::from_error_kind(input, ErrorKind::Verify))?; + Ok((i, o)) + } } /// Creates a new parser from the output of the first parser, then apply that parser over the rest of the input. /// @@ -548,45 +548,45 @@ where /// ``` #[deprecated(since = "0.1.0", note = "Replaced with `Parser::flat_map")] pub fn flat_map, F, G, H>( - mut parser: F, - mut applied_parser: G, + mut parser: F, + mut applied_parser: G, ) -> impl FnMut(I) -> IResult where - F: Parser, - G: FnMut(O1) -> H, - H: Parser, + F: Parser, + G: FnMut(O1) -> H, + H: Parser, { - move |input: I| { - let (input, o1) = parser.parse_next(input)?; - applied_parser(o1).parse_next(input) - } + move |input: I| { + let (input, o1) = parser.parse_next(input)?; + applied_parser(o1).parse_next(input) + } } /// Implementation of [`Parser::flat_map`] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct FlatMap { - f: F, - g: G, - phantom: core::marker::PhantomData, + f: F, + g: G, + phantom: core::marker::PhantomData, } impl FlatMap { - pub(crate) fn new(f: F, g: G) -> Self { - Self { - f, - g, - phantom: Default::default(), + pub(crate) fn new(f: F, g: G) -> Self { + Self { + f, + g, + phantom: Default::default(), + } } - } } impl, G: Fn(O1) -> H, H: Parser> Parser - for FlatMap + for FlatMap { - fn parse_next(&mut self, i: I) -> IResult { - let (i, o1) = self.f.parse_next(i)?; - (self.g)(o1).parse_next(i) - } + fn parse_next(&mut self, i: I) -> IResult { + let (i, o1) = self.f.parse_next(i)?; + (self.g)(o1).parse_next(i) + } } /// Optional parser, will return `None` on [`ErrMode::Backtrack`]. @@ -609,64 +609,64 @@ impl, G: Fn(O1) -> H, H: Parser> Par /// ``` pub fn opt, F>(mut f: F) -> impl FnMut(I) -> IResult, E> where - F: Parser, + F: Parser, { - move |input: I| { - let i = input.clone(); - match f.parse_next(input) { - Ok((i, o)) => Ok((i, Some(o))), - Err(ErrMode::Backtrack(_)) => Ok((i, None)), - Err(e) => Err(e), + move |input: I| { + let i = input.clone(); + match f.parse_next(input) { + Ok((i, o)) => Ok((i, Some(o))), + Err(ErrMode::Backtrack(_)) => Ok((i, None)), + Err(e) => Err(e), + } } - } } /// Implementation of [`Parser::and`] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct And { - f: F, - g: G, + f: F, + g: G, } impl And { - pub(crate) fn new(f: F, g: G) -> Self { - Self { f, g } - } + pub(crate) fn new(f: F, g: G) -> Self { + Self { f, g } + } } impl, G: Parser> Parser for And { - fn parse_next(&mut self, i: I) -> IResult { - let (i, o1) = self.f.parse_next(i)?; - let (i, o2) = self.g.parse_next(i)?; - Ok((i, (o1, o2))) - } + fn parse_next(&mut self, i: I) -> IResult { + let (i, o1) = self.f.parse_next(i)?; + let (i, o2) = self.g.parse_next(i)?; + Ok((i, (o1, o2))) + } } /// Implementation of [`Parser::or`] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct Or { - f: F, - g: G, + f: F, + g: G, } impl Or { - pub(crate) fn new(f: F, g: G) -> Self { - Self { f, g } - } + pub(crate) fn new(f: F, g: G) -> Self { + Self { f, g } + } } impl, F: Parser, G: Parser> - Parser for Or + Parser for Or { - fn parse_next(&mut self, i: I) -> IResult { - match self.f.parse_next(i.clone()) { - Err(ErrMode::Backtrack(e1)) => match self.g.parse_next(i) { - Err(ErrMode::Backtrack(e2)) => Err(ErrMode::Backtrack(e1.or(e2))), - res => res, - }, - res => res, + fn parse_next(&mut self, i: I) -> IResult { + match self.f.parse_next(i.clone()) { + Err(ErrMode::Backtrack(e1)) => match self.g.parse_next(i) { + Err(ErrMode::Backtrack(e2)) => Err(ErrMode::Backtrack(e1.or(e2))), + res => res, + }, + res => res, + } } - } } /// Calls the parser if the condition is met. @@ -688,22 +688,22 @@ impl, F: Parser, G: Parser< /// # } /// ``` pub fn cond, F>( - b: bool, - mut f: F, + b: bool, + mut f: F, ) -> impl FnMut(I) -> IResult, E> where - F: Parser, + F: Parser, { - move |input: I| { - if b { - match f.parse_next(input) { - Ok((i, o)) => Ok((i, Some(o))), - Err(e) => Err(e), - } - } else { - Ok((input, None)) + move |input: I| { + if b { + match f.parse_next(input) { + Ok((i, o)) => Ok((i, Some(o))), + Err(e) => Err(e), + } + } else { + Ok((input, None)) + } } - } } /// Tries to apply its parser without consuming the input. @@ -722,15 +722,15 @@ where /// ``` pub fn peek, F>(mut f: F) -> impl FnMut(I) -> IResult where - F: Parser, + F: Parser, { - move |input: I| { - let i = input.clone(); - match f.parse_next(input) { - Ok((_, o)) => Ok((i, o)), - Err(e) => Err(e), + move |input: I| { + let i = input.clone(); + match f.parse_next(input) { + Ok((_, o)) => Ok((i, o)), + Err(e) => Err(e), + } } - } } /// returns its input if it is at the end of input data @@ -751,13 +751,13 @@ where /// ``` pub fn eof>(input: I) -> IResult::Slice, E> where - I: Input, + I: Input, { - if input.input_len() == 0 { - Ok(input.next_slice(0)) - } else { - Err(ErrMode::from_error_kind(input, ErrorKind::Eof)) - } + if input.input_len() == 0 { + Ok(input.next_slice(0)) + } else { + Err(ErrMode::from_error_kind(input, ErrorKind::Eof)) + } } /// Transforms Incomplete into `Error`. @@ -779,42 +779,42 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `Parser::complete")] pub fn complete, F>(mut f: F) -> impl FnMut(I) -> IResult where - F: Parser, + F: Parser, { - move |input: I| { - let i = input.clone(); - match f.parse_next(input) { - Err(ErrMode::Incomplete(_)) => Err(ErrMode::from_error_kind(i, ErrorKind::Complete)), - rest => rest, + move |input: I| { + let i = input.clone(); + match f.parse_next(input) { + Err(ErrMode::Incomplete(_)) => Err(ErrMode::from_error_kind(i, ErrorKind::Complete)), + rest => rest, + } } - } } /// Implementation of [`Parser::complete`] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct Complete { - f: F, + f: F, } impl Complete { - pub(crate) fn new(f: F) -> Self { - Self { f } - } + pub(crate) fn new(f: F) -> Self { + Self { f } + } } impl Parser for Complete where - I: Clone, - F: Parser, - E: ParseError, + I: Clone, + F: Parser, + E: ParseError, { - fn parse_next(&mut self, input: I) -> IResult { - let i = input.clone(); - match (self.f).parse_next(input) { - Err(ErrMode::Incomplete(_)) => Err(ErrMode::from_error_kind(i, ErrorKind::Complete)), - rest => rest, + fn parse_next(&mut self, input: I) -> IResult { + let i = input.clone(); + match (self.f).parse_next(input) { + Err(ErrMode::Incomplete(_)) => Err(ErrMode::from_error_kind(i, ErrorKind::Complete)), + rest => rest, + } } - } } /// Succeeds if all the input has been consumed by its child parser. @@ -836,22 +836,22 @@ where /// # } /// ``` #[deprecated( - since = "0.1.0", - note = "Replaced with `eof` or `FinishIResult::finish`" + since = "0.1.0", + note = "Replaced with `eof` or `FinishIResult::finish`" )] pub fn all_consuming, F>(mut f: F) -> impl FnMut(I) -> IResult where - I: Input, - F: Parser, + I: Input, + F: Parser, { - move |input: I| { - let (input, res) = f.parse_next(input)?; - if input.input_len() == 0 { - Ok((input, res)) - } else { - Err(ErrMode::from_error_kind(input, ErrorKind::Eof)) + move |input: I| { + let (input, res) = f.parse_next(input)?; + if input.input_len() == 0 { + Ok((input, res)) + } else { + Err(ErrMode::from_error_kind(input, ErrorKind::Eof)) + } } - } } /// Returns the result of the child parser if it satisfies a verification function. @@ -876,64 +876,64 @@ where /// ``` #[deprecated(since = "0.1.0", note = "Replaced with `Parser::verify")] pub fn verify, F, G>( - mut first: F, - second: G, + mut first: F, + second: G, ) -> impl FnMut(I) -> IResult where - F: Parser, - G: Fn(&O2) -> bool, - O1: Borrow, - O2: ?Sized, + F: Parser, + G: Fn(&O2) -> bool, + O1: Borrow, + O2: ?Sized, { - move |input: I| { - let i = input.clone(); - let (input, o) = first.parse_next(input)?; - - if second(o.borrow()) { - Ok((input, o)) - } else { - Err(ErrMode::from_error_kind(i, ErrorKind::Verify)) + move |input: I| { + let i = input.clone(); + let (input, o) = first.parse_next(input)?; + + if second(o.borrow()) { + Ok((input, o)) + } else { + Err(ErrMode::from_error_kind(i, ErrorKind::Verify)) + } } - } } /// Implementation of [`Parser::verify`] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct Verify { - first: F, - second: G, - phantom: core::marker::PhantomData, + first: F, + second: G, + phantom: core::marker::PhantomData, } impl Verify { - pub(crate) fn new(first: F, second: G) -> Self { - Self { - first, - second, - phantom: Default::default(), + pub(crate) fn new(first: F, second: G) -> Self { + Self { + first, + second, + phantom: Default::default(), + } } - } } impl Parser for Verify where - I: Clone, - E: ParseError, - F: Parser, - G: Fn(&O2) -> bool, - O1: Borrow, - O2: ?Sized, + I: Clone, + E: ParseError, + F: Parser, + G: Fn(&O2) -> bool, + O1: Borrow, + O2: ?Sized, { - fn parse_next(&mut self, input: I) -> IResult { - let i = input.clone(); - let (input, o) = (self.first).parse_next(input)?; - - if (self.second)(o.borrow()) { - Ok((input, o)) - } else { - Err(ErrMode::from_error_kind(i, ErrorKind::Verify)) + fn parse_next(&mut self, input: I) -> IResult { + let i = input.clone(); + let (input, o) = (self.first).parse_next(input)?; + + if (self.second)(o.borrow()) { + Ok((input, o)) + } else { + Err(ErrMode::from_error_kind(i, ErrorKind::Verify)) + } } - } } /// Returns the provided value if the child parser succeeds. @@ -954,63 +954,63 @@ where /// ``` #[deprecated(since = "0.1.0", note = "Replaced with `Parser::value")] pub fn value, F>( - val: O1, - mut parser: F, + val: O1, + mut parser: F, ) -> impl FnMut(I) -> IResult where - F: Parser, + F: Parser, { - move |input: I| parser.parse_next(input).map(|(i, _)| (i, val.clone())) + move |input: I| parser.parse_next(input).map(|(i, _)| (i, val.clone())) } /// Implementation of [`Parser::value`] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct Value { - parser: F, - val: O2, - phantom: core::marker::PhantomData, + parser: F, + val: O2, + phantom: core::marker::PhantomData, } impl Value { - pub(crate) fn new(parser: F, val: O2) -> Self { - Self { - parser, - val, - phantom: Default::default(), + pub(crate) fn new(parser: F, val: O2) -> Self { + Self { + parser, + val, + phantom: Default::default(), + } } - } } impl, F: Parser> Parser - for Value + for Value { - fn parse_next(&mut self, input: I) -> IResult { - (self.parser) - .parse_next(input) - .map(|(i, _)| (i, self.val.clone())) - } + fn parse_next(&mut self, input: I) -> IResult { + (self.parser) + .parse_next(input) + .map(|(i, _)| (i, self.val.clone())) + } } /// Implementation of [`Parser::void`] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct Void { - parser: F, - phantom: core::marker::PhantomData, + parser: F, + phantom: core::marker::PhantomData, } impl Void { - pub(crate) fn new(parser: F) -> Self { - Self { - parser, - phantom: Default::default(), + pub(crate) fn new(parser: F) -> Self { + Self { + parser, + phantom: Default::default(), + } } - } } impl, F: Parser> Parser for Void { - fn parse_next(&mut self, input: I) -> IResult { - (self.parser).parse_next(input).map(|(i, _)| (i, ())) - } + fn parse_next(&mut self, input: I) -> IResult { + (self.parser).parse_next(input).map(|(i, _)| (i, ())) + } } /// Succeeds if the child parser returns an error. @@ -1029,16 +1029,16 @@ impl, F: Parser> Parser for Void /// ``` pub fn not, F>(mut parser: F) -> impl FnMut(I) -> IResult where - F: Parser, + F: Parser, { - move |input: I| { - let i = input.clone(); - match parser.parse_next(input) { - Ok(_) => Err(ErrMode::from_error_kind(i, ErrorKind::Not)), - Err(ErrMode::Backtrack(_)) => Ok((i, ())), - Err(e) => Err(e), + move |input: I| { + let i = input.clone(); + match parser.parse_next(input) { + Ok(_) => Err(ErrMode::from_error_kind(i, ErrorKind::Not)), + Err(ErrMode::Backtrack(_)) => Ok((i, ())), + Err(e) => Err(e), + } } - } } /// If the child parser was successful, return the consumed input as produced value. @@ -1060,56 +1060,56 @@ where /// ``` #[deprecated(since = "0.1.0", note = "Replaced with `Parser::recognize")] pub fn recognize, F>( - mut parser: F, + mut parser: F, ) -> impl FnMut(I) -> IResult::Slice, E> where - I: Input + Offset, - F: Parser, + I: Input + Offset, + F: Parser, { - move |input: I| { - let i = input.clone(); - match parser.parse_next(i) { - Ok((i, _)) => { - let offset = input.offset_to(&i); - Ok(input.next_slice(offset)) - } - Err(e) => Err(e), + move |input: I| { + let i = input.clone(); + match parser.parse_next(i) { + Ok((i, _)) => { + let offset = input.offset_to(&i); + Ok(input.next_slice(offset)) + } + Err(e) => Err(e), + } } - } } /// Implementation of [`Parser::recognize`] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct Recognize { - parser: F, - o: core::marker::PhantomData, + parser: F, + o: core::marker::PhantomData, } impl Recognize { - pub(crate) fn new(parser: F) -> Self { - Self { - parser, - o: Default::default(), + pub(crate) fn new(parser: F) -> Self { + Self { + parser, + o: Default::default(), + } } - } } impl Parser::Slice, E> for Recognize where - I: Input + Offset, - E: ParseError, - F: Parser, + I: Input + Offset, + E: ParseError, + F: Parser, { - fn parse_next(&mut self, input: I) -> IResult::Slice, E> { - let i = input.clone(); - match (self.parser).parse_next(i) { - Ok((i, _)) => { - let offset = input.offset_to(&i); - Ok(input.next_slice(offset)) - } - Err(e) => Err(e), + fn parse_next(&mut self, input: I) -> IResult::Slice, E> { + let i = input.clone(); + match (self.parser).parse_next(i) { + Ok((i, _)) => { + let offset = input.offset_to(&i); + Ok(input.next_slice(offset)) + } + Err(e) => Err(e), + } } - } } /// if the child parser was successful, return the consumed input with the output @@ -1153,128 +1153,127 @@ where /// # } /// ``` #[deprecated( - since = "0.1.0", - note = "Replaced with `Parser::with_recognized (output ordering is changed)" + since = "0.1.0", + note = "Replaced with `Parser::with_recognized (output ordering is changed)" )] pub fn consumed( - mut parser: F, + mut parser: F, ) -> impl FnMut(I) -> IResult::Slice, O), E> where - I: Input + Offset, - E: ParseError, - F: Parser, + I: Input + Offset, + E: ParseError, + F: Parser, { - move |input: I| { - let i = input.clone(); - match parser.parse_next(i) { - Ok((remaining, result)) => { - let offset = input.offset_to(&remaining); - let (remaining, recognized) = input.next_slice(offset); - Ok((remaining, (recognized, result))) - } - Err(e) => Err(e), + move |input: I| { + let i = input.clone(); + match parser.parse_next(i) { + Ok((remaining, result)) => { + let offset = input.offset_to(&remaining); + let (remaining, recognized) = input.next_slice(offset); + Ok((remaining, (recognized, result))) + } + Err(e) => Err(e), + } } - } } /// Implementation of [`Parser::with_recognized`] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct WithRecognized { - parser: F, - o: core::marker::PhantomData, + parser: F, + o: core::marker::PhantomData, } impl WithRecognized { - pub(crate) fn new(parser: F) -> Self { - Self { - parser, - o: Default::default(), + pub(crate) fn new(parser: F) -> Self { + Self { + parser, + o: Default::default(), + } } - } } impl Parser::Slice), E> for WithRecognized where - I: Input + Offset, - E: ParseError, - F: Parser, + I: Input + Offset, + E: ParseError, + F: Parser, { - fn parse_next(&mut self, input: I) -> IResult::Slice), E> { - let i = input.clone(); - match (self.parser).parse_next(i) { - Ok((remaining, result)) => { - let offset = input.offset_to(&remaining); - let (remaining, recognized) = input.next_slice(offset); - Ok((remaining, (result, recognized))) - } - Err(e) => Err(e), + fn parse_next(&mut self, input: I) -> IResult::Slice), E> { + let i = input.clone(); + match (self.parser).parse_next(i) { + Ok((remaining, result)) => { + let offset = input.offset_to(&remaining); + let (remaining, recognized) = input.next_slice(offset); + Ok((remaining, (result, recognized))) + } + Err(e) => Err(e), + } } - } } /// Implementation of [`Parser::span`] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct Span { - parser: F, - o: core::marker::PhantomData, + parser: F, + o: core::marker::PhantomData, } impl Span { - pub(crate) fn new(parser: F) -> Self { - Self { - parser, - o: Default::default(), + pub(crate) fn new(parser: F) -> Self { + Self { + parser, + o: Default::default(), + } } - } } impl Parser, E> for Span where - I: Clone + Location, - E: ParseError, - F: Parser, + I: Clone + Location, + E: ParseError, + F: Parser, { - fn parse_next(&mut self, input: I) -> IResult, E> { - let start = input.location(); - self.parser.parse_next(input).map(move |(remaining, _)| { - let end = remaining.location(); - (remaining, (start..end)) - }) - } + fn parse_next(&mut self, input: I) -> IResult, E> { + let start = input.location(); + self.parser.parse_next(input).map(move |(remaining, _)| { + let end = remaining.location(); + (remaining, (start..end)) + }) + } } /// Implementation of [`Parser::with_span`] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct WithSpan { - parser: F, - o: core::marker::PhantomData, + parser: F, + o: core::marker::PhantomData, } impl WithSpan { - pub(crate) fn new(parser: F) -> Self { - Self { - parser, - o: Default::default(), + pub(crate) fn new(parser: F) -> Self { + Self { + parser, + o: Default::default(), + } } - } } impl Parser), E> for WithSpan where - I: Clone + Location, - E: ParseError, - F: Parser, + I: Clone + Location, + E: ParseError, + F: Parser, { - fn parse_next(&mut self, input: I) -> IResult), E> { - let start = input.location(); - self - .parser - .parse_next(input) - .map(move |(remaining, output)| { - let end = remaining.location(); - (remaining, (output, (start..end))) - }) - } + fn parse_next(&mut self, input: I) -> IResult), E> { + let start = input.location(); + self.parser + .parse_next(input) + .map(move |(remaining, output)| { + let end = remaining.location(); + (remaining, (output, (start..end))) + }) + } } /// Transforms an [`ErrMode::Backtrack`] (recoverable) to [`ErrMode::Cut`] (unrecoverable) @@ -1332,18 +1331,18 @@ where /// ``` pub fn cut_err, F>(mut parser: F) -> impl FnMut(I) -> IResult where - F: Parser, + F: Parser, { - move |input: I| parser.parse_next(input).map_err(|e| e.cut()) + move |input: I| parser.parse_next(input).map_err(|e| e.cut()) } /// Deprecated, see [`cut_err`] #[deprecated(since = "0.3.0", note = "Replaced with `cut_err`")] pub fn cut, F>(parser: F) -> impl FnMut(I) -> IResult where - F: Parser, + F: Parser, { - cut_err(parser) + cut_err(parser) } /// Transforms an [`ErrMode::Cut`] (unrecoverable) to [`ErrMode::Backtrack`] (recoverable) @@ -1352,9 +1351,9 @@ where /// [`winnow::branch::alt`][crate::branch::alt]. pub fn backtrack_err, F>(mut parser: F) -> impl FnMut(I) -> IResult where - F: Parser, + F: Parser, { - move |input: I| parser.parse_next(input).map_err(|e| e.backtrack()) + move |input: I| parser.parse_next(input).map_err(|e| e.backtrack()) } /// A placeholder for a not-yet-implemented [`Parser`] @@ -1377,8 +1376,8 @@ where /// ``` #[track_caller] pub fn todo(_input: I) -> IResult { - #![allow(clippy::todo)] - todo!("unimplemented parse") + #![allow(clippy::todo)] + todo!("unimplemented parse") } /// automatically converts the child parser's result to another type @@ -1406,99 +1405,99 @@ pub fn todo(_input: I) -> IResult { /// # } /// ``` #[deprecated( - since = "0.1.0", - note = "Replaced with `Parser::output_into` and `Parser::err_into`" + since = "0.1.0", + note = "Replaced with `Parser::output_into` and `Parser::err_into`" )] pub fn into(mut parser: F) -> impl FnMut(I) -> IResult where - O1: convert::Into, - E1: convert::Into, - E1: ParseError, - E2: ParseError, - F: Parser, + O1: convert::Into, + E1: convert::Into, + E1: ParseError, + E2: ParseError, + F: Parser, { - //map(parser, Into::into) - move |input: I| match parser.parse_next(input) { - Ok((i, o)) => Ok((i, o.into())), - Err(ErrMode::Backtrack(e)) => Err(ErrMode::Backtrack(e.into())), - Err(ErrMode::Cut(e)) => Err(ErrMode::Cut(e.into())), - Err(ErrMode::Incomplete(e)) => Err(ErrMode::Incomplete(e)), - } + //map(parser, Into::into) + move |input: I| match parser.parse_next(input) { + Ok((i, o)) => Ok((i, o.into())), + Err(ErrMode::Backtrack(e)) => Err(ErrMode::Backtrack(e.into())), + Err(ErrMode::Cut(e)) => Err(ErrMode::Cut(e.into())), + Err(ErrMode::Incomplete(e)) => Err(ErrMode::Incomplete(e)), + } } /// Implementation of [`Parser::output_into`] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct OutputInto where - O1: Into, + O1: Into, { - f: F, - phantom_out1: core::marker::PhantomData, - phantom_out2: core::marker::PhantomData, + f: F, + phantom_out1: core::marker::PhantomData, + phantom_out2: core::marker::PhantomData, } impl OutputInto where - O1: Into, + O1: Into, { - pub(crate) fn new(f: F) -> Self { - Self { - f, - phantom_out1: Default::default(), - phantom_out2: Default::default(), + pub(crate) fn new(f: F) -> Self { + Self { + f, + phantom_out1: Default::default(), + phantom_out2: Default::default(), + } } - } } impl> Parser for OutputInto where - O1: Into, + O1: Into, { - fn parse_next(&mut self, i: I) -> IResult { - match self.f.parse_next(i) { - Ok((i, o)) => Ok((i, o.into())), - Err(err) => Err(err), + fn parse_next(&mut self, i: I) -> IResult { + match self.f.parse_next(i) { + Ok((i, o)) => Ok((i, o.into())), + Err(err) => Err(err), + } } - } } /// Implementation of [`Parser::err_into`] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct ErrInto where - E1: Into, + E1: Into, { - f: F, - phantom_err1: core::marker::PhantomData, - phantom_err2: core::marker::PhantomData, + f: F, + phantom_err1: core::marker::PhantomData, + phantom_err2: core::marker::PhantomData, } impl ErrInto where - E1: Into, + E1: Into, { - pub(crate) fn new(f: F) -> Self { - Self { - f, - phantom_err1: Default::default(), - phantom_err2: Default::default(), + pub(crate) fn new(f: F) -> Self { + Self { + f, + phantom_err1: Default::default(), + phantom_err2: Default::default(), + } } - } } impl, F: Parser> Parser - for ErrInto + for ErrInto where - E1: Into, + E1: Into, { - fn parse_next(&mut self, i: I) -> IResult { - match self.f.parse_next(i) { - Ok(ok) => Ok(ok), - Err(ErrMode::Backtrack(e)) => Err(ErrMode::Backtrack(e.into())), - Err(ErrMode::Cut(e)) => Err(ErrMode::Cut(e.into())), - Err(ErrMode::Incomplete(e)) => Err(ErrMode::Incomplete(e)), + fn parse_next(&mut self, i: I) -> IResult { + match self.f.parse_next(i) { + Ok(ok) => Ok(ok), + Err(ErrMode::Backtrack(e)) => Err(ErrMode::Backtrack(e.into())), + Err(ErrMode::Cut(e)) => Err(ErrMode::Cut(e.into())), + Err(ErrMode::Incomplete(e)) => Err(ErrMode::Incomplete(e)), + } } - } } /// Creates an iterator from input data and a parser. @@ -1523,77 +1522,77 @@ where /// ``` pub fn iterator(input: I, f: F) -> ParserIterator where - F: Parser, - Error: ParseError, + F: Parser, + Error: ParseError, { - ParserIterator { - iterator: f, - input, - output: Default::default(), - state: Some(State::Running), - } + ParserIterator { + iterator: f, + input, + output: Default::default(), + state: Some(State::Running), + } } /// Main structure associated to the [iterator] function. pub struct ParserIterator { - iterator: F, - input: I, - output: core::marker::PhantomData, - state: Option>, + iterator: F, + input: I, + output: core::marker::PhantomData, + state: Option>, } impl ParserIterator { - /// Returns the remaining input if parsing was successful, or the error if we encountered an error. - pub fn finish(mut self) -> IResult { - match self.state.take().unwrap() { - State::Running | State::Done => Ok((self.input, ())), - State::Failure(e) => Err(ErrMode::Cut(e)), - State::Incomplete(i) => Err(ErrMode::Incomplete(i)), + /// Returns the remaining input if parsing was successful, or the error if we encountered an error. + pub fn finish(mut self) -> IResult { + match self.state.take().unwrap() { + State::Running | State::Done => Ok((self.input, ())), + State::Failure(e) => Err(ErrMode::Cut(e)), + State::Incomplete(i) => Err(ErrMode::Incomplete(i)), + } } - } } impl<'a, I, O, E, F> core::iter::Iterator for &'a mut ParserIterator where - F: Parser, - I: Clone, + F: Parser, + I: Clone, { - type Item = O; - - fn next(&mut self) -> Option { - if let State::Running = self.state.take().unwrap() { - let input = self.input.clone(); - - match self.iterator.parse_next(input) { - Ok((i, o)) => { - self.input = i; - self.state = Some(State::Running); - Some(o) - } - Err(ErrMode::Backtrack(_)) => { - self.state = Some(State::Done); - None - } - Err(ErrMode::Cut(e)) => { - self.state = Some(State::Failure(e)); - None + type Item = O; + + fn next(&mut self) -> Option { + if let State::Running = self.state.take().unwrap() { + let input = self.input.clone(); + + match self.iterator.parse_next(input) { + Ok((i, o)) => { + self.input = i; + self.state = Some(State::Running); + Some(o) + } + Err(ErrMode::Backtrack(_)) => { + self.state = Some(State::Done); + None + } + Err(ErrMode::Cut(e)) => { + self.state = Some(State::Failure(e)); + None + } + Err(ErrMode::Incomplete(i)) => { + self.state = Some(State::Incomplete(i)); + None + } + } + } else { + None } - Err(ErrMode::Incomplete(i)) => { - self.state = Some(State::Incomplete(i)); - None - } - } - } else { - None } - } } enum State { - Running, - Done, - Failure(E), - Incomplete(Needed), + Running, + Done, + Failure(E), + Incomplete(Needed), } /// a parser which always succeeds with given value without consuming any input. @@ -1617,7 +1616,7 @@ enum State { /// # } /// ``` pub fn success>(val: O) -> impl Fn(I) -> IResult { - move |input: I| Ok((input, val.clone())) + move |input: I| Ok((input, val.clone())) } /// A parser which always fails. @@ -1630,80 +1629,80 @@ pub fn success>(val: O) -> impl Fn(I) -> IResult(s), Err(ErrMode::Backtrack(Error::new(s, ErrorKind::Fail)))); /// ``` pub fn fail>(i: I) -> IResult { - Err(ErrMode::from_error_kind(i, ErrorKind::Fail)) + Err(ErrMode::from_error_kind(i, ErrorKind::Fail)) } /// Implementation of [`Parser::context`] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub struct Context { - f: F, - context: C, - phantom: core::marker::PhantomData, + f: F, + context: C, + phantom: core::marker::PhantomData, } impl Context { - pub(crate) fn new(f: F, context: C) -> Self { - Self { - f, - context, - phantom: Default::default(), + pub(crate) fn new(f: F, context: C) -> Self { + Self { + f, + context, + phantom: Default::default(), + } } - } } impl Parser for Context where - I: Clone, - C: Clone, - E: ContextError, - F: Parser, + I: Clone, + C: Clone, + E: ContextError, + F: Parser, { - fn parse_next(&mut self, i: I) -> IResult { - (self.f) - .parse_next(i.clone()) - .map_err(|err| err.map(|err| err.add_context(i, self.context.clone()))) - } + fn parse_next(&mut self, i: I) -> IResult { + (self.f) + .parse_next(i.clone()) + .map_err(|err| err.map(|err| err.add_context(i, self.context.clone()))) + } } /// Implementation of [`Parser::dbg_err`] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] #[cfg(feature = "std")] pub struct DbgErr { - f: F, - context: C, - phantom: core::marker::PhantomData, + f: F, + context: C, + phantom: core::marker::PhantomData, } #[cfg(feature = "std")] impl DbgErr { - pub(crate) fn new(f: F, context: C) -> Self { - Self { - f, - context, - phantom: Default::default(), + pub(crate) fn new(f: F, context: C) -> Self { + Self { + f, + context, + phantom: Default::default(), + } } - } } #[cfg(feature = "std")] impl Parser for DbgErr where - I: crate::input::AsBytes, - I: Clone, - E: std::fmt::Debug, - F: Parser, - C: std::fmt::Display, + I: crate::input::AsBytes, + I: Clone, + E: std::fmt::Debug, + F: Parser, + C: std::fmt::Display, { - fn parse_next(&mut self, input: I) -> IResult { - use crate::input::HexDisplay; - let i = input.clone(); - match self.f.parse_next(i) { - Err(e) => { - let input = input.as_bytes(); - eprintln!("{}: Error({:?}) at:\n{}", self.context, e, input.to_hex(8)); - Err(e) - } - a => a, + fn parse_next(&mut self, input: I) -> IResult { + use crate::input::HexDisplay; + let i = input.clone(); + match self.f.parse_next(i) { + Err(e) => { + let input = input.as_bytes(); + eprintln!("{}: Error({:?}) at:\n{}", self.context, e, input.to_hex(8)); + Err(e) + } + a => a, + } } - } } diff --git a/src/combinator/tests.rs b/src/combinator/tests.rs index a88dab58..90b0f017 100644 --- a/src/combinator/tests.rs +++ b/src/combinator/tests.rs @@ -20,424 +20,424 @@ macro_rules! assert_parse( #[test] fn eof_on_slices() { - let not_over: &[u8] = &b"Hello, world!"[..]; - let is_over: &[u8] = &b""[..]; - - let res_not_over = eof(not_over); - assert_parse!( - res_not_over, - Err(ErrMode::Backtrack(error_position!( - not_over, - ErrorKind::Eof - ))) - ); - - let res_over = eof(is_over); - assert_parse!(res_over, Ok((is_over, is_over))); + let not_over: &[u8] = &b"Hello, world!"[..]; + let is_over: &[u8] = &b""[..]; + + let res_not_over = eof(not_over); + assert_parse!( + res_not_over, + Err(ErrMode::Backtrack(error_position!( + not_over, + ErrorKind::Eof + ))) + ); + + let res_over = eof(is_over); + assert_parse!(res_over, Ok((is_over, is_over))); } #[test] fn eof_on_strs() { - let not_over: &str = "Hello, world!"; - let is_over: &str = ""; - - let res_not_over = eof(not_over); - assert_parse!( - res_not_over, - Err(ErrMode::Backtrack(error_position!( - not_over, - ErrorKind::Eof - ))) - ); - - let res_over = eof(is_over); - assert_parse!(res_over, Ok((is_over, is_over))); + let not_over: &str = "Hello, world!"; + let is_over: &str = ""; + + let res_not_over = eof(not_over); + assert_parse!( + res_not_over, + Err(ErrMode::Backtrack(error_position!( + not_over, + ErrorKind::Eof + ))) + ); + + let res_over = eof(is_over); + assert_parse!(res_over, Ok((is_over, is_over))); } #[test] fn rest_on_slices() { - let input: &[u8] = &b"Hello, world!"[..]; - let empty: &[u8] = &b""[..]; - assert_parse!(rest(input), Ok((empty, input))); + let input: &[u8] = &b"Hello, world!"[..]; + let empty: &[u8] = &b""[..]; + assert_parse!(rest(input), Ok((empty, input))); } #[test] fn rest_on_strs() { - let input: &str = "Hello, world!"; - let empty: &str = ""; - assert_parse!(rest(input), Ok((empty, input))); + let input: &str = "Hello, world!"; + let empty: &str = ""; + assert_parse!(rest(input), Ok((empty, input))); } #[test] fn rest_len_on_slices() { - let input: &[u8] = &b"Hello, world!"[..]; - assert_parse!(rest_len(input), Ok((input, input.len()))); + let input: &[u8] = &b"Hello, world!"[..]; + assert_parse!(rest_len(input), Ok((input, input.len()))); } use crate::lib::std::convert::From; impl From for CustomError { - fn from(_: u32) -> Self { - CustomError - } + fn from(_: u32) -> Self { + CustomError + } } impl ParseError for CustomError { - fn from_error_kind(_: I, _: ErrorKind) -> Self { - CustomError - } + fn from_error_kind(_: I, _: ErrorKind) -> Self { + CustomError + } - fn append(self, _: I, _: ErrorKind) -> Self { - CustomError - } + fn append(self, _: I, _: ErrorKind) -> Self { + CustomError + } } struct CustomError; #[allow(dead_code)] fn custom_error(input: &[u8]) -> IResult<&[u8], &[u8], CustomError> { - //fix_error!(input, CustomError<_>, alphanumeric) - crate::character::alphanumeric1(input) + //fix_error!(input, CustomError<_>, alphanumeric) + crate::character::alphanumeric1(input) } #[test] fn test_flat_map() { - #![allow(deprecated)] - let input: &[u8] = &[3, 100, 101, 102, 103, 104][..]; - assert_parse!( - flat_map(u8, take)(input), - Ok((&[103, 104][..], &[100, 101, 102][..])) - ); + #![allow(deprecated)] + let input: &[u8] = &[3, 100, 101, 102, 103, 104][..]; + assert_parse!( + flat_map(u8, take)(input), + Ok((&[103, 104][..], &[100, 101, 102][..])) + ); } #[test] fn test_parser_flat_map() { - let input: &[u8] = &[3, 100, 101, 102, 103, 104][..]; - assert_parse!( - u8.flat_map(take).parse_next(input), - Ok((&[103, 104][..], &[100, 101, 102][..])) - ); + let input: &[u8] = &[3, 100, 101, 102, 103, 104][..]; + assert_parse!( + u8.flat_map(take).parse_next(input), + Ok((&[103, 104][..], &[100, 101, 102][..])) + ); } #[test] fn test_map_opt() { - #![allow(deprecated)] - let input: &[u8] = &[50][..]; - assert_parse!( - map_opt(u8, |u| if u < 20 { Some(u) } else { None })(input), - Err(ErrMode::Backtrack(Error { - input: &[50][..], - kind: ErrorKind::MapOpt - })) - ); - assert_parse!( - map_opt(u8, |u| if u > 20 { Some(u) } else { None })(input), - Ok((&[][..], 50)) - ); + #![allow(deprecated)] + let input: &[u8] = &[50][..]; + assert_parse!( + map_opt(u8, |u| if u < 20 { Some(u) } else { None })(input), + Err(ErrMode::Backtrack(Error { + input: &[50][..], + kind: ErrorKind::MapOpt + })) + ); + assert_parse!( + map_opt(u8, |u| if u > 20 { Some(u) } else { None })(input), + Ok((&[][..], 50)) + ); } #[test] fn test_parser_map_opt() { - let input: &[u8] = &[50][..]; - assert_parse!( - u8.map_opt(|u| if u < 20 { Some(u) } else { None }) - .parse_next(input), - Err(ErrMode::Backtrack(Error { - input: &[50][..], - kind: ErrorKind::MapOpt - })) - ); - assert_parse!( - u8.map_opt(|u| if u > 20 { Some(u) } else { None }) - .parse_next(input), - Ok((&[][..], 50)) - ); + let input: &[u8] = &[50][..]; + assert_parse!( + u8.map_opt(|u| if u < 20 { Some(u) } else { None }) + .parse_next(input), + Err(ErrMode::Backtrack(Error { + input: &[50][..], + kind: ErrorKind::MapOpt + })) + ); + assert_parse!( + u8.map_opt(|u| if u > 20 { Some(u) } else { None }) + .parse_next(input), + Ok((&[][..], 50)) + ); } #[test] fn test_map_parser() { - #![allow(deprecated)] - let input: &[u8] = &[100, 101, 102, 103, 104][..]; - assert_parse!( - map_parser(take(4usize), take(2usize))(input), - Ok((&[104][..], &[100, 101][..])) - ); + #![allow(deprecated)] + let input: &[u8] = &[100, 101, 102, 103, 104][..]; + assert_parse!( + map_parser(take(4usize), take(2usize))(input), + Ok((&[104][..], &[100, 101][..])) + ); } #[test] fn test_parser_map_parser() { - let input: &[u8] = &[100, 101, 102, 103, 104][..]; - assert_parse!( - take(4usize).and_then(take(2usize)).parse_next(input), - Ok((&[104][..], &[100, 101][..])) - ); + let input: &[u8] = &[100, 101, 102, 103, 104][..]; + assert_parse!( + take(4usize).and_then(take(2usize)).parse_next(input), + Ok((&[104][..], &[100, 101][..])) + ); } #[test] fn test_all_consuming() { - #![allow(deprecated)] - let input: &[u8] = &[100, 101, 102][..]; - assert_parse!( - all_consuming(take(2usize))(input), - Err(ErrMode::Backtrack(Error { - input: &[102][..], - kind: ErrorKind::Eof - })) - ); - assert_parse!( - all_consuming(take(3usize))(input), - Ok((&[][..], &[100, 101, 102][..])) - ); + #![allow(deprecated)] + let input: &[u8] = &[100, 101, 102][..]; + assert_parse!( + all_consuming(take(2usize))(input), + Err(ErrMode::Backtrack(Error { + input: &[102][..], + kind: ErrorKind::Eof + })) + ); + assert_parse!( + all_consuming(take(3usize))(input), + Ok((&[][..], &[100, 101, 102][..])) + ); } #[test] #[allow(unused)] fn test_verify_ref() { - #![allow(deprecated)] - use crate::bytes::take; - - let mut parser1 = verify(take(3u8), |s: &[u8]| s == &b"abc"[..]); - - assert_eq!(parser1(&b"abcd"[..]), Ok((&b"d"[..], &b"abc"[..]))); - assert_eq!( - parser1(&b"defg"[..]), - Err(ErrMode::Backtrack(Error { - input: &b"defg"[..], - kind: ErrorKind::Verify - })) - ); - - fn parser2(i: &[u8]) -> IResult<&[u8], u32> { - verify(crate::number::be_u32, |val: &u32| *val < 3)(i) - } + #![allow(deprecated)] + use crate::bytes::take; + + let mut parser1 = verify(take(3u8), |s: &[u8]| s == &b"abc"[..]); + + assert_eq!(parser1(&b"abcd"[..]), Ok((&b"d"[..], &b"abc"[..]))); + assert_eq!( + parser1(&b"defg"[..]), + Err(ErrMode::Backtrack(Error { + input: &b"defg"[..], + kind: ErrorKind::Verify + })) + ); + + fn parser2(i: &[u8]) -> IResult<&[u8], u32> { + verify(crate::number::be_u32, |val: &u32| *val < 3)(i) + } } #[test] #[cfg(feature = "alloc")] fn test_verify_alloc() { - #![allow(deprecated)] - use crate::bytes::take; - let mut parser1 = verify(take(3u8).map(|s: &[u8]| s.to_vec()), |s: &[u8]| { - s == &b"abc"[..] - }); - - assert_eq!(parser1(&b"abcd"[..]), Ok((&b"d"[..], b"abc".to_vec()))); - assert_eq!( - parser1(&b"defg"[..]), - Err(ErrMode::Backtrack(Error { - input: &b"defg"[..], - kind: ErrorKind::Verify - })) - ); + #![allow(deprecated)] + use crate::bytes::take; + let mut parser1 = verify(take(3u8).map(|s: &[u8]| s.to_vec()), |s: &[u8]| { + s == &b"abc"[..] + }); + + assert_eq!(parser1(&b"abcd"[..]), Ok((&b"d"[..], b"abc".to_vec()))); + assert_eq!( + parser1(&b"defg"[..]), + Err(ErrMode::Backtrack(Error { + input: &b"defg"[..], + kind: ErrorKind::Verify + })) + ); } #[test] #[cfg(feature = "std")] fn test_into() { - #![allow(deprecated)] - use crate::bytes::take; - use crate::error::Error; + #![allow(deprecated)] + use crate::bytes::take; + use crate::error::Error; - let mut parser = into(take::<_, _, Error<_>, false>(3u8)); - let result: IResult<&[u8], Vec> = parser(&b"abcdefg"[..]); + let mut parser = into(take::<_, _, Error<_>, false>(3u8)); + let result: IResult<&[u8], Vec> = parser(&b"abcdefg"[..]); - assert_eq!(result, Ok((&b"defg"[..], vec![97, 98, 99]))); + assert_eq!(result, Ok((&b"defg"[..], vec![97, 98, 99]))); } #[test] #[cfg(feature = "std")] fn test_parser_into() { - use crate::bytes::take; - use crate::error::Error; + use crate::bytes::take; + use crate::error::Error; - let mut parser = take::<_, _, Error<_>, false>(3u8).output_into(); - let result: IResult<&[u8], Vec> = parser.parse_next(&b"abcdefg"[..]); + let mut parser = take::<_, _, Error<_>, false>(3u8).output_into(); + let result: IResult<&[u8], Vec> = parser.parse_next(&b"abcdefg"[..]); - assert_eq!(result, Ok((&b"defg"[..], vec![97, 98, 99]))); + assert_eq!(result, Ok((&b"defg"[..], vec![97, 98, 99]))); } #[test] fn opt_test() { - fn opt_abcd(i: Streaming<&[u8]>) -> IResult, Option<&[u8]>> { - opt(tag("abcd"))(i) - } - - let a = &b"abcdef"[..]; - let b = &b"bcdefg"[..]; - let c = &b"ab"[..]; - assert_eq!( - opt_abcd(Streaming(a)), - Ok((Streaming(&b"ef"[..]), Some(&b"abcd"[..]))) - ); - assert_eq!( - opt_abcd(Streaming(b)), - Ok((Streaming(&b"bcdefg"[..]), None)) - ); - assert_eq!( - opt_abcd(Streaming(c)), - Err(ErrMode::Incomplete(Needed::new(2))) - ); + fn opt_abcd(i: Streaming<&[u8]>) -> IResult, Option<&[u8]>> { + opt(tag("abcd"))(i) + } + + let a = &b"abcdef"[..]; + let b = &b"bcdefg"[..]; + let c = &b"ab"[..]; + assert_eq!( + opt_abcd(Streaming(a)), + Ok((Streaming(&b"ef"[..]), Some(&b"abcd"[..]))) + ); + assert_eq!( + opt_abcd(Streaming(b)), + Ok((Streaming(&b"bcdefg"[..]), None)) + ); + assert_eq!( + opt_abcd(Streaming(c)), + Err(ErrMode::Incomplete(Needed::new(2))) + ); } #[test] fn peek_test() { - fn peek_tag(i: Streaming<&[u8]>) -> IResult, &[u8]> { - peek(tag("abcd"))(i) - } - - assert_eq!( - peek_tag(Streaming(&b"abcdef"[..])), - Ok((Streaming(&b"abcdef"[..]), &b"abcd"[..])) - ); - assert_eq!( - peek_tag(Streaming(&b"ab"[..])), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_eq!( - peek_tag(Streaming(&b"xxx"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxx"[..]), - ErrorKind::Tag - ))) - ); + fn peek_tag(i: Streaming<&[u8]>) -> IResult, &[u8]> { + peek(tag("abcd"))(i) + } + + assert_eq!( + peek_tag(Streaming(&b"abcdef"[..])), + Ok((Streaming(&b"abcdef"[..]), &b"abcd"[..])) + ); + assert_eq!( + peek_tag(Streaming(&b"ab"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_eq!( + peek_tag(Streaming(&b"xxx"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); } #[test] fn not_test() { - fn not_aaa(i: Streaming<&[u8]>) -> IResult, ()> { - not(tag("aaa"))(i) - } - - assert_eq!( - not_aaa(Streaming(&b"aaa"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"aaa"[..]), - ErrorKind::Not - ))) - ); - assert_eq!( - not_aaa(Streaming(&b"aa"[..])), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - not_aaa(Streaming(&b"abcd"[..])), - Ok((Streaming(&b"abcd"[..]), ())) - ); + fn not_aaa(i: Streaming<&[u8]>) -> IResult, ()> { + not(tag("aaa"))(i) + } + + assert_eq!( + not_aaa(Streaming(&b"aaa"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"aaa"[..]), + ErrorKind::Not + ))) + ); + assert_eq!( + not_aaa(Streaming(&b"aa"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + not_aaa(Streaming(&b"abcd"[..])), + Ok((Streaming(&b"abcd"[..]), ())) + ); } #[test] fn verify_test() { - #![allow(deprecated)] - use crate::bytes::take; - - fn test(i: Streaming<&[u8]>) -> IResult, &[u8]> { - verify(take(5u8), |slice: &[u8]| slice[0] == b'a')(i) - } - assert_eq!( - test(Streaming(&b"bcd"[..])), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_eq!( - test(Streaming(&b"bcdefg"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"bcdefg"[..]), - ErrorKind::Verify - ))) - ); - assert_eq!( - test(Streaming(&b"abcdefg"[..])), - Ok((Streaming(&b"fg"[..]), &b"abcde"[..])) - ); + #![allow(deprecated)] + use crate::bytes::take; + + fn test(i: Streaming<&[u8]>) -> IResult, &[u8]> { + verify(take(5u8), |slice: &[u8]| slice[0] == b'a')(i) + } + assert_eq!( + test(Streaming(&b"bcd"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_eq!( + test(Streaming(&b"bcdefg"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"bcdefg"[..]), + ErrorKind::Verify + ))) + ); + assert_eq!( + test(Streaming(&b"abcdefg"[..])), + Ok((Streaming(&b"fg"[..]), &b"abcde"[..])) + ); } #[test] fn test_parser_verify() { - use crate::bytes::take; - - fn test(i: Streaming<&[u8]>) -> IResult, &[u8]> { - take(5u8) - .verify(|slice: &[u8]| slice[0] == b'a') - .parse_next(i) - } - assert_eq!( - test(Streaming(&b"bcd"[..])), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_eq!( - test(Streaming(&b"bcdefg"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"bcdefg"[..]), - ErrorKind::Verify - ))) - ); - assert_eq!( - test(Streaming(&b"abcdefg"[..])), - Ok((Streaming(&b"fg"[..]), &b"abcde"[..])) - ); + use crate::bytes::take; + + fn test(i: Streaming<&[u8]>) -> IResult, &[u8]> { + take(5u8) + .verify(|slice: &[u8]| slice[0] == b'a') + .parse_next(i) + } + assert_eq!( + test(Streaming(&b"bcd"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_eq!( + test(Streaming(&b"bcdefg"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"bcdefg"[..]), + ErrorKind::Verify + ))) + ); + assert_eq!( + test(Streaming(&b"abcdefg"[..])), + Ok((Streaming(&b"fg"[..]), &b"abcde"[..])) + ); } #[test] #[allow(unused)] fn test_parser_verify_ref() { - use crate::bytes::take; - - let mut parser1 = take(3u8).verify(|s: &[u8]| s == &b"abc"[..]); - - assert_eq!( - parser1.parse_next(&b"abcd"[..]), - Ok((&b"d"[..], &b"abc"[..])) - ); - assert_eq!( - parser1.parse_next(&b"defg"[..]), - Err(ErrMode::Backtrack(Error { - input: &b"defg"[..], - kind: ErrorKind::Verify - })) - ); - - fn parser2(i: &[u8]) -> IResult<&[u8], u32> { - crate::number::be_u32 - .verify(|val: &u32| *val < 3) - .parse_next(i) - } + use crate::bytes::take; + + let mut parser1 = take(3u8).verify(|s: &[u8]| s == &b"abc"[..]); + + assert_eq!( + parser1.parse_next(&b"abcd"[..]), + Ok((&b"d"[..], &b"abc"[..])) + ); + assert_eq!( + parser1.parse_next(&b"defg"[..]), + Err(ErrMode::Backtrack(Error { + input: &b"defg"[..], + kind: ErrorKind::Verify + })) + ); + + fn parser2(i: &[u8]) -> IResult<&[u8], u32> { + crate::number::be_u32 + .verify(|val: &u32| *val < 3) + .parse_next(i) + } } #[test] #[cfg(feature = "alloc")] fn test_parser_verify_alloc() { - use crate::bytes::take; - let mut parser1 = take(3u8) - .map(|s: &[u8]| s.to_vec()) - .verify(|s: &[u8]| s == &b"abc"[..]); - - assert_eq!( - parser1.parse_next(&b"abcd"[..]), - Ok((&b"d"[..], b"abc".to_vec())) - ); - assert_eq!( - parser1.parse_next(&b"defg"[..]), - Err(ErrMode::Backtrack(Error { - input: &b"defg"[..], - kind: ErrorKind::Verify - })) - ); + use crate::bytes::take; + let mut parser1 = take(3u8) + .map(|s: &[u8]| s.to_vec()) + .verify(|s: &[u8]| s == &b"abc"[..]); + + assert_eq!( + parser1.parse_next(&b"abcd"[..]), + Ok((&b"d"[..], b"abc".to_vec())) + ); + assert_eq!( + parser1.parse_next(&b"defg"[..]), + Err(ErrMode::Backtrack(Error { + input: &b"defg"[..], + kind: ErrorKind::Verify + })) + ); } #[test] fn fail_test() { - let a = "string"; - let b = "another string"; - - assert_eq!( - fail::<_, &str, _>(a), - Err(ErrMode::Backtrack(Error { - input: a, - kind: ErrorKind::Fail - })) - ); - assert_eq!( - fail::<_, &str, _>(b), - Err(ErrMode::Backtrack(Error { - input: b, - kind: ErrorKind::Fail - })) - ); + let a = "string"; + let b = "another string"; + + assert_eq!( + fail::<_, &str, _>(a), + Err(ErrMode::Backtrack(Error { + input: a, + kind: ErrorKind::Fail + })) + ); + assert_eq!( + fail::<_, &str, _>(b), + Err(ErrMode::Backtrack(Error { + input: b, + kind: ErrorKind::Fail + })) + ); } diff --git a/src/error.rs b/src/error.rs index d9732c91..4d167412 100644 --- a/src/error.rs +++ b/src/error.rs @@ -465,83 +465,83 @@ pub type IResult> = Result<(I, O), ErrMode>; /// Extension trait to convert a parser's [`IResult`] to a more manageable type pub trait FinishIResult { - /// Converts the parser's [`IResult`] to a type that is more consumable by callers. - /// - /// Errors if the parser is not at the [end of input][crate::combinator::eof]. See - /// [`FinishIResult::finish_err`] if the remaining input is needed. - /// - /// # Panic - /// - /// If the result is `Err(ErrMode::Incomplete(_))`, this method will panic. - /// - "complete" parsers: It will not be an issue, `Incomplete` is never used - /// - "streaming" parsers: `Incomplete` will be returned if there's not enough data - /// for the parser to decide, and you should gather more data before parsing again. - /// Once the parser returns either `Ok(_)`, `Err(ErrMode::Backtrack(_))` or `Err(ErrMode::Cut(_))`, - /// you can get out of the parsing loop and call `finish_err()` on the parser's result - fn finish(self) -> Result; - - /// Converts the parser's [`IResult`] to a type that is more consumable by errors. - /// - /// It keeps the same `Ok` branch, and merges `ErrMode::Backtrack` and `ErrMode::Cut` into the `Err` - /// side. - /// - /// # Panic - /// - /// If the result is `Err(ErrMode::Incomplete(_))`, this method will panic as [`ErrMode::Incomplete`] - /// should only be set when the input is [`InputIsStreaming`] which this isn't implemented - /// for. - fn finish_err(self) -> Result<(I, O), E>; + /// Converts the parser's [`IResult`] to a type that is more consumable by callers. + /// + /// Errors if the parser is not at the [end of input][crate::combinator::eof]. See + /// [`FinishIResult::finish_err`] if the remaining input is needed. + /// + /// # Panic + /// + /// If the result is `Err(ErrMode::Incomplete(_))`, this method will panic. + /// - "complete" parsers: It will not be an issue, `Incomplete` is never used + /// - "streaming" parsers: `Incomplete` will be returned if there's not enough data + /// for the parser to decide, and you should gather more data before parsing again. + /// Once the parser returns either `Ok(_)`, `Err(ErrMode::Backtrack(_))` or `Err(ErrMode::Cut(_))`, + /// you can get out of the parsing loop and call `finish_err()` on the parser's result + fn finish(self) -> Result; + + /// Converts the parser's [`IResult`] to a type that is more consumable by errors. + /// + /// It keeps the same `Ok` branch, and merges `ErrMode::Backtrack` and `ErrMode::Cut` into the `Err` + /// side. + /// + /// # Panic + /// + /// If the result is `Err(ErrMode::Incomplete(_))`, this method will panic as [`ErrMode::Incomplete`] + /// should only be set when the input is [`InputIsStreaming`] which this isn't implemented + /// for. + fn finish_err(self) -> Result<(I, O), E>; } impl FinishIResult for IResult where - I: Input, - // Force users to deal with `Incomplete` when `InputIsStreaming` - I: InputIsStreaming, - I: Clone, - E: ParseError, + I: Input, + // Force users to deal with `Incomplete` when `InputIsStreaming` + I: InputIsStreaming, + I: Clone, + E: ParseError, { - fn finish(self) -> Result { - let (i, o) = self.finish_err()?; - crate::combinator::eof(i).finish_err()?; - Ok(o) - } + fn finish(self) -> Result { + let (i, o) = self.finish_err()?; + crate::combinator::eof(i).finish_err()?; + Ok(o) + } - fn finish_err(self) -> Result<(I, O), E> { - match self { - Ok(res) => Ok(res), - Err(ErrMode::Backtrack(e)) | Err(ErrMode::Cut(e)) => Err(e), - Err(ErrMode::Incomplete(_)) => { - panic!("`InputIsStreaming` conflicts with `Err(ErrMode::Incomplete(_))`") - } + fn finish_err(self) -> Result<(I, O), E> { + match self { + Ok(res) => Ok(res), + Err(ErrMode::Backtrack(e)) | Err(ErrMode::Cut(e)) => Err(e), + Err(ErrMode::Incomplete(_)) => { + panic!("`InputIsStreaming` conflicts with `Err(ErrMode::Incomplete(_))`") + } + } } - } } #[doc(hidden)] #[deprecated( - since = "0.1.0", - note = "Replaced with `FinishIResult` which is available via `winnow::prelude`" + since = "0.1.0", + note = "Replaced with `FinishIResult` which is available via `winnow::prelude`" )] pub trait Finish { - #[deprecated( - since = "0.1.0", - note = "Replaced with `FinishIResult::finish_err` which is available via `winnow::prelude`" - )] - fn finish(self) -> Result<(I, O), E>; + #[deprecated( + since = "0.1.0", + note = "Replaced with `FinishIResult::finish_err` which is available via `winnow::prelude`" + )] + fn finish(self) -> Result<(I, O), E>; } #[allow(deprecated)] impl Finish for IResult { - fn finish(self) -> Result<(I, O), E> { - match self { - Ok(res) => Ok(res), - Err(ErrMode::Backtrack(e)) | Err(ErrMode::Cut(e)) => Err(e), - Err(ErrMode::Incomplete(_)) => { - panic!("Cannot call `finish()` on `Err(ErrMode::Incomplete(_))`: this result means that the parser does not have enough data to decide, you should gather more data and try to reapply the parser instead") - } + fn finish(self) -> Result<(I, O), E> { + match self { + Ok(res) => Ok(res), + Err(ErrMode::Backtrack(e)) | Err(ErrMode::Cut(e)) => Err(e), + Err(ErrMode::Incomplete(_)) => { + panic!("Cannot call `finish()` on `Err(ErrMode::Incomplete(_))`: this result means that the parser does not have enough data to decide, you should gather more data and try to reapply the parser instead") + } + } } - } } /// Contains information on needed data if a parser returned `Incomplete` @@ -551,34 +551,34 @@ impl Finish for IResult { #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub enum Needed { - /// Needs more data, but we do not know how much - Unknown, - /// Contains the required data size in bytes - Size(NonZeroUsize), + /// Needs more data, but we do not know how much + Unknown, + /// Contains the required data size in bytes + Size(NonZeroUsize), } impl Needed { - /// Creates `Needed` instance, returns `Needed::Unknown` if the argument is zero - pub fn new(s: usize) -> Self { - match NonZeroUsize::new(s) { - Some(sz) => Needed::Size(sz), - None => Needed::Unknown, + /// Creates `Needed` instance, returns `Needed::Unknown` if the argument is zero + pub fn new(s: usize) -> Self { + match NonZeroUsize::new(s) { + Some(sz) => Needed::Size(sz), + None => Needed::Unknown, + } } - } - /// Indicates if we know how many bytes we need - pub fn is_known(&self) -> bool { - *self != Needed::Unknown - } + /// Indicates if we know how many bytes we need + pub fn is_known(&self) -> bool { + *self != Needed::Unknown + } - /// Maps a `Needed` to `Needed` by applying a function to a contained `Size` value. - #[inline] - pub fn map usize>(self, f: F) -> Needed { - match self { - Needed::Unknown => Needed::Unknown, - Needed::Size(n) => Needed::new(f(n)), + /// Maps a `Needed` to `Needed` by applying a function to a contained `Size` value. + #[inline] + pub fn map usize>(self, f: F) -> Needed { + match self { + Needed::Unknown => Needed::Unknown, + Needed::Size(n) => Needed::new(f(n)), + } } - } } /// The `Err` enum indicates the parser was not successful @@ -598,146 +598,146 @@ impl Needed { #[derive(Debug, Clone, PartialEq)] #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))] pub enum ErrMode { - /// There was not enough data - /// - /// This must only be set when the `Input` is [`InputIsStreaming`], like with - /// [`Streaming`][crate::input::Streaming] - /// - /// Convert this into an `Error` with [`Parser::complete`][Parser::complete] - Incomplete(Needed), - /// The parser had an error (recoverable) - Backtrack(E), - /// The parser had an unrecoverable error: we got to the right - /// branch and we know other branches won't work, so backtrack - /// as fast as possible - Cut(E), + /// There was not enough data + /// + /// This must only be set when the `Input` is [`InputIsStreaming`], like with + /// [`Streaming`][crate::input::Streaming] + /// + /// Convert this into an `Error` with [`Parser::complete`][Parser::complete] + Incomplete(Needed), + /// The parser had an error (recoverable) + Backtrack(E), + /// The parser had an unrecoverable error: we got to the right + /// branch and we know other branches won't work, so backtrack + /// as fast as possible + Cut(E), } impl ErrMode { - /// Tests if the result is Incomplete - pub fn is_incomplete(&self) -> bool { - matches!(self, ErrMode::Incomplete(_)) - } + /// Tests if the result is Incomplete + pub fn is_incomplete(&self) -> bool { + matches!(self, ErrMode::Incomplete(_)) + } - /// Prevent backtracking, bubbling the error up to the top - pub fn cut(self) -> Self { - match self { - ErrMode::Backtrack(e) => ErrMode::Cut(e), - rest => rest, + /// Prevent backtracking, bubbling the error up to the top + pub fn cut(self) -> Self { + match self { + ErrMode::Backtrack(e) => ErrMode::Cut(e), + rest => rest, + } } - } - /// Enable backtracking support - pub fn backtrack(self) -> Self { - match self { - ErrMode::Cut(e) => ErrMode::Backtrack(e), - rest => rest, + /// Enable backtracking support + pub fn backtrack(self) -> Self { + match self { + ErrMode::Cut(e) => ErrMode::Backtrack(e), + rest => rest, + } } - } - /// Applies the given function to the inner error - pub fn map(self, f: F) -> ErrMode - where - F: FnOnce(E) -> E2, - { - match self { - ErrMode::Incomplete(n) => ErrMode::Incomplete(n), - ErrMode::Cut(t) => ErrMode::Cut(f(t)), - ErrMode::Backtrack(t) => ErrMode::Backtrack(f(t)), + /// Applies the given function to the inner error + pub fn map(self, f: F) -> ErrMode + where + F: FnOnce(E) -> E2, + { + match self { + ErrMode::Incomplete(n) => ErrMode::Incomplete(n), + ErrMode::Cut(t) => ErrMode::Cut(f(t)), + ErrMode::Backtrack(t) => ErrMode::Backtrack(f(t)), + } } - } - /// Automatically converts between errors if the underlying type supports it - pub fn convert(self) -> ErrMode - where - E: ErrorConvert, - { - self.map(ErrorConvert::convert) - } + /// Automatically converts between errors if the underlying type supports it + pub fn convert(self) -> ErrMode + where + E: ErrorConvert, + { + self.map(ErrorConvert::convert) + } } impl> ParseError for ErrMode { - fn from_error_kind(input: I, kind: ErrorKind) -> Self { - ErrMode::Backtrack(E::from_error_kind(input, kind)) - } + fn from_error_kind(input: I, kind: ErrorKind) -> Self { + ErrMode::Backtrack(E::from_error_kind(input, kind)) + } - fn append(self, input: I, kind: ErrorKind) -> Self { - match self { - ErrMode::Backtrack(e) => ErrMode::Backtrack(e.append(input, kind)), - e => e, + fn append(self, input: I, kind: ErrorKind) -> Self { + match self { + ErrMode::Backtrack(e) => ErrMode::Backtrack(e.append(input, kind)), + e => e, + } } - } - fn or(self, other: Self) -> Self { - match (self, other) { - (ErrMode::Backtrack(e), ErrMode::Backtrack(o)) => ErrMode::Backtrack(e.or(o)), - (ErrMode::Incomplete(e), _) | (_, ErrMode::Incomplete(e)) => ErrMode::Incomplete(e), - (ErrMode::Cut(e), _) | (_, ErrMode::Cut(e)) => ErrMode::Cut(e), + fn or(self, other: Self) -> Self { + match (self, other) { + (ErrMode::Backtrack(e), ErrMode::Backtrack(o)) => ErrMode::Backtrack(e.or(o)), + (ErrMode::Incomplete(e), _) | (_, ErrMode::Incomplete(e)) => ErrMode::Incomplete(e), + (ErrMode::Cut(e), _) | (_, ErrMode::Cut(e)) => ErrMode::Cut(e), + } } - } } impl FromExternalError for ErrMode where - E: FromExternalError, + E: FromExternalError, { - fn from_external_error(input: I, kind: ErrorKind, e: EXT) -> Self { - ErrMode::Backtrack(E::from_external_error(input, kind, e)) - } + fn from_external_error(input: I, kind: ErrorKind, e: EXT) -> Self { + ErrMode::Backtrack(E::from_external_error(input, kind, e)) + } } impl ErrMode> { - /// Maps `ErrMode>` to `ErrMode>` with the given `F: T -> U` - pub fn map_input(self, f: F) -> ErrMode> - where - F: FnOnce(T) -> U, - { - match self { - ErrMode::Incomplete(n) => ErrMode::Incomplete(n), - ErrMode::Cut(Error { input, kind }) => ErrMode::Cut(Error { - input: f(input), - kind, - }), - ErrMode::Backtrack(Error { input, kind }) => ErrMode::Backtrack(Error { - input: f(input), - kind, - }), + /// Maps `ErrMode>` to `ErrMode>` with the given `F: T -> U` + pub fn map_input(self, f: F) -> ErrMode> + where + F: FnOnce(T) -> U, + { + match self { + ErrMode::Incomplete(n) => ErrMode::Incomplete(n), + ErrMode::Cut(Error { input, kind }) => ErrMode::Cut(Error { + input: f(input), + kind, + }), + ErrMode::Backtrack(Error { input, kind }) => ErrMode::Backtrack(Error { + input: f(input), + kind, + }), + } } - } } #[cfg(feature = "alloc")] impl ErrMode> { - /// Deprecated, replaced with [`Error::into_owned`] - #[deprecated(since = "0.3.0", note = "Replaced with `Error::into_owned`")] - pub fn to_owned(self) -> ErrMode>> { - self.map_input(ToOwned::to_owned) - } + /// Deprecated, replaced with [`Error::into_owned`] + #[deprecated(since = "0.3.0", note = "Replaced with `Error::into_owned`")] + pub fn to_owned(self) -> ErrMode>> { + self.map_input(ToOwned::to_owned) + } } #[cfg(feature = "alloc")] impl ErrMode> { - /// Deprecated, replaced with [`Error::into_owned`] - #[deprecated(since = "0.3.0", note = "Replaced with `Error::into_owned`")] - pub fn to_owned(self) -> ErrMode> { - self.map_input(ToOwned::to_owned) - } + /// Deprecated, replaced with [`Error::into_owned`] + #[deprecated(since = "0.3.0", note = "Replaced with `Error::into_owned`")] + pub fn to_owned(self) -> ErrMode> { + self.map_input(ToOwned::to_owned) + } } impl Eq for ErrMode {} impl fmt::Display for ErrMode where - E: fmt::Debug, + E: fmt::Debug, { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - ErrMode::Incomplete(Needed::Size(u)) => write!(f, "Parsing requires {} bytes/chars", u), - ErrMode::Incomplete(Needed::Unknown) => write!(f, "Parsing requires more data"), - ErrMode::Cut(c) => write!(f, "Parsing Failure: {:?}", c), - ErrMode::Backtrack(c) => write!(f, "Parsing Error: {:?}", c), + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ErrMode::Incomplete(Needed::Size(u)) => write!(f, "Parsing requires {} bytes/chars", u), + ErrMode::Incomplete(Needed::Unknown) => write!(f, "Parsing requires more data"), + ErrMode::Cut(c) => write!(f, "Parsing Failure: {:?}", c), + ErrMode::Backtrack(c) => write!(f, "Parsing Error: {:?}", c), + } } - } } /// This trait must be implemented by the error type of a nom parser. @@ -745,148 +745,148 @@ where /// It provides methods to create an error from some combinators, /// and combine existing errors in combinators like `alt`. pub trait ParseError: Sized { - /// Creates an error from the input position and an [`ErrorKind`] - fn from_error_kind(input: I, kind: ErrorKind) -> Self; - - /// Combines an existing error with a new one created from the input - /// position and an [`ErrorKind`]. This is useful when backtracking - /// through a parse tree, accumulating error context on the way - fn append(self, input: I, kind: ErrorKind) -> Self; - - /// Creates an error from an input position and an expected character - #[deprecated(since = "0.2.0", note = "Replaced with `ContextError`")] - fn from_char(input: I, _: char) -> Self { - Self::from_error_kind(input, ErrorKind::Char) - } + /// Creates an error from the input position and an [`ErrorKind`] + fn from_error_kind(input: I, kind: ErrorKind) -> Self; + + /// Combines an existing error with a new one created from the input + /// position and an [`ErrorKind`]. This is useful when backtracking + /// through a parse tree, accumulating error context on the way + fn append(self, input: I, kind: ErrorKind) -> Self; + + /// Creates an error from an input position and an expected character + #[deprecated(since = "0.2.0", note = "Replaced with `ContextError`")] + fn from_char(input: I, _: char) -> Self { + Self::from_error_kind(input, ErrorKind::Char) + } - /// Combines two existing errors. This function is used to compare errors - /// generated in various branches of `alt`. - fn or(self, other: Self) -> Self { - other - } + /// Combines two existing errors. This function is used to compare errors + /// generated in various branches of `alt`. + fn or(self, other: Self) -> Self { + other + } } /// Used by the [`context`] to add custom data to errors /// /// May be implemented multiple times for different kinds of context. pub trait ContextError: Sized { - /// Creates a new error from an input position, a data, and an existing error. - /// - /// This is used mainly in the [`context`] combinator, to add user friendly information - /// to errors when backtracking through a parse tree - fn add_context(self, _input: I, _ctx: C) -> Self { - self - } + /// Creates a new error from an input position, a data, and an existing error. + /// + /// This is used mainly in the [`context`] combinator, to add user friendly information + /// to errors when backtracking through a parse tree + fn add_context(self, _input: I, _ctx: C) -> Self { + self + } } /// This trait is required by the `map_res` combinator to integrate /// error types from external functions, like [`std::str::FromStr`] pub trait FromExternalError { - /// Creates a new error from an input position, an [`ErrorKind`] indicating the - /// wrapping parser, and an external error - fn from_external_error(input: I, kind: ErrorKind, e: E) -> Self; + /// Creates a new error from an input position, an [`ErrorKind`] indicating the + /// wrapping parser, and an external error + fn from_external_error(input: I, kind: ErrorKind, e: E) -> Self; } /// Equivalent From implementation to avoid orphan rules in bits parsers pub trait ErrorConvert { - /// Transform to another error type - fn convert(self) -> E; + /// Transform to another error type + fn convert(self) -> E; } /// default error type, only contains the error' location and kind #[derive(Debug, Eq, PartialEq)] pub struct Error { - /// position of the error in the input data - pub input: I, - /// nom error kind - pub kind: ErrorKind, + /// position of the error in the input data + pub input: I, + /// nom error kind + pub kind: ErrorKind, } impl Error { - /// creates a new basic error - pub fn new(input: I, kind: ErrorKind) -> Error { - Error { input, kind } - } + /// creates a new basic error + pub fn new(input: I, kind: ErrorKind) -> Error { + Error { input, kind } + } } #[cfg(feature = "alloc")] impl Error { - /// Obtaining ownership - pub fn into_owned(self) -> Error<::Owned> { - Error { - input: self.input.to_owned(), - kind: self.kind, + /// Obtaining ownership + pub fn into_owned(self) -> Error<::Owned> { + Error { + input: self.input.to_owned(), + kind: self.kind, + } } - } } impl ParseError for Error { - fn from_error_kind(input: I, kind: ErrorKind) -> Self { - Error { input, kind } - } + fn from_error_kind(input: I, kind: ErrorKind) -> Self { + Error { input, kind } + } - fn append(self, _: I, _: ErrorKind) -> Self { - self - } + fn append(self, _: I, _: ErrorKind) -> Self { + self + } } impl ContextError for Error {} impl FromExternalError for Error { - /// Create a new error from an input position and an external error - fn from_external_error(input: I, kind: ErrorKind, _e: E) -> Self { - Error { input, kind } - } + /// Create a new error from an input position and an external error + fn from_external_error(input: I, kind: ErrorKind, _e: E) -> Self { + Error { input, kind } + } } impl ErrorConvert> for Error { - fn convert(self) -> Error<(I, usize)> { - Error { - input: (self.input, 0), - kind: self.kind, + fn convert(self) -> Error<(I, usize)> { + Error { + input: (self.input, 0), + kind: self.kind, + } } - } } impl ErrorConvert> for Error<(I, usize)> { - fn convert(self) -> Error { - Error { - input: self.input.0, - kind: self.kind, + fn convert(self) -> Error { + Error { + input: self.input.0, + kind: self.kind, + } } - } } /// The Display implementation allows the `std::error::Error` implementation impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "error {:?} at: {}", self.kind, self.input) - } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "error {:?} at: {}", self.kind, self.input) + } } #[cfg(feature = "std")] impl std::error::Error for Error {} impl ParseError for () { - fn from_error_kind(_: I, _: ErrorKind) -> Self {} + fn from_error_kind(_: I, _: ErrorKind) -> Self {} - fn append(self, _: I, _: ErrorKind) -> Self {} + fn append(self, _: I, _: ErrorKind) -> Self {} } impl ContextError for () {} impl FromExternalError for () { - fn from_external_error(_input: I, _kind: ErrorKind, _e: E) -> Self {} + fn from_external_error(_input: I, _kind: ErrorKind, _e: E) -> Self {} } impl ErrorConvert<()> for () { - fn convert(self) {} + fn convert(self) {} } /// Creates an error from the input position and an [`ErrorKind`] #[deprecated(since = "0.2.0", note = "Replaced with `ParseError::from_error_kind`")] pub fn make_error>(input: I, kind: ErrorKind) -> E { - E::from_error_kind(input, kind) + E::from_error_kind(input, kind) } /// Combines an existing error with a new one created from the input @@ -894,7 +894,7 @@ pub fn make_error>(input: I, kind: ErrorKind) -> E { /// through a parse tree, accumulating error context on the way #[deprecated(since = "0.2.0", note = "Replaced with `ParseError::append`")] pub fn append_error>(input: I, kind: ErrorKind, other: E) -> E { - other.append(input, kind) + other.append(input, kind) } /// This error type accumulates errors and their position when backtracking @@ -903,97 +903,97 @@ pub fn append_error>(input: I, kind: ErrorKind, other: E) -> #[cfg(feature = "alloc")] #[derive(Clone, Debug, Eq, PartialEq)] pub struct VerboseError { - /// List of errors accumulated by `VerboseError`, containing the affected - /// part of input data, and some context - pub errors: crate::lib::std::vec::Vec<(I, VerboseErrorKind)>, + /// List of errors accumulated by `VerboseError`, containing the affected + /// part of input data, and some context + pub errors: crate::lib::std::vec::Vec<(I, VerboseErrorKind)>, } #[cfg(feature = "alloc")] impl VerboseError { - /// Obtaining ownership - pub fn into_owned(self) -> VerboseError<::Owned> { - #[allow(clippy::redundant_clone)] // false positive - VerboseError { - errors: self - .errors - .into_iter() - .map(|(i, k)| (i.to_owned(), k)) - .collect(), + /// Obtaining ownership + pub fn into_owned(self) -> VerboseError<::Owned> { + #[allow(clippy::redundant_clone)] // false positive + VerboseError { + errors: self + .errors + .into_iter() + .map(|(i, k)| (i.to_owned(), k)) + .collect(), + } } - } } #[cfg(feature = "alloc")] #[derive(Clone, Debug, Eq, PartialEq)] /// Error context for `VerboseError` pub enum VerboseErrorKind { - /// Static string added by the `context` function - Context(&'static str), - /// Error kind given by various nom parsers - Nom(ErrorKind), + /// Static string added by the `context` function + Context(&'static str), + /// Error kind given by various nom parsers + Nom(ErrorKind), } #[cfg(feature = "alloc")] impl ParseError for VerboseError { - fn from_error_kind(input: I, kind: ErrorKind) -> Self { - VerboseError { - errors: vec![(input, VerboseErrorKind::Nom(kind))], + fn from_error_kind(input: I, kind: ErrorKind) -> Self { + VerboseError { + errors: vec![(input, VerboseErrorKind::Nom(kind))], + } } - } - fn append(mut self, input: I, kind: ErrorKind) -> Self { - self.errors.push((input, VerboseErrorKind::Nom(kind))); - self - } + fn append(mut self, input: I, kind: ErrorKind) -> Self { + self.errors.push((input, VerboseErrorKind::Nom(kind))); + self + } } #[cfg(feature = "alloc")] impl ContextError for VerboseError { - fn add_context(mut self, input: I, ctx: &'static str) -> Self { - self.errors.push((input, VerboseErrorKind::Context(ctx))); - self - } + fn add_context(mut self, input: I, ctx: &'static str) -> Self { + self.errors.push((input, VerboseErrorKind::Context(ctx))); + self + } } #[cfg(feature = "alloc")] impl FromExternalError for VerboseError { - /// Create a new error from an input position and an external error - fn from_external_error(input: I, kind: ErrorKind, _e: E) -> Self { - Self::from_error_kind(input, kind) - } + /// Create a new error from an input position and an external error + fn from_external_error(input: I, kind: ErrorKind, _e: E) -> Self { + Self::from_error_kind(input, kind) + } } #[cfg(feature = "alloc")] impl ErrorConvert> for VerboseError<(I, usize)> { - fn convert(self) -> VerboseError { - VerboseError { - errors: self.errors.into_iter().map(|(i, e)| (i.0, e)).collect(), + fn convert(self) -> VerboseError { + VerboseError { + errors: self.errors.into_iter().map(|(i, e)| (i.0, e)).collect(), + } } - } } #[cfg(feature = "alloc")] impl ErrorConvert> for VerboseError { - fn convert(self) -> VerboseError<(I, usize)> { - VerboseError { - errors: self.errors.into_iter().map(|(i, e)| ((i, 0), e)).collect(), + fn convert(self) -> VerboseError<(I, usize)> { + VerboseError { + errors: self.errors.into_iter().map(|(i, e)| ((i, 0), e)).collect(), + } } - } } #[cfg(feature = "alloc")] impl fmt::Display for VerboseError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - writeln!(f, "Parse error:")?; - for (input, error) in &self.errors { - match error { - VerboseErrorKind::Nom(e) => writeln!(f, "{:?} at: {}", e, input)?, - VerboseErrorKind::Context(s) => writeln!(f, "in section '{}', at: {}", s, input)?, - } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, "Parse error:")?; + for (input, error) in &self.errors { + match error { + VerboseErrorKind::Nom(e) => writeln!(f, "{:?} at: {}", e, input)?, + VerboseErrorKind::Context(s) => writeln!(f, "in section '{}', at: {}", s, input)?, + } + } + + Ok(()) } - - Ok(()) - } } #[cfg(feature = "std")] @@ -1006,96 +1006,100 @@ impl std::error::Error for /// **WARNING:** Deprecated, replaced with [`Parser::context`] #[deprecated(since = "0.1.0", note = "Replaced with `Parser::context")] pub fn context, F, O>( - context: &'static str, - mut f: F, + context: &'static str, + mut f: F, ) -> impl FnMut(I) -> IResult where - F: Parser, + F: Parser, { - move |i: I| match f.parse_next(i.clone()) { - Ok(o) => Ok(o), - Err(ErrMode::Incomplete(i)) => Err(ErrMode::Incomplete(i)), - Err(ErrMode::Backtrack(e)) => Err(ErrMode::Backtrack(e.add_context(i, context))), - Err(ErrMode::Cut(e)) => Err(ErrMode::Cut(e.add_context(i, context))), - } + move |i: I| match f.parse_next(i.clone()) { + Ok(o) => Ok(o), + Err(ErrMode::Incomplete(i)) => Err(ErrMode::Incomplete(i)), + Err(ErrMode::Backtrack(e)) => Err(ErrMode::Backtrack(e.add_context(i, context))), + Err(ErrMode::Cut(e)) => Err(ErrMode::Cut(e.add_context(i, context))), + } } /// Transforms a `VerboseError` into a trace with input position information #[cfg(feature = "alloc")] pub fn convert_error>( - input: I, - e: VerboseError, + input: I, + e: VerboseError, ) -> crate::lib::std::string::String { - use crate::input::Offset; - use crate::lib::std::fmt::Write; - - let mut result = crate::lib::std::string::String::new(); - - for (i, (substring, kind)) in e.errors.iter().enumerate() { - let offset = input.offset_to(substring); - - if input.is_empty() { - match kind { - VerboseErrorKind::Context(s) => write!(&mut result, "{}: in {}, got empty input\n\n", i, s), - VerboseErrorKind::Nom(e) => write!(&mut result, "{}: in {:?}, got empty input\n\n", i, e), - } - } else { - let prefix = &input.as_bytes()[..offset]; - - // Count the number of newlines in the first `offset` bytes of input - let line_number = prefix.iter().filter(|&&b| b == b'\n').count() + 1; - - // Find the line that includes the subslice: - // Find the *last* newline before the substring starts - let line_begin = prefix - .iter() - .rev() - .position(|&b| b == b'\n') - .map(|pos| offset - pos) - .unwrap_or(0); - - // Find the full line after that newline - let line = input[line_begin..] - .lines() - .next() - .unwrap_or(&input[line_begin..]) - .trim_end(); - - // The (1-indexed) column number is the offset of our substring into that line - let column_number = line.offset_to(substring) + 1; - - match kind { - VerboseErrorKind::Context(s) => write!( - &mut result, - "{i}: at line {line_number}, in {context}:\n\ + use crate::input::Offset; + use crate::lib::std::fmt::Write; + + let mut result = crate::lib::std::string::String::new(); + + for (i, (substring, kind)) in e.errors.iter().enumerate() { + let offset = input.offset_to(substring); + + if input.is_empty() { + match kind { + VerboseErrorKind::Context(s) => { + write!(&mut result, "{}: in {}, got empty input\n\n", i, s) + } + VerboseErrorKind::Nom(e) => { + write!(&mut result, "{}: in {:?}, got empty input\n\n", i, e) + } + } + } else { + let prefix = &input.as_bytes()[..offset]; + + // Count the number of newlines in the first `offset` bytes of input + let line_number = prefix.iter().filter(|&&b| b == b'\n').count() + 1; + + // Find the line that includes the subslice: + // Find the *last* newline before the substring starts + let line_begin = prefix + .iter() + .rev() + .position(|&b| b == b'\n') + .map(|pos| offset - pos) + .unwrap_or(0); + + // Find the full line after that newline + let line = input[line_begin..] + .lines() + .next() + .unwrap_or(&input[line_begin..]) + .trim_end(); + + // The (1-indexed) column number is the offset of our substring into that line + let column_number = line.offset_to(substring) + 1; + + match kind { + VerboseErrorKind::Context(s) => write!( + &mut result, + "{i}: at line {line_number}, in {context}:\n\ {line}\n\ {caret:>column$}\n\n", - i = i, - line_number = line_number, - context = s, - line = line, - caret = '^', - column = column_number, - ), - VerboseErrorKind::Nom(e) => write!( - &mut result, - "{i}: at line {line_number}, in {nom_err:?}:\n\ + i = i, + line_number = line_number, + context = s, + line = line, + caret = '^', + column = column_number, + ), + VerboseErrorKind::Nom(e) => write!( + &mut result, + "{i}: at line {line_number}, in {nom_err:?}:\n\ {line}\n\ {caret:>column$}\n\n", - i = i, - line_number = line_number, - nom_err = e, - line = line, - caret = '^', - column = column_number, - ), - } + i = i, + line_number = line_number, + nom_err = e, + line = line, + caret = '^', + column = column_number, + ), + } + } + // Because `write!` to a `String` is infallible, this `unwrap` is fine. + .unwrap(); } - // Because `write!` to a `String` is infallible, this `unwrap` is fine. - .unwrap(); - } - result + result } /// Indicates which parser returned an error @@ -1159,10 +1163,10 @@ pub enum ErrorKind { } impl ErrorKind { - #[rustfmt::skip] + #[rustfmt::skip] #[allow(deprecated)] - /// Converts an `ErrorKind` to a text description - pub fn description(&self) -> &str { + /// Converts an `ErrorKind` to a text description + pub fn description(&self) -> &str { match *self { ErrorKind::Tag => "Tag", ErrorKind::MapRes => "Map on Result", @@ -1226,8 +1230,8 @@ impl ErrorKind { #[allow(unused_variables)] #[macro_export(local_inner_macros)] #[cfg_attr( - not(test), - deprecated(since = "0.3.0", note = "Replaced with `E::from_error_kind`") + not(test), + deprecated(since = "0.3.0", note = "Replaced with `E::from_error_kind`") )] macro_rules! error_position( ($input:expr, $code:expr) => ({ @@ -1241,8 +1245,8 @@ macro_rules! error_position( #[allow(unused_variables)] #[macro_export(local_inner_macros)] #[cfg_attr( - not(test), - deprecated(since = "0.3.0", note = "Replaced with `E::append`") + not(test), + deprecated(since = "0.3.0", note = "Replaced with `E::append`") )] macro_rules! error_node_position( ($input:expr, $code:expr, $next:expr) => ({ @@ -1276,32 +1280,32 @@ macro_rules! error_node_position( #[deprecated(since = "0.1.0", note = "Replaced with `Parser::dbg_err")] #[cfg(feature = "std")] pub fn dbg_dmp<'a, F, O, E: std::fmt::Debug>( - f: F, - context: &'static str, + f: F, + context: &'static str, ) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], O, E> where - F: Fn(&'a [u8]) -> IResult<&'a [u8], O, E>, + F: Fn(&'a [u8]) -> IResult<&'a [u8], O, E>, { - use crate::input::HexDisplay; - move |i: &'a [u8]| match f(i) { - Err(e) => { - println!("{}: Error({:?}) at:\n{}", context, e, i.to_hex(8)); - Err(e) + use crate::input::HexDisplay; + move |i: &'a [u8]| match f(i) { + Err(e) => { + println!("{}: Error({:?}) at:\n{}", context, e, i.to_hex(8)); + Err(e) + } + a => a, } - a => a, - } } #[cfg(test)] #[cfg(feature = "alloc")] mod tests { - use super::*; - use crate::bytes::one_of; + use super::*; + use crate::bytes::one_of; - #[test] - fn convert_error_panic() { - let input = ""; + #[test] + fn convert_error_panic() { + let input = ""; - let _result: IResult<_, _, VerboseError<&str>> = one_of('x')(input); - } + let _result: IResult<_, _, VerboseError<&str>> = one_of('x')(input); + } } diff --git a/src/input.rs b/src/input.rs index d52ea0ed..ff46d5fc 100644 --- a/src/input.rs +++ b/src/input.rs @@ -59,7 +59,7 @@ use core::num::NonZeroUsize; use crate::error::{ErrMode, ErrorKind, Needed, ParseError}; use crate::lib::std::iter::{Cloned, Enumerate}; use crate::lib::std::ops::{ - Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, + Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, }; use crate::lib::std::slice::Iter; use crate::lib::std::str::from_utf8; @@ -81,38 +81,38 @@ use crate::lib::std::vec::Vec; /// See [`Parser::span`][crate::Parser::span] and [`Parser::with_span`][crate::Parser::with_span] for more details #[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Located { - initial: I, - input: I, + initial: I, + input: I, } impl Located where - I: Clone + Offset, + I: Clone + Offset, { - /// Wrap another Input with span tracking - pub fn new(input: I) -> Self { - let initial = input.clone(); - Self { initial, input } - } + /// Wrap another Input with span tracking + pub fn new(input: I) -> Self { + let initial = input.clone(); + Self { initial, input } + } - fn location(&self) -> usize { - self.initial.offset_to(&self.input) - } + fn location(&self) -> usize { + self.initial.offset_to(&self.input) + } } impl AsRef for Located { - fn as_ref(&self) -> &I { - &self.input - } + fn as_ref(&self) -> &I { + &self.input + } } impl crate::lib::std::ops::Deref for Located { - type Target = I; + type Target = I; - #[inline(always)] - fn deref(&self) -> &Self::Target { - &self.input - } + #[inline(always)] + fn deref(&self) -> &Self::Target { + &self.input + } } /// Thread global state through your parsers @@ -155,24 +155,24 @@ impl crate::lib::std::ops::Deref for Located { /// ``` #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct Stateful { - /// Inner input being wrapped in state - pub input: I, - /// User-provided state - pub state: S, + /// Inner input being wrapped in state + pub input: I, + /// User-provided state + pub state: S, } impl AsRef for Stateful { - fn as_ref(&self) -> &I { - &self.input - } + fn as_ref(&self) -> &I { + &self.input + } } impl crate::lib::std::ops::Deref for Stateful { - type Target = I; + type Target = I; - fn deref(&self) -> &Self::Target { - self.as_ref() - } + fn deref(&self) -> &Self::Target { + self.as_ref() + } } /// Mark the input as a partial buffer for streaming input. @@ -240,1208 +240,1208 @@ impl crate::lib::std::ops::Deref for Stateful { pub struct Streaming(pub I); impl Streaming { - /// Convert to complete counterpart - #[inline(always)] - pub fn into_complete(self) -> I { - self.0 - } + /// Convert to complete counterpart + #[inline(always)] + pub fn into_complete(self) -> I { + self.0 + } } impl crate::lib::std::ops::Deref for Streaming { - type Target = I; + type Target = I; - #[inline(always)] - fn deref(&self) -> &Self::Target { - &self.0 - } + #[inline(always)] + fn deref(&self) -> &Self::Target { + &self.0 + } } /// Abstract method to calculate the input length pub trait SliceLen { - /// Calculates the input length, as indicated by its name, - /// and the name of the trait itself - fn slice_len(&self) -> usize; + /// Calculates the input length, as indicated by its name, + /// and the name of the trait itself + fn slice_len(&self) -> usize; } impl SliceLen for Located where - I: SliceLen, + I: SliceLen, { - fn slice_len(&self) -> usize { - self.input.slice_len() - } + fn slice_len(&self) -> usize { + self.input.slice_len() + } } impl SliceLen for Stateful where - I: SliceLen, + I: SliceLen, { - fn slice_len(&self) -> usize { - self.input.slice_len() - } + fn slice_len(&self) -> usize { + self.input.slice_len() + } } impl SliceLen for Streaming where - I: SliceLen, + I: SliceLen, { - #[inline(always)] - fn slice_len(&self) -> usize { - self.0.slice_len() - } + #[inline(always)] + fn slice_len(&self) -> usize { + self.0.slice_len() + } } impl<'a, T> SliceLen for &'a [T] { - #[inline] - fn slice_len(&self) -> usize { - self.len() - } + #[inline] + fn slice_len(&self) -> usize { + self.len() + } } impl SliceLen for [T; LEN] { - #[inline] - fn slice_len(&self) -> usize { - self.len() - } + #[inline] + fn slice_len(&self) -> usize { + self.len() + } } impl<'a, T, const LEN: usize> SliceLen for &'a [T; LEN] { - #[inline] - fn slice_len(&self) -> usize { - self.len() - } + #[inline] + fn slice_len(&self) -> usize { + self.len() + } } impl<'a> SliceLen for &'a str { - #[inline] - fn slice_len(&self) -> usize { - self.len() - } + #[inline] + fn slice_len(&self) -> usize { + self.len() + } } /// Core definition for parser input state pub trait Input: Clone { - /// The smallest unit being parsed - /// - /// Example: `u8` for `&[u8]` or `char` for `&str` - type Token; - /// Sequence of `Token`s - /// - /// Example: `&[u8]` for `Located<&[u8]>` or `&str` for `Located<&str>` - type Slice; - - /// Iterate with the offset from the current location - type IterOffsets: Iterator; - - /// Iterate with the offset from the current location - fn iter_offsets(&self) -> Self::IterOffsets; - /// Returns the offaet to the end of the input - fn input_len(&self) -> usize; - - /// Split off the next token from the input - fn next_token(&self) -> Option<(Self, Self::Token)>; - - /// Finds the offset of the next matching token - fn offset_for

(&self, predicate: P) -> Option - where - P: Fn(Self::Token) -> bool; - /// Get the offset for the number of `tokens` into the stream - /// - /// This means "0 tokens" will return `0` offset - fn offset_at(&self, tokens: usize) -> Result; - /// Split off a slice of tokens from the input - /// - /// **NOTE:** For inputs with variable width tokens, like `&str`'s `char`, `offset` might not correspond - /// with the number of tokens. To get a valid offset, use: - /// - [`Input::input_len`] - /// - [`Input::iter_offsets`] - /// - [`Input::offset_for`] - /// - [`Input::offset_at`] - /// - /// # Panic - /// - /// This will panic if - /// - /// * Indexes must be within bounds of the original input; - /// * Indexes must uphold invariants of the Input, like for `str` they must lie on UTF-8 - /// sequence boundaries. - /// - fn next_slice(&self, offset: usize) -> (Self, Self::Slice); + /// The smallest unit being parsed + /// + /// Example: `u8` for `&[u8]` or `char` for `&str` + type Token; + /// Sequence of `Token`s + /// + /// Example: `&[u8]` for `Located<&[u8]>` or `&str` for `Located<&str>` + type Slice; + + /// Iterate with the offset from the current location + type IterOffsets: Iterator; + + /// Iterate with the offset from the current location + fn iter_offsets(&self) -> Self::IterOffsets; + /// Returns the offaet to the end of the input + fn input_len(&self) -> usize; + + /// Split off the next token from the input + fn next_token(&self) -> Option<(Self, Self::Token)>; + + /// Finds the offset of the next matching token + fn offset_for

(&self, predicate: P) -> Option + where + P: Fn(Self::Token) -> bool; + /// Get the offset for the number of `tokens` into the stream + /// + /// This means "0 tokens" will return `0` offset + fn offset_at(&self, tokens: usize) -> Result; + /// Split off a slice of tokens from the input + /// + /// **NOTE:** For inputs with variable width tokens, like `&str`'s `char`, `offset` might not correspond + /// with the number of tokens. To get a valid offset, use: + /// - [`Input::input_len`] + /// - [`Input::iter_offsets`] + /// - [`Input::offset_for`] + /// - [`Input::offset_at`] + /// + /// # Panic + /// + /// This will panic if + /// + /// * Indexes must be within bounds of the original input; + /// * Indexes must uphold invariants of the Input, like for `str` they must lie on UTF-8 + /// sequence boundaries. + /// + fn next_slice(&self, offset: usize) -> (Self, Self::Slice); } impl<'i, T> Input for &'i [T] where - T: Clone, + T: Clone, { - type Token = T; - type Slice = &'i [T]; - - type IterOffsets = Enumerate>>; - - #[inline(always)] - fn iter_offsets(&self) -> Self::IterOffsets { - self.iter().cloned().enumerate() - } - #[inline(always)] - fn input_len(&self) -> usize { - self.len() - } - - #[inline(always)] - fn next_token(&self) -> Option<(Self, Self::Token)> { - if self.is_empty() { - None - } else { - Some((&self[1..], self[0].clone())) - } - } - - #[inline(always)] - fn offset_for

(&self, predicate: P) -> Option - where - P: Fn(Self::Token) -> bool, - { - self.iter().position(|b| predicate(b.clone())) - } - #[inline(always)] - fn offset_at(&self, tokens: usize) -> Result { - if let Some(needed) = tokens.checked_sub(self.len()).and_then(NonZeroUsize::new) { - Err(Needed::Size(needed)) - } else { - Ok(tokens) + type Token = T; + type Slice = &'i [T]; + + type IterOffsets = Enumerate>>; + + #[inline(always)] + fn iter_offsets(&self) -> Self::IterOffsets { + self.iter().cloned().enumerate() + } + #[inline(always)] + fn input_len(&self) -> usize { + self.len() + } + + #[inline(always)] + fn next_token(&self) -> Option<(Self, Self::Token)> { + if self.is_empty() { + None + } else { + Some((&self[1..], self[0].clone())) + } + } + + #[inline(always)] + fn offset_for

(&self, predicate: P) -> Option + where + P: Fn(Self::Token) -> bool, + { + self.iter().position(|b| predicate(b.clone())) + } + #[inline(always)] + fn offset_at(&self, tokens: usize) -> Result { + if let Some(needed) = tokens.checked_sub(self.len()).and_then(NonZeroUsize::new) { + Err(Needed::Size(needed)) + } else { + Ok(tokens) + } + } + #[inline(always)] + fn next_slice(&self, offset: usize) -> (Self, Self::Slice) { + (&self[offset..], &self[0..offset]) } - } - #[inline(always)] - fn next_slice(&self, offset: usize) -> (Self, Self::Slice) { - (&self[offset..], &self[0..offset]) - } } impl<'i> Input for &'i str { - type Token = char; - type Slice = &'i str; - - type IterOffsets = CharIndices<'i>; - - #[inline(always)] - fn iter_offsets(&self) -> Self::IterOffsets { - self.char_indices() - } - #[inline(always)] - fn input_len(&self) -> usize { - self.len() - } - - #[inline(always)] - fn next_token(&self) -> Option<(Self, Self::Token)> { - let c = self.chars().next()?; - let offset = c.len(); - Some((&self[offset..], c)) - } - - #[inline(always)] - fn offset_for

(&self, predicate: P) -> Option - where - P: Fn(Self::Token) -> bool, - { - for (o, c) in self.iter_offsets() { - if predicate(c) { - return Some(o); - } + type Token = char; + type Slice = &'i str; + + type IterOffsets = CharIndices<'i>; + + #[inline(always)] + fn iter_offsets(&self) -> Self::IterOffsets { + self.char_indices() } - None - } - #[inline] - fn offset_at(&self, tokens: usize) -> Result { - let mut cnt = 0; - for (offset, _) in self.iter_offsets() { - if cnt == tokens { - return Ok(offset); - } - cnt += 1; + #[inline(always)] + fn input_len(&self) -> usize { + self.len() } - if cnt == tokens { - Ok(self.input_len()) - } else { - Err(Needed::Unknown) + #[inline(always)] + fn next_token(&self) -> Option<(Self, Self::Token)> { + let c = self.chars().next()?; + let offset = c.len(); + Some((&self[offset..], c)) + } + + #[inline(always)] + fn offset_for

(&self, predicate: P) -> Option + where + P: Fn(Self::Token) -> bool, + { + for (o, c) in self.iter_offsets() { + if predicate(c) { + return Some(o); + } + } + None + } + #[inline] + fn offset_at(&self, tokens: usize) -> Result { + let mut cnt = 0; + for (offset, _) in self.iter_offsets() { + if cnt == tokens { + return Ok(offset); + } + cnt += 1; + } + + if cnt == tokens { + Ok(self.input_len()) + } else { + Err(Needed::Unknown) + } + } + #[inline(always)] + fn next_slice(&self, offset: usize) -> (Self, Self::Slice) { + (&self[offset..], &self[0..offset]) } - } - #[inline(always)] - fn next_slice(&self, offset: usize) -> (Self, Self::Slice) { - (&self[offset..], &self[0..offset]) - } } impl Input for Located { - type Token = ::Token; - type Slice = ::Slice; - - type IterOffsets = ::IterOffsets; - - #[inline(always)] - fn iter_offsets(&self) -> Self::IterOffsets { - self.input.iter_offsets() - } - #[inline(always)] - fn input_len(&self) -> usize { - self.input.input_len() - } - - #[inline(always)] - fn next_token(&self) -> Option<(Self, Self::Token)> { - let (next, token) = self.input.next_token()?; - Some(( - Self { - initial: self.initial.clone(), - input: next, - }, - token, - )) - } - - #[inline(always)] - fn offset_for

(&self, predicate: P) -> Option - where - P: Fn(Self::Token) -> bool, - { - self.input.offset_for(predicate) - } - #[inline(always)] - fn offset_at(&self, tokens: usize) -> Result { - self.input.offset_at(tokens) - } - #[inline(always)] - fn next_slice(&self, offset: usize) -> (Self, Self::Slice) { - let (next, slice) = self.input.next_slice(offset); - ( - Self { - initial: self.initial.clone(), - input: next, - }, - slice, - ) - } + type Token = ::Token; + type Slice = ::Slice; + + type IterOffsets = ::IterOffsets; + + #[inline(always)] + fn iter_offsets(&self) -> Self::IterOffsets { + self.input.iter_offsets() + } + #[inline(always)] + fn input_len(&self) -> usize { + self.input.input_len() + } + + #[inline(always)] + fn next_token(&self) -> Option<(Self, Self::Token)> { + let (next, token) = self.input.next_token()?; + Some(( + Self { + initial: self.initial.clone(), + input: next, + }, + token, + )) + } + + #[inline(always)] + fn offset_for

(&self, predicate: P) -> Option + where + P: Fn(Self::Token) -> bool, + { + self.input.offset_for(predicate) + } + #[inline(always)] + fn offset_at(&self, tokens: usize) -> Result { + self.input.offset_at(tokens) + } + #[inline(always)] + fn next_slice(&self, offset: usize) -> (Self, Self::Slice) { + let (next, slice) = self.input.next_slice(offset); + ( + Self { + initial: self.initial.clone(), + input: next, + }, + slice, + ) + } } impl Input for Stateful { - type Token = ::Token; - type Slice = ::Slice; - - type IterOffsets = ::IterOffsets; - - #[inline(always)] - fn iter_offsets(&self) -> Self::IterOffsets { - self.input.iter_offsets() - } - #[inline(always)] - fn input_len(&self) -> usize { - self.input.input_len() - } - - #[inline(always)] - fn next_token(&self) -> Option<(Self, Self::Token)> { - let (next, token) = self.input.next_token()?; - Some(( - Self { - input: next, - state: self.state.clone(), - }, - token, - )) - } - - #[inline(always)] - fn offset_for

(&self, predicate: P) -> Option - where - P: Fn(Self::Token) -> bool, - { - self.input.offset_for(predicate) - } - #[inline(always)] - fn offset_at(&self, tokens: usize) -> Result { - self.input.offset_at(tokens) - } - #[inline(always)] - fn next_slice(&self, offset: usize) -> (Self, Self::Slice) { - let (next, slice) = self.input.next_slice(offset); - ( - Self { - input: next, - state: self.state.clone(), - }, - slice, - ) - } + type Token = ::Token; + type Slice = ::Slice; + + type IterOffsets = ::IterOffsets; + + #[inline(always)] + fn iter_offsets(&self) -> Self::IterOffsets { + self.input.iter_offsets() + } + #[inline(always)] + fn input_len(&self) -> usize { + self.input.input_len() + } + + #[inline(always)] + fn next_token(&self) -> Option<(Self, Self::Token)> { + let (next, token) = self.input.next_token()?; + Some(( + Self { + input: next, + state: self.state.clone(), + }, + token, + )) + } + + #[inline(always)] + fn offset_for

(&self, predicate: P) -> Option + where + P: Fn(Self::Token) -> bool, + { + self.input.offset_for(predicate) + } + #[inline(always)] + fn offset_at(&self, tokens: usize) -> Result { + self.input.offset_at(tokens) + } + #[inline(always)] + fn next_slice(&self, offset: usize) -> (Self, Self::Slice) { + let (next, slice) = self.input.next_slice(offset); + ( + Self { + input: next, + state: self.state.clone(), + }, + slice, + ) + } } impl Input for Streaming { - type Token = ::Token; - type Slice = ::Slice; - - type IterOffsets = ::IterOffsets; - - #[inline(always)] - fn iter_offsets(&self) -> Self::IterOffsets { - self.0.iter_offsets() - } - #[inline(always)] - fn input_len(&self) -> usize { - self.0.input_len() - } - - #[inline(always)] - fn next_token(&self) -> Option<(Self, Self::Token)> { - let (next, token) = self.0.next_token()?; - Some((Streaming(next), token)) - } - - #[inline(always)] - fn offset_for

(&self, predicate: P) -> Option - where - P: Fn(Self::Token) -> bool, - { - self.0.offset_for(predicate) - } - #[inline(always)] - fn offset_at(&self, tokens: usize) -> Result { - self.0.offset_at(tokens) - } - #[inline(always)] - fn next_slice(&self, offset: usize) -> (Self, Self::Slice) { - let (next, slice) = self.0.next_slice(offset); - (Streaming(next), slice) - } + type Token = ::Token; + type Slice = ::Slice; + + type IterOffsets = ::IterOffsets; + + #[inline(always)] + fn iter_offsets(&self) -> Self::IterOffsets { + self.0.iter_offsets() + } + #[inline(always)] + fn input_len(&self) -> usize { + self.0.input_len() + } + + #[inline(always)] + fn next_token(&self) -> Option<(Self, Self::Token)> { + let (next, token) = self.0.next_token()?; + Some((Streaming(next), token)) + } + + #[inline(always)] + fn offset_for

(&self, predicate: P) -> Option + where + P: Fn(Self::Token) -> bool, + { + self.0.offset_for(predicate) + } + #[inline(always)] + fn offset_at(&self, tokens: usize) -> Result { + self.0.offset_at(tokens) + } + #[inline(always)] + fn next_slice(&self, offset: usize) -> (Self, Self::Slice) { + let (next, slice) = self.0.next_slice(offset); + (Streaming(next), slice) + } } /// Number of indices input has advanced since start of parsing pub trait Location { - /// Number of indices input has advanced since start of parsing - fn location(&self) -> usize; + /// Number of indices input has advanced since start of parsing + fn location(&self) -> usize; } impl Location for Located where - I: Clone + Offset, + I: Clone + Offset, { - fn location(&self) -> usize { - self.location() - } + fn location(&self) -> usize { + self.location() + } } impl Location for Stateful where - I: Location, + I: Location, { - fn location(&self) -> usize { - self.input.location() - } + fn location(&self) -> usize { + self.input.location() + } } impl Location for Streaming where - I: Location, + I: Location, { - fn location(&self) -> usize { - self.0.location() - } + fn location(&self) -> usize { + self.0.location() + } } /// Marks the input as being the complete buffer or a partial buffer for streaming input /// /// See [Streaming] for marking a presumed complete buffer type as a streaming buffer. pub trait InputIsStreaming: Sized { - /// Complete counterpart - /// - /// - Set to `Self` if this is a complete buffer. - /// - Set to [`std::convert::Infallible`] if there isn't an associated complete buffer type - type Complete: InputIsStreaming; - /// Streaming counterpart - /// - /// - Set to `Self` if this is a streaming buffer. - /// - Set to [`std::convert::Infallible`] if there isn't an associated streaming buffer type - type Streaming: InputIsStreaming; - - /// Convert to complete counterpart - fn into_complete(self) -> Self::Complete; - /// Convert to streaming counterpart - fn into_streaming(self) -> Self::Streaming; + /// Complete counterpart + /// + /// - Set to `Self` if this is a complete buffer. + /// - Set to [`std::convert::Infallible`] if there isn't an associated complete buffer type + type Complete: InputIsStreaming; + /// Streaming counterpart + /// + /// - Set to `Self` if this is a streaming buffer. + /// - Set to [`std::convert::Infallible`] if there isn't an associated streaming buffer type + type Streaming: InputIsStreaming; + + /// Convert to complete counterpart + fn into_complete(self) -> Self::Complete; + /// Convert to streaming counterpart + fn into_streaming(self) -> Self::Streaming; } impl<'a, T> InputIsStreaming for &'a [T] { - type Complete = Self; - type Streaming = Streaming; + type Complete = Self; + type Streaming = Streaming; - #[inline(always)] - fn into_complete(self) -> Self::Complete { - self - } - #[inline(always)] - fn into_streaming(self) -> Self::Streaming { - Streaming(self) - } + #[inline(always)] + fn into_complete(self) -> Self::Complete { + self + } + #[inline(always)] + fn into_streaming(self) -> Self::Streaming { + Streaming(self) + } } impl<'a> InputIsStreaming for &'a str { - type Complete = Self; - type Streaming = Streaming; + type Complete = Self; + type Streaming = Streaming; - #[inline(always)] - fn into_complete(self) -> Self::Complete { - self - } - #[inline(always)] - fn into_streaming(self) -> Self::Streaming { - Streaming(self) - } + #[inline(always)] + fn into_complete(self) -> Self::Complete { + self + } + #[inline(always)] + fn into_streaming(self) -> Self::Streaming { + Streaming(self) + } } impl InputIsStreaming for crate::lib::std::convert::Infallible { - type Complete = Self; - type Streaming = Self; + type Complete = Self; + type Streaming = Self; - #[inline(always)] - fn into_complete(self) -> Self::Complete { - self - } - #[inline(always)] - fn into_streaming(self) -> Self::Streaming { - self - } + #[inline(always)] + fn into_complete(self) -> Self::Complete { + self + } + #[inline(always)] + fn into_streaming(self) -> Self::Streaming { + self + } } impl InputIsStreaming for Located where - I: InputIsStreaming, + I: InputIsStreaming, { - type Complete = Located<>::Complete>; - type Streaming = Self; - - #[inline(always)] - fn into_complete(self) -> Self::Complete { - Located { - initial: self.initial.into_complete(), - input: self.input.into_complete(), + type Complete = Located<>::Complete>; + type Streaming = Self; + + #[inline(always)] + fn into_complete(self) -> Self::Complete { + Located { + initial: self.initial.into_complete(), + input: self.input.into_complete(), + } + } + #[inline(always)] + fn into_streaming(self) -> Self::Streaming { + self } - } - #[inline(always)] - fn into_streaming(self) -> Self::Streaming { - self - } } impl InputIsStreaming for Located where - I: InputIsStreaming, + I: InputIsStreaming, { - type Complete = Self; - type Streaming = Located<>::Streaming>; + type Complete = Self; + type Streaming = Located<>::Streaming>; - #[inline(always)] - fn into_complete(self) -> Self::Complete { - self - } - #[inline(always)] - fn into_streaming(self) -> Self::Streaming { - Located { - initial: self.initial.into_streaming(), - input: self.input.into_streaming(), + #[inline(always)] + fn into_complete(self) -> Self::Complete { + self + } + #[inline(always)] + fn into_streaming(self) -> Self::Streaming { + Located { + initial: self.initial.into_streaming(), + input: self.input.into_streaming(), + } } - } } impl InputIsStreaming for Stateful where - I: InputIsStreaming, + I: InputIsStreaming, { - type Complete = Stateful<>::Complete, S>; - type Streaming = Self; - - #[inline(always)] - fn into_complete(self) -> Self::Complete { - Stateful { - input: self.input.into_complete(), - state: self.state, + type Complete = Stateful<>::Complete, S>; + type Streaming = Self; + + #[inline(always)] + fn into_complete(self) -> Self::Complete { + Stateful { + input: self.input.into_complete(), + state: self.state, + } + } + #[inline(always)] + fn into_streaming(self) -> Self::Streaming { + self } - } - #[inline(always)] - fn into_streaming(self) -> Self::Streaming { - self - } } impl InputIsStreaming for Stateful where - I: InputIsStreaming, + I: InputIsStreaming, { - type Complete = Self; - type Streaming = Stateful<>::Streaming, S>; + type Complete = Self; + type Streaming = Stateful<>::Streaming, S>; - #[inline(always)] - fn into_complete(self) -> Self::Complete { - self - } - #[inline(always)] - fn into_streaming(self) -> Self::Streaming { - Stateful { - input: self.input.into_streaming(), - state: self.state, + #[inline(always)] + fn into_complete(self) -> Self::Complete { + self + } + #[inline(always)] + fn into_streaming(self) -> Self::Streaming { + Stateful { + input: self.input.into_streaming(), + state: self.state, + } } - } } impl InputIsStreaming for Streaming where - I: InputIsStreaming, + I: InputIsStreaming, { - type Complete = I; - type Streaming = Self; + type Complete = I; + type Streaming = Self; - #[inline(always)] - fn into_complete(self) -> Self::Complete { - self.0 - } - #[inline(always)] - fn into_streaming(self) -> Self::Streaming { - self - } + #[inline(always)] + fn into_complete(self) -> Self::Complete { + self.0 + } + #[inline(always)] + fn into_streaming(self) -> Self::Streaming { + self + } } /// Useful functions to calculate the offset between slices and show a hexdump of a slice pub trait Offset { - /// Offset between the first byte of self and the first byte of the argument - fn offset_to(&self, second: &Self) -> usize; + /// Offset between the first byte of self and the first byte of the argument + fn offset_to(&self, second: &Self) -> usize; } impl<'a, T> Offset for &'a [T] { - fn offset_to(&self, second: &Self) -> usize { - let fst = self.as_ptr(); - let snd = second.as_ptr(); - - debug_assert!( - fst <= snd, - "`Offset::offset_to` only accepts slices of `self`" - ); - snd as usize - fst as usize - } + fn offset_to(&self, second: &Self) -> usize { + let fst = self.as_ptr(); + let snd = second.as_ptr(); + + debug_assert!( + fst <= snd, + "`Offset::offset_to` only accepts slices of `self`" + ); + snd as usize - fst as usize + } } /// Convenience implementation to accept `&[T]` instead of `&&[T]` as above impl Offset for [T] { - fn offset_to(&self, second: &Self) -> usize { - let fst = self.as_ptr(); - let snd = second.as_ptr(); - - debug_assert!( - fst <= snd, - "`Offset::offset_to` only accepts slices of `self`" - ); - snd as usize - fst as usize - } + fn offset_to(&self, second: &Self) -> usize { + let fst = self.as_ptr(); + let snd = second.as_ptr(); + + debug_assert!( + fst <= snd, + "`Offset::offset_to` only accepts slices of `self`" + ); + snd as usize - fst as usize + } } impl<'a> Offset for &'a str { - fn offset_to(&self, second: &Self) -> usize { - let fst = self.as_ptr(); - let snd = second.as_ptr(); - - debug_assert!( - fst <= snd, - "`Offset::offset_to` only accepts slices of `self`" - ); - snd as usize - fst as usize - } + fn offset_to(&self, second: &Self) -> usize { + let fst = self.as_ptr(); + let snd = second.as_ptr(); + + debug_assert!( + fst <= snd, + "`Offset::offset_to` only accepts slices of `self`" + ); + snd as usize - fst as usize + } } /// Convenience implementation to accept `&str` instead of `&&str` as above impl Offset for str { - fn offset_to(&self, second: &Self) -> usize { - let fst = self.as_ptr(); - let snd = second.as_ptr(); - - debug_assert!( - fst <= snd, - "`Offset::offset_to` only accepts slices of `self`" - ); - snd as usize - fst as usize - } + fn offset_to(&self, second: &Self) -> usize { + let fst = self.as_ptr(); + let snd = second.as_ptr(); + + debug_assert!( + fst <= snd, + "`Offset::offset_to` only accepts slices of `self`" + ); + snd as usize - fst as usize + } } impl Offset for Located where - I: Offset, + I: Offset, { - fn offset_to(&self, other: &Self) -> usize { - self.input.offset_to(&other.input) - } + fn offset_to(&self, other: &Self) -> usize { + self.input.offset_to(&other.input) + } } impl Offset for Stateful where - I: Offset, + I: Offset, { - fn offset_to(&self, other: &Self) -> usize { - self.input.offset_to(&other.input) - } + fn offset_to(&self, other: &Self) -> usize { + self.input.offset_to(&other.input) + } } impl Offset for Streaming where - I: Offset, + I: Offset, { - #[inline(always)] - fn offset_to(&self, second: &Self) -> usize { - self.0.offset_to(&second.0) - } + #[inline(always)] + fn offset_to(&self, second: &Self) -> usize { + self.0.offset_to(&second.0) + } } /// Helper trait for types that can be viewed as a byte slice pub trait AsBytes { - /// Casts the input type to a byte slice - fn as_bytes(&self) -> &[u8]; + /// Casts the input type to a byte slice + fn as_bytes(&self) -> &[u8]; } impl<'a> AsBytes for &'a [u8] { - #[inline(always)] - fn as_bytes(&self) -> &[u8] { - self - } + #[inline(always)] + fn as_bytes(&self) -> &[u8] { + self + } } impl AsBytes for Located where - I: AsBytes, + I: AsBytes, { - fn as_bytes(&self) -> &[u8] { - self.input.as_bytes() - } + fn as_bytes(&self) -> &[u8] { + self.input.as_bytes() + } } impl AsBytes for Stateful where - I: AsBytes, + I: AsBytes, { - fn as_bytes(&self) -> &[u8] { - self.input.as_bytes() - } + fn as_bytes(&self) -> &[u8] { + self.input.as_bytes() + } } impl AsBytes for Streaming where - I: AsBytes, + I: AsBytes, { - #[inline(always)] - fn as_bytes(&self) -> &[u8] { - self.0.as_bytes() - } + #[inline(always)] + fn as_bytes(&self) -> &[u8] { + self.0.as_bytes() + } } /// Helper trait for types that can be viewed as a byte slice pub trait AsBStr { - /// Casts the input type to a byte slice - fn as_bstr(&self) -> &[u8]; + /// Casts the input type to a byte slice + fn as_bstr(&self) -> &[u8]; } impl<'a> AsBStr for &'a [u8] { - #[inline(always)] - fn as_bstr(&self) -> &[u8] { - self - } + #[inline(always)] + fn as_bstr(&self) -> &[u8] { + self + } } impl<'a> AsBStr for &'a str { - #[inline(always)] - fn as_bstr(&self) -> &[u8] { - (*self).as_bytes() - } + #[inline(always)] + fn as_bstr(&self) -> &[u8] { + (*self).as_bytes() + } } impl AsBStr for Located where - I: AsBStr, + I: AsBStr, { - fn as_bstr(&self) -> &[u8] { - self.input.as_bstr() - } + fn as_bstr(&self) -> &[u8] { + self.input.as_bstr() + } } impl AsBStr for Stateful where - I: AsBStr, + I: AsBStr, { - fn as_bstr(&self) -> &[u8] { - self.input.as_bstr() - } + fn as_bstr(&self) -> &[u8] { + self.input.as_bstr() + } } impl AsBStr for Streaming where - I: AsBStr, + I: AsBStr, { - #[inline(always)] - fn as_bstr(&self) -> &[u8] { - self.0.as_bstr() - } + #[inline(always)] + fn as_bstr(&self) -> &[u8] { + self.0.as_bstr() + } } /// Indicates whether a comparison was successful, an error, or /// if more data was needed #[derive(Debug, Eq, PartialEq)] pub enum CompareResult { - /// Comparison was successful - Ok, - /// We need more data to be sure - Incomplete, - /// Comparison failed - Error, + /// Comparison was successful + Ok, + /// We need more data to be sure + Incomplete, + /// Comparison failed + Error, } /// Abstracts comparison operations pub trait Compare { - /// Compares self to another value for equality - fn compare(&self, t: T) -> CompareResult; - /// Compares self to another value for equality - /// independently of the case. - /// - /// Warning: for `&str`, the comparison is done - /// by lowercasing both strings and comparing - /// the result. This is a temporary solution until - /// a better one appears - fn compare_no_case(&self, t: T) -> CompareResult; + /// Compares self to another value for equality + fn compare(&self, t: T) -> CompareResult; + /// Compares self to another value for equality + /// independently of the case. + /// + /// Warning: for `&str`, the comparison is done + /// by lowercasing both strings and comparing + /// the result. This is a temporary solution until + /// a better one appears + fn compare_no_case(&self, t: T) -> CompareResult; } fn lowercase_byte(c: u8) -> u8 { - match c { - b'A'..=b'Z' => c - b'A' + b'a', - _ => c, - } + match c { + b'A'..=b'Z' => c - b'A' + b'a', + _ => c, + } } impl<'a, 'b> Compare<&'b [u8]> for &'a [u8] { - #[inline(always)] - fn compare(&self, t: &'b [u8]) -> CompareResult { - let pos = self.iter().zip(t.iter()).position(|(a, b)| a != b); - - match pos { - Some(_) => CompareResult::Error, - None => { - if self.len() >= t.len() { - CompareResult::Ok - } else { - CompareResult::Incomplete + #[inline(always)] + fn compare(&self, t: &'b [u8]) -> CompareResult { + let pos = self.iter().zip(t.iter()).position(|(a, b)| a != b); + + match pos { + Some(_) => CompareResult::Error, + None => { + if self.len() >= t.len() { + CompareResult::Ok + } else { + CompareResult::Incomplete + } + } } - } } - } - #[inline(always)] - fn compare_no_case(&self, t: &'b [u8]) -> CompareResult { - if self - .iter() - .zip(t) - .any(|(a, b)| lowercase_byte(*a) != lowercase_byte(*b)) - { - CompareResult::Error - } else if self.len() < t.len() { - CompareResult::Incomplete - } else { - CompareResult::Ok + #[inline(always)] + fn compare_no_case(&self, t: &'b [u8]) -> CompareResult { + if self + .iter() + .zip(t) + .any(|(a, b)| lowercase_byte(*a) != lowercase_byte(*b)) + { + CompareResult::Error + } else if self.len() < t.len() { + CompareResult::Incomplete + } else { + CompareResult::Ok + } } - } } impl<'a, 'b, const LEN: usize> Compare<&'b [u8; LEN]> for &'a [u8] { - #[inline(always)] - fn compare(&self, t: &'b [u8; LEN]) -> CompareResult { - self.compare(&t[..]) - } + #[inline(always)] + fn compare(&self, t: &'b [u8; LEN]) -> CompareResult { + self.compare(&t[..]) + } - #[inline(always)] - fn compare_no_case(&self, t: &'b [u8; LEN]) -> CompareResult { - self.compare_no_case(&t[..]) - } + #[inline(always)] + fn compare_no_case(&self, t: &'b [u8; LEN]) -> CompareResult { + self.compare_no_case(&t[..]) + } } impl<'a, 'b> Compare<&'b str> for &'a [u8] { - #[inline(always)] - fn compare(&self, t: &'b str) -> CompareResult { - self.compare(t.as_bytes()) - } - #[inline(always)] - fn compare_no_case(&self, t: &'b str) -> CompareResult { - self.compare_no_case(t.as_bytes()) - } + #[inline(always)] + fn compare(&self, t: &'b str) -> CompareResult { + self.compare(t.as_bytes()) + } + #[inline(always)] + fn compare_no_case(&self, t: &'b str) -> CompareResult { + self.compare_no_case(t.as_bytes()) + } } impl<'a, 'b> Compare<&'b str> for &'a str { - #[inline(always)] - fn compare(&self, t: &'b str) -> CompareResult { - self.as_bytes().compare(t.as_bytes()) - } - - //FIXME: this version is too simple and does not use the current locale - #[inline(always)] - fn compare_no_case(&self, t: &'b str) -> CompareResult { - let pos = self - .chars() - .zip(t.chars()) - .position(|(a, b)| a.to_lowercase().ne(b.to_lowercase())); - - match pos { - Some(_) => CompareResult::Error, - None => { - if self.len() >= t.len() { - CompareResult::Ok - } else { - CompareResult::Incomplete + #[inline(always)] + fn compare(&self, t: &'b str) -> CompareResult { + self.as_bytes().compare(t.as_bytes()) + } + + //FIXME: this version is too simple and does not use the current locale + #[inline(always)] + fn compare_no_case(&self, t: &'b str) -> CompareResult { + let pos = self + .chars() + .zip(t.chars()) + .position(|(a, b)| a.to_lowercase().ne(b.to_lowercase())); + + match pos { + Some(_) => CompareResult::Error, + None => { + if self.len() >= t.len() { + CompareResult::Ok + } else { + CompareResult::Incomplete + } + } } - } } - } } impl<'a, 'b> Compare<&'b [u8]> for &'a str { - #[inline(always)] - fn compare(&self, t: &'b [u8]) -> CompareResult { - AsBStr::as_bstr(self).compare(t) - } - #[inline(always)] - fn compare_no_case(&self, t: &'b [u8]) -> CompareResult { - AsBStr::as_bstr(self).compare_no_case(t) - } + #[inline(always)] + fn compare(&self, t: &'b [u8]) -> CompareResult { + AsBStr::as_bstr(self).compare(t) + } + #[inline(always)] + fn compare_no_case(&self, t: &'b [u8]) -> CompareResult { + AsBStr::as_bstr(self).compare_no_case(t) + } } impl<'a, const LEN: usize> Compare<[u8; LEN]> for &'a [u8] { - #[inline(always)] - fn compare(&self, t: [u8; LEN]) -> CompareResult { - self.compare(&t[..]) - } + #[inline(always)] + fn compare(&self, t: [u8; LEN]) -> CompareResult { + self.compare(&t[..]) + } - #[inline(always)] - fn compare_no_case(&self, t: [u8; LEN]) -> CompareResult { - self.compare_no_case(&t[..]) - } + #[inline(always)] + fn compare_no_case(&self, t: [u8; LEN]) -> CompareResult { + self.compare_no_case(&t[..]) + } } impl Compare for Located where - I: Compare, + I: Compare, { - fn compare(&self, other: U) -> CompareResult { - self.input.compare(other) - } + fn compare(&self, other: U) -> CompareResult { + self.input.compare(other) + } - fn compare_no_case(&self, other: U) -> CompareResult { - self.input.compare_no_case(other) - } + fn compare_no_case(&self, other: U) -> CompareResult { + self.input.compare_no_case(other) + } } impl Compare for Stateful where - I: Compare, + I: Compare, { - fn compare(&self, other: U) -> CompareResult { - self.input.compare(other) - } + fn compare(&self, other: U) -> CompareResult { + self.input.compare(other) + } - fn compare_no_case(&self, other: U) -> CompareResult { - self.input.compare_no_case(other) - } + fn compare_no_case(&self, other: U) -> CompareResult { + self.input.compare_no_case(other) + } } impl Compare for Streaming where - I: Compare, + I: Compare, { - #[inline(always)] - fn compare(&self, t: T) -> CompareResult { - self.0.compare(t) - } + #[inline(always)] + fn compare(&self, t: T) -> CompareResult { + self.0.compare(t) + } - #[inline(always)] - fn compare_no_case(&self, t: T) -> CompareResult { - self.0.compare_no_case(t) - } + #[inline(always)] + fn compare_no_case(&self, t: T) -> CompareResult { + self.0.compare_no_case(t) + } } /// Look for a slice in self pub trait FindSlice { - /// Returns the offset of the slice if it is found - fn find_slice(&self, substr: T) -> Option; + /// Returns the offset of the slice if it is found + fn find_slice(&self, substr: T) -> Option; } impl<'i, 's> FindSlice<&'s [u8]> for &'i [u8] { - fn find_slice(&self, substr: &'s [u8]) -> Option { - memchr::memmem::find(self, substr) - } + fn find_slice(&self, substr: &'s [u8]) -> Option { + memchr::memmem::find(self, substr) + } } impl<'i> FindSlice for &'i [u8] { - fn find_slice(&self, substr: u8) -> Option { - memchr::memchr(substr, self) - } + fn find_slice(&self, substr: u8) -> Option { + memchr::memchr(substr, self) + } } impl<'i, 's> FindSlice<&'s str> for &'i [u8] { - fn find_slice(&self, substr: &'s str) -> Option { - self.find_slice(substr.as_bytes()) - } + fn find_slice(&self, substr: &'s str) -> Option { + self.find_slice(substr.as_bytes()) + } } impl<'i, 's> FindSlice<&'s str> for &'i str { - fn find_slice(&self, substr: &'s str) -> Option { - self.find(substr) - } + fn find_slice(&self, substr: &'s str) -> Option { + self.find(substr) + } } impl<'i> FindSlice for &'i str { - fn find_slice(&self, substr: char) -> Option { - self.find(substr) - } + fn find_slice(&self, substr: char) -> Option { + self.find(substr) + } } impl FindSlice for Located where - I: FindSlice, + I: FindSlice, { - #[inline(always)] - fn find_slice(&self, substr: T) -> Option { - self.input.find_slice(substr) - } + #[inline(always)] + fn find_slice(&self, substr: T) -> Option { + self.input.find_slice(substr) + } } impl FindSlice for Stateful where - I: FindSlice, + I: FindSlice, { - #[inline(always)] - fn find_slice(&self, substr: T) -> Option { - self.input.find_slice(substr) - } + #[inline(always)] + fn find_slice(&self, substr: T) -> Option { + self.input.find_slice(substr) + } } impl FindSlice for Streaming where - I: FindSlice, + I: FindSlice, { - #[inline(always)] - fn find_slice(&self, substr: T) -> Option { - self.0.find_slice(substr) - } + #[inline(always)] + fn find_slice(&self, substr: T) -> Option { + self.0.find_slice(substr) + } } /// Used to integrate `str`'s `parse()` method pub trait ParseSlice { - /// Succeeds if `parse()` succeeded. The byte slice implementation - /// will first convert it to a `&str`, then apply the `parse()` function - fn parse_slice(&self) -> Option; + /// Succeeds if `parse()` succeeded. The byte slice implementation + /// will first convert it to a `&str`, then apply the `parse()` function + fn parse_slice(&self) -> Option; } impl<'a, R: FromStr> ParseSlice for &'a [u8] { - fn parse_slice(&self) -> Option { - from_utf8(self).ok().and_then(|s| s.parse().ok()) - } + fn parse_slice(&self) -> Option { + from_utf8(self).ok().and_then(|s| s.parse().ok()) + } } impl<'a, R: FromStr> ParseSlice for &'a str { - fn parse_slice(&self) -> Option { - self.parse().ok() - } + fn parse_slice(&self) -> Option { + self.parse().ok() + } } /// Convert an `Input` into an appropriate `Output` type pub trait UpdateSlice: Input { - /// Convert an `Output` type to be used as `Input` - fn update_slice(self, inner: Self::Slice) -> Self; + /// Convert an `Output` type to be used as `Input` + fn update_slice(self, inner: Self::Slice) -> Self; } impl<'a, T> UpdateSlice for &'a [T] where - T: Clone, + T: Clone, { - #[inline] - fn update_slice(self, inner: Self::Slice) -> Self { - inner - } + #[inline] + fn update_slice(self, inner: Self::Slice) -> Self { + inner + } } impl<'a> UpdateSlice for &'a str { - #[inline] - fn update_slice(self, inner: Self::Slice) -> Self { - inner - } + #[inline] + fn update_slice(self, inner: Self::Slice) -> Self { + inner + } } impl UpdateSlice for Located where - I: UpdateSlice, + I: UpdateSlice, { - #[inline] - fn update_slice(mut self, inner: Self::Slice) -> Self { - self.input = I::update_slice(self.input, inner); - self - } + #[inline] + fn update_slice(mut self, inner: Self::Slice) -> Self { + self.input = I::update_slice(self.input, inner); + self + } } impl UpdateSlice for Stateful where - I: UpdateSlice, - S: Clone, + I: UpdateSlice, + S: Clone, { - #[inline] - fn update_slice(mut self, inner: Self::Slice) -> Self { - self.input = I::update_slice(self.input, inner); - self - } + #[inline] + fn update_slice(mut self, inner: Self::Slice) -> Self { + self.input = I::update_slice(self.input, inner); + self + } } impl UpdateSlice for Streaming where - I: UpdateSlice, + I: UpdateSlice, { - #[inline] - fn update_slice(self, inner: Self::Slice) -> Self { - Streaming(I::update_slice(self.0, inner)) - } + #[inline] + fn update_slice(self, inner: Self::Slice) -> Self { + Streaming(I::update_slice(self.0, inner)) + } } /// Abstracts something which can extend an `Extend`. /// Used to build modified input slices in `escaped_transform` pub trait Accumulate: Sized { - /// Create a new `Extend` of the correct type - fn initial(capacity: Option) -> Self; - /// Accumulate the input into an accumulator - fn accumulate(&mut self, acc: T); + /// Create a new `Extend` of the correct type + fn initial(capacity: Option) -> Self; + /// Accumulate the input into an accumulator + fn accumulate(&mut self, acc: T); } impl Accumulate for () { - #[inline(always)] - fn initial(_capacity: Option) -> Self {} - #[inline(always)] - fn accumulate(&mut self, _acc: T) {} + #[inline(always)] + fn initial(_capacity: Option) -> Self {} + #[inline(always)] + fn accumulate(&mut self, _acc: T) {} } impl Accumulate for usize { - #[inline(always)] - fn initial(_capacity: Option) -> Self { - 0 - } - #[inline(always)] - fn accumulate(&mut self, _acc: T) { - *self += 1; - } + #[inline(always)] + fn initial(_capacity: Option) -> Self { + 0 + } + #[inline(always)] + fn accumulate(&mut self, _acc: T) { + *self += 1; + } } #[cfg(feature = "alloc")] impl Accumulate for Vec { - #[inline(always)] - fn initial(capacity: Option) -> Self { - match capacity { - Some(capacity) => Vec::with_capacity(clamp_capacity::(capacity)), - None => Vec::new(), + #[inline(always)] + fn initial(capacity: Option) -> Self { + match capacity { + Some(capacity) => Vec::with_capacity(clamp_capacity::(capacity)), + None => Vec::new(), + } + } + #[inline(always)] + fn accumulate(&mut self, acc: T) { + self.push(acc); } - } - #[inline(always)] - fn accumulate(&mut self, acc: T) { - self.push(acc); - } } #[cfg(feature = "alloc")] impl<'i, T: Clone> Accumulate<&'i [T]> for Vec { - #[inline(always)] - fn initial(capacity: Option) -> Self { - match capacity { - Some(capacity) => Vec::with_capacity(clamp_capacity::(capacity)), - None => Vec::new(), + #[inline(always)] + fn initial(capacity: Option) -> Self { + match capacity { + Some(capacity) => Vec::with_capacity(clamp_capacity::(capacity)), + None => Vec::new(), + } + } + #[inline(always)] + fn accumulate(&mut self, acc: &'i [T]) { + self.extend(acc.iter().cloned()); } - } - #[inline(always)] - fn accumulate(&mut self, acc: &'i [T]) { - self.extend(acc.iter().cloned()); - } } #[cfg(feature = "alloc")] impl Accumulate for String { - #[inline(always)] - fn initial(capacity: Option) -> Self { - match capacity { - Some(capacity) => String::with_capacity(clamp_capacity::(capacity)), - None => String::new(), + #[inline(always)] + fn initial(capacity: Option) -> Self { + match capacity { + Some(capacity) => String::with_capacity(clamp_capacity::(capacity)), + None => String::new(), + } + } + #[inline(always)] + fn accumulate(&mut self, acc: char) { + self.push(acc); } - } - #[inline(always)] - fn accumulate(&mut self, acc: char) { - self.push(acc); - } } #[cfg(feature = "alloc")] impl<'i> Accumulate<&'i str> for String { - #[inline(always)] - fn initial(capacity: Option) -> Self { - match capacity { - Some(capacity) => String::with_capacity(clamp_capacity::(capacity)), - None => String::new(), + #[inline(always)] + fn initial(capacity: Option) -> Self { + match capacity { + Some(capacity) => String::with_capacity(clamp_capacity::(capacity)), + None => String::new(), + } + } + #[inline(always)] + fn accumulate(&mut self, acc: &'i str) { + self.push_str(acc); } - } - #[inline(always)] - fn accumulate(&mut self, acc: &'i str) { - self.push_str(acc); - } } #[cfg(feature = "alloc")] impl Accumulate<(K, V)> for BTreeMap where - K: crate::lib::std::cmp::Ord, + K: crate::lib::std::cmp::Ord, { - #[inline(always)] - fn initial(_capacity: Option) -> Self { - BTreeMap::new() - } - #[inline(always)] - fn accumulate(&mut self, (key, value): (K, V)) { - self.insert(key, value); - } + #[inline(always)] + fn initial(_capacity: Option) -> Self { + BTreeMap::new() + } + #[inline(always)] + fn accumulate(&mut self, (key, value): (K, V)) { + self.insert(key, value); + } } #[cfg(feature = "std")] impl Accumulate<(K, V)> for HashMap where - K: crate::lib::std::cmp::Eq + crate::lib::std::hash::Hash, + K: crate::lib::std::cmp::Eq + crate::lib::std::hash::Hash, { - #[inline(always)] - fn initial(capacity: Option) -> Self { - match capacity { - Some(capacity) => HashMap::with_capacity(clamp_capacity::<(K, V)>(capacity)), - None => HashMap::new(), + #[inline(always)] + fn initial(capacity: Option) -> Self { + match capacity { + Some(capacity) => HashMap::with_capacity(clamp_capacity::<(K, V)>(capacity)), + None => HashMap::new(), + } + } + #[inline(always)] + fn accumulate(&mut self, (key, value): (K, V)) { + self.insert(key, value); } - } - #[inline(always)] - fn accumulate(&mut self, (key, value): (K, V)) { - self.insert(key, value); - } } #[cfg(feature = "alloc")] #[inline] pub(crate) fn clamp_capacity(capacity: usize) -> usize { - /// Don't pre-allocate more than 64KiB when calling `Vec::with_capacity`. - /// - /// Pre-allocating memory is a nice optimization but count fields can't - /// always be trusted. We should clamp initial capacities to some reasonable - /// amount. This reduces the risk of a bogus count value triggering a panic - /// due to an OOM error. - /// - /// This does not affect correctness. Nom will always read the full number - /// of elements regardless of the capacity cap. - const MAX_INITIAL_CAPACITY_BYTES: usize = 65536; - - let max_initial_capacity = - MAX_INITIAL_CAPACITY_BYTES / crate::lib::std::mem::size_of::().max(1); - capacity.min(max_initial_capacity) + /// Don't pre-allocate more than 64KiB when calling `Vec::with_capacity`. + /// + /// Pre-allocating memory is a nice optimization but count fields can't + /// always be trusted. We should clamp initial capacities to some reasonable + /// amount. This reduces the risk of a bogus count value triggering a panic + /// due to an OOM error. + /// + /// This does not affect correctness. Nom will always read the full number + /// of elements regardless of the capacity cap. + const MAX_INITIAL_CAPACITY_BYTES: usize = 65536; + + let max_initial_capacity = + MAX_INITIAL_CAPACITY_BYTES / crate::lib::std::mem::size_of::().max(1); + capacity.min(max_initial_capacity) } /// Helper trait to convert numbers to usize. @@ -1451,57 +1451,57 @@ pub(crate) fn clamp_capacity(capacity: usize) -> usize { /// platforms. This trait implements the conversion for platforms /// with 32 and 64 bits pointer platforms pub trait ToUsize { - /// converts self to usize - fn to_usize(&self) -> usize; + /// converts self to usize + fn to_usize(&self) -> usize; } impl ToUsize for u8 { - #[inline] - fn to_usize(&self) -> usize { - *self as usize - } + #[inline] + fn to_usize(&self) -> usize { + *self as usize + } } impl ToUsize for u16 { - #[inline] - fn to_usize(&self) -> usize { - *self as usize - } + #[inline] + fn to_usize(&self) -> usize { + *self as usize + } } impl ToUsize for usize { - #[inline] - fn to_usize(&self) -> usize { - *self - } + #[inline] + fn to_usize(&self) -> usize { + *self + } } #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] impl ToUsize for u32 { - #[inline] - fn to_usize(&self) -> usize { - *self as usize - } + #[inline] + fn to_usize(&self) -> usize { + *self as usize + } } #[cfg(target_pointer_width = "64")] impl ToUsize for u64 { - #[inline] - fn to_usize(&self) -> usize { - *self as usize - } + #[inline] + fn to_usize(&self) -> usize { + *self as usize + } } /// Helper trait to show a byte slice as a hex dump #[cfg(feature = "std")] pub trait HexDisplay { - /// Converts the value of `self` to a hex dump, returning the owned - /// `String`. - fn to_hex(&self, chunk_size: usize) -> String; + /// Converts the value of `self` to a hex dump, returning the owned + /// `String`. + fn to_hex(&self, chunk_size: usize) -> String; - /// Converts the value of `self` to a hex dump beginning at `from` address, returning the owned - /// `String`. - fn to_hex_from(&self, chunk_size: usize, from: usize) -> String; + /// Converts the value of `self` to a hex dump beginning at `from` address, returning the owned + /// `String`. + fn to_hex_from(&self, chunk_size: usize, from: usize) -> String; } #[cfg(feature = "std")] @@ -1509,299 +1509,299 @@ static CHARS: &[u8] = b"0123456789abcdef"; #[cfg(feature = "std")] impl HexDisplay for &'_ [u8] { - #[allow(unused_variables)] - fn to_hex(&self, chunk_size: usize) -> String { - self.to_hex_from(chunk_size, 0) - } - - #[allow(unused_variables)] - fn to_hex_from(&self, chunk_size: usize, from: usize) -> String { - let mut v = Vec::with_capacity(self.len() * 3); - let mut i = from; - for chunk in self.chunks(chunk_size) { - let s = format!("{:08x}", i); - for &ch in s.as_bytes().iter() { - v.push(ch); - } - v.push(b'\t'); - - i += chunk_size; + #[allow(unused_variables)] + fn to_hex(&self, chunk_size: usize) -> String { + self.to_hex_from(chunk_size, 0) + } - for &byte in chunk { - v.push(CHARS[(byte >> 4) as usize]); - v.push(CHARS[(byte & 0xf) as usize]); - v.push(b' '); - } - if chunk_size > chunk.len() { - for j in 0..(chunk_size - chunk.len()) { - v.push(b' '); - v.push(b' '); - v.push(b' '); + #[allow(unused_variables)] + fn to_hex_from(&self, chunk_size: usize, from: usize) -> String { + let mut v = Vec::with_capacity(self.len() * 3); + let mut i = from; + for chunk in self.chunks(chunk_size) { + let s = format!("{:08x}", i); + for &ch in s.as_bytes().iter() { + v.push(ch); + } + v.push(b'\t'); + + i += chunk_size; + + for &byte in chunk { + v.push(CHARS[(byte >> 4) as usize]); + v.push(CHARS[(byte & 0xf) as usize]); + v.push(b' '); + } + if chunk_size > chunk.len() { + for j in 0..(chunk_size - chunk.len()) { + v.push(b' '); + v.push(b' '); + v.push(b' '); + } + } + v.push(b'\t'); + + for &byte in chunk { + if matches!(byte, 32..=126 | 128..=255) { + v.push(byte); + } else { + v.push(b'.'); + } + } + v.push(b'\n'); } - } - v.push(b'\t'); - for &byte in chunk { - if matches!(byte, 32..=126 | 128..=255) { - v.push(byte); - } else { - v.push(b'.'); - } - } - v.push(b'\n'); + String::from_utf8_lossy(&v[..]).into_owned() } - - String::from_utf8_lossy(&v[..]).into_owned() - } } #[cfg(feature = "std")] impl HexDisplay for &'_ str { - #[allow(unused_variables)] - fn to_hex(&self, chunk_size: usize) -> String { - self.to_hex_from(chunk_size, 0) - } + #[allow(unused_variables)] + fn to_hex(&self, chunk_size: usize) -> String { + self.to_hex_from(chunk_size, 0) + } - #[allow(unused_variables)] - fn to_hex_from(&self, chunk_size: usize, from: usize) -> String { - self.as_bytes().to_hex_from(chunk_size, from) - } + #[allow(unused_variables)] + fn to_hex_from(&self, chunk_size: usize, from: usize) -> String { + self.as_bytes().to_hex_from(chunk_size, from) + } } #[cfg(feature = "std")] impl HexDisplay for Located where - I: HexDisplay, + I: HexDisplay, { - #[inline(always)] - fn to_hex(&self, chunk_size: usize) -> String { - self.input.to_hex(chunk_size) - } + #[inline(always)] + fn to_hex(&self, chunk_size: usize) -> String { + self.input.to_hex(chunk_size) + } - #[inline(always)] - fn to_hex_from(&self, chunk_size: usize, from: usize) -> String { - self.input.to_hex_from(chunk_size, from) - } + #[inline(always)] + fn to_hex_from(&self, chunk_size: usize, from: usize) -> String { + self.input.to_hex_from(chunk_size, from) + } } #[cfg(feature = "std")] impl HexDisplay for Stateful where - I: HexDisplay, + I: HexDisplay, { - #[inline(always)] - fn to_hex(&self, chunk_size: usize) -> String { - self.input.to_hex(chunk_size) - } + #[inline(always)] + fn to_hex(&self, chunk_size: usize) -> String { + self.input.to_hex(chunk_size) + } - #[inline(always)] - fn to_hex_from(&self, chunk_size: usize, from: usize) -> String { - self.input.to_hex_from(chunk_size, from) - } + #[inline(always)] + fn to_hex_from(&self, chunk_size: usize, from: usize) -> String { + self.input.to_hex_from(chunk_size, from) + } } #[cfg(feature = "std")] impl HexDisplay for Streaming where - I: HexDisplay, + I: HexDisplay, { - #[inline(always)] - fn to_hex(&self, chunk_size: usize) -> String { - self.0.to_hex(chunk_size) - } + #[inline(always)] + fn to_hex(&self, chunk_size: usize) -> String { + self.0.to_hex(chunk_size) + } - #[inline(always)] - fn to_hex_from(&self, chunk_size: usize, from: usize) -> String { - self.0.to_hex_from(chunk_size, from) - } + #[inline(always)] + fn to_hex_from(&self, chunk_size: usize, from: usize) -> String { + self.0.to_hex_from(chunk_size, from) + } } /// Transforms common types to a char for basic token parsing #[allow(clippy::len_without_is_empty)] #[allow(clippy::wrong_self_convention)] pub trait AsChar { - /// Makes a char from self - /// - /// ``` - /// use winnow::input::AsChar as _; - /// - /// assert_eq!('a'.as_char(), 'a'); - /// assert_eq!(u8::MAX.as_char(), std::char::from_u32(u8::MAX as u32).unwrap()); - /// ``` - fn as_char(self) -> char; - - /// Tests that self is an alphabetic character - /// - /// Warning: for `&str` it recognizes alphabetic - /// characters outside of the 52 ASCII letters - fn is_alpha(self) -> bool; - - /// Tests that self is an alphabetic character - /// or a decimal digit - fn is_alphanum(self) -> bool; - /// Tests that self is a decimal digit - fn is_dec_digit(self) -> bool; - /// Tests that self is an hex digit - fn is_hex_digit(self) -> bool; - /// Tests that self is an octal digit - fn is_oct_digit(self) -> bool; - /// Gets the len in bytes for self - fn len(self) -> usize; - /// Tests that self is ASCII space or tab - fn is_space(self) -> bool; - /// Tests if byte is ASCII newline: \n - fn is_newline(self) -> bool; + /// Makes a char from self + /// + /// ``` + /// use winnow::input::AsChar as _; + /// + /// assert_eq!('a'.as_char(), 'a'); + /// assert_eq!(u8::MAX.as_char(), std::char::from_u32(u8::MAX as u32).unwrap()); + /// ``` + fn as_char(self) -> char; + + /// Tests that self is an alphabetic character + /// + /// Warning: for `&str` it recognizes alphabetic + /// characters outside of the 52 ASCII letters + fn is_alpha(self) -> bool; + + /// Tests that self is an alphabetic character + /// or a decimal digit + fn is_alphanum(self) -> bool; + /// Tests that self is a decimal digit + fn is_dec_digit(self) -> bool; + /// Tests that self is an hex digit + fn is_hex_digit(self) -> bool; + /// Tests that self is an octal digit + fn is_oct_digit(self) -> bool; + /// Gets the len in bytes for self + fn len(self) -> usize; + /// Tests that self is ASCII space or tab + fn is_space(self) -> bool; + /// Tests if byte is ASCII newline: \n + fn is_newline(self) -> bool; } impl AsChar for u8 { - #[inline] - fn as_char(self) -> char { - self as char - } - #[inline] - fn is_alpha(self) -> bool { - matches!(self, 0x41..=0x5A | 0x61..=0x7A) - } - #[inline] - fn is_alphanum(self) -> bool { - self.is_alpha() || self.is_dec_digit() - } - #[inline] - fn is_dec_digit(self) -> bool { - matches!(self, 0x30..=0x39) - } - #[inline] - fn is_hex_digit(self) -> bool { - matches!(self, 0x30..=0x39 | 0x41..=0x46 | 0x61..=0x66) - } - #[inline] - fn is_oct_digit(self) -> bool { - matches!(self, 0x30..=0x37) - } - #[inline] - fn len(self) -> usize { - 1 - } - #[inline] - fn is_space(self) -> bool { - self == b' ' || self == b'\t' - } - fn is_newline(self) -> bool { - self == b'\n' - } + #[inline] + fn as_char(self) -> char { + self as char + } + #[inline] + fn is_alpha(self) -> bool { + matches!(self, 0x41..=0x5A | 0x61..=0x7A) + } + #[inline] + fn is_alphanum(self) -> bool { + self.is_alpha() || self.is_dec_digit() + } + #[inline] + fn is_dec_digit(self) -> bool { + matches!(self, 0x30..=0x39) + } + #[inline] + fn is_hex_digit(self) -> bool { + matches!(self, 0x30..=0x39 | 0x41..=0x46 | 0x61..=0x66) + } + #[inline] + fn is_oct_digit(self) -> bool { + matches!(self, 0x30..=0x37) + } + #[inline] + fn len(self) -> usize { + 1 + } + #[inline] + fn is_space(self) -> bool { + self == b' ' || self == b'\t' + } + fn is_newline(self) -> bool { + self == b'\n' + } } impl<'a> AsChar for &'a u8 { - #[inline] - fn as_char(self) -> char { - *self as char - } - #[inline] - fn is_alpha(self) -> bool { - matches!(*self, 0x41..=0x5A | 0x61..=0x7A) - } - #[inline] - fn is_alphanum(self) -> bool { - self.is_alpha() || self.is_dec_digit() - } - #[inline] - fn is_dec_digit(self) -> bool { - matches!(*self, 0x30..=0x39) - } - #[inline] - fn is_hex_digit(self) -> bool { - matches!(*self, 0x30..=0x39 | 0x41..=0x46 | 0x61..=0x66) - } - #[inline] - fn is_oct_digit(self) -> bool { - matches!(*self, 0x30..=0x37) - } - #[inline] - fn len(self) -> usize { - 1 - } - #[inline] - fn is_space(self) -> bool { - *self == b' ' || *self == b'\t' - } - fn is_newline(self) -> bool { - *self == b'\n' - } + #[inline] + fn as_char(self) -> char { + *self as char + } + #[inline] + fn is_alpha(self) -> bool { + matches!(*self, 0x41..=0x5A | 0x61..=0x7A) + } + #[inline] + fn is_alphanum(self) -> bool { + self.is_alpha() || self.is_dec_digit() + } + #[inline] + fn is_dec_digit(self) -> bool { + matches!(*self, 0x30..=0x39) + } + #[inline] + fn is_hex_digit(self) -> bool { + matches!(*self, 0x30..=0x39 | 0x41..=0x46 | 0x61..=0x66) + } + #[inline] + fn is_oct_digit(self) -> bool { + matches!(*self, 0x30..=0x37) + } + #[inline] + fn len(self) -> usize { + 1 + } + #[inline] + fn is_space(self) -> bool { + *self == b' ' || *self == b'\t' + } + fn is_newline(self) -> bool { + *self == b'\n' + } } impl AsChar for char { - #[inline] - fn as_char(self) -> char { - self - } - #[inline] - fn is_alpha(self) -> bool { - self.is_ascii_alphabetic() - } - #[inline] - fn is_alphanum(self) -> bool { - self.is_alpha() || self.is_dec_digit() - } - #[inline] - fn is_dec_digit(self) -> bool { - self.is_ascii_digit() - } - #[inline] - fn is_hex_digit(self) -> bool { - self.is_ascii_hexdigit() - } - #[inline] - fn is_oct_digit(self) -> bool { - self.is_digit(8) - } - #[inline] - fn len(self) -> usize { - self.len_utf8() - } - #[inline] - fn is_space(self) -> bool { - self == ' ' || self == '\t' - } - fn is_newline(self) -> bool { - self == '\n' - } + #[inline] + fn as_char(self) -> char { + self + } + #[inline] + fn is_alpha(self) -> bool { + self.is_ascii_alphabetic() + } + #[inline] + fn is_alphanum(self) -> bool { + self.is_alpha() || self.is_dec_digit() + } + #[inline] + fn is_dec_digit(self) -> bool { + self.is_ascii_digit() + } + #[inline] + fn is_hex_digit(self) -> bool { + self.is_ascii_hexdigit() + } + #[inline] + fn is_oct_digit(self) -> bool { + self.is_digit(8) + } + #[inline] + fn len(self) -> usize { + self.len_utf8() + } + #[inline] + fn is_space(self) -> bool { + self == ' ' || self == '\t' + } + fn is_newline(self) -> bool { + self == '\n' + } } impl<'a> AsChar for &'a char { - #[inline] - fn as_char(self) -> char { - *self - } - #[inline] - fn is_alpha(self) -> bool { - self.is_ascii_alphabetic() - } - #[inline] - fn is_alphanum(self) -> bool { - self.is_alpha() || self.is_dec_digit() - } - #[inline] - fn is_dec_digit(self) -> bool { - self.is_ascii_digit() - } - #[inline] - fn is_hex_digit(self) -> bool { - self.is_ascii_hexdigit() - } - #[inline] - fn is_oct_digit(self) -> bool { - self.is_digit(8) - } - #[inline] - fn len(self) -> usize { - self.len_utf8() - } - #[inline] - fn is_space(self) -> bool { - *self == ' ' || *self == '\t' - } - fn is_newline(self) -> bool { - *self == '\n' - } + #[inline] + fn as_char(self) -> char { + *self + } + #[inline] + fn is_alpha(self) -> bool { + self.is_ascii_alphabetic() + } + #[inline] + fn is_alphanum(self) -> bool { + self.is_alpha() || self.is_dec_digit() + } + #[inline] + fn is_dec_digit(self) -> bool { + self.is_ascii_digit() + } + #[inline] + fn is_hex_digit(self) -> bool { + self.is_ascii_hexdigit() + } + #[inline] + fn is_oct_digit(self) -> bool { + self.is_digit(8) + } + #[inline] + fn len(self) -> usize { + self.len_utf8() + } + #[inline] + fn is_space(self) -> bool { + *self == ' ' || *self == '\t' + } + fn is_newline(self) -> bool { + *self == '\n' + } } /// Check if a token in in a set of possible tokens @@ -1828,189 +1828,189 @@ impl<'a> AsChar for &'a char { /// assert_eq!(hex_digit1(""), Err(ErrMode::Backtrack(Error::new("", ErrorKind::TakeWhile1)))); /// ``` pub trait ContainsToken { - /// Returns true if self contains the token - fn contains_token(&self, token: T) -> bool; + /// Returns true if self contains the token + fn contains_token(&self, token: T) -> bool; } impl ContainsToken for u8 { - fn contains_token(&self, token: u8) -> bool { - *self == token - } + fn contains_token(&self, token: u8) -> bool { + *self == token + } } impl<'a> ContainsToken<&'a u8> for u8 { - fn contains_token(&self, token: &u8) -> bool { - self.contains_token(*token) - } + fn contains_token(&self, token: &u8) -> bool { + self.contains_token(*token) + } } impl ContainsToken for u8 { - fn contains_token(&self, token: char) -> bool { - self.as_char() == token - } + fn contains_token(&self, token: char) -> bool { + self.as_char() == token + } } impl<'a> ContainsToken<&'a char> for u8 { - fn contains_token(&self, token: &char) -> bool { - self.contains_token(*token) - } + fn contains_token(&self, token: &char) -> bool { + self.contains_token(*token) + } } impl ContainsToken for char { - fn contains_token(&self, token: C) -> bool { - *self == token.as_char() - } + fn contains_token(&self, token: C) -> bool { + *self == token.as_char() + } } impl bool> ContainsToken for F { - fn contains_token(&self, token: C) -> bool { - self(token) - } + fn contains_token(&self, token: C) -> bool { + self(token) + } } impl ContainsToken for Range { - fn contains_token(&self, token: C1) -> bool { - let start = self.start.clone().as_char(); - let end = self.end.clone().as_char(); - (start..end).contains(&token.as_char()) - } + fn contains_token(&self, token: C1) -> bool { + let start = self.start.clone().as_char(); + let end = self.end.clone().as_char(); + (start..end).contains(&token.as_char()) + } } impl ContainsToken for RangeInclusive { - fn contains_token(&self, token: C1) -> bool { - let start = self.start().clone().as_char(); - let end = self.end().clone().as_char(); - (start..=end).contains(&token.as_char()) - } + fn contains_token(&self, token: C1) -> bool { + let start = self.start().clone().as_char(); + let end = self.end().clone().as_char(); + (start..=end).contains(&token.as_char()) + } } impl ContainsToken for RangeFrom { - fn contains_token(&self, token: C1) -> bool { - let start = self.start.clone().as_char(); - (start..).contains(&token.as_char()) - } + fn contains_token(&self, token: C1) -> bool { + let start = self.start.clone().as_char(); + (start..).contains(&token.as_char()) + } } impl ContainsToken for RangeTo { - fn contains_token(&self, token: C1) -> bool { - let end = self.end.clone().as_char(); - (..end).contains(&token.as_char()) - } + fn contains_token(&self, token: C1) -> bool { + let end = self.end.clone().as_char(); + (..end).contains(&token.as_char()) + } } impl ContainsToken for RangeToInclusive { - fn contains_token(&self, token: C1) -> bool { - let end = self.end.clone().as_char(); - (..=end).contains(&token.as_char()) - } + fn contains_token(&self, token: C1) -> bool { + let end = self.end.clone().as_char(); + (..=end).contains(&token.as_char()) + } } impl ContainsToken for RangeFull { - fn contains_token(&self, _token: C1) -> bool { - true - } + fn contains_token(&self, _token: C1) -> bool { + true + } } impl<'a> ContainsToken for &'a [u8] { - fn contains_token(&self, token: u8) -> bool { - memchr::memchr(token, self).is_some() - } + fn contains_token(&self, token: u8) -> bool { + memchr::memchr(token, self).is_some() + } } impl<'a, 'b> ContainsToken<&'a u8> for &'b [u8] { - fn contains_token(&self, token: &u8) -> bool { - self.contains_token(*token) - } + fn contains_token(&self, token: &u8) -> bool { + self.contains_token(*token) + } } impl<'a> ContainsToken for &'a [u8] { - fn contains_token(&self, token: char) -> bool { - self.iter().any(|i| i.as_char() == token) - } + fn contains_token(&self, token: char) -> bool { + self.iter().any(|i| i.as_char() == token) + } } impl<'a, 'b> ContainsToken<&'a char> for &'b [u8] { - fn contains_token(&self, token: &char) -> bool { - self.contains_token(*token) - } + fn contains_token(&self, token: &char) -> bool { + self.contains_token(*token) + } } impl ContainsToken for [u8; LEN] { - fn contains_token(&self, token: u8) -> bool { - memchr::memchr(token, &self[..]).is_some() - } + fn contains_token(&self, token: u8) -> bool { + memchr::memchr(token, &self[..]).is_some() + } } impl<'a, const LEN: usize> ContainsToken<&'a u8> for [u8; LEN] { - fn contains_token(&self, token: &u8) -> bool { - self.contains_token(*token) - } + fn contains_token(&self, token: &u8) -> bool { + self.contains_token(*token) + } } impl ContainsToken for [u8; LEN] { - fn contains_token(&self, token: char) -> bool { - self.iter().any(|i| i.as_char() == token) - } + fn contains_token(&self, token: char) -> bool { + self.iter().any(|i| i.as_char() == token) + } } impl<'a, const LEN: usize> ContainsToken<&'a char> for [u8; LEN] { - fn contains_token(&self, token: &char) -> bool { - self.contains_token(*token) - } + fn contains_token(&self, token: &char) -> bool { + self.contains_token(*token) + } } impl<'a> ContainsToken for &'a str { - fn contains_token(&self, token: u8) -> bool { - self.as_bytes().contains_token(token) - } + fn contains_token(&self, token: u8) -> bool { + self.as_bytes().contains_token(token) + } } impl<'a, 'b> ContainsToken<&'a u8> for &'b str { - fn contains_token(&self, token: &u8) -> bool { - self.as_bytes().contains_token(token) - } + fn contains_token(&self, token: &u8) -> bool { + self.as_bytes().contains_token(token) + } } impl<'a> ContainsToken for &'a str { - fn contains_token(&self, token: char) -> bool { - self.chars().any(|i| i == token) - } + fn contains_token(&self, token: char) -> bool { + self.chars().any(|i| i == token) + } } impl<'a, 'b> ContainsToken<&'a char> for &'b str { - fn contains_token(&self, token: &char) -> bool { - self.contains_token(*token) - } + fn contains_token(&self, token: &char) -> bool { + self.contains_token(*token) + } } impl<'a> ContainsToken for &'a [char] { - fn contains_token(&self, token: u8) -> bool { - self.iter().any(|i| *i == token.as_char()) - } + fn contains_token(&self, token: u8) -> bool { + self.iter().any(|i| *i == token.as_char()) + } } impl<'a, 'b> ContainsToken<&'a u8> for &'b [char] { - fn contains_token(&self, token: &u8) -> bool { - self.contains_token(*token) - } + fn contains_token(&self, token: &u8) -> bool { + self.contains_token(*token) + } } impl<'a> ContainsToken for &'a [char] { - fn contains_token(&self, token: char) -> bool { - self.iter().any(|i| *i == token) - } + fn contains_token(&self, token: char) -> bool { + self.iter().any(|i| *i == token) + } } impl<'a, 'b> ContainsToken<&'a char> for &'b [char] { - fn contains_token(&self, token: &char) -> bool { - self.contains_token(*token) - } + fn contains_token(&self, token: &char) -> bool { + self.contains_token(*token) + } } impl ContainsToken for () { - fn contains_token(&self, _token: T) -> bool { - false - } + fn contains_token(&self, _token: T) -> bool { + false + } } macro_rules! impl_contains_token_for_tuple { @@ -2043,7 +2043,7 @@ macro_rules! impl_contains_token_for_tuples { } impl_contains_token_for_tuples!( - F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21 + F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21 ); /// Looks for the first element of the input type for which the condition returns true, @@ -2051,16 +2051,16 @@ impl_contains_token_for_tuples!( /// /// *streaming version*: If no element is found matching the condition, this will return `Incomplete` pub(crate) fn split_at_offset_streaming>( - input: &I, - predicate: P, + input: &I, + predicate: P, ) -> IResult::Slice, E> where - P: Fn(I::Token) -> bool, + P: Fn(I::Token) -> bool, { - let offset = input - .offset_for(predicate) - .ok_or_else(|| ErrMode::Incomplete(Needed::new(1)))?; - Ok(input.next_slice(offset)) + let offset = input + .offset_for(predicate) + .ok_or_else(|| ErrMode::Incomplete(Needed::new(1)))?; + Ok(input.next_slice(offset)) } /// Looks for the first element of the input type for which the condition returns true @@ -2070,21 +2070,21 @@ where /// /// *streaming version*: If no element is found matching the condition, this will return `Incomplete` pub(crate) fn split_at_offset1_streaming>( - input: &I, - predicate: P, - e: ErrorKind, + input: &I, + predicate: P, + e: ErrorKind, ) -> IResult::Slice, E> where - P: Fn(I::Token) -> bool, + P: Fn(I::Token) -> bool, { - let offset = input - .offset_for(predicate) - .ok_or_else(|| ErrMode::Incomplete(Needed::new(1)))?; - if offset == 0 { - Err(ErrMode::from_error_kind(input.clone(), e)) - } else { - Ok(input.next_slice(offset)) - } + let offset = input + .offset_for(predicate) + .ok_or_else(|| ErrMode::Incomplete(Needed::new(1)))?; + if offset == 0 { + Err(ErrMode::from_error_kind(input.clone(), e)) + } else { + Ok(input.next_slice(offset)) + } } /// Looks for the first element of the input type for which the condition returns true, @@ -2092,16 +2092,16 @@ where /// /// *complete version*: If no element is found matching the condition, this will return the whole input pub(crate) fn split_at_offset_complete>( - input: &I, - predicate: P, + input: &I, + predicate: P, ) -> IResult::Slice, E> where - P: Fn(I::Token) -> bool, + P: Fn(I::Token) -> bool, { - let offset = input - .offset_for(predicate) - .unwrap_or_else(|| input.input_len()); - Ok(input.next_slice(offset)) + let offset = input + .offset_for(predicate) + .unwrap_or_else(|| input.input_len()); + Ok(input.next_slice(offset)) } /// Looks for the first element of the input type for which the condition returns true @@ -2111,47 +2111,47 @@ where /// /// *complete version*: If no element is found matching the condition, this will return the whole input pub(crate) fn split_at_offset1_complete>( - input: &I, - predicate: P, - e: ErrorKind, + input: &I, + predicate: P, + e: ErrorKind, ) -> IResult::Slice, E> where - P: Fn(I::Token) -> bool, + P: Fn(I::Token) -> bool, { - let offset = input - .offset_for(predicate) - .unwrap_or_else(|| input.input_len()); - if offset == 0 { - Err(ErrMode::from_error_kind(input.clone(), e)) - } else { - Ok(input.next_slice(offset)) - } + let offset = input + .offset_for(predicate) + .unwrap_or_else(|| input.input_len()); + if offset == 0 { + Err(ErrMode::from_error_kind(input.clone(), e)) + } else { + Ok(input.next_slice(offset)) + } } #[cfg(test)] mod tests { - use super::*; - - #[test] - fn test_offset_u8() { - let s = b"abcd123"; - let a = &s[..]; - let b = &a[2..]; - let c = &a[..4]; - let d = &a[3..5]; - assert_eq!(a.offset_to(b), 2); - assert_eq!(a.offset_to(c), 0); - assert_eq!(a.offset_to(d), 3); - } - - #[test] - fn test_offset_str() { - let a = "abcřèÂßÇd123"; - let b = &a[7..]; - let c = &a[..5]; - let d = &a[5..9]; - assert_eq!(a.offset_to(b), 7); - assert_eq!(a.offset_to(c), 0); - assert_eq!(a.offset_to(d), 5); - } + use super::*; + + #[test] + fn test_offset_u8() { + let s = b"abcd123"; + let a = &s[..]; + let b = &a[2..]; + let c = &a[..4]; + let d = &a[3..5]; + assert_eq!(a.offset_to(b), 2); + assert_eq!(a.offset_to(c), 0); + assert_eq!(a.offset_to(d), 3); + } + + #[test] + fn test_offset_str() { + let a = "abcřèÂßÇd123"; + let b = &a[7..]; + let c = &a[..5]; + let d = &a[5..9]; + assert_eq!(a.offset_to(b), 7); + assert_eq!(a.offset_to(c), 0); + assert_eq!(a.offset_to(d), 5); + } } diff --git a/src/lib.rs b/src/lib.rs index 6914240d..3322955b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -415,44 +415,44 @@ doc_comment::doctest!("../README.md"); /// it, albeit there it is not public. #[doc(hidden)] pub(crate) mod lib { - /// `std` facade allowing `std`/`core` to be interchangeable. Reexports `alloc` crate optionally, - /// as well as `core` or `std` - #[cfg(not(feature = "std"))] - /// internal std exports for no_std compatibility - pub mod std { - #[doc(hidden)] - #[cfg(not(feature = "alloc"))] - pub use core::borrow; + /// `std` facade allowing `std`/`core` to be interchangeable. Reexports `alloc` crate optionally, + /// as well as `core` or `std` + #[cfg(not(feature = "std"))] + /// internal std exports for no_std compatibility + pub mod std { + #[doc(hidden)] + #[cfg(not(feature = "alloc"))] + pub use core::borrow; - #[cfg(feature = "alloc")] - #[doc(hidden)] - pub use alloc::{borrow, boxed, collections, string, vec}; + #[cfg(feature = "alloc")] + #[doc(hidden)] + pub use alloc::{borrow, boxed, collections, string, vec}; - #[doc(hidden)] - pub use core::{cmp, convert, fmt, hash, iter, mem, ops, option, result, slice, str}; + #[doc(hidden)] + pub use core::{cmp, convert, fmt, hash, iter, mem, ops, option, result, slice, str}; - /// internal reproduction of std prelude - #[doc(hidden)] - pub mod prelude { - pub use core::prelude as v1; + /// internal reproduction of std prelude + #[doc(hidden)] + pub mod prelude { + pub use core::prelude as v1; + } } - } - #[cfg(feature = "std")] - /// internal std exports for `no_std` compatibility - pub mod std { - #[doc(hidden)] - pub use std::{ - alloc, borrow, boxed, cmp, collections, convert, fmt, hash, iter, mem, ops, option, result, - slice, str, string, vec, - }; + #[cfg(feature = "std")] + /// internal std exports for `no_std` compatibility + pub mod std { + #[doc(hidden)] + pub use std::{ + alloc, borrow, boxed, cmp, collections, convert, fmt, hash, iter, mem, ops, option, + result, slice, str, string, vec, + }; - /// internal reproduction of std prelude - #[doc(hidden)] - pub mod prelude { - pub use std::prelude as v1; + /// internal reproduction of std prelude + #[doc(hidden)] + pub mod prelude { + pub use std::prelude as v1; + } } - } } #[macro_use] @@ -501,10 +501,10 @@ pub mod _tutorial; /// } /// ``` pub mod prelude { - pub use crate::input::InputIsStreaming as _; - pub use crate::FinishIResult as _; - pub use crate::IResult; - pub use crate::Parser as _; + pub use crate::input::InputIsStreaming as _; + pub use crate::FinishIResult as _; + pub use crate::IResult; + pub use crate::Parser as _; } pub use error::FinishIResult; diff --git a/src/multi/mod.rs b/src/multi/mod.rs index ed3c09c5..6505c795 100644 --- a/src/multi/mod.rs +++ b/src/multi/mod.rs @@ -38,30 +38,30 @@ use crate::{IResult, Parser}; /// ``` pub fn many0(mut f: F) -> impl FnMut(I) -> IResult where - I: Input, - C: Accumulate, - F: Parser, - E: ParseError, + I: Input, + C: Accumulate, + F: Parser, + E: ParseError, { - move |mut i: I| { - let mut acc = C::initial(None); - loop { - let len = i.input_len(); - match f.parse_next(i.clone()) { - Err(ErrMode::Backtrack(_)) => return Ok((i, acc)), - Err(e) => return Err(e), - Ok((i1, o)) => { - // infinite loop check: the parser must always consume - if i1.input_len() == len { - return Err(ErrMode::from_error_kind(i, ErrorKind::Many0)); - } + move |mut i: I| { + let mut acc = C::initial(None); + loop { + let len = i.input_len(); + match f.parse_next(i.clone()) { + Err(ErrMode::Backtrack(_)) => return Ok((i, acc)), + Err(e) => return Err(e), + Ok((i1, o)) => { + // infinite loop check: the parser must always consume + if i1.input_len() == len { + return Err(ErrMode::from_error_kind(i, ErrorKind::Many0)); + } - i = i1; - acc.accumulate(o); + i = i1; + acc.accumulate(o); + } + } } - } } - } } /// Runs the embedded parser, gathering the results in a `Vec`. @@ -93,49 +93,49 @@ where /// ``` pub fn many1(mut f: F) -> impl FnMut(I) -> IResult where - I: Input, - C: Accumulate, - F: Parser, - E: ParseError, + I: Input, + C: Accumulate, + F: Parser, + E: ParseError, { - move |mut i: I| match f.parse_next(i.clone()) { - Err(e) => Err(e.append(i, ErrorKind::Many1)), - Ok((i1, o)) => { - let mut acc = C::initial(None); - acc.accumulate(o); - i = i1; + move |mut i: I| match f.parse_next(i.clone()) { + Err(e) => Err(e.append(i, ErrorKind::Many1)), + Ok((i1, o)) => { + let mut acc = C::initial(None); + acc.accumulate(o); + i = i1; - loop { - let len = i.input_len(); - match f.parse_next(i.clone()) { - Err(ErrMode::Backtrack(_)) => return Ok((i, acc)), - Err(e) => return Err(e), - Ok((i1, o)) => { - // infinite loop check: the parser must always consume - if i1.input_len() == len { - return Err(ErrMode::from_error_kind(i, ErrorKind::Many1)); - } + loop { + let len = i.input_len(); + match f.parse_next(i.clone()) { + Err(ErrMode::Backtrack(_)) => return Ok((i, acc)), + Err(e) => return Err(e), + Ok((i1, o)) => { + // infinite loop check: the parser must always consume + if i1.input_len() == len { + return Err(ErrMode::from_error_kind(i, ErrorKind::Many1)); + } - i = i1; - acc.accumulate(o); - } + i = i1; + acc.accumulate(o); + } + } + } } - } } - } } /// **WARNING:** Deprecated, replaced with [`many_till0`] #[deprecated(since = "0.3.0", note = "Replaced with `many_till0`")] pub fn many_till(f: F, g: G) -> impl FnMut(I) -> IResult where - I: Input, - C: Accumulate, - F: Parser, - G: Parser, - E: ParseError, + I: Input, + C: Accumulate, + F: Parser, + G: Parser, + E: ParseError, { - many_till0(f, g) + many_till0(f, g) } /// Applies the parser `f` until the parser `g` produces a result. @@ -162,36 +162,36 @@ where /// ``` pub fn many_till0(mut f: F, mut g: G) -> impl FnMut(I) -> IResult where - I: Input, - C: Accumulate, - F: Parser, - G: Parser, - E: ParseError, + I: Input, + C: Accumulate, + F: Parser, + G: Parser, + E: ParseError, { - move |mut i: I| { - let mut res = C::initial(None); - loop { - let len = i.input_len(); - match g.parse_next(i.clone()) { - Ok((i1, o)) => return Ok((i1, (res, o))), - Err(ErrMode::Backtrack(_)) => { - match f.parse_next(i.clone()) { - Err(e) => return Err(e.append(i, ErrorKind::ManyTill)), - Ok((i1, o)) => { - // infinite loop check: the parser must always consume - if i1.input_len() == len { - return Err(ErrMode::from_error_kind(i1, ErrorKind::ManyTill)); - } + move |mut i: I| { + let mut res = C::initial(None); + loop { + let len = i.input_len(); + match g.parse_next(i.clone()) { + Ok((i1, o)) => return Ok((i1, (res, o))), + Err(ErrMode::Backtrack(_)) => { + match f.parse_next(i.clone()) { + Err(e) => return Err(e.append(i, ErrorKind::ManyTill)), + Ok((i1, o)) => { + // infinite loop check: the parser must always consume + if i1.input_len() == len { + return Err(ErrMode::from_error_kind(i1, ErrorKind::ManyTill)); + } - res.accumulate(o); - i = i1; + res.accumulate(o); + i = i1; + } + } + } + Err(e) => return Err(e), } - } } - Err(e) => return Err(e), - } } - } } /// Alternates between two parsers to produce a list of elements. @@ -220,51 +220,51 @@ where /// assert_eq!(parser("def|abc"), Ok(("def|abc", vec![]))); /// ``` pub fn separated_list0( - mut sep: G, - mut f: F, + mut sep: G, + mut f: F, ) -> impl FnMut(I) -> IResult where - I: Input, - C: Accumulate, - F: Parser, - G: Parser, - E: ParseError, + I: Input, + C: Accumulate, + F: Parser, + G: Parser, + E: ParseError, { - move |mut i: I| { - let mut res = C::initial(None); - - match f.parse_next(i.clone()) { - Err(ErrMode::Backtrack(_)) => return Ok((i, res)), - Err(e) => return Err(e), - Ok((i1, o)) => { - res.accumulate(o); - i = i1; - } - } + move |mut i: I| { + let mut res = C::initial(None); - loop { - let len = i.input_len(); - match sep.parse_next(i.clone()) { - Err(ErrMode::Backtrack(_)) => return Ok((i, res)), - Err(e) => return Err(e), - Ok((i1, _)) => { - // infinite loop check: the parser must always consume - if i1.input_len() == len { - return Err(ErrMode::from_error_kind(i1, ErrorKind::SeparatedList)); - } - - match f.parse_next(i1.clone()) { + match f.parse_next(i.clone()) { Err(ErrMode::Backtrack(_)) => return Ok((i, res)), Err(e) => return Err(e), - Ok((i2, o)) => { - res.accumulate(o); - i = i2; + Ok((i1, o)) => { + res.accumulate(o); + i = i1; + } + } + + loop { + let len = i.input_len(); + match sep.parse_next(i.clone()) { + Err(ErrMode::Backtrack(_)) => return Ok((i, res)), + Err(e) => return Err(e), + Ok((i1, _)) => { + // infinite loop check: the parser must always consume + if i1.input_len() == len { + return Err(ErrMode::from_error_kind(i1, ErrorKind::SeparatedList)); + } + + match f.parse_next(i1.clone()) { + Err(ErrMode::Backtrack(_)) => return Ok((i, res)), + Err(e) => return Err(e), + Ok((i2, o)) => { + res.accumulate(o); + i = i2; + } + } + } } - } } - } } - } } /// Alternates between two parsers to produce a list of elements until [`ErrMode::Backtrack`]. @@ -294,51 +294,51 @@ where /// assert_eq!(parser("def|abc"), Err(ErrMode::Backtrack(Error::new("def|abc", ErrorKind::Tag)))); /// ``` pub fn separated_list1( - mut sep: G, - mut f: F, + mut sep: G, + mut f: F, ) -> impl FnMut(I) -> IResult where - I: Input, - C: Accumulate, - F: Parser, - G: Parser, - E: ParseError, + I: Input, + C: Accumulate, + F: Parser, + G: Parser, + E: ParseError, { - move |mut i: I| { - let mut res = C::initial(None); + move |mut i: I| { + let mut res = C::initial(None); - // Parse the first element - match f.parse_next(i.clone()) { - Err(e) => return Err(e), - Ok((i1, o)) => { - res.accumulate(o); - i = i1; - } - } + // Parse the first element + match f.parse_next(i.clone()) { + Err(e) => return Err(e), + Ok((i1, o)) => { + res.accumulate(o); + i = i1; + } + } - loop { - let len = i.input_len(); - match sep.parse_next(i.clone()) { - Err(ErrMode::Backtrack(_)) => return Ok((i, res)), - Err(e) => return Err(e), - Ok((i1, _)) => { - // infinite loop check: the parser must always consume - if i1.input_len() == len { - return Err(ErrMode::from_error_kind(i1, ErrorKind::SeparatedList)); - } + loop { + let len = i.input_len(); + match sep.parse_next(i.clone()) { + Err(ErrMode::Backtrack(_)) => return Ok((i, res)), + Err(e) => return Err(e), + Ok((i1, _)) => { + // infinite loop check: the parser must always consume + if i1.input_len() == len { + return Err(ErrMode::from_error_kind(i1, ErrorKind::SeparatedList)); + } - match f.parse_next(i1.clone()) { - Err(ErrMode::Backtrack(_)) => return Ok((i, res)), - Err(e) => return Err(e), - Ok((i2, o)) => { - res.accumulate(o); - i = i2; + match f.parse_next(i1.clone()) { + Err(ErrMode::Backtrack(_)) => return Ok((i, res)), + Err(e) => return Err(e), + Ok((i2, o)) => { + res.accumulate(o); + i = i2; + } + } + } } - } } - } } - } } /// Repeats the embedded parser `m..=n` times @@ -372,49 +372,49 @@ where /// assert_eq!(parser("abcabcabc"), Ok(("abc", vec!["abc", "abc"]))); /// ``` pub fn many_m_n( - min: usize, - max: usize, - mut parse: F, + min: usize, + max: usize, + mut parse: F, ) -> impl FnMut(I) -> IResult where - I: Input, - C: Accumulate, - F: Parser, - E: ParseError, + I: Input, + C: Accumulate, + F: Parser, + E: ParseError, { - move |mut input: I| { - if min > max { - return Err(ErrMode::Cut(E::from_error_kind(input, ErrorKind::ManyMN))); - } + move |mut input: I| { + if min > max { + return Err(ErrMode::Cut(E::from_error_kind(input, ErrorKind::ManyMN))); + } - let mut res = C::initial(Some(min)); - for count in 0..max { - let len = input.input_len(); - match parse.parse_next(input.clone()) { - Ok((tail, value)) => { - // infinite loop check: the parser must always consume - if tail.input_len() == len { - return Err(ErrMode::from_error_kind(input, ErrorKind::ManyMN)); - } + let mut res = C::initial(Some(min)); + for count in 0..max { + let len = input.input_len(); + match parse.parse_next(input.clone()) { + Ok((tail, value)) => { + // infinite loop check: the parser must always consume + if tail.input_len() == len { + return Err(ErrMode::from_error_kind(input, ErrorKind::ManyMN)); + } - res.accumulate(value); - input = tail; - } - Err(ErrMode::Backtrack(e)) => { - if count < min { - return Err(ErrMode::Backtrack(e.append(input, ErrorKind::ManyMN))); - } else { - return Ok((input, res)); - } - } - Err(e) => { - return Err(e); + res.accumulate(value); + input = tail; + } + Err(ErrMode::Backtrack(e)) => { + if count < min { + return Err(ErrMode::Backtrack(e.append(input, ErrorKind::ManyMN))); + } else { + return Ok((input, res)); + } + } + Err(e) => { + return Err(e); + } + } } - } - } - Ok((input, res)) - } + Ok((input, res)) + } } /// Repeats the embedded parser, counting the results @@ -447,34 +447,34 @@ where #[deprecated(since = "0.3.0", note = "Replaced with `many0`")] pub fn many0_count(mut f: F) -> impl FnMut(I) -> IResult where - I: Input, - F: Parser, - E: ParseError, + I: Input, + F: Parser, + E: ParseError, { - move |i: I| { - let mut input = i; - let mut count = 0; + move |i: I| { + let mut input = i; + let mut count = 0; - loop { - let input_ = input.clone(); - let len = input.input_len(); - match f.parse_next(input_) { - Ok((i, _)) => { - // infinite loop check: the parser must always consume - if i.input_len() == len { - return Err(ErrMode::from_error_kind(input, ErrorKind::Many0Count)); - } + loop { + let input_ = input.clone(); + let len = input.input_len(); + match f.parse_next(input_) { + Ok((i, _)) => { + // infinite loop check: the parser must always consume + if i.input_len() == len { + return Err(ErrMode::from_error_kind(input, ErrorKind::Many0Count)); + } - input = i; - count += 1; - } + input = i; + count += 1; + } - Err(ErrMode::Backtrack(_)) => return Ok((input, count)), + Err(ErrMode::Backtrack(_)) => return Ok((input, count)), - Err(e) => return Err(e), - } + Err(e) => return Err(e), + } + } } - } } /// Runs the embedded parser, counting the results. @@ -508,39 +508,39 @@ where #[deprecated(since = "0.3.0", note = "Replaced with `many0`")] pub fn many1_count(mut f: F) -> impl FnMut(I) -> IResult where - I: Input, - F: Parser, - E: ParseError, + I: Input, + F: Parser, + E: ParseError, { - move |i: I| { - let i_ = i.clone(); - match f.parse_next(i_) { - Err(ErrMode::Backtrack(_)) => Err(ErrMode::from_error_kind(i, ErrorKind::Many1Count)), - Err(i) => Err(i), - Ok((i1, _)) => { - let mut count = 1; - let mut input = i1; + move |i: I| { + let i_ = i.clone(); + match f.parse_next(i_) { + Err(ErrMode::Backtrack(_)) => Err(ErrMode::from_error_kind(i, ErrorKind::Many1Count)), + Err(i) => Err(i), + Ok((i1, _)) => { + let mut count = 1; + let mut input = i1; - loop { - let len = input.input_len(); - let input_ = input.clone(); - match f.parse_next(input_) { - Err(ErrMode::Backtrack(_)) => return Ok((input, count)), - Err(e) => return Err(e), - Ok((i, _)) => { - // infinite loop check: the parser must always consume - if i.input_len() == len { - return Err(ErrMode::from_error_kind(i, ErrorKind::Many1Count)); - } + loop { + let len = input.input_len(); + let input_ = input.clone(); + match f.parse_next(input_) { + Err(ErrMode::Backtrack(_)) => return Ok((input, count)), + Err(e) => return Err(e), + Ok((i, _)) => { + // infinite loop check: the parser must always consume + if i.input_len() == len { + return Err(ErrMode::from_error_kind(i, ErrorKind::Many1Count)); + } - count += 1; - input = i; + count += 1; + input = i; + } + } + } } - } } - } } - } } /// Runs the embedded parser `count` times, gathering the results in a `Vec` @@ -566,30 +566,30 @@ where /// ``` pub fn count(mut f: F, count: usize) -> impl FnMut(I) -> IResult where - I: Clone + PartialEq, - C: Accumulate, - F: Parser, - E: ParseError, + I: Clone + PartialEq, + C: Accumulate, + F: Parser, + E: ParseError, { - move |i: I| { - let mut input = i.clone(); - let mut res = C::initial(Some(count)); + move |i: I| { + let mut input = i.clone(); + let mut res = C::initial(Some(count)); - for _ in 0..count { - let input_ = input.clone(); - match f.parse_next(input_) { - Ok((i, o)) => { - res.accumulate(o); - input = i; - } - Err(e) => { - return Err(e.append(i, ErrorKind::Count)); + for _ in 0..count { + let input_ = input.clone(); + match f.parse_next(input_) { + Ok((i, o)) => { + res.accumulate(o); + input = i; + } + Err(e) => { + return Err(e.append(i, ErrorKind::Count)); + } + } } - } - } - Ok((input, res)) - } + Ok((input, res)) + } } /// Runs the embedded parser repeatedly, filling the given slice with results. @@ -618,28 +618,28 @@ where /// ``` pub fn fill<'a, I, O, E, F>(mut f: F, buf: &'a mut [O]) -> impl FnMut(I) -> IResult + 'a where - I: Clone + PartialEq, - F: Parser + 'a, - E: ParseError, + I: Clone + PartialEq, + F: Parser + 'a, + E: ParseError, { - move |i: I| { - let mut input = i.clone(); + move |i: I| { + let mut input = i.clone(); - for elem in buf.iter_mut() { - let input_ = input.clone(); - match f.parse_next(input_) { - Ok((i, o)) => { - *elem = o; - input = i; - } - Err(e) => { - return Err(e.append(i, ErrorKind::Count)); + for elem in buf.iter_mut() { + let input_ = input.clone(); + match f.parse_next(input_) { + Ok((i, o)) => { + *elem = o; + input = i; + } + Err(e) => { + return Err(e.append(i, ErrorKind::Count)); + } + } } - } - } - Ok((input, ())) - } + Ok((input, ())) + } } /// Repeats the embedded parser, calling `g` to gather the results. @@ -678,43 +678,43 @@ where /// assert_eq!(parser(""), Ok(("", vec![]))); /// ``` pub fn fold_many0( - mut f: F, - mut init: H, - mut g: G, + mut f: F, + mut init: H, + mut g: G, ) -> impl FnMut(I) -> IResult where - I: Input, - F: Parser, - G: FnMut(R, O) -> R, - H: FnMut() -> R, - E: ParseError, + I: Input, + F: Parser, + G: FnMut(R, O) -> R, + H: FnMut() -> R, + E: ParseError, { - move |i: I| { - let mut res = init(); - let mut input = i; + move |i: I| { + let mut res = init(); + let mut input = i; - loop { - let i_ = input.clone(); - let len = input.input_len(); - match f.parse_next(i_) { - Ok((i, o)) => { - // infinite loop check: the parser must always consume - if i.input_len() == len { - return Err(ErrMode::from_error_kind(input, ErrorKind::Many0)); - } + loop { + let i_ = input.clone(); + let len = input.input_len(); + match f.parse_next(i_) { + Ok((i, o)) => { + // infinite loop check: the parser must always consume + if i.input_len() == len { + return Err(ErrMode::from_error_kind(input, ErrorKind::Many0)); + } - res = g(res, o); - input = i; - } - Err(ErrMode::Backtrack(_)) => { - return Ok((input, res)); - } - Err(e) => { - return Err(e); + res = g(res, o); + input = i; + } + Err(ErrMode::Backtrack(_)) => { + return Ok((input, res)); + } + Err(e) => { + return Err(e); + } + } } - } } - } } /// Repeats the embedded parser, calling `g` to gather the results. @@ -754,51 +754,51 @@ where /// assert_eq!(parser(""), Err(ErrMode::Backtrack(Error::new("", ErrorKind::Many1)))); /// ``` pub fn fold_many1( - mut f: F, - mut init: H, - mut g: G, + mut f: F, + mut init: H, + mut g: G, ) -> impl FnMut(I) -> IResult where - I: Input, - F: Parser, - G: FnMut(R, O) -> R, - H: FnMut() -> R, - E: ParseError, + I: Input, + F: Parser, + G: FnMut(R, O) -> R, + H: FnMut() -> R, + E: ParseError, { - move |i: I| { - let _i = i.clone(); - let init = init(); - match f.parse_next(_i) { - Err(ErrMode::Backtrack(_)) => Err(ErrMode::from_error_kind(i, ErrorKind::Many1)), - Err(e) => Err(e), - Ok((i1, o1)) => { - let mut acc = g(init, o1); - let mut input = i1; + move |i: I| { + let _i = i.clone(); + let init = init(); + match f.parse_next(_i) { + Err(ErrMode::Backtrack(_)) => Err(ErrMode::from_error_kind(i, ErrorKind::Many1)), + Err(e) => Err(e), + Ok((i1, o1)) => { + let mut acc = g(init, o1); + let mut input = i1; - loop { - let _input = input.clone(); - let len = input.input_len(); - match f.parse_next(_input) { - Err(ErrMode::Backtrack(_)) => { - break; - } - Err(e) => return Err(e), - Ok((i, o)) => { - // infinite loop check: the parser must always consume - if i.input_len() == len { - return Err(ErrMode::Cut(E::from_error_kind(i, ErrorKind::Many1))); - } + loop { + let _input = input.clone(); + let len = input.input_len(); + match f.parse_next(_input) { + Err(ErrMode::Backtrack(_)) => { + break; + } + Err(e) => return Err(e), + Ok((i, o)) => { + // infinite loop check: the parser must always consume + if i.input_len() == len { + return Err(ErrMode::Cut(E::from_error_kind(i, ErrorKind::Many1))); + } - acc = g(acc, o); - input = i; + acc = g(acc, o); + input = i; + } + } + } + + Ok((input, acc)) } - } } - - Ok((input, acc)) - } } - } } /// Repeats the embedded parser `m..=n` times, calling `g` to gather the results @@ -843,51 +843,51 @@ where /// assert_eq!(parser("abcabcabc"), Ok(("abc", vec!["abc", "abc"]))); /// ``` pub fn fold_many_m_n( - min: usize, - max: usize, - mut parse: F, - mut init: H, - mut fold: G, + min: usize, + max: usize, + mut parse: F, + mut init: H, + mut fold: G, ) -> impl FnMut(I) -> IResult where - I: Input, - F: Parser, - G: FnMut(R, O) -> R, - H: FnMut() -> R, - E: ParseError, + I: Input, + F: Parser, + G: FnMut(R, O) -> R, + H: FnMut() -> R, + E: ParseError, { - move |mut input: I| { - if min > max { - return Err(ErrMode::Cut(E::from_error_kind(input, ErrorKind::ManyMN))); - } + move |mut input: I| { + if min > max { + return Err(ErrMode::Cut(E::from_error_kind(input, ErrorKind::ManyMN))); + } - let mut acc = init(); - for count in 0..max { - let len = input.input_len(); - match parse.parse_next(input.clone()) { - Ok((tail, value)) => { - // infinite loop check: the parser must always consume - if tail.input_len() == len { - return Err(ErrMode::from_error_kind(tail, ErrorKind::ManyMN)); - } + let mut acc = init(); + for count in 0..max { + let len = input.input_len(); + match parse.parse_next(input.clone()) { + Ok((tail, value)) => { + // infinite loop check: the parser must always consume + if tail.input_len() == len { + return Err(ErrMode::from_error_kind(tail, ErrorKind::ManyMN)); + } - acc = fold(acc, value); - input = tail; - } - //FInputXMError: handle failure properly - Err(ErrMode::Backtrack(err)) => { - if count < min { - return Err(ErrMode::Backtrack(err.append(input, ErrorKind::ManyMN))); - } else { - break; - } + acc = fold(acc, value); + input = tail; + } + //FInputXMError: handle failure properly + Err(ErrMode::Backtrack(err)) => { + if count < min { + return Err(ErrMode::Backtrack(err.append(input, ErrorKind::ManyMN))); + } else { + break; + } + } + Err(e) => return Err(e), + } } - Err(e) => return Err(e), - } - } - Ok((input, acc)) - } + Ok((input, acc)) + } } /// Gets a number from the parser and returns a @@ -913,20 +913,20 @@ where /// assert_eq!(parser(Streaming(b"\x00\x03a")), Err(ErrMode::Incomplete(Needed::new(2)))); /// ``` pub fn length_data( - mut f: F, + mut f: F, ) -> impl FnMut(I) -> IResult::Slice, E> where - I: InputIsStreaming, - I: Input, - N: ToUsize, - F: Parser, - E: ParseError, + I: InputIsStreaming, + I: Input, + N: ToUsize, + F: Parser, + E: ParseError, { - move |i: I| { - let (i, length) = f.parse_next(i)?; + move |i: I| { + let (i, length) = f.parse_next(i)?; - crate::bytes::take(length).parse_next(i) - } + crate::bytes::take(length).parse_next(i) + } } /// Gets a number from the first parser, @@ -957,23 +957,23 @@ where /// assert_eq!(parser(Streaming(b"\x00\x03a")), Err(ErrMode::Incomplete(Needed::new(2)))); /// ``` pub fn length_value( - mut f: F, - mut g: G, + mut f: F, + mut g: G, ) -> impl FnMut(I) -> IResult where - I: InputIsStreaming, - I: Input + UpdateSlice, - N: ToUsize, - F: Parser, - G: Parser, - E: ParseError, + I: InputIsStreaming, + I: Input + UpdateSlice, + N: ToUsize, + F: Parser, + G: Parser, + E: ParseError, { - move |i: I| { - let (i, data) = length_data(f.by_ref()).parse_next(i)?; - let data = I::update_slice(i.clone(), data); - let (_, o) = g.by_ref().complete().parse_next(data)?; - Ok((i, o)) - } + move |i: I| { + let (i, data) = length_data(f.by_ref()).parse_next(i)?; + let data = I::update_slice(i.clone(), data); + let (_, o) = g.by_ref().complete().parse_next(data)?; + Ok((i, o)) + } } /// Gets a number from the first parser, @@ -1002,31 +1002,31 @@ where /// ``` pub fn length_count(mut f: F, mut g: G) -> impl FnMut(I) -> IResult where - I: Clone, - N: ToUsize, - C: Accumulate, - F: Parser, - G: Parser, - E: ParseError, + I: Clone, + N: ToUsize, + C: Accumulate, + F: Parser, + G: Parser, + E: ParseError, { - move |i: I| { - let (i, count) = f.parse_next(i)?; - let mut input = i.clone(); - let mut res = C::initial(Some(count.to_usize())); + move |i: I| { + let (i, count) = f.parse_next(i)?; + let mut input = i.clone(); + let mut res = C::initial(Some(count.to_usize())); - for _ in 0..count.to_usize() { - let input_ = input.clone(); - match g.parse_next(input_) { - Ok((i, o)) => { - res.accumulate(o); - input = i; - } - Err(e) => { - return Err(e.append(i, ErrorKind::Count)); + for _ in 0..count.to_usize() { + let input_ = input.clone(); + match g.parse_next(input_) { + Ok((i, o)) => { + res.accumulate(o); + input = i; + } + Err(e) => { + return Err(e.append(i, ErrorKind::Count)); + } + } } - } - } - Ok((input, res)) - } + Ok((input, res)) + } } diff --git a/src/multi/tests.rs b/src/multi/tests.rs index 93b8acfb..bc893883 100644 --- a/src/multi/tests.rs +++ b/src/multi/tests.rs @@ -2,678 +2,678 @@ use super::{length_data, length_value, many0, many1}; use crate::input::Streaming; use crate::Parser; use crate::{ - bytes::tag, - character::digit1 as digit, - error::{ErrMode, ErrorKind, Needed, ParseError}, - lib::std::str::{self, FromStr}, - number::{be_u16, be_u8}, - IResult, + bytes::tag, + character::digit1 as digit, + error::{ErrMode, ErrorKind, Needed, ParseError}, + lib::std::str::{self, FromStr}, + number::{be_u16, be_u8}, + IResult, }; #[cfg(feature = "alloc")] use crate::{ - lib::std::vec::Vec, - multi::{ - count, fold_many0, fold_many1, fold_many_m_n, length_count, many_m_n, many_till0, - separated_list0, separated_list1, - }, + lib::std::vec::Vec, + multi::{ + count, fold_many0, fold_many1, fold_many_m_n, length_count, many_m_n, many_till0, + separated_list0, separated_list1, + }, }; #[test] #[cfg(feature = "alloc")] fn separated_list0_test() { - fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - separated_list0(tag(","), tag("abcd"))(i) - } - fn multi_empty(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - separated_list0(tag(","), tag(""))(i) - } - fn empty_sep(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - separated_list0(tag(""), tag("abc"))(i) - } - fn multi_longsep(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - separated_list0(tag(".."), tag("abcd"))(i) - } - - let a = &b"abcdef"[..]; - let b = &b"abcd,abcdef"[..]; - let c = &b"azerty"[..]; - let d = &b",,abc"[..]; - let e = &b"abcd,abcd,ef"[..]; - let f = &b"abc"[..]; - let g = &b"abcd."[..]; - let h = &b"abcd,abc"[..]; - let i = &b"abcabc"[..]; - - let res1 = vec![&b"abcd"[..]]; - assert_eq!(multi(Streaming(a)), Ok((Streaming(&b"ef"[..]), res1))); - let res2 = vec![&b"abcd"[..], &b"abcd"[..]]; - assert_eq!(multi(Streaming(b)), Ok((Streaming(&b"ef"[..]), res2))); - assert_eq!( - multi(Streaming(c)), - Ok((Streaming(&b"azerty"[..]), Vec::new())) - ); - let res3 = vec![&b""[..], &b""[..], &b""[..]]; - assert_eq!( - multi_empty(Streaming(d)), - Ok((Streaming(&b"abc"[..]), res3)) - ); - let i_err_pos = &i[3..]; - assert_eq!( - empty_sep(Streaming(i)), - Err(ErrMode::Backtrack(error_position!( - Streaming(i_err_pos), - ErrorKind::SeparatedList - ))) - ); - let res4 = vec![&b"abcd"[..], &b"abcd"[..]]; - assert_eq!(multi(Streaming(e)), Ok((Streaming(&b",ef"[..]), res4))); - - assert_eq!( - multi(Streaming(f)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - multi_longsep(Streaming(g)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - multi(Streaming(h)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); + fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + separated_list0(tag(","), tag("abcd"))(i) + } + fn multi_empty(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + separated_list0(tag(","), tag(""))(i) + } + fn empty_sep(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + separated_list0(tag(""), tag("abc"))(i) + } + fn multi_longsep(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + separated_list0(tag(".."), tag("abcd"))(i) + } + + let a = &b"abcdef"[..]; + let b = &b"abcd,abcdef"[..]; + let c = &b"azerty"[..]; + let d = &b",,abc"[..]; + let e = &b"abcd,abcd,ef"[..]; + let f = &b"abc"[..]; + let g = &b"abcd."[..]; + let h = &b"abcd,abc"[..]; + let i = &b"abcabc"[..]; + + let res1 = vec![&b"abcd"[..]]; + assert_eq!(multi(Streaming(a)), Ok((Streaming(&b"ef"[..]), res1))); + let res2 = vec![&b"abcd"[..], &b"abcd"[..]]; + assert_eq!(multi(Streaming(b)), Ok((Streaming(&b"ef"[..]), res2))); + assert_eq!( + multi(Streaming(c)), + Ok((Streaming(&b"azerty"[..]), Vec::new())) + ); + let res3 = vec![&b""[..], &b""[..], &b""[..]]; + assert_eq!( + multi_empty(Streaming(d)), + Ok((Streaming(&b"abc"[..]), res3)) + ); + let i_err_pos = &i[3..]; + assert_eq!( + empty_sep(Streaming(i)), + Err(ErrMode::Backtrack(error_position!( + Streaming(i_err_pos), + ErrorKind::SeparatedList + ))) + ); + let res4 = vec![&b"abcd"[..], &b"abcd"[..]]; + assert_eq!(multi(Streaming(e)), Ok((Streaming(&b",ef"[..]), res4))); + + assert_eq!( + multi(Streaming(f)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + multi_longsep(Streaming(g)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + multi(Streaming(h)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); } #[test] #[cfg(feature = "alloc")] fn separated_list1_test() { - fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - separated_list1(tag(","), tag("abcd"))(i) - } - fn multi_longsep(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - separated_list1(tag(".."), tag("abcd"))(i) - } - - let a = &b"abcdef"[..]; - let b = &b"abcd,abcdef"[..]; - let c = &b"azerty"[..]; - let d = &b"abcd,abcd,ef"[..]; - - let f = &b"abc"[..]; - let g = &b"abcd."[..]; - let h = &b"abcd,abc"[..]; - - let res1 = vec![&b"abcd"[..]]; - assert_eq!(multi(Streaming(a)), Ok((Streaming(&b"ef"[..]), res1))); - let res2 = vec![&b"abcd"[..], &b"abcd"[..]]; - assert_eq!(multi(Streaming(b)), Ok((Streaming(&b"ef"[..]), res2))); - assert_eq!( - multi(Streaming(c)), - Err(ErrMode::Backtrack(error_position!( - Streaming(c), - ErrorKind::Tag - ))) - ); - let res3 = vec![&b"abcd"[..], &b"abcd"[..]]; - assert_eq!(multi(Streaming(d)), Ok((Streaming(&b",ef"[..]), res3))); - - assert_eq!( - multi(Streaming(f)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - multi_longsep(Streaming(g)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - multi(Streaming(h)), - Err(ErrMode::Incomplete(Needed::new(1))) - ); + fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + separated_list1(tag(","), tag("abcd"))(i) + } + fn multi_longsep(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + separated_list1(tag(".."), tag("abcd"))(i) + } + + let a = &b"abcdef"[..]; + let b = &b"abcd,abcdef"[..]; + let c = &b"azerty"[..]; + let d = &b"abcd,abcd,ef"[..]; + + let f = &b"abc"[..]; + let g = &b"abcd."[..]; + let h = &b"abcd,abc"[..]; + + let res1 = vec![&b"abcd"[..]]; + assert_eq!(multi(Streaming(a)), Ok((Streaming(&b"ef"[..]), res1))); + let res2 = vec![&b"abcd"[..], &b"abcd"[..]]; + assert_eq!(multi(Streaming(b)), Ok((Streaming(&b"ef"[..]), res2))); + assert_eq!( + multi(Streaming(c)), + Err(ErrMode::Backtrack(error_position!( + Streaming(c), + ErrorKind::Tag + ))) + ); + let res3 = vec![&b"abcd"[..], &b"abcd"[..]]; + assert_eq!(multi(Streaming(d)), Ok((Streaming(&b",ef"[..]), res3))); + + assert_eq!( + multi(Streaming(f)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + multi_longsep(Streaming(g)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + multi(Streaming(h)), + Err(ErrMode::Incomplete(Needed::new(1))) + ); } #[test] #[cfg(feature = "alloc")] fn many0_test() { - fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - many0(tag("abcd"))(i) - } - fn multi_empty(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - many0(tag(""))(i) - } - - assert_eq!( - multi(Streaming(&b"abcdef"[..])), - Ok((Streaming(&b"ef"[..]), vec![&b"abcd"[..]])) - ); - assert_eq!( - multi(Streaming(&b"abcdabcdefgh"[..])), - Ok((Streaming(&b"efgh"[..]), vec![&b"abcd"[..], &b"abcd"[..]])) - ); - assert_eq!( - multi(Streaming(&b"azerty"[..])), - Ok((Streaming(&b"azerty"[..]), Vec::new())) - ); - assert_eq!( - multi(Streaming(&b"abcdab"[..])), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_eq!( - multi(Streaming(&b"abcd"[..])), - Err(ErrMode::Incomplete(Needed::new(4))) - ); - assert_eq!( - multi(Streaming(&b""[..])), - Err(ErrMode::Incomplete(Needed::new(4))) - ); - assert_eq!( - multi_empty(Streaming(&b"abcdef"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"abcdef"[..]), - ErrorKind::Many0 - ))) - ); + fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + many0(tag("abcd"))(i) + } + fn multi_empty(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + many0(tag(""))(i) + } + + assert_eq!( + multi(Streaming(&b"abcdef"[..])), + Ok((Streaming(&b"ef"[..]), vec![&b"abcd"[..]])) + ); + assert_eq!( + multi(Streaming(&b"abcdabcdefgh"[..])), + Ok((Streaming(&b"efgh"[..]), vec![&b"abcd"[..], &b"abcd"[..]])) + ); + assert_eq!( + multi(Streaming(&b"azerty"[..])), + Ok((Streaming(&b"azerty"[..]), Vec::new())) + ); + assert_eq!( + multi(Streaming(&b"abcdab"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_eq!( + multi(Streaming(&b"abcd"[..])), + Err(ErrMode::Incomplete(Needed::new(4))) + ); + assert_eq!( + multi(Streaming(&b""[..])), + Err(ErrMode::Incomplete(Needed::new(4))) + ); + assert_eq!( + multi_empty(Streaming(&b"abcdef"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"abcdef"[..]), + ErrorKind::Many0 + ))) + ); } #[test] #[cfg(feature = "alloc")] fn many1_test() { - fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - many1(tag("abcd"))(i) - } - - let a = &b"abcdef"[..]; - let b = &b"abcdabcdefgh"[..]; - let c = &b"azerty"[..]; - let d = &b"abcdab"[..]; - - let res1 = vec![&b"abcd"[..]]; - assert_eq!(multi(Streaming(a)), Ok((Streaming(&b"ef"[..]), res1))); - let res2 = vec![&b"abcd"[..], &b"abcd"[..]]; - assert_eq!(multi(Streaming(b)), Ok((Streaming(&b"efgh"[..]), res2))); - assert_eq!( - multi(Streaming(c)), - Err(ErrMode::Backtrack(error_position!( - Streaming(c), - ErrorKind::Tag - ))) - ); - assert_eq!( - multi(Streaming(d)), - Err(ErrMode::Incomplete(Needed::new(2))) - ); + fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + many1(tag("abcd"))(i) + } + + let a = &b"abcdef"[..]; + let b = &b"abcdabcdefgh"[..]; + let c = &b"azerty"[..]; + let d = &b"abcdab"[..]; + + let res1 = vec![&b"abcd"[..]]; + assert_eq!(multi(Streaming(a)), Ok((Streaming(&b"ef"[..]), res1))); + let res2 = vec![&b"abcd"[..], &b"abcd"[..]]; + assert_eq!(multi(Streaming(b)), Ok((Streaming(&b"efgh"[..]), res2))); + assert_eq!( + multi(Streaming(c)), + Err(ErrMode::Backtrack(error_position!( + Streaming(c), + ErrorKind::Tag + ))) + ); + assert_eq!( + multi(Streaming(d)), + Err(ErrMode::Incomplete(Needed::new(2))) + ); } #[test] #[cfg(feature = "alloc")] fn many_till_test() { - #[allow(clippy::type_complexity)] - fn multi(i: &[u8]) -> IResult<&[u8], (Vec<&[u8]>, &[u8])> { - many_till0(tag("abcd"), tag("efgh"))(i) - } - - let a = b"abcdabcdefghabcd"; - let b = b"efghabcd"; - let c = b"azerty"; - - let res_a = (vec![&b"abcd"[..], &b"abcd"[..]], &b"efgh"[..]); - let res_b: (Vec<&[u8]>, &[u8]) = (Vec::new(), &b"efgh"[..]); - assert_eq!(multi(&a[..]), Ok((&b"abcd"[..], res_a))); - assert_eq!(multi(&b[..]), Ok((&b"abcd"[..], res_b))); - assert_eq!( - multi(&c[..]), - Err(ErrMode::Backtrack(error_node_position!( - &c[..], - ErrorKind::ManyTill, - error_position!(&c[..], ErrorKind::Tag) - ))) - ); + #[allow(clippy::type_complexity)] + fn multi(i: &[u8]) -> IResult<&[u8], (Vec<&[u8]>, &[u8])> { + many_till0(tag("abcd"), tag("efgh"))(i) + } + + let a = b"abcdabcdefghabcd"; + let b = b"efghabcd"; + let c = b"azerty"; + + let res_a = (vec![&b"abcd"[..], &b"abcd"[..]], &b"efgh"[..]); + let res_b: (Vec<&[u8]>, &[u8]) = (Vec::new(), &b"efgh"[..]); + assert_eq!(multi(&a[..]), Ok((&b"abcd"[..], res_a))); + assert_eq!(multi(&b[..]), Ok((&b"abcd"[..], res_b))); + assert_eq!( + multi(&c[..]), + Err(ErrMode::Backtrack(error_node_position!( + &c[..], + ErrorKind::ManyTill, + error_position!(&c[..], ErrorKind::Tag) + ))) + ); } #[test] #[cfg(feature = "std")] fn infinite_many() { - fn tst(input: &[u8]) -> IResult<&[u8], &[u8]> { - println!("input: {:?}", input); - Err(ErrMode::Backtrack(error_position!(input, ErrorKind::Tag))) - } - - // should not go into an infinite loop - fn multi0(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - many0(tst)(i) - } - let a = &b"abcdef"[..]; - assert_eq!(multi0(a), Ok((a, Vec::new()))); - - fn multi1(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - many1(tst)(i) - } - let a = &b"abcdef"[..]; - assert_eq!( - multi1(a), - Err(ErrMode::Backtrack(error_position!(a, ErrorKind::Tag))) - ); + fn tst(input: &[u8]) -> IResult<&[u8], &[u8]> { + println!("input: {:?}", input); + Err(ErrMode::Backtrack(error_position!(input, ErrorKind::Tag))) + } + + // should not go into an infinite loop + fn multi0(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many0(tst)(i) + } + let a = &b"abcdef"[..]; + assert_eq!(multi0(a), Ok((a, Vec::new()))); + + fn multi1(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + many1(tst)(i) + } + let a = &b"abcdef"[..]; + assert_eq!( + multi1(a), + Err(ErrMode::Backtrack(error_position!(a, ErrorKind::Tag))) + ); } #[test] #[cfg(feature = "alloc")] fn many_m_n_test() { - fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - many_m_n(2, 4, tag("Abcd"))(i) - } - - let a = &b"Abcdef"[..]; - let b = &b"AbcdAbcdefgh"[..]; - let c = &b"AbcdAbcdAbcdAbcdefgh"[..]; - let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..]; - let e = &b"AbcdAb"[..]; - - assert_eq!( - multi(Streaming(a)), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"ef"[..]), - ErrorKind::Tag - ))) - ); - let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]]; - assert_eq!(multi(Streaming(b)), Ok((Streaming(&b"efgh"[..]), res1))); - let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]]; - assert_eq!(multi(Streaming(c)), Ok((Streaming(&b"efgh"[..]), res2))); - let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]]; - assert_eq!(multi(Streaming(d)), Ok((Streaming(&b"Abcdefgh"[..]), res3))); - assert_eq!( - multi(Streaming(e)), - Err(ErrMode::Incomplete(Needed::new(2))) - ); + fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + many_m_n(2, 4, tag("Abcd"))(i) + } + + let a = &b"Abcdef"[..]; + let b = &b"AbcdAbcdefgh"[..]; + let c = &b"AbcdAbcdAbcdAbcdefgh"[..]; + let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..]; + let e = &b"AbcdAb"[..]; + + assert_eq!( + multi(Streaming(a)), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"ef"[..]), + ErrorKind::Tag + ))) + ); + let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(multi(Streaming(b)), Ok((Streaming(&b"efgh"[..]), res1))); + let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(multi(Streaming(c)), Ok((Streaming(&b"efgh"[..]), res2))); + let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(multi(Streaming(d)), Ok((Streaming(&b"Abcdefgh"[..]), res3))); + assert_eq!( + multi(Streaming(e)), + Err(ErrMode::Incomplete(Needed::new(2))) + ); } #[test] #[cfg(feature = "alloc")] fn count_test() { - const TIMES: usize = 2; - fn cnt_2(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - count(tag("abc"), TIMES)(i) - } - - assert_eq!( - cnt_2(Streaming(&b"abcabcabcdef"[..])), - Ok((Streaming(&b"abcdef"[..]), vec![&b"abc"[..], &b"abc"[..]])) - ); - assert_eq!( - cnt_2(Streaming(&b"ab"[..])), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - cnt_2(Streaming(&b"abcab"[..])), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - cnt_2(Streaming(&b"xxx"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxx"[..]), - ErrorKind::Tag - ))) - ); - assert_eq!( - cnt_2(Streaming(&b"xxxabcabcdef"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxxabcabcdef"[..]), - ErrorKind::Tag - ))) - ); - assert_eq!( - cnt_2(Streaming(&b"abcxxxabcdef"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxxabcdef"[..]), - ErrorKind::Tag - ))) - ); + const TIMES: usize = 2; + fn cnt_2(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + count(tag("abc"), TIMES)(i) + } + + assert_eq!( + cnt_2(Streaming(&b"abcabcabcdef"[..])), + Ok((Streaming(&b"abcdef"[..]), vec![&b"abc"[..], &b"abc"[..]])) + ); + assert_eq!( + cnt_2(Streaming(&b"ab"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + cnt_2(Streaming(&b"abcab"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + cnt_2(Streaming(&b"xxx"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + cnt_2(Streaming(&b"xxxabcabcdef"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxxabcabcdef"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + cnt_2(Streaming(&b"abcxxxabcdef"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxxabcdef"[..]), + ErrorKind::Tag + ))) + ); } #[test] #[cfg(feature = "alloc")] fn count_zero() { - const TIMES: usize = 0; - fn counter_2(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - count(tag("abc"), TIMES)(i) - } - - let done = &b"abcabcabcdef"[..]; - let parsed_done = Vec::new(); - let rest = done; - let incomplete_1 = &b"ab"[..]; - let parsed_incompl_1 = Vec::new(); - let incomplete_2 = &b"abcab"[..]; - let parsed_incompl_2 = Vec::new(); - let error = &b"xxx"[..]; - let error_remain = &b"xxx"[..]; - let parsed_err = Vec::new(); - let error_1 = &b"xxxabcabcdef"[..]; - let parsed_err_1 = Vec::new(); - let error_1_remain = &b"xxxabcabcdef"[..]; - let error_2 = &b"abcxxxabcdef"[..]; - let parsed_err_2 = Vec::new(); - let error_2_remain = &b"abcxxxabcdef"[..]; - - assert_eq!(counter_2(done), Ok((rest, parsed_done))); - assert_eq!( - counter_2(incomplete_1), - Ok((incomplete_1, parsed_incompl_1)) - ); - assert_eq!( - counter_2(incomplete_2), - Ok((incomplete_2, parsed_incompl_2)) - ); - assert_eq!(counter_2(error), Ok((error_remain, parsed_err))); - assert_eq!(counter_2(error_1), Ok((error_1_remain, parsed_err_1))); - assert_eq!(counter_2(error_2), Ok((error_2_remain, parsed_err_2))); + const TIMES: usize = 0; + fn counter_2(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + count(tag("abc"), TIMES)(i) + } + + let done = &b"abcabcabcdef"[..]; + let parsed_done = Vec::new(); + let rest = done; + let incomplete_1 = &b"ab"[..]; + let parsed_incompl_1 = Vec::new(); + let incomplete_2 = &b"abcab"[..]; + let parsed_incompl_2 = Vec::new(); + let error = &b"xxx"[..]; + let error_remain = &b"xxx"[..]; + let parsed_err = Vec::new(); + let error_1 = &b"xxxabcabcdef"[..]; + let parsed_err_1 = Vec::new(); + let error_1_remain = &b"xxxabcabcdef"[..]; + let error_2 = &b"abcxxxabcdef"[..]; + let parsed_err_2 = Vec::new(); + let error_2_remain = &b"abcxxxabcdef"[..]; + + assert_eq!(counter_2(done), Ok((rest, parsed_done))); + assert_eq!( + counter_2(incomplete_1), + Ok((incomplete_1, parsed_incompl_1)) + ); + assert_eq!( + counter_2(incomplete_2), + Ok((incomplete_2, parsed_incompl_2)) + ); + assert_eq!(counter_2(error), Ok((error_remain, parsed_err))); + assert_eq!(counter_2(error_1), Ok((error_1_remain, parsed_err_1))); + assert_eq!(counter_2(error_2), Ok((error_2_remain, parsed_err_2))); } #[derive(Debug, Clone, Eq, PartialEq)] pub struct NilError; impl From<(I, ErrorKind)> for NilError { - fn from(_: (I, ErrorKind)) -> Self { - NilError - } + fn from(_: (I, ErrorKind)) -> Self { + NilError + } } impl ParseError for NilError { - fn from_error_kind(_: I, _: ErrorKind) -> NilError { - NilError - } - fn append(self, _: I, _: ErrorKind) -> NilError { - NilError - } + fn from_error_kind(_: I, _: ErrorKind) -> NilError { + NilError + } + fn append(self, _: I, _: ErrorKind) -> NilError { + NilError + } } #[test] #[cfg(feature = "alloc")] fn length_count_test() { - fn number(i: Streaming<&[u8]>) -> IResult, u32> { - digit - .map_res(str::from_utf8) - .map_res(FromStr::from_str) - .parse_next(i) - } - - fn cnt(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - length_count(number, tag("abc"))(i) - } - - assert_eq!( - cnt(Streaming(&b"2abcabcabcdef"[..])), - Ok((Streaming(&b"abcdef"[..]), vec![&b"abc"[..], &b"abc"[..]])) - ); - assert_eq!( - cnt(Streaming(&b"2ab"[..])), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - cnt(Streaming(&b"3abcab"[..])), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - cnt(Streaming(&b"xxx"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxx"[..]), - ErrorKind::Digit - ))) - ); - assert_eq!( - cnt(Streaming(&b"2abcxxx"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxx"[..]), - ErrorKind::Tag - ))) - ); + fn number(i: Streaming<&[u8]>) -> IResult, u32> { + digit + .map_res(str::from_utf8) + .map_res(FromStr::from_str) + .parse_next(i) + } + + fn cnt(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + length_count(number, tag("abc"))(i) + } + + assert_eq!( + cnt(Streaming(&b"2abcabcabcdef"[..])), + Ok((Streaming(&b"abcdef"[..]), vec![&b"abc"[..], &b"abc"[..]])) + ); + assert_eq!( + cnt(Streaming(&b"2ab"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + cnt(Streaming(&b"3abcab"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + cnt(Streaming(&b"xxx"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxx"[..]), + ErrorKind::Digit + ))) + ); + assert_eq!( + cnt(Streaming(&b"2abcxxx"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); } #[test] fn length_data_test() { - fn number(i: Streaming<&[u8]>) -> IResult, u32> { - digit - .map_res(str::from_utf8) - .map_res(FromStr::from_str) - .parse_next(i) - } - - fn take(i: Streaming<&[u8]>) -> IResult, &[u8]> { - length_data(number)(i) - } - - assert_eq!( - take(Streaming(&b"6abcabcabcdef"[..])), - Ok((Streaming(&b"abcdef"[..]), &b"abcabc"[..])) - ); - assert_eq!( - take(Streaming(&b"3ab"[..])), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - take(Streaming(&b"xxx"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxx"[..]), - ErrorKind::Digit - ))) - ); - assert_eq!( - take(Streaming(&b"2abcxxx"[..])), - Ok((Streaming(&b"cxxx"[..]), &b"ab"[..])) - ); + fn number(i: Streaming<&[u8]>) -> IResult, u32> { + digit + .map_res(str::from_utf8) + .map_res(FromStr::from_str) + .parse_next(i) + } + + fn take(i: Streaming<&[u8]>) -> IResult, &[u8]> { + length_data(number)(i) + } + + assert_eq!( + take(Streaming(&b"6abcabcabcdef"[..])), + Ok((Streaming(&b"abcdef"[..]), &b"abcabc"[..])) + ); + assert_eq!( + take(Streaming(&b"3ab"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + take(Streaming(&b"xxx"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxx"[..]), + ErrorKind::Digit + ))) + ); + assert_eq!( + take(Streaming(&b"2abcxxx"[..])), + Ok((Streaming(&b"cxxx"[..]), &b"ab"[..])) + ); } #[test] fn length_value_test() { - fn length_value_1(i: Streaming<&[u8]>) -> IResult, u16> { - length_value(be_u8, be_u16)(i) - } - fn length_value_2(i: Streaming<&[u8]>) -> IResult, (u8, u8)> { - length_value(be_u8, (be_u8, be_u8))(i) - } - - let i1 = [0, 5, 6]; - assert_eq!( - length_value_1(Streaming(&i1)), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b""[..]), - ErrorKind::Complete - ))) - ); - assert_eq!( - length_value_2(Streaming(&i1)), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b""[..]), - ErrorKind::Complete - ))) - ); - - let i2 = [1, 5, 6, 3]; - assert_eq!( - length_value_1(Streaming(&i2)), - Err(ErrMode::Backtrack(error_position!( - Streaming(&i2[1..2]), - ErrorKind::Complete - ))) - ); - assert_eq!( - length_value_2(Streaming(&i2)), - Err(ErrMode::Backtrack(error_position!( - Streaming(&i2[1..2]), - ErrorKind::Complete - ))) - ); - - let i3 = [2, 5, 6, 3, 4, 5, 7]; - assert_eq!( - length_value_1(Streaming(&i3)), - Ok((Streaming(&i3[3..]), 1286)) - ); - assert_eq!( - length_value_2(Streaming(&i3)), - Ok((Streaming(&i3[3..]), (5, 6))) - ); - - let i4 = [3, 5, 6, 3, 4, 5]; - assert_eq!( - length_value_1(Streaming(&i4)), - Ok((Streaming(&i4[4..]), 1286)) - ); - assert_eq!( - length_value_2(Streaming(&i4)), - Ok((Streaming(&i4[4..]), (5, 6))) - ); + fn length_value_1(i: Streaming<&[u8]>) -> IResult, u16> { + length_value(be_u8, be_u16)(i) + } + fn length_value_2(i: Streaming<&[u8]>) -> IResult, (u8, u8)> { + length_value(be_u8, (be_u8, be_u8))(i) + } + + let i1 = [0, 5, 6]; + assert_eq!( + length_value_1(Streaming(&i1)), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b""[..]), + ErrorKind::Complete + ))) + ); + assert_eq!( + length_value_2(Streaming(&i1)), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b""[..]), + ErrorKind::Complete + ))) + ); + + let i2 = [1, 5, 6, 3]; + assert_eq!( + length_value_1(Streaming(&i2)), + Err(ErrMode::Backtrack(error_position!( + Streaming(&i2[1..2]), + ErrorKind::Complete + ))) + ); + assert_eq!( + length_value_2(Streaming(&i2)), + Err(ErrMode::Backtrack(error_position!( + Streaming(&i2[1..2]), + ErrorKind::Complete + ))) + ); + + let i3 = [2, 5, 6, 3, 4, 5, 7]; + assert_eq!( + length_value_1(Streaming(&i3)), + Ok((Streaming(&i3[3..]), 1286)) + ); + assert_eq!( + length_value_2(Streaming(&i3)), + Ok((Streaming(&i3[3..]), (5, 6))) + ); + + let i4 = [3, 5, 6, 3, 4, 5]; + assert_eq!( + length_value_1(Streaming(&i4)), + Ok((Streaming(&i4[4..]), 1286)) + ); + assert_eq!( + length_value_2(Streaming(&i4)), + Ok((Streaming(&i4[4..]), (5, 6))) + ); } #[test] #[cfg(feature = "alloc")] fn fold_many0_test() { - fn fold_into_vec(mut acc: Vec, item: T) -> Vec { - acc.push(item); - acc - } - fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - fold_many0(tag("abcd"), Vec::new, fold_into_vec)(i) - } - fn multi_empty(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - fold_many0(tag(""), Vec::new, fold_into_vec)(i) - } - - assert_eq!( - multi(Streaming(&b"abcdef"[..])), - Ok((Streaming(&b"ef"[..]), vec![&b"abcd"[..]])) - ); - assert_eq!( - multi(Streaming(&b"abcdabcdefgh"[..])), - Ok((Streaming(&b"efgh"[..]), vec![&b"abcd"[..], &b"abcd"[..]])) - ); - assert_eq!( - multi(Streaming(&b"azerty"[..])), - Ok((Streaming(&b"azerty"[..]), Vec::new())) - ); - assert_eq!( - multi(Streaming(&b"abcdab"[..])), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_eq!( - multi(Streaming(&b"abcd"[..])), - Err(ErrMode::Incomplete(Needed::new(4))) - ); - assert_eq!( - multi(Streaming(&b""[..])), - Err(ErrMode::Incomplete(Needed::new(4))) - ); - assert_eq!( - multi_empty(Streaming(&b"abcdef"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"abcdef"[..]), - ErrorKind::Many0 - ))) - ); + fn fold_into_vec(mut acc: Vec, item: T) -> Vec { + acc.push(item); + acc + } + fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + fold_many0(tag("abcd"), Vec::new, fold_into_vec)(i) + } + fn multi_empty(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + fold_many0(tag(""), Vec::new, fold_into_vec)(i) + } + + assert_eq!( + multi(Streaming(&b"abcdef"[..])), + Ok((Streaming(&b"ef"[..]), vec![&b"abcd"[..]])) + ); + assert_eq!( + multi(Streaming(&b"abcdabcdefgh"[..])), + Ok((Streaming(&b"efgh"[..]), vec![&b"abcd"[..], &b"abcd"[..]])) + ); + assert_eq!( + multi(Streaming(&b"azerty"[..])), + Ok((Streaming(&b"azerty"[..]), Vec::new())) + ); + assert_eq!( + multi(Streaming(&b"abcdab"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_eq!( + multi(Streaming(&b"abcd"[..])), + Err(ErrMode::Incomplete(Needed::new(4))) + ); + assert_eq!( + multi(Streaming(&b""[..])), + Err(ErrMode::Incomplete(Needed::new(4))) + ); + assert_eq!( + multi_empty(Streaming(&b"abcdef"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"abcdef"[..]), + ErrorKind::Many0 + ))) + ); } #[test] #[cfg(feature = "alloc")] fn fold_many1_test() { - fn fold_into_vec(mut acc: Vec, item: T) -> Vec { - acc.push(item); - acc - } - fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - fold_many1(tag("abcd"), Vec::new, fold_into_vec)(i) - } - - let a = &b"abcdef"[..]; - let b = &b"abcdabcdefgh"[..]; - let c = &b"azerty"[..]; - let d = &b"abcdab"[..]; - - let res1 = vec![&b"abcd"[..]]; - assert_eq!(multi(Streaming(a)), Ok((Streaming(&b"ef"[..]), res1))); - let res2 = vec![&b"abcd"[..], &b"abcd"[..]]; - assert_eq!(multi(Streaming(b)), Ok((Streaming(&b"efgh"[..]), res2))); - assert_eq!( - multi(Streaming(c)), - Err(ErrMode::Backtrack(error_position!( - Streaming(c), - ErrorKind::Many1 - ))) - ); - assert_eq!( - multi(Streaming(d)), - Err(ErrMode::Incomplete(Needed::new(2))) - ); + fn fold_into_vec(mut acc: Vec, item: T) -> Vec { + acc.push(item); + acc + } + fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + fold_many1(tag("abcd"), Vec::new, fold_into_vec)(i) + } + + let a = &b"abcdef"[..]; + let b = &b"abcdabcdefgh"[..]; + let c = &b"azerty"[..]; + let d = &b"abcdab"[..]; + + let res1 = vec![&b"abcd"[..]]; + assert_eq!(multi(Streaming(a)), Ok((Streaming(&b"ef"[..]), res1))); + let res2 = vec![&b"abcd"[..], &b"abcd"[..]]; + assert_eq!(multi(Streaming(b)), Ok((Streaming(&b"efgh"[..]), res2))); + assert_eq!( + multi(Streaming(c)), + Err(ErrMode::Backtrack(error_position!( + Streaming(c), + ErrorKind::Many1 + ))) + ); + assert_eq!( + multi(Streaming(d)), + Err(ErrMode::Incomplete(Needed::new(2))) + ); } #[test] #[cfg(feature = "alloc")] fn fold_many_m_n_test() { - fn fold_into_vec(mut acc: Vec, item: T) -> Vec { - acc.push(item); - acc - } - fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - fold_many_m_n(2, 4, tag("Abcd"), Vec::new, fold_into_vec)(i) - } - - let a = &b"Abcdef"[..]; - let b = &b"AbcdAbcdefgh"[..]; - let c = &b"AbcdAbcdAbcdAbcdefgh"[..]; - let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..]; - let e = &b"AbcdAb"[..]; - - assert_eq!( - multi(Streaming(a)), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"ef"[..]), - ErrorKind::Tag - ))) - ); - let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]]; - assert_eq!(multi(Streaming(b)), Ok((Streaming(&b"efgh"[..]), res1))); - let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]]; - assert_eq!(multi(Streaming(c)), Ok((Streaming(&b"efgh"[..]), res2))); - let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]]; - assert_eq!(multi(Streaming(d)), Ok((Streaming(&b"Abcdefgh"[..]), res3))); - assert_eq!( - multi(Streaming(e)), - Err(ErrMode::Incomplete(Needed::new(2))) - ); + fn fold_into_vec(mut acc: Vec, item: T) -> Vec { + acc.push(item); + acc + } + fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + fold_many_m_n(2, 4, tag("Abcd"), Vec::new, fold_into_vec)(i) + } + + let a = &b"Abcdef"[..]; + let b = &b"AbcdAbcdefgh"[..]; + let c = &b"AbcdAbcdAbcdAbcdefgh"[..]; + let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..]; + let e = &b"AbcdAb"[..]; + + assert_eq!( + multi(Streaming(a)), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"ef"[..]), + ErrorKind::Tag + ))) + ); + let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(multi(Streaming(b)), Ok((Streaming(&b"efgh"[..]), res1))); + let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(multi(Streaming(c)), Ok((Streaming(&b"efgh"[..]), res2))); + let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]]; + assert_eq!(multi(Streaming(d)), Ok((Streaming(&b"Abcdefgh"[..]), res3))); + assert_eq!( + multi(Streaming(e)), + Err(ErrMode::Incomplete(Needed::new(2))) + ); } #[test] fn many0_count_test() { - fn count0_nums(i: &[u8]) -> IResult<&[u8], usize> { - many0((digit, tag(",")))(i) - } + fn count0_nums(i: &[u8]) -> IResult<&[u8], usize> { + many0((digit, tag(",")))(i) + } - assert_eq!(count0_nums(&b"123,junk"[..]), Ok((&b"junk"[..], 1))); + assert_eq!(count0_nums(&b"123,junk"[..]), Ok((&b"junk"[..], 1))); - assert_eq!(count0_nums(&b"123,45,junk"[..]), Ok((&b"junk"[..], 2))); + assert_eq!(count0_nums(&b"123,45,junk"[..]), Ok((&b"junk"[..], 2))); - assert_eq!( - count0_nums(&b"1,2,3,4,5,6,7,8,9,0,junk"[..]), - Ok((&b"junk"[..], 10)) - ); + assert_eq!( + count0_nums(&b"1,2,3,4,5,6,7,8,9,0,junk"[..]), + Ok((&b"junk"[..], 10)) + ); - assert_eq!(count0_nums(&b"hello"[..]), Ok((&b"hello"[..], 0))); + assert_eq!(count0_nums(&b"hello"[..]), Ok((&b"hello"[..], 0))); } #[test] fn many1_count_test() { - fn count1_nums(i: &[u8]) -> IResult<&[u8], usize> { - many1((digit, tag(",")))(i) - } - - assert_eq!(count1_nums(&b"123,45,junk"[..]), Ok((&b"junk"[..], 2))); - - assert_eq!( - count1_nums(&b"1,2,3,4,5,6,7,8,9,0,junk"[..]), - Ok((&b"junk"[..], 10)) - ); - - assert_eq!( - count1_nums(&b"hello"[..]), - Err(ErrMode::Backtrack(error_position!( - &b"hello"[..], - ErrorKind::Digit - ))) - ); + fn count1_nums(i: &[u8]) -> IResult<&[u8], usize> { + many1((digit, tag(",")))(i) + } + + assert_eq!(count1_nums(&b"123,45,junk"[..]), Ok((&b"junk"[..], 2))); + + assert_eq!( + count1_nums(&b"1,2,3,4,5,6,7,8,9,0,junk"[..]), + Ok((&b"junk"[..], 10)) + ); + + assert_eq!( + count1_nums(&b"hello"[..]), + Err(ErrMode::Backtrack(error_position!( + &b"hello"[..], + ErrorKind::Digit + ))) + ); } diff --git a/src/number/complete.rs b/src/number/complete.rs index b04ade88..bec09efa 100644 --- a/src/number/complete.rs +++ b/src/number/complete.rs @@ -35,9 +35,9 @@ use crate::*; #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::be_u8`")] pub fn be_u8>(input: I) -> IResult where - I: Input, + I: Input, { - u8(input) + u8(input) } /// Recognizes a big endian unsigned 2 bytes integer. @@ -61,10 +61,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::be_u16`")] pub fn be_u16>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - be_uint(input, 2) + be_uint(input, 2) } /// Recognizes a big endian unsigned 3 byte integer. @@ -88,10 +88,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::be_u24`")] pub fn be_u24>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - be_uint(input, 3) + be_uint(input, 3) } /// Recognizes a big endian unsigned 4 bytes integer. @@ -115,10 +115,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::be_u32`")] pub fn be_u32>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - be_uint(input, 4) + be_uint(input, 4) } /// Recognizes a big endian unsigned 8 bytes integer. @@ -142,10 +142,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::be_u64`")] pub fn be_u64>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - be_uint(input, 8) + be_uint(input, 8) } /// Recognizes a big endian unsigned 16 bytes integer. @@ -169,38 +169,38 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::be_u128`")] pub fn be_u128>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - be_uint(input, 16) + be_uint(input, 16) } #[inline] fn be_uint>(input: I, bound: usize) -> IResult where - I: Input, - ::Slice: AsBytes, - Uint: Default + Shl + Add + From, + I: Input, + ::Slice: AsBytes, + Uint: Default + Shl + Add + From, { - let offset = input - .offset_at(bound) - .map_err(|_err| ErrMode::Backtrack(make_error(input.clone(), ErrorKind::Eof)))?; - let (input, number) = input.next_slice(offset); - let number = number.as_bytes(); - - let mut res = Uint::default(); - // special case to avoid shift a byte with overflow - if bound > 1 { - for byte in number.iter().copied().take(bound) { - res = (res << 8) + byte.into(); - } - } else { - for byte in number.iter().copied().take(bound) { - res = byte.into(); + let offset = input + .offset_at(bound) + .map_err(|_err| ErrMode::Backtrack(make_error(input.clone(), ErrorKind::Eof)))?; + let (input, number) = input.next_slice(offset); + let number = number.as_bytes(); + + let mut res = Uint::default(); + // special case to avoid shift a byte with overflow + if bound > 1 { + for byte in number.iter().copied().take(bound) { + res = (res << 8) + byte.into(); + } + } else { + for byte in number.iter().copied().take(bound) { + res = byte.into(); + } } - } - Ok((input, res)) + Ok((input, res)) } /// Recognizes a signed 1 byte integer. @@ -224,9 +224,9 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::be_i8`")] pub fn be_i8>(input: I) -> IResult where - I: Input, + I: Input, { - be_u8.map(|x| x as i8).parse_next(input) + be_u8.map(|x| x as i8).parse_next(input) } /// Recognizes a big endian signed 2 bytes integer. @@ -250,10 +250,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::be_i16`")] pub fn be_i16>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - be_u16.map(|x| x as i16).parse_next(input) + be_u16.map(|x| x as i16).parse_next(input) } /// Recognizes a big endian signed 3 bytes integer. @@ -277,19 +277,19 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::be_i24`")] pub fn be_i24>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - // Same as the unsigned version but we need to sign-extend manually here - be_u24 - .map(|x| { - if x & 0x80_00_00 != 0 { - (x | 0xff_00_00_00) as i32 - } else { - x as i32 - } - }) - .parse_next(input) + // Same as the unsigned version but we need to sign-extend manually here + be_u24 + .map(|x| { + if x & 0x80_00_00 != 0 { + (x | 0xff_00_00_00) as i32 + } else { + x as i32 + } + }) + .parse_next(input) } /// Recognizes a big endian signed 4 bytes integer. @@ -313,10 +313,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::be_i32`")] pub fn be_i32>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - be_u32.map(|x| x as i32).parse_next(input) + be_u32.map(|x| x as i32).parse_next(input) } /// Recognizes a big endian signed 8 bytes integer. @@ -340,10 +340,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::be_i64`")] pub fn be_i64>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - be_u64.map(|x| x as i64).parse_next(input) + be_u64.map(|x| x as i64).parse_next(input) } /// Recognizes a big endian signed 16 bytes integer. @@ -367,10 +367,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::be_i128`")] pub fn be_i128>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - be_u128.map(|x| x as i128).parse_next(input) + be_u128.map(|x| x as i128).parse_next(input) } /// Recognizes an unsigned 1 byte integer. @@ -394,9 +394,9 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::le_u8`")] pub fn le_u8>(input: I) -> IResult where - I: Input, + I: Input, { - u8(input) + u8(input) } /// Recognizes a little endian unsigned 2 bytes integer. @@ -420,10 +420,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::le_u16`")] pub fn le_u16>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - le_uint(input, 2) + le_uint(input, 2) } /// Recognizes a little endian unsigned 3 byte integer. @@ -447,10 +447,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::le_u24`")] pub fn le_u24>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - le_uint(input, 3) + le_uint(input, 3) } /// Recognizes a little endian unsigned 4 bytes integer. @@ -474,10 +474,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::le_u32`")] pub fn le_u32>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - le_uint(input, 4) + le_uint(input, 4) } /// Recognizes a little endian unsigned 8 bytes integer. @@ -501,10 +501,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::le_u64`")] pub fn le_u64>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - le_uint(input, 8) + le_uint(input, 8) } /// Recognizes a little endian unsigned 16 bytes integer. @@ -528,31 +528,31 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::le_u128`")] pub fn le_u128>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - le_uint(input, 16) + le_uint(input, 16) } #[inline] fn le_uint>(input: I, bound: usize) -> IResult where - I: Input, - ::Slice: AsBytes, - Uint: Default + Shl + Add + From, + I: Input, + ::Slice: AsBytes, + Uint: Default + Shl + Add + From, { - let offset = input - .offset_at(bound) - .map_err(|_err| ErrMode::Backtrack(make_error(input.clone(), ErrorKind::Eof)))?; - let (input, number) = input.next_slice(offset); - let number = number.as_bytes(); - - let mut res = Uint::default(); - for (index, byte) in number.iter_offsets().take(bound) { - res = res + (Uint::from(byte) << (8 * index as u8)); - } - - Ok((input, res)) + let offset = input + .offset_at(bound) + .map_err(|_err| ErrMode::Backtrack(make_error(input.clone(), ErrorKind::Eof)))?; + let (input, number) = input.next_slice(offset); + let number = number.as_bytes(); + + let mut res = Uint::default(); + for (index, byte) in number.iter_offsets().take(bound) { + res = res + (Uint::from(byte) << (8 * index as u8)); + } + + Ok((input, res)) } /// Recognizes a signed 1 byte integer. @@ -576,9 +576,9 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::le_i8`")] pub fn le_i8>(input: I) -> IResult where - I: Input, + I: Input, { - be_u8.map(|x| x as i8).parse_next(input) + be_u8.map(|x| x as i8).parse_next(input) } /// Recognizes a little endian signed 2 bytes integer. @@ -602,10 +602,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::le_i16`")] pub fn le_i16>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - le_u16.map(|x| x as i16).parse_next(input) + le_u16.map(|x| x as i16).parse_next(input) } /// Recognizes a little endian signed 3 bytes integer. @@ -629,19 +629,19 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::le_i24`")] pub fn le_i24>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - // Same as the unsigned version but we need to sign-extend manually here - le_u24 - .map(|x| { - if x & 0x80_00_00 != 0 { - (x | 0xff_00_00_00) as i32 - } else { - x as i32 - } - }) - .parse_next(input) + // Same as the unsigned version but we need to sign-extend manually here + le_u24 + .map(|x| { + if x & 0x80_00_00 != 0 { + (x | 0xff_00_00_00) as i32 + } else { + x as i32 + } + }) + .parse_next(input) } /// Recognizes a little endian signed 4 bytes integer. @@ -665,10 +665,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::le_i32`")] pub fn le_i32>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - le_u32.map(|x| x as i32).parse_next(input) + le_u32.map(|x| x as i32).parse_next(input) } /// Recognizes a little endian signed 8 bytes integer. @@ -692,10 +692,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::le_i64`")] pub fn le_i64>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - le_u64.map(|x| x as i64).parse_next(input) + le_u64.map(|x| x as i64).parse_next(input) } /// Recognizes a little endian signed 16 bytes integer. @@ -719,10 +719,10 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::le_i128`")] pub fn le_i128>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - le_u128.map(|x| x as i128).parse_next(input) + le_u128.map(|x| x as i128).parse_next(input) } /// Recognizes an unsigned 1 byte integer @@ -747,11 +747,11 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::u8`")] pub fn u8>(input: I) -> IResult where - I: Input, + I: Input, { - input - .next_token() - .ok_or_else(|| ErrMode::Backtrack(make_error(input, ErrorKind::Eof))) + input + .next_token() + .ok_or_else(|| ErrMode::Backtrack(make_error(input, ErrorKind::Eof))) } /// Recognizes an unsigned 2 bytes integer @@ -785,17 +785,17 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::u16`")] pub fn u16>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_u16, - crate::number::Endianness::Little => le_u16, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_u16, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_u16, - } + match endian { + crate::number::Endianness::Big => be_u16, + crate::number::Endianness::Little => le_u16, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_u16, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_u16, + } } /// Recognizes an unsigned 3 byte integer @@ -828,17 +828,17 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::u24`")] pub fn u24>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_u24, - crate::number::Endianness::Little => le_u24, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_u24, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_u24, - } + match endian { + crate::number::Endianness::Big => be_u24, + crate::number::Endianness::Little => le_u24, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_u24, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_u24, + } } /// Recognizes an unsigned 4 byte integer @@ -871,17 +871,17 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::u32`")] pub fn u32>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_u32, - crate::number::Endianness::Little => le_u32, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_u32, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_u32, - } + match endian { + crate::number::Endianness::Big => be_u32, + crate::number::Endianness::Little => le_u32, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_u32, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_u32, + } } /// Recognizes an unsigned 8 byte integer @@ -914,17 +914,17 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::u64`")] pub fn u64>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_u64, - crate::number::Endianness::Little => le_u64, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_u64, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_u64, - } + match endian { + crate::number::Endianness::Big => be_u64, + crate::number::Endianness::Little => le_u64, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_u64, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_u64, + } } /// Recognizes an unsigned 16 byte integer @@ -957,17 +957,17 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::u128`")] pub fn u128>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_u128, - crate::number::Endianness::Little => le_u128, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_u128, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_u128, - } + match endian { + crate::number::Endianness::Big => be_u128, + crate::number::Endianness::Little => le_u128, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_u128, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_u128, + } } /// Recognizes a signed 1 byte integer @@ -992,9 +992,9 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::i8`")] pub fn i8>(i: I) -> IResult where - I: Input, + I: Input, { - u8.map(|x| x as i8).parse_next(i) + u8.map(|x| x as i8).parse_next(i) } /// Recognizes a signed 2 byte integer @@ -1027,17 +1027,17 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::i16`")] pub fn i16>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_i16, - crate::number::Endianness::Little => le_i16, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_i16, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_i16, - } + match endian { + crate::number::Endianness::Big => be_i16, + crate::number::Endianness::Little => le_i16, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_i16, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_i16, + } } /// Recognizes a signed 3 byte integer @@ -1070,17 +1070,17 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::i24`")] pub fn i24>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_i24, - crate::number::Endianness::Little => le_i24, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_i24, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_i24, - } + match endian { + crate::number::Endianness::Big => be_i24, + crate::number::Endianness::Little => le_i24, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_i24, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_i24, + } } /// Recognizes a signed 4 byte integer @@ -1113,17 +1113,17 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::i32`")] pub fn i32>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_i32, - crate::number::Endianness::Little => le_i32, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_i32, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_i32, - } + match endian { + crate::number::Endianness::Big => be_i32, + crate::number::Endianness::Little => le_i32, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_i32, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_i32, + } } /// Recognizes a signed 8 byte integer @@ -1156,17 +1156,17 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::i64`")] pub fn i64>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_i64, - crate::number::Endianness::Little => le_i64, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_i64, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_i64, - } + match endian { + crate::number::Endianness::Big => be_i64, + crate::number::Endianness::Little => le_i64, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_i64, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_i64, + } } /// Recognizes a signed 16 byte integer @@ -1199,17 +1199,17 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::i128`")] pub fn i128>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_i128, - crate::number::Endianness::Little => le_i128, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_i128, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_i128, - } + match endian { + crate::number::Endianness::Big => be_i128, + crate::number::Endianness::Little => le_i128, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_i128, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_i128, + } } /// Recognizes a big endian 4 bytes floating point number. @@ -1233,13 +1233,13 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::be_f32`")] pub fn be_f32>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match be_u32(input) { - Err(e) => Err(e), - Ok((i, o)) => Ok((i, f32::from_bits(o))), - } + match be_u32(input) { + Err(e) => Err(e), + Ok((i, o)) => Ok((i, f32::from_bits(o))), + } } /// Recognizes a big endian 8 bytes floating point number. @@ -1263,13 +1263,13 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::be_f64`")] pub fn be_f64>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match be_u64(input) { - Err(e) => Err(e), - Ok((i, o)) => Ok((i, f64::from_bits(o))), - } + match be_u64(input) { + Err(e) => Err(e), + Ok((i, o)) => Ok((i, f64::from_bits(o))), + } } /// Recognizes a little endian 4 bytes floating point number. @@ -1293,13 +1293,13 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::le_f32`")] pub fn le_f32>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match le_u32(input) { - Err(e) => Err(e), - Ok((i, o)) => Ok((i, f32::from_bits(o))), - } + match le_u32(input) { + Err(e) => Err(e), + Ok((i, o)) => Ok((i, f32::from_bits(o))), + } } /// Recognizes a little endian 8 bytes floating point number. @@ -1323,13 +1323,13 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::le_f64`")] pub fn le_f64>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match le_u64(input) { - Err(e) => Err(e), - Ok((i, o)) => Ok((i, f64::from_bits(o))), - } + match le_u64(input) { + Err(e) => Err(e), + Ok((i, o)) => Ok((i, f64::from_bits(o))), + } } /// Recognizes a 4 byte floating point number @@ -1362,17 +1362,17 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::f32`")] pub fn f32>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_f32, - crate::number::Endianness::Little => le_f32, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_f32, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_f32, - } + match endian { + crate::number::Endianness::Big => be_f32, + crate::number::Endianness::Little => le_f32, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_f32, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_f32, + } } /// Recognizes an 8 byte floating point number @@ -1405,17 +1405,17 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::number::f64`")] pub fn f64>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_f64, - crate::number::Endianness::Little => le_f64, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_f64, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_f64, - } + match endian { + crate::number::Endianness::Big => be_f64, + crate::number::Endianness::Little => le_f64, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_f64, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_f64, + } } /// Recognizes a hex-encoded integer. @@ -1440,170 +1440,172 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::character::hex_uint`")] pub fn hex_u32>(input: I) -> IResult where - I: Input, - ::Token: AsChar, - ::Slice: AsBStr, + I: Input, + ::Token: AsChar, + ::Slice: AsBStr, { - let invalid_offset = input - .offset_for(|c| { - let c = c.as_char(); - !"0123456789abcdefABCDEF".contains(c) - }) - .unwrap_or_else(|| input.input_len()); - const MAX_DIGITS: usize = 8; - let max_offset = input - .offset_at(MAX_DIGITS) - .unwrap_or_else(|_err| input.input_len()); - let offset = invalid_offset.min(max_offset); - if offset == 0 { - return Err(ErrMode::from_error_kind(input, ErrorKind::IsA)); - } - let (remaining, parsed) = input.next_slice(offset); - - let res = parsed - .as_bstr() - .iter() - .rev() - .enumerate() - .map(|(k, &v)| { - let digit = v as char; - digit.to_digit(16).unwrap_or(0) << (k * 4) - }) - .sum(); - - Ok((remaining, res)) + let invalid_offset = input + .offset_for(|c| { + let c = c.as_char(); + !"0123456789abcdefABCDEF".contains(c) + }) + .unwrap_or_else(|| input.input_len()); + const MAX_DIGITS: usize = 8; + let max_offset = input + .offset_at(MAX_DIGITS) + .unwrap_or_else(|_err| input.input_len()); + let offset = invalid_offset.min(max_offset); + if offset == 0 { + return Err(ErrMode::from_error_kind(input, ErrorKind::IsA)); + } + let (remaining, parsed) = input.next_slice(offset); + + let res = parsed + .as_bstr() + .iter() + .rev() + .enumerate() + .map(|(k, &v)| { + let digit = v as char; + digit.to_digit(16).unwrap_or(0) << (k * 4) + }) + .sum(); + + Ok((remaining, res)) } /// **WARNING:** Deprecated, no longer supported #[deprecated(since = "0.3.0", note = "No longer supported")] pub fn recognize_float>(input: T) -> IResult::Slice, E> where - T: Input, - T: Offset + Compare<&'static str>, - ::Token: AsChar + Copy, - ::IterOffsets: Clone, - T: AsBStr, + T: Input, + T: Offset + Compare<&'static str>, + ::Token: AsChar + Copy, + ::IterOffsets: Clone, + T: AsBStr, { - tuple(( - opt(alt((char('+'), char('-')))), - alt(( - map(tuple((digit1, opt(pair(char('.'), opt(digit1))))), |_| ()), - map(tuple((char('.'), digit1)), |_| ()), - )), - opt(tuple(( - alt((char('e'), char('E'))), - opt(alt((char('+'), char('-')))), - cut_err(digit1), - ))), - )) - .recognize() - .parse_next(input) + tuple(( + opt(alt((char('+'), char('-')))), + alt(( + map(tuple((digit1, opt(pair(char('.'), opt(digit1))))), |_| ()), + map(tuple((char('.'), digit1)), |_| ()), + )), + opt(tuple(( + alt((char('e'), char('E'))), + opt(alt((char('+'), char('-')))), + cut_err(digit1), + ))), + )) + .recognize() + .parse_next(input) } /// **WARNING:** Deprecated, no longer supported #[deprecated(since = "0.3.0", note = "No longer supported")] pub fn recognize_float_or_exceptions>( - input: T, + input: T, ) -> IResult::Slice, E> where - T: Input, - T: Offset + Compare<&'static str>, - ::Token: AsChar + Copy, - ::IterOffsets: Clone, - T: AsBStr, + T: Input, + T: Offset + Compare<&'static str>, + ::Token: AsChar + Copy, + ::IterOffsets: Clone, + T: AsBStr, { - alt(( - |i: T| { - recognize_float::<_, E>(i.clone()).map_err(|e| match e { - crate::error::ErrMode::Backtrack(_) => { - crate::error::ErrMode::from_error_kind(i, ErrorKind::Float) - } - crate::error::ErrMode::Cut(_) => { - crate::error::ErrMode::Cut(E::from_error_kind(i, ErrorKind::Float)) - } - crate::error::ErrMode::Incomplete(needed) => crate::error::ErrMode::Incomplete(needed), - }) - }, - |i: T| { - crate::bytes::complete::tag_no_case::<_, _, E>("nan")(i.clone()) - .map_err(|_err| crate::error::ErrMode::from_error_kind(i, ErrorKind::Float)) - }, - |i: T| { - crate::bytes::complete::tag_no_case::<_, _, E>("inf")(i.clone()) - .map_err(|_err| crate::error::ErrMode::from_error_kind(i, ErrorKind::Float)) - }, - |i: T| { - crate::bytes::complete::tag_no_case::<_, _, E>("infinity")(i.clone()) - .map_err(|_err| crate::error::ErrMode::from_error_kind(i, ErrorKind::Float)) - }, - ))(input) + alt(( + |i: T| { + recognize_float::<_, E>(i.clone()).map_err(|e| match e { + crate::error::ErrMode::Backtrack(_) => { + crate::error::ErrMode::from_error_kind(i, ErrorKind::Float) + } + crate::error::ErrMode::Cut(_) => { + crate::error::ErrMode::Cut(E::from_error_kind(i, ErrorKind::Float)) + } + crate::error::ErrMode::Incomplete(needed) => { + crate::error::ErrMode::Incomplete(needed) + } + }) + }, + |i: T| { + crate::bytes::complete::tag_no_case::<_, _, E>("nan")(i.clone()) + .map_err(|_err| crate::error::ErrMode::from_error_kind(i, ErrorKind::Float)) + }, + |i: T| { + crate::bytes::complete::tag_no_case::<_, _, E>("inf")(i.clone()) + .map_err(|_err| crate::error::ErrMode::from_error_kind(i, ErrorKind::Float)) + }, + |i: T| { + crate::bytes::complete::tag_no_case::<_, _, E>("infinity")(i.clone()) + .map_err(|_err| crate::error::ErrMode::from_error_kind(i, ErrorKind::Float)) + }, + ))(input) } /// **WARNING:** Deprecated, no longer supported #[allow(clippy::type_complexity)] #[deprecated(since = "0.3.0", note = "No longer supported")] pub fn recognize_float_parts>( - input: T, + input: T, ) -> IResult::Slice, ::Slice, i32), E> where - T: Input + Compare<&'static [u8]> + AsBStr, - ::Token: AsChar + Copy, - ::Slice: SliceLen, + T: Input + Compare<&'static [u8]> + AsBStr, + ::Token: AsChar + Copy, + ::Slice: SliceLen, { - let (i, sign) = sign(input.clone())?; - - let (i, integer) = match i.offset_for(|c| !c.is_dec_digit()) { - Some(offset) => i.next_slice(offset), - None => i.next_slice(i.input_len()), - }; - - let (i, opt_dot) = opt(tag(&b"."[..]))(i)?; - let (i, fraction) = if opt_dot.is_none() { - i.next_slice(0) - } else { - // match number - let mut zero_count = 0usize; - let mut offset = None; - for (pos, c) in i.as_bstr().iter().enumerate() { - if *c >= b'0' && *c <= b'9' { - if *c == b'0' { - zero_count += 1; - } else { - zero_count = 0; + let (i, sign) = sign(input.clone())?; + + let (i, integer) = match i.offset_for(|c| !c.is_dec_digit()) { + Some(offset) => i.next_slice(offset), + None => i.next_slice(i.input_len()), + }; + + let (i, opt_dot) = opt(tag(&b"."[..]))(i)?; + let (i, fraction) = if opt_dot.is_none() { + i.next_slice(0) + } else { + // match number + let mut zero_count = 0usize; + let mut offset = None; + for (pos, c) in i.as_bstr().iter().enumerate() { + if *c >= b'0' && *c <= b'9' { + if *c == b'0' { + zero_count += 1; + } else { + zero_count = 0; + } + } else { + offset = Some(pos); + break; + } } - } else { - offset = Some(pos); - break; - } + let offset = offset.unwrap_or_else(|| i.input_len()); + + // trim right zeroes + let trimmed_offset = (offset - zero_count).max(1); + + let (_, frac) = i.next_slice(trimmed_offset); + let (i, _) = i.next_slice(offset); + (i, frac) + }; + + if integer.slice_len() == 0 && fraction.slice_len() == 0 { + return Err(ErrMode::from_error_kind(input, ErrorKind::Float)); } - let offset = offset.unwrap_or_else(|| i.input_len()); - - // trim right zeroes - let trimmed_offset = (offset - zero_count).max(1); - - let (_, frac) = i.next_slice(trimmed_offset); - let (i, _) = i.next_slice(offset); - (i, frac) - }; - - if integer.slice_len() == 0 && fraction.slice_len() == 0 { - return Err(ErrMode::from_error_kind(input, ErrorKind::Float)); - } - - let i2 = i.clone(); - let (i, e) = i - .next_token() - .filter(|(_, t)| t.as_char() == 'e' || t.as_char() == 'E') - .map(|(i, _)| (i, true)) - .unwrap_or((i, false)); - - let (i, exp) = if e { - cut_err(crate::character::complete::i32)(i)? - } else { - (i2, 0) - }; - - Ok((i, (sign, integer, fraction, exp))) + + let i2 = i.clone(); + let (i, e) = i + .next_token() + .filter(|(_, t)| t.as_char() == 'e' || t.as_char() == 'E') + .map(|(i, _)| (i, true)) + .unwrap_or((i, false)); + + let (i, exp) = if e { + cut_err(crate::character::complete::i32)(i)? + } else { + (i2, 0) + }; + + Ok((i, (sign, integer, fraction, exp))) } use crate::input::ParseSlice; @@ -1630,21 +1632,21 @@ use crate::input::ParseSlice; #[deprecated(since = "0.1.0", note = "Replaced with `winnow::character::float`")] pub fn float>(input: T) -> IResult where - T: Input, - T: Offset + Compare<&'static str>, - ::Slice: ParseSlice, - ::Token: AsChar + Copy, - ::IterOffsets: Clone, - T: AsBStr, + T: Input, + T: Offset + Compare<&'static str>, + ::Slice: ParseSlice, + ::Token: AsChar + Copy, + ::IterOffsets: Clone, + T: AsBStr, { - let (i, s) = recognize_float_or_exceptions(input)?; - match s.parse_slice() { - Some(f) => Ok((i, f)), - None => Err(crate::error::ErrMode::from_error_kind( - i, - crate::error::ErrorKind::Float, - )), - } + let (i, s) = recognize_float_or_exceptions(input)?; + match s.parse_slice() { + Some(f) => Ok((i, f)), + None => Err(crate::error::ErrMode::from_error_kind( + i, + crate::error::ErrorKind::Float, + )), + } } /// Recognizes floating point number in text format and returns a f64. @@ -1669,504 +1671,504 @@ where #[deprecated(since = "0.1.0", note = "Replaced with `winnow::character::float`")] pub fn double>(input: T) -> IResult where - T: Input, - T: Offset + Compare<&'static str>, - ::Slice: ParseSlice, - ::Token: AsChar + Copy, - ::IterOffsets: Clone, - T: AsBStr, + T: Input, + T: Offset + Compare<&'static str>, + ::Slice: ParseSlice, + ::Token: AsChar + Copy, + ::IterOffsets: Clone, + T: AsBStr, { - let (i, s) = recognize_float_or_exceptions(input)?; - match s.parse_slice() { - Some(f) => Ok((i, f)), - None => Err(crate::error::ErrMode::from_error_kind( - i, - crate::error::ErrorKind::Float, - )), - } + let (i, s) = recognize_float_or_exceptions(input)?; + match s.parse_slice() { + Some(f) => Ok((i, f)), + None => Err(crate::error::ErrMode::from_error_kind( + i, + crate::error::ErrorKind::Float, + )), + } } #[cfg(test)] mod tests { - use super::*; - use crate::error::ErrMode; - use crate::error::ErrorKind; - use proptest::prelude::*; + use super::*; + use crate::error::ErrMode; + use crate::error::ErrorKind; + use proptest::prelude::*; - macro_rules! assert_parse( + macro_rules! assert_parse( ($left: expr, $right: expr) => { let res: $crate::IResult<_, _> = $left; assert_eq!(res, $right); }; ); - #[test] - fn i8_tests() { - assert_parse!(i8(&[0x00][..]), Ok((&b""[..], 0))); - assert_parse!(i8(&[0x7f][..]), Ok((&b""[..], 127))); - assert_parse!(i8(&[0xff][..]), Ok((&b""[..], -1))); - assert_parse!(i8(&[0x80][..]), Ok((&b""[..], -128))); - } - - #[test] - fn be_i8_tests() { - assert_parse!(be_i8(&[0x00][..]), Ok((&b""[..], 0))); - assert_parse!(be_i8(&[0x7f][..]), Ok((&b""[..], 127))); - assert_parse!(be_i8(&[0xff][..]), Ok((&b""[..], -1))); - assert_parse!(be_i8(&[0x80][..]), Ok((&b""[..], -128))); - } - - #[test] - fn be_i16_tests() { - assert_parse!(be_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0))); - assert_parse!(be_i16(&[0x7f, 0xff][..]), Ok((&b""[..], 32_767_i16))); - assert_parse!(be_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1))); - assert_parse!(be_i16(&[0x80, 0x00][..]), Ok((&b""[..], -32_768_i16))); - } - - #[test] - fn be_u24_tests() { - assert_parse!(be_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); - assert_parse!(be_u24(&[0x00, 0xFF, 0xFF][..]), Ok((&b""[..], 65_535_u32))); - assert_parse!( - be_u24(&[0x12, 0x34, 0x56][..]), - Ok((&b""[..], 1_193_046_u32)) - ); - } - - #[test] - fn be_i24_tests() { - assert_parse!(be_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32))); - assert_parse!(be_i24(&[0xFF, 0x00, 0x00][..]), Ok((&b""[..], -65_536_i32))); - assert_parse!( - be_i24(&[0xED, 0xCB, 0xAA][..]), - Ok((&b""[..], -1_193_046_i32)) - ); - } - - #[test] - fn be_i32_tests() { - assert_parse!(be_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); - assert_parse!( - be_i32(&[0x7f, 0xff, 0xff, 0xff][..]), - Ok((&b""[..], 2_147_483_647_i32)) - ); - assert_parse!(be_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1))); - assert_parse!( - be_i32(&[0x80, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], -2_147_483_648_i32)) - ); - } - - #[test] - fn be_i64_tests() { - assert_parse!( - be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], 0)) - ); - assert_parse!( - be_i64(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), - Ok((&b""[..], 9_223_372_036_854_775_807_i64)) - ); - assert_parse!( - be_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), - Ok((&b""[..], -1)) - ); - assert_parse!( - be_i64(&[0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], -9_223_372_036_854_775_808_i64)) - ); - } - - #[test] - fn be_i128_tests() { - assert_parse!( - be_i128( - &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 - ][..] - ), - Ok((&b""[..], 0)) - ); - assert_parse!( - be_i128( - &[ - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff - ][..] - ), - Ok(( - &b""[..], - 170_141_183_460_469_231_731_687_303_715_884_105_727_i128 - )) - ); - assert_parse!( - be_i128( - &[ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff - ][..] - ), - Ok((&b""[..], -1)) - ); - assert_parse!( - be_i128( - &[ - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 - ][..] - ), - Ok(( - &b""[..], - -170_141_183_460_469_231_731_687_303_715_884_105_728_i128 - )) - ); - } - - #[test] - fn le_i8_tests() { - assert_parse!(le_i8(&[0x00][..]), Ok((&b""[..], 0))); - assert_parse!(le_i8(&[0x7f][..]), Ok((&b""[..], 127))); - assert_parse!(le_i8(&[0xff][..]), Ok((&b""[..], -1))); - assert_parse!(le_i8(&[0x80][..]), Ok((&b""[..], -128))); - } - - #[test] - fn le_i16_tests() { - assert_parse!(le_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0))); - assert_parse!(le_i16(&[0xff, 0x7f][..]), Ok((&b""[..], 32_767_i16))); - assert_parse!(le_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1))); - assert_parse!(le_i16(&[0x00, 0x80][..]), Ok((&b""[..], -32_768_i16))); - } - - #[test] - fn le_u24_tests() { - assert_parse!(le_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); - assert_parse!(le_u24(&[0xFF, 0xFF, 0x00][..]), Ok((&b""[..], 65_535_u32))); - assert_parse!( - le_u24(&[0x56, 0x34, 0x12][..]), - Ok((&b""[..], 1_193_046_u32)) - ); - } - - #[test] - fn le_i24_tests() { - assert_parse!(le_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32))); - assert_parse!(le_i24(&[0x00, 0x00, 0xFF][..]), Ok((&b""[..], -65_536_i32))); - assert_parse!( - le_i24(&[0xAA, 0xCB, 0xED][..]), - Ok((&b""[..], -1_193_046_i32)) - ); - } - - #[test] - fn le_i32_tests() { - assert_parse!(le_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); - assert_parse!( - le_i32(&[0xff, 0xff, 0xff, 0x7f][..]), - Ok((&b""[..], 2_147_483_647_i32)) - ); - assert_parse!(le_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1))); - assert_parse!( - le_i32(&[0x00, 0x00, 0x00, 0x80][..]), - Ok((&b""[..], -2_147_483_648_i32)) - ); - } - - #[test] - fn le_i64_tests() { - assert_parse!( - le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], 0)) - ); - assert_parse!( - le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f][..]), - Ok((&b""[..], 9_223_372_036_854_775_807_i64)) - ); - assert_parse!( - le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), - Ok((&b""[..], -1)) - ); - assert_parse!( - le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80][..]), - Ok((&b""[..], -9_223_372_036_854_775_808_i64)) - ); - } - - #[test] - fn le_i128_tests() { - assert_parse!( - le_i128( - &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 - ][..] - ), - Ok((&b""[..], 0)) - ); - assert_parse!( - le_i128( - &[ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x7f - ][..] - ), - Ok(( - &b""[..], - 170_141_183_460_469_231_731_687_303_715_884_105_727_i128 - )) - ); - assert_parse!( - le_i128( - &[ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff - ][..] - ), - Ok((&b""[..], -1)) - ); - assert_parse!( - le_i128( - &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80 - ][..] - ), - Ok(( - &b""[..], - -170_141_183_460_469_231_731_687_303_715_884_105_728_i128 - )) - ); - } - - #[test] - fn be_f32_tests() { - assert_parse!(be_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32))); - assert_parse!( - be_f32(&[0x4d, 0x31, 0x1f, 0xd8][..]), - Ok((&b""[..], 185_728_380_f32)) - ); - } - - #[test] - fn be_f64_tests() { - assert_parse!( - be_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], 0_f64)) - ); - assert_parse!( - be_f64(&[0x41, 0xa6, 0x23, 0xfb, 0x10, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], 185_728_392_f64)) - ); - } - - #[test] - fn le_f32_tests() { - assert_parse!(le_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32))); - assert_parse!( - le_f32(&[0xd8, 0x1f, 0x31, 0x4d][..]), - Ok((&b""[..], 185_728_380_f32)) - ); - } - - #[test] - fn le_f64_tests() { - assert_parse!( - le_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], 0_f64)) - ); - assert_parse!( - le_f64(&[0x00, 0x00, 0x00, 0x10, 0xfb, 0x23, 0xa6, 0x41][..]), - Ok((&b""[..], 185_728_392_f64)) - ); - } - - #[test] - fn hex_u32_tests() { - assert_parse!( - hex_u32(&b";"[..]), - Err(ErrMode::Backtrack(error_position!( - &b";"[..], - ErrorKind::IsA - ))) - ); - assert_parse!(hex_u32(&b"ff;"[..]), Ok((&b";"[..], 255))); - assert_parse!(hex_u32(&b"1be2;"[..]), Ok((&b";"[..], 7138))); - assert_parse!(hex_u32(&b"c5a31be2;"[..]), Ok((&b";"[..], 3_315_801_058))); - assert_parse!(hex_u32(&b"C5A31be2;"[..]), Ok((&b";"[..], 3_315_801_058))); - assert_parse!(hex_u32(&b"00c5a31be2;"[..]), Ok((&b"e2;"[..], 12_952_347))); - assert_parse!( - hex_u32(&b"c5a31be201;"[..]), - Ok((&b"01;"[..], 3_315_801_058)) - ); - assert_parse!(hex_u32(&b"ffffffff;"[..]), Ok((&b";"[..], 4_294_967_295))); - assert_parse!(hex_u32(&b"0x1be2;"[..]), Ok((&b"x1be2;"[..], 0))); - assert_parse!(hex_u32(&b"12af"[..]), Ok((&b""[..], 0x12af))); - } - - #[test] - #[cfg(feature = "std")] - fn float_test() { - use crate::error::Error; - - let mut test_cases = vec![ - "+3.14", - "3.14", - "-3.14", - "0", - "0.0", - "1.", - ".789", - "-.5", - "1e7", - "-1E-7", - ".3e-2", - "1.e4", - "1.2e4", - "12.34", - "-1.234E-12", - "-1.234e-12", - "0.00000000000000000087", - ]; - - for test in test_cases.drain(..) { - let expected32 = str::parse::(test).unwrap(); - let expected64 = str::parse::(test).unwrap(); - - println!("now parsing: {} -> {}", test, expected32); - - assert_parse!(recognize_float(test), Ok(("", test))); - - assert_parse!(float(test.as_bytes()), Ok((&b""[..], expected32))); - assert_parse!(float(test), Ok(("", expected32))); - - assert_parse!(double(test.as_bytes()), Ok((&b""[..], expected64))); - assert_parse!(double(test), Ok(("", expected64))); + #[test] + fn i8_tests() { + assert_parse!(i8(&[0x00][..]), Ok((&b""[..], 0))); + assert_parse!(i8(&[0x7f][..]), Ok((&b""[..], 127))); + assert_parse!(i8(&[0xff][..]), Ok((&b""[..], -1))); + assert_parse!(i8(&[0x80][..]), Ok((&b""[..], -128))); + } + + #[test] + fn be_i8_tests() { + assert_parse!(be_i8(&[0x00][..]), Ok((&b""[..], 0))); + assert_parse!(be_i8(&[0x7f][..]), Ok((&b""[..], 127))); + assert_parse!(be_i8(&[0xff][..]), Ok((&b""[..], -1))); + assert_parse!(be_i8(&[0x80][..]), Ok((&b""[..], -128))); + } + + #[test] + fn be_i16_tests() { + assert_parse!(be_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!(be_i16(&[0x7f, 0xff][..]), Ok((&b""[..], 32_767_i16))); + assert_parse!(be_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1))); + assert_parse!(be_i16(&[0x80, 0x00][..]), Ok((&b""[..], -32_768_i16))); + } + + #[test] + fn be_u24_tests() { + assert_parse!(be_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!(be_u24(&[0x00, 0xFF, 0xFF][..]), Ok((&b""[..], 65_535_u32))); + assert_parse!( + be_u24(&[0x12, 0x34, 0x56][..]), + Ok((&b""[..], 1_193_046_u32)) + ); + } + + #[test] + fn be_i24_tests() { + assert_parse!(be_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32))); + assert_parse!(be_i24(&[0xFF, 0x00, 0x00][..]), Ok((&b""[..], -65_536_i32))); + assert_parse!( + be_i24(&[0xED, 0xCB, 0xAA][..]), + Ok((&b""[..], -1_193_046_i32)) + ); } - let remaining_exponent = "-1.234E-"; - assert_parse!( - recognize_float(remaining_exponent), - Err(ErrMode::Cut(Error::new("", ErrorKind::Digit))) - ); + #[test] + fn be_i32_tests() { + assert_parse!(be_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!( + be_i32(&[0x7f, 0xff, 0xff, 0xff][..]), + Ok((&b""[..], 2_147_483_647_i32)) + ); + assert_parse!(be_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1))); + assert_parse!( + be_i32(&[0x80, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], -2_147_483_648_i32)) + ); + } - let (_i, nan) = float::<_, ()>("NaN").unwrap(); - assert!(nan.is_nan()); + #[test] + fn be_i64_tests() { + assert_parse!( + be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 0)) + ); + assert_parse!( + be_i64(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), + Ok((&b""[..], 9_223_372_036_854_775_807_i64)) + ); + assert_parse!( + be_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), + Ok((&b""[..], -1)) + ); + assert_parse!( + be_i64(&[0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], -9_223_372_036_854_775_808_i64)) + ); + } - let (_i, inf) = float::<_, ()>("inf").unwrap(); - assert!(inf.is_infinite()); - let (_i, inf) = float::<_, ()>("infinite").unwrap(); - assert!(inf.is_infinite()); - } + #[test] + fn be_i128_tests() { + assert_parse!( + be_i128( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 + ][..] + ), + Ok((&b""[..], 0)) + ); + assert_parse!( + be_i128( + &[ + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff + ][..] + ), + Ok(( + &b""[..], + 170_141_183_460_469_231_731_687_303_715_884_105_727_i128 + )) + ); + assert_parse!( + be_i128( + &[ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff + ][..] + ), + Ok((&b""[..], -1)) + ); + assert_parse!( + be_i128( + &[ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 + ][..] + ), + Ok(( + &b""[..], + -170_141_183_460_469_231_731_687_303_715_884_105_728_i128 + )) + ); + } - #[test] - fn configurable_endianness() { - use crate::number::Endianness; + #[test] + fn le_i8_tests() { + assert_parse!(le_i8(&[0x00][..]), Ok((&b""[..], 0))); + assert_parse!(le_i8(&[0x7f][..]), Ok((&b""[..], 127))); + assert_parse!(le_i8(&[0xff][..]), Ok((&b""[..], -1))); + assert_parse!(le_i8(&[0x80][..]), Ok((&b""[..], -128))); + } - fn be_tst16(i: &[u8]) -> IResult<&[u8], u16> { - u16(Endianness::Big)(i) + #[test] + fn le_i16_tests() { + assert_parse!(le_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!(le_i16(&[0xff, 0x7f][..]), Ok((&b""[..], 32_767_i16))); + assert_parse!(le_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1))); + assert_parse!(le_i16(&[0x00, 0x80][..]), Ok((&b""[..], -32_768_i16))); } - fn le_tst16(i: &[u8]) -> IResult<&[u8], u16> { - u16(Endianness::Little)(i) + + #[test] + fn le_u24_tests() { + assert_parse!(le_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!(le_u24(&[0xFF, 0xFF, 0x00][..]), Ok((&b""[..], 65_535_u32))); + assert_parse!( + le_u24(&[0x56, 0x34, 0x12][..]), + Ok((&b""[..], 1_193_046_u32)) + ); } - assert_eq!(be_tst16(&[0x80, 0x00]), Ok((&b""[..], 32_768_u16))); - assert_eq!(le_tst16(&[0x80, 0x00]), Ok((&b""[..], 128_u16))); - fn be_tst32(i: &[u8]) -> IResult<&[u8], u32> { - u32(Endianness::Big)(i) + #[test] + fn le_i24_tests() { + assert_parse!(le_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32))); + assert_parse!(le_i24(&[0x00, 0x00, 0xFF][..]), Ok((&b""[..], -65_536_i32))); + assert_parse!( + le_i24(&[0xAA, 0xCB, 0xED][..]), + Ok((&b""[..], -1_193_046_i32)) + ); } - fn le_tst32(i: &[u8]) -> IResult<&[u8], u32> { - u32(Endianness::Little)(i) + + #[test] + fn le_i32_tests() { + assert_parse!(le_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!( + le_i32(&[0xff, 0xff, 0xff, 0x7f][..]), + Ok((&b""[..], 2_147_483_647_i32)) + ); + assert_parse!(le_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1))); + assert_parse!( + le_i32(&[0x00, 0x00, 0x00, 0x80][..]), + Ok((&b""[..], -2_147_483_648_i32)) + ); } - assert_eq!( - be_tst32(&[0x12, 0x00, 0x60, 0x00]), - Ok((&b""[..], 302_014_464_u32)) - ); - assert_eq!( - le_tst32(&[0x12, 0x00, 0x60, 0x00]), - Ok((&b""[..], 6_291_474_u32)) - ); - - fn be_tst64(i: &[u8]) -> IResult<&[u8], u64> { - u64(Endianness::Big)(i) + + #[test] + fn le_i64_tests() { + assert_parse!( + le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 0)) + ); + assert_parse!( + le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f][..]), + Ok((&b""[..], 9_223_372_036_854_775_807_i64)) + ); + assert_parse!( + le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), + Ok((&b""[..], -1)) + ); + assert_parse!( + le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80][..]), + Ok((&b""[..], -9_223_372_036_854_775_808_i64)) + ); } - fn le_tst64(i: &[u8]) -> IResult<&[u8], u64> { - u64(Endianness::Little)(i) + + #[test] + fn le_i128_tests() { + assert_parse!( + le_i128( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 + ][..] + ), + Ok((&b""[..], 0)) + ); + assert_parse!( + le_i128( + &[ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f + ][..] + ), + Ok(( + &b""[..], + 170_141_183_460_469_231_731_687_303_715_884_105_727_i128 + )) + ); + assert_parse!( + le_i128( + &[ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff + ][..] + ), + Ok((&b""[..], -1)) + ); + assert_parse!( + le_i128( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80 + ][..] + ), + Ok(( + &b""[..], + -170_141_183_460_469_231_731_687_303_715_884_105_728_i128 + )) + ); } - assert_eq!( - be_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), - Ok((&b""[..], 1_297_142_246_100_992_000_u64)) - ); - assert_eq!( - le_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), - Ok((&b""[..], 36_028_874_334_666_770_u64)) - ); - - fn be_tsti16(i: &[u8]) -> IResult<&[u8], i16> { - i16(Endianness::Big)(i) + + #[test] + fn be_f32_tests() { + assert_parse!(be_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32))); + assert_parse!( + be_f32(&[0x4d, 0x31, 0x1f, 0xd8][..]), + Ok((&b""[..], 185_728_380_f32)) + ); } - fn le_tsti16(i: &[u8]) -> IResult<&[u8], i16> { - i16(Endianness::Little)(i) + + #[test] + fn be_f64_tests() { + assert_parse!( + be_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 0_f64)) + ); + assert_parse!( + be_f64(&[0x41, 0xa6, 0x23, 0xfb, 0x10, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 185_728_392_f64)) + ); } - assert_eq!(be_tsti16(&[0x00, 0x80]), Ok((&b""[..], 128_i16))); - assert_eq!(le_tsti16(&[0x00, 0x80]), Ok((&b""[..], -32_768_i16))); - fn be_tsti32(i: &[u8]) -> IResult<&[u8], i32> { - i32(Endianness::Big)(i) + #[test] + fn le_f32_tests() { + assert_parse!(le_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32))); + assert_parse!( + le_f32(&[0xd8, 0x1f, 0x31, 0x4d][..]), + Ok((&b""[..], 185_728_380_f32)) + ); } - fn le_tsti32(i: &[u8]) -> IResult<&[u8], i32> { - i32(Endianness::Little)(i) + + #[test] + fn le_f64_tests() { + assert_parse!( + le_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 0_f64)) + ); + assert_parse!( + le_f64(&[0x00, 0x00, 0x00, 0x10, 0xfb, 0x23, 0xa6, 0x41][..]), + Ok((&b""[..], 185_728_392_f64)) + ); } - assert_eq!( - be_tsti32(&[0x00, 0x12, 0x60, 0x00]), - Ok((&b""[..], 1_204_224_i32)) - ); - assert_eq!( - le_tsti32(&[0x00, 0x12, 0x60, 0x00]), - Ok((&b""[..], 6_296_064_i32)) - ); - - fn be_tsti64(i: &[u8]) -> IResult<&[u8], i64> { - i64(Endianness::Big)(i) + + #[test] + fn hex_u32_tests() { + assert_parse!( + hex_u32(&b";"[..]), + Err(ErrMode::Backtrack(error_position!( + &b";"[..], + ErrorKind::IsA + ))) + ); + assert_parse!(hex_u32(&b"ff;"[..]), Ok((&b";"[..], 255))); + assert_parse!(hex_u32(&b"1be2;"[..]), Ok((&b";"[..], 7138))); + assert_parse!(hex_u32(&b"c5a31be2;"[..]), Ok((&b";"[..], 3_315_801_058))); + assert_parse!(hex_u32(&b"C5A31be2;"[..]), Ok((&b";"[..], 3_315_801_058))); + assert_parse!(hex_u32(&b"00c5a31be2;"[..]), Ok((&b"e2;"[..], 12_952_347))); + assert_parse!( + hex_u32(&b"c5a31be201;"[..]), + Ok((&b"01;"[..], 3_315_801_058)) + ); + assert_parse!(hex_u32(&b"ffffffff;"[..]), Ok((&b";"[..], 4_294_967_295))); + assert_parse!(hex_u32(&b"0x1be2;"[..]), Ok((&b"x1be2;"[..], 0))); + assert_parse!(hex_u32(&b"12af"[..]), Ok((&b""[..], 0x12af))); } - fn le_tsti64(i: &[u8]) -> IResult<&[u8], i64> { - i64(Endianness::Little)(i) + + #[test] + #[cfg(feature = "std")] + fn float_test() { + use crate::error::Error; + + let mut test_cases = vec![ + "+3.14", + "3.14", + "-3.14", + "0", + "0.0", + "1.", + ".789", + "-.5", + "1e7", + "-1E-7", + ".3e-2", + "1.e4", + "1.2e4", + "12.34", + "-1.234E-12", + "-1.234e-12", + "0.00000000000000000087", + ]; + + for test in test_cases.drain(..) { + let expected32 = str::parse::(test).unwrap(); + let expected64 = str::parse::(test).unwrap(); + + println!("now parsing: {} -> {}", test, expected32); + + assert_parse!(recognize_float(test), Ok(("", test))); + + assert_parse!(float(test.as_bytes()), Ok((&b""[..], expected32))); + assert_parse!(float(test), Ok(("", expected32))); + + assert_parse!(double(test.as_bytes()), Ok((&b""[..], expected64))); + assert_parse!(double(test), Ok(("", expected64))); + } + + let remaining_exponent = "-1.234E-"; + assert_parse!( + recognize_float(remaining_exponent), + Err(ErrMode::Cut(Error::new("", ErrorKind::Digit))) + ); + + let (_i, nan) = float::<_, ()>("NaN").unwrap(); + assert!(nan.is_nan()); + + let (_i, inf) = float::<_, ()>("inf").unwrap(); + assert!(inf.is_infinite()); + let (_i, inf) = float::<_, ()>("infinite").unwrap(); + assert!(inf.is_infinite()); } - assert_eq!( - be_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), - Ok((&b""[..], 71_881_672_479_506_432_i64)) - ); - assert_eq!( - le_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), - Ok((&b""[..], 36_028_874_334_732_032_i64)) - ); - } - - #[cfg(feature = "std")] - fn parse_f64(i: &str) -> IResult<&str, f64, ()> { - match recognize_float_or_exceptions(i) { - Err(e) => Err(e), - Ok((i, s)) => { - if s.is_empty() { - return Err(ErrMode::Backtrack(())); + + #[test] + fn configurable_endianness() { + use crate::number::Endianness; + + fn be_tst16(i: &[u8]) -> IResult<&[u8], u16> { + u16(Endianness::Big)(i) } - match s.parse_slice() { - Some(n) => Ok((i, n)), - None => Err(ErrMode::Backtrack(())), + fn le_tst16(i: &[u8]) -> IResult<&[u8], u16> { + u16(Endianness::Little)(i) } - } + assert_eq!(be_tst16(&[0x80, 0x00]), Ok((&b""[..], 32_768_u16))); + assert_eq!(le_tst16(&[0x80, 0x00]), Ok((&b""[..], 128_u16))); + + fn be_tst32(i: &[u8]) -> IResult<&[u8], u32> { + u32(Endianness::Big)(i) + } + fn le_tst32(i: &[u8]) -> IResult<&[u8], u32> { + u32(Endianness::Little)(i) + } + assert_eq!( + be_tst32(&[0x12, 0x00, 0x60, 0x00]), + Ok((&b""[..], 302_014_464_u32)) + ); + assert_eq!( + le_tst32(&[0x12, 0x00, 0x60, 0x00]), + Ok((&b""[..], 6_291_474_u32)) + ); + + fn be_tst64(i: &[u8]) -> IResult<&[u8], u64> { + u64(Endianness::Big)(i) + } + fn le_tst64(i: &[u8]) -> IResult<&[u8], u64> { + u64(Endianness::Little)(i) + } + assert_eq!( + be_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), + Ok((&b""[..], 1_297_142_246_100_992_000_u64)) + ); + assert_eq!( + le_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), + Ok((&b""[..], 36_028_874_334_666_770_u64)) + ); + + fn be_tsti16(i: &[u8]) -> IResult<&[u8], i16> { + i16(Endianness::Big)(i) + } + fn le_tsti16(i: &[u8]) -> IResult<&[u8], i16> { + i16(Endianness::Little)(i) + } + assert_eq!(be_tsti16(&[0x00, 0x80]), Ok((&b""[..], 128_i16))); + assert_eq!(le_tsti16(&[0x00, 0x80]), Ok((&b""[..], -32_768_i16))); + + fn be_tsti32(i: &[u8]) -> IResult<&[u8], i32> { + i32(Endianness::Big)(i) + } + fn le_tsti32(i: &[u8]) -> IResult<&[u8], i32> { + i32(Endianness::Little)(i) + } + assert_eq!( + be_tsti32(&[0x00, 0x12, 0x60, 0x00]), + Ok((&b""[..], 1_204_224_i32)) + ); + assert_eq!( + le_tsti32(&[0x00, 0x12, 0x60, 0x00]), + Ok((&b""[..], 6_296_064_i32)) + ); + + fn be_tsti64(i: &[u8]) -> IResult<&[u8], i64> { + i64(Endianness::Big)(i) + } + fn le_tsti64(i: &[u8]) -> IResult<&[u8], i64> { + i64(Endianness::Little)(i) + } + assert_eq!( + be_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), + Ok((&b""[..], 71_881_672_479_506_432_i64)) + ); + assert_eq!( + le_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), + Ok((&b""[..], 36_028_874_334_732_032_i64)) + ); } - } - proptest! { - #[test] #[cfg(feature = "std")] - fn floats(s in "\\PC*") { - println!("testing {}", s); - let res1 = parse_f64(&s); - let res2 = double::<_, ()>(s.as_str()); - assert_eq!(res1, res2); + fn parse_f64(i: &str) -> IResult<&str, f64, ()> { + match recognize_float_or_exceptions(i) { + Err(e) => Err(e), + Ok((i, s)) => { + if s.is_empty() { + return Err(ErrMode::Backtrack(())); + } + match s.parse_slice() { + Some(n) => Ok((i, n)), + None => Err(ErrMode::Backtrack(())), + } + } + } + } + + proptest! { + #[test] + #[cfg(feature = "std")] + fn floats(s in "\\PC*") { + println!("testing {}", s); + let res1 = parse_f64(&s); + let res2 = double::<_, ()>(s.as_str()); + assert_eq!(res1, res2); + } } - } } diff --git a/src/number/mod.rs b/src/number/mod.rs index 8749d065..2d02bc4f 100644 --- a/src/number/mod.rs +++ b/src/number/mod.rs @@ -14,12 +14,12 @@ use crate::IResult; /// Configurable endianness #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum Endianness { - /// Big endian - Big, - /// Little endian - Little, - /// Will match the host's endianness - Native, + /// Big endian + Big, + /// Little endian + Little, + /// Will match the host's endianness + Native, } /// Recognizes an unsigned 1 byte integer. @@ -58,14 +58,14 @@ pub enum Endianness { #[inline(always)] pub fn be_u8, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, + I: InputIsStreaming, + I: Input, { - if STREAMING { - streaming::be_u8(input) - } else { - complete::be_u8(input) - } + if STREAMING { + streaming::be_u8(input) + } else { + complete::be_u8(input) + } } /// Recognizes a big endian unsigned 2 bytes integer. @@ -104,15 +104,15 @@ where #[inline(always)] pub fn be_u16, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::be_u16(input) - } else { - complete::be_u16(input) - } + if STREAMING { + streaming::be_u16(input) + } else { + complete::be_u16(input) + } } /// Recognizes a big endian unsigned 3 byte integer. @@ -151,15 +151,15 @@ where #[inline(always)] pub fn be_u24, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::be_u24(input) - } else { - complete::be_u24(input) - } + if STREAMING { + streaming::be_u24(input) + } else { + complete::be_u24(input) + } } /// Recognizes a big endian unsigned 4 bytes integer. @@ -198,15 +198,15 @@ where #[inline(always)] pub fn be_u32, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::be_u32(input) - } else { - complete::be_u32(input) - } + if STREAMING { + streaming::be_u32(input) + } else { + complete::be_u32(input) + } } /// Recognizes a big endian unsigned 8 bytes integer. @@ -245,15 +245,15 @@ where #[inline(always)] pub fn be_u64, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::be_u64(input) - } else { - complete::be_u64(input) - } + if STREAMING { + streaming::be_u64(input) + } else { + complete::be_u64(input) + } } /// Recognizes a big endian unsigned 16 bytes integer. @@ -292,15 +292,15 @@ where #[inline(always)] pub fn be_u128, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::be_u128(input) - } else { - complete::be_u128(input) - } + if STREAMING { + streaming::be_u128(input) + } else { + complete::be_u128(input) + } } /// Recognizes a signed 1 byte integer. @@ -337,14 +337,14 @@ where #[inline(always)] pub fn be_i8, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, + I: InputIsStreaming, + I: Input, { - if STREAMING { - streaming::be_i8(input) - } else { - complete::be_i8(input) - } + if STREAMING { + streaming::be_i8(input) + } else { + complete::be_i8(input) + } } /// Recognizes a big endian signed 2 bytes integer. @@ -381,15 +381,15 @@ where #[inline(always)] pub fn be_i16, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::be_i16(input) - } else { - complete::be_i16(input) - } + if STREAMING { + streaming::be_i16(input) + } else { + complete::be_i16(input) + } } /// Recognizes a big endian signed 3 bytes integer. @@ -426,15 +426,15 @@ where #[inline(always)] pub fn be_i24, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::be_i24(input) - } else { - complete::be_i24(input) - } + if STREAMING { + streaming::be_i24(input) + } else { + complete::be_i24(input) + } } /// Recognizes a big endian signed 4 bytes integer. @@ -471,15 +471,15 @@ where #[inline(always)] pub fn be_i32, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::be_i32(input) - } else { - complete::be_i32(input) - } + if STREAMING { + streaming::be_i32(input) + } else { + complete::be_i32(input) + } } /// Recognizes a big endian signed 8 bytes integer. @@ -516,15 +516,15 @@ where #[inline(always)] pub fn be_i64, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::be_i64(input) - } else { - complete::be_i64(input) - } + if STREAMING { + streaming::be_i64(input) + } else { + complete::be_i64(input) + } } /// Recognizes a big endian signed 16 bytes integer. @@ -561,15 +561,15 @@ where #[inline(always)] pub fn be_i128, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::be_i128(input) - } else { - complete::be_i128(input) - } + if STREAMING { + streaming::be_i128(input) + } else { + complete::be_i128(input) + } } /// Recognizes an unsigned 1 byte integer. @@ -606,14 +606,14 @@ where #[inline(always)] pub fn le_u8, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, + I: InputIsStreaming, + I: Input, { - if STREAMING { - streaming::le_u8(input) - } else { - complete::le_u8(input) - } + if STREAMING { + streaming::le_u8(input) + } else { + complete::le_u8(input) + } } /// Recognizes a little endian unsigned 2 bytes integer. @@ -652,15 +652,15 @@ where #[inline(always)] pub fn le_u16, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::le_u16(input) - } else { - complete::le_u16(input) - } + if STREAMING { + streaming::le_u16(input) + } else { + complete::le_u16(input) + } } /// Recognizes a little endian unsigned 3 byte integer. @@ -699,15 +699,15 @@ where #[inline(always)] pub fn le_u24, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::le_u24(input) - } else { - complete::le_u24(input) - } + if STREAMING { + streaming::le_u24(input) + } else { + complete::le_u24(input) + } } /// Recognizes a little endian unsigned 4 bytes integer. @@ -746,15 +746,15 @@ where #[inline(always)] pub fn le_u32, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::le_u32(input) - } else { - complete::le_u32(input) - } + if STREAMING { + streaming::le_u32(input) + } else { + complete::le_u32(input) + } } /// Recognizes a little endian unsigned 8 bytes integer. @@ -793,15 +793,15 @@ where #[inline(always)] pub fn le_u64, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::le_u64(input) - } else { - complete::le_u64(input) - } + if STREAMING { + streaming::le_u64(input) + } else { + complete::le_u64(input) + } } /// Recognizes a little endian unsigned 16 bytes integer. @@ -840,15 +840,15 @@ where #[inline(always)] pub fn le_u128, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::le_u128(input) - } else { - complete::le_u128(input) - } + if STREAMING { + streaming::le_u128(input) + } else { + complete::le_u128(input) + } } /// Recognizes a signed 1 byte integer. @@ -885,14 +885,14 @@ where #[inline(always)] pub fn le_i8, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, + I: InputIsStreaming, + I: Input, { - if STREAMING { - streaming::le_i8(input) - } else { - complete::le_i8(input) - } + if STREAMING { + streaming::le_i8(input) + } else { + complete::le_i8(input) + } } /// Recognizes a little endian signed 2 bytes integer. @@ -931,15 +931,15 @@ where #[inline(always)] pub fn le_i16, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::le_i16(input) - } else { - complete::le_i16(input) - } + if STREAMING { + streaming::le_i16(input) + } else { + complete::le_i16(input) + } } /// Recognizes a little endian signed 3 bytes integer. @@ -978,15 +978,15 @@ where #[inline(always)] pub fn le_i24, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::le_i24(input) - } else { - complete::le_i24(input) - } + if STREAMING { + streaming::le_i24(input) + } else { + complete::le_i24(input) + } } /// Recognizes a little endian signed 4 bytes integer. @@ -1025,15 +1025,15 @@ where #[inline(always)] pub fn le_i32, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::le_i32(input) - } else { - complete::le_i32(input) - } + if STREAMING { + streaming::le_i32(input) + } else { + complete::le_i32(input) + } } /// Recognizes a little endian signed 8 bytes integer. @@ -1072,15 +1072,15 @@ where #[inline(always)] pub fn le_i64, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::le_i64(input) - } else { - complete::le_i64(input) - } + if STREAMING { + streaming::le_i64(input) + } else { + complete::le_i64(input) + } } /// Recognizes a little endian signed 16 bytes integer. @@ -1119,15 +1119,15 @@ where #[inline(always)] pub fn le_i128, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::le_i128(input) - } else { - complete::le_i128(input) - } + if STREAMING { + streaming::le_i128(input) + } else { + complete::le_i128(input) + } } /// Recognizes an unsigned 1 byte integer @@ -1169,14 +1169,14 @@ where #[inline(always)] pub fn u8, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, + I: InputIsStreaming, + I: Input, { - if STREAMING { - streaming::u8(input) - } else { - complete::u8(input) - } + if STREAMING { + streaming::u8(input) + } else { + complete::u8(input) + } } /// Recognizes an unsigned 2 bytes integer @@ -1232,18 +1232,18 @@ where /// ``` #[inline(always)] pub fn u16, const STREAMING: bool>( - endian: crate::number::Endianness, + endian: crate::number::Endianness, ) -> fn(I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::u16(endian) - } else { - complete::u16(endian) - } + if STREAMING { + streaming::u16(endian) + } else { + complete::u16(endian) + } } /// Recognizes an unsigned 3 byte integer @@ -1299,18 +1299,18 @@ where /// ``` #[inline(always)] pub fn u24, const STREAMING: bool>( - endian: crate::number::Endianness, + endian: crate::number::Endianness, ) -> fn(I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::u24(endian) - } else { - complete::u24(endian) - } + if STREAMING { + streaming::u24(endian) + } else { + complete::u24(endian) + } } /// Recognizes an unsigned 4 byte integer @@ -1366,18 +1366,18 @@ where /// ``` #[inline(always)] pub fn u32, const STREAMING: bool>( - endian: crate::number::Endianness, + endian: crate::number::Endianness, ) -> fn(I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::u32(endian) - } else { - complete::u32(endian) - } + if STREAMING { + streaming::u32(endian) + } else { + complete::u32(endian) + } } /// Recognizes an unsigned 8 byte integer @@ -1433,18 +1433,18 @@ where /// ``` #[inline(always)] pub fn u64, const STREAMING: bool>( - endian: crate::number::Endianness, + endian: crate::number::Endianness, ) -> fn(I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::u64(endian) - } else { - complete::u64(endian) - } + if STREAMING { + streaming::u64(endian) + } else { + complete::u64(endian) + } } /// Recognizes an unsigned 16 byte integer @@ -1500,18 +1500,18 @@ where /// ``` #[inline(always)] pub fn u128, const STREAMING: bool>( - endian: crate::number::Endianness, + endian: crate::number::Endianness, ) -> fn(I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::u128(endian) - } else { - complete::u128(endian) - } + if STREAMING { + streaming::u128(endian) + } else { + complete::u128(endian) + } } /// Recognizes a signed 1 byte integer @@ -1553,14 +1553,14 @@ where #[inline(always)] pub fn i8, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, + I: InputIsStreaming, + I: Input, { - if STREAMING { - streaming::i8(input) - } else { - complete::i8(input) - } + if STREAMING { + streaming::i8(input) + } else { + complete::i8(input) + } } /// Recognizes a signed 2 byte integer @@ -1616,18 +1616,18 @@ where /// ``` #[inline(always)] pub fn i16, const STREAMING: bool>( - endian: crate::number::Endianness, + endian: crate::number::Endianness, ) -> fn(I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::i16(endian) - } else { - complete::i16(endian) - } + if STREAMING { + streaming::i16(endian) + } else { + complete::i16(endian) + } } /// Recognizes a signed 3 byte integer @@ -1683,18 +1683,18 @@ where /// ``` #[inline(always)] pub fn i24, const STREAMING: bool>( - endian: crate::number::Endianness, + endian: crate::number::Endianness, ) -> fn(I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::i24(endian) - } else { - complete::i24(endian) - } + if STREAMING { + streaming::i24(endian) + } else { + complete::i24(endian) + } } /// Recognizes a signed 4 byte integer @@ -1750,18 +1750,18 @@ where /// ``` #[inline(always)] pub fn i32, const STREAMING: bool>( - endian: crate::number::Endianness, + endian: crate::number::Endianness, ) -> fn(I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::i32(endian) - } else { - complete::i32(endian) - } + if STREAMING { + streaming::i32(endian) + } else { + complete::i32(endian) + } } /// Recognizes a signed 8 byte integer @@ -1817,18 +1817,18 @@ where /// ``` #[inline(always)] pub fn i64, const STREAMING: bool>( - endian: crate::number::Endianness, + endian: crate::number::Endianness, ) -> fn(I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::i64(endian) - } else { - complete::i64(endian) - } + if STREAMING { + streaming::i64(endian) + } else { + complete::i64(endian) + } } /// Recognizes a signed 16 byte integer @@ -1884,18 +1884,18 @@ where /// ``` #[inline(always)] pub fn i128, const STREAMING: bool>( - endian: crate::number::Endianness, + endian: crate::number::Endianness, ) -> fn(I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::i128(endian) - } else { - complete::i128(endian) - } + if STREAMING { + streaming::i128(endian) + } else { + complete::i128(endian) + } } /// Recognizes a big endian 4 bytes floating point number. @@ -1934,15 +1934,15 @@ where #[inline(always)] pub fn be_f32, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::be_f32(input) - } else { - complete::be_f32(input) - } + if STREAMING { + streaming::be_f32(input) + } else { + complete::be_f32(input) + } } /// Recognizes a big endian 8 bytes floating point number. @@ -1981,15 +1981,15 @@ where #[inline(always)] pub fn be_f64, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::be_f64(input) - } else { - complete::be_f64(input) - } + if STREAMING { + streaming::be_f64(input) + } else { + complete::be_f64(input) + } } /// Recognizes a little endian 4 bytes floating point number. @@ -2028,15 +2028,15 @@ where #[inline(always)] pub fn le_f32, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::le_f32(input) - } else { - complete::le_f32(input) - } + if STREAMING { + streaming::le_f32(input) + } else { + complete::le_f32(input) + } } /// Recognizes a little endian 8 bytes floating point number. @@ -2075,15 +2075,15 @@ where #[inline(always)] pub fn le_f64, const STREAMING: bool>(input: I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::le_f64(input) - } else { - complete::le_f64(input) - } + if STREAMING { + streaming::le_f64(input) + } else { + complete::le_f64(input) + } } /// Recognizes a 4 byte floating point number @@ -2139,18 +2139,18 @@ where /// ``` #[inline(always)] pub fn f32, const STREAMING: bool>( - endian: crate::number::Endianness, + endian: crate::number::Endianness, ) -> fn(I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::f32(endian) - } else { - complete::f32(endian) - } + if STREAMING { + streaming::f32(endian) + } else { + complete::f32(endian) + } } /// Recognizes an 8 byte floating point number @@ -2206,16 +2206,16 @@ where /// ``` #[inline(always)] pub fn f64, const STREAMING: bool>( - endian: crate::number::Endianness, + endian: crate::number::Endianness, ) -> fn(I) -> IResult where - I: InputIsStreaming, - I: Input, - ::Slice: AsBytes, + I: InputIsStreaming, + I: Input, + ::Slice: AsBytes, { - if STREAMING { - streaming::f64(endian) - } else { - complete::f64(endian) - } + if STREAMING { + streaming::f64(endian) + } else { + complete::f64(endian) + } } diff --git a/src/number/streaming.rs b/src/number/streaming.rs index 5eae7728..fd1a00f3 100644 --- a/src/number/streaming.rs +++ b/src/number/streaming.rs @@ -31,14 +31,14 @@ use crate::*; /// /// **WARNING:** Deprecated, replaced with [`winnow::number::be_u8`][crate::number::be_u8] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::be_u8` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::be_u8` with input wrapped in `winnow::input::Streaming`" )] pub fn be_u8>(input: I) -> IResult where - I: Input, + I: Input, { - u8(input) + u8(input) } /// Recognizes a big endian unsigned 2 bytes integer. @@ -60,15 +60,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::be_u16`][crate::number::be_u16] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::be_u16` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::be_u16` with input wrapped in `winnow::input::Streaming`" )] pub fn be_u16>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - be_uint(input, 2) + be_uint(input, 2) } /// Recognizes a big endian unsigned 3 byte integer. @@ -90,15 +90,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::be_u24`][crate::number::be_u24] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::be_u24` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::be_u24` with input wrapped in `winnow::input::Streaming`" )] pub fn be_u24>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - be_uint(input, 3) + be_uint(input, 3) } /// Recognizes a big endian unsigned 4 bytes integer. @@ -120,15 +120,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::be_u32`][crate::number::be_u32] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::be_u32` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::be_u32` with input wrapped in `winnow::input::Streaming`" )] pub fn be_u32>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - be_uint(input, 4) + be_uint(input, 4) } /// Recognizes a big endian unsigned 8 bytes integer. @@ -150,15 +150,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::be_u64`][crate::number::be_u64] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::be_u64` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::be_u64` with input wrapped in `winnow::input::Streaming`" )] pub fn be_u64>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - be_uint(input, 8) + be_uint(input, 8) } /// Recognizes a big endian unsigned 16 bytes integer. @@ -179,41 +179,41 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::be_u128`][crate::number::be_u128] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::be_u128` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::be_u128` with input wrapped in `winnow::input::Streaming`" )] pub fn be_u128>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - be_uint(input, 16) + be_uint(input, 16) } #[inline] fn be_uint>(input: I, bound: usize) -> IResult where - I: Input, - ::Slice: AsBytes, - Uint: Default + Shl + Add + From, + I: Input, + ::Slice: AsBytes, + Uint: Default + Shl + Add + From, { - let offset = input.offset_at(bound).map_err(ErrMode::Incomplete)?; - let (input, number) = input.next_slice(offset); - let number = number.as_bytes(); - - let mut res = Uint::default(); - // special case to avoid shift a byte with overflow - if bound > 1 { - for byte in number.iter().copied().take(bound) { - res = (res << 8) + byte.into(); - } - } else { - for byte in number.iter().copied().take(bound) { - res = byte.into(); + let offset = input.offset_at(bound).map_err(ErrMode::Incomplete)?; + let (input, number) = input.next_slice(offset); + let number = number.as_bytes(); + + let mut res = Uint::default(); + // special case to avoid shift a byte with overflow + if bound > 1 { + for byte in number.iter().copied().take(bound) { + res = (res << 8) + byte.into(); + } + } else { + for byte in number.iter().copied().take(bound) { + res = byte.into(); + } } - } - Ok((input, res)) + Ok((input, res)) } /// Recognizes a signed 1 byte integer. @@ -232,14 +232,14 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::be_i8`][crate::number::be_i8] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::be_i8` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::be_i8` with input wrapped in `winnow::input::Streaming`" )] pub fn be_i8>(input: I) -> IResult where - I: Input, + I: Input, { - be_u8.map(|x| x as i8).parse_next(input) + be_u8.map(|x| x as i8).parse_next(input) } /// Recognizes a big endian signed 2 bytes integer. @@ -258,15 +258,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::be_i16`][crate::number::be_i16] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::be_i16` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::be_i16` with input wrapped in `winnow::input::Streaming`" )] pub fn be_i16>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - be_u16.map(|x| x as i16).parse_next(input) + be_u16.map(|x| x as i16).parse_next(input) } /// Recognizes a big endian signed 3 bytes integer. @@ -285,24 +285,24 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::be_i24`][crate::number::be_i24] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::be_i24` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::be_i24` with input wrapped in `winnow::input::Streaming`" )] pub fn be_i24>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - // Same as the unsigned version but we need to sign-extend manually here - be_u24 - .map(|x| { - if x & 0x80_00_00 != 0 { - (x | 0xff_00_00_00) as i32 - } else { - x as i32 - } - }) - .parse_next(input) + // Same as the unsigned version but we need to sign-extend manually here + be_u24 + .map(|x| { + if x & 0x80_00_00 != 0 { + (x | 0xff_00_00_00) as i32 + } else { + x as i32 + } + }) + .parse_next(input) } /// Recognizes a big endian signed 4 bytes integer. @@ -321,15 +321,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::be_i32`][crate::number::be_i32] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::be_i32` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::be_i32` with input wrapped in `winnow::input::Streaming`" )] pub fn be_i32>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - be_u32.map(|x| x as i32).parse_next(input) + be_u32.map(|x| x as i32).parse_next(input) } /// Recognizes a big endian signed 8 bytes integer. @@ -349,15 +349,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::be_i64`][crate::number::be_i64] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::be_i64` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::be_i64` with input wrapped in `winnow::input::Streaming`" )] pub fn be_i64>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - be_u64.map(|x| x as i64).parse_next(input) + be_u64.map(|x| x as i64).parse_next(input) } /// Recognizes a big endian signed 16 bytes integer. @@ -376,15 +376,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::be_i128`][crate::number::be_i128] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::be_i128` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::be_i128` with input wrapped in `winnow::input::Streaming`" )] pub fn be_i128>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - be_u128.map(|x| x as i128).parse_next(input) + be_u128.map(|x| x as i128).parse_next(input) } /// Recognizes an unsigned 1 byte integer. @@ -403,14 +403,14 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::le_u8`][crate::number::le_u8] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::le_u8` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::le_u8` with input wrapped in `winnow::input::Streaming`" )] pub fn le_u8>(input: I) -> IResult where - I: Input, + I: Input, { - u8(input) + u8(input) } /// Recognizes a little endian unsigned 2 bytes integer. @@ -432,15 +432,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::le_u16`][crate::number::le_u16] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::le_u16` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::le_u16` with input wrapped in `winnow::input::Streaming`" )] pub fn le_u16>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - le_uint(input, 2) + le_uint(input, 2) } /// Recognizes a little endian unsigned 3 bytes integer. @@ -462,15 +462,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::le_u24`][crate::number::le_u24] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::le_u24` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::le_u24` with input wrapped in `winnow::input::Streaming`" )] pub fn le_u24>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - le_uint(input, 3) + le_uint(input, 3) } /// Recognizes a little endian unsigned 4 bytes integer. @@ -492,15 +492,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::le_u32`][crate::number::le_u32] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::le_u32` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::le_u32` with input wrapped in `winnow::input::Streaming`" )] pub fn le_u32>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - le_uint(input, 4) + le_uint(input, 4) } /// Recognizes a little endian unsigned 8 bytes integer. @@ -522,15 +522,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::le_u64`][crate::number::le_u64] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::le_u64` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::le_u64` with input wrapped in `winnow::input::Streaming`" )] pub fn le_u64>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - le_uint(input, 8) + le_uint(input, 8) } /// Recognizes a little endian unsigned 16 bytes integer. @@ -552,34 +552,34 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::le_u128`][crate::number::le_u128] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::le_u128` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::le_u128` with input wrapped in `winnow::input::Streaming`" )] pub fn le_u128>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - le_uint(input, 16) + le_uint(input, 16) } #[inline] fn le_uint>(input: I, bound: usize) -> IResult where - I: Input, - ::Slice: AsBytes, - Uint: Default + Shl + Add + From, + I: Input, + ::Slice: AsBytes, + Uint: Default + Shl + Add + From, { - let offset = input.offset_at(bound).map_err(ErrMode::Incomplete)?; - let (input, number) = input.next_slice(offset); - let number = number.as_bytes(); + let offset = input.offset_at(bound).map_err(ErrMode::Incomplete)?; + let (input, number) = input.next_slice(offset); + let number = number.as_bytes(); - let mut res = Uint::default(); - for (index, byte) in number.iter_offsets().take(bound) { - res = res + (Uint::from(byte) << (8 * index as u8)); - } + let mut res = Uint::default(); + for (index, byte) in number.iter_offsets().take(bound) { + res = res + (Uint::from(byte) << (8 * index as u8)); + } - Ok((input, res)) + Ok((input, res)) } /// Recognizes a signed 1 byte integer. @@ -598,14 +598,14 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::le_i8`][crate::number::le_i8] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::le_i8` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::le_i8` with input wrapped in `winnow::input::Streaming`" )] pub fn le_i8>(input: I) -> IResult where - I: Input, + I: Input, { - le_u8.map(|x| x as i8).parse_next(input) + le_u8.map(|x| x as i8).parse_next(input) } /// Recognizes a little endian signed 2 bytes integer. @@ -627,15 +627,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::le_i16`][crate::number::le_i16] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::le_i16` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::le_i16` with input wrapped in `winnow::input::Streaming`" )] pub fn le_i16>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - le_u16.map(|x| x as i16).parse_next(input) + le_u16.map(|x| x as i16).parse_next(input) } /// Recognizes a little endian signed 3 bytes integer. @@ -657,24 +657,24 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::le_i24`][crate::number::le_i24] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::le_i24` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::le_i24` with input wrapped in `winnow::input::Streaming`" )] pub fn le_i24>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - // Same as the unsigned version but we need to sign-extend manually here - le_u24 - .map(|x| { - if x & 0x80_00_00 != 0 { - (x | 0xff_00_00_00) as i32 - } else { - x as i32 - } - }) - .parse_next(input) + // Same as the unsigned version but we need to sign-extend manually here + le_u24 + .map(|x| { + if x & 0x80_00_00 != 0 { + (x | 0xff_00_00_00) as i32 + } else { + x as i32 + } + }) + .parse_next(input) } /// Recognizes a little endian signed 4 bytes integer. @@ -696,15 +696,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::le_i32`][crate::number::le_i32] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::le_i32` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::le_i32` with input wrapped in `winnow::input::Streaming`" )] pub fn le_i32>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - le_u32.map(|x| x as i32).parse_next(input) + le_u32.map(|x| x as i32).parse_next(input) } /// Recognizes a little endian signed 8 bytes integer. @@ -726,15 +726,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::le_i64`][crate::number::le_i64] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::le_i64` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::le_i64` with input wrapped in `winnow::input::Streaming`" )] pub fn le_i64>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - le_u64.map(|x| x as i64).parse_next(input) + le_u64.map(|x| x as i64).parse_next(input) } /// Recognizes a little endian signed 16 bytes integer. @@ -756,15 +756,15 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::le_i128`][crate::number::le_i128] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::le_i128` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::le_i128` with input wrapped in `winnow::input::Streaming`" )] pub fn le_i128>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - le_u128.map(|x| x as i128).parse_next(input) + le_u128.map(|x| x as i128).parse_next(input) } /// Recognizes an unsigned 1 byte integer @@ -787,16 +787,16 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::u8`][crate::number::u8] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::u8` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::u8` with input wrapped in `winnow::input::Streaming`" )] pub fn u8>(input: I) -> IResult where - I: Input, + I: Input, { - input - .next_token() - .ok_or_else(|| ErrMode::Incomplete(Needed::new(1))) + input + .next_token() + .ok_or_else(|| ErrMode::Incomplete(Needed::new(1))) } /// Recognizes an unsigned 2 bytes integer @@ -828,22 +828,22 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::u16`][crate::number::u16] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::u16` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::u16` with input wrapped in `winnow::input::Streaming`" )] pub fn u16>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_u16, - crate::number::Endianness::Little => le_u16, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_u16, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_u16, - } + match endian { + crate::number::Endianness::Big => be_u16, + crate::number::Endianness::Little => le_u16, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_u16, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_u16, + } } /// Recognizes an unsigned 3 byte integer @@ -874,22 +874,22 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::u24`][crate::number::u24] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::u24` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::u24` with input wrapped in `winnow::input::Streaming`" )] pub fn u24>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_u24, - crate::number::Endianness::Little => le_u24, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_u24, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_u24, - } + match endian { + crate::number::Endianness::Big => be_u24, + crate::number::Endianness::Little => le_u24, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_u24, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_u24, + } } /// Recognizes an unsigned 4 byte integer @@ -920,22 +920,22 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::u32`][crate::number::u32] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::u32` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::u32` with input wrapped in `winnow::input::Streaming`" )] pub fn u32>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_u32, - crate::number::Endianness::Little => le_u32, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_u32, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_u32, - } + match endian { + crate::number::Endianness::Big => be_u32, + crate::number::Endianness::Little => le_u32, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_u32, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_u32, + } } /// Recognizes an unsigned 8 byte integer @@ -966,22 +966,22 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::u64`][crate::number::u64] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::u64` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::u64` with input wrapped in `winnow::input::Streaming`" )] pub fn u64>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_u64, - crate::number::Endianness::Little => le_u64, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_u64, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_u64, - } + match endian { + crate::number::Endianness::Big => be_u64, + crate::number::Endianness::Little => le_u64, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_u64, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_u64, + } } /// Recognizes an unsigned 16 byte integer @@ -1012,22 +1012,22 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::u128`][crate::number::u128] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::u128` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::u128` with input wrapped in `winnow::input::Streaming`" )] pub fn u128>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_u128, - crate::number::Endianness::Little => le_u128, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_u128, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_u128, - } + match endian { + crate::number::Endianness::Big => be_u128, + crate::number::Endianness::Little => le_u128, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_u128, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_u128, + } } /// Recognizes a signed 1 byte integer @@ -1050,14 +1050,14 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::i8`][crate::number::i8] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::i8` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::i8` with input wrapped in `winnow::input::Streaming`" )] pub fn i8>(i: I) -> IResult where - I: Input, + I: Input, { - u8.map(|x| x as i8).parse_next(i) + u8.map(|x| x as i8).parse_next(i) } /// Recognizes a signed 2 byte integer @@ -1088,22 +1088,22 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::i16`][crate::number::i16] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::i16` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::i16` with input wrapped in `winnow::input::Streaming`" )] pub fn i16>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_i16, - crate::number::Endianness::Little => le_i16, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_i16, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_i16, - } + match endian { + crate::number::Endianness::Big => be_i16, + crate::number::Endianness::Little => le_i16, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_i16, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_i16, + } } /// Recognizes a signed 3 byte integer @@ -1134,22 +1134,22 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::i24`][crate::number::i24] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::i24` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::i24` with input wrapped in `winnow::input::Streaming`" )] pub fn i24>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_i24, - crate::number::Endianness::Little => le_i24, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_i24, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_i24, - } + match endian { + crate::number::Endianness::Big => be_i24, + crate::number::Endianness::Little => le_i24, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_i24, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_i24, + } } /// Recognizes a signed 4 byte integer @@ -1180,22 +1180,22 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::i32`][crate::number::i32] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::i32` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::i32` with input wrapped in `winnow::input::Streaming`" )] pub fn i32>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_i32, - crate::number::Endianness::Little => le_i32, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_i32, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_i32, - } + match endian { + crate::number::Endianness::Big => be_i32, + crate::number::Endianness::Little => le_i32, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_i32, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_i32, + } } /// Recognizes a signed 8 byte integer @@ -1226,22 +1226,22 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::i64`][crate::number::i64] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::i64` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::i64` with input wrapped in `winnow::input::Streaming`" )] pub fn i64>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_i64, - crate::number::Endianness::Little => le_i64, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_i64, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_i64, - } + match endian { + crate::number::Endianness::Big => be_i64, + crate::number::Endianness::Little => le_i64, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_i64, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_i64, + } } /// Recognizes a signed 16 byte integer @@ -1272,22 +1272,22 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::i128`][crate::number::i128] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::i128` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::i128` with input wrapped in `winnow::input::Streaming`" )] pub fn i128>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_i128, - crate::number::Endianness::Little => le_i128, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_i128, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_i128, - } + match endian { + crate::number::Endianness::Big => be_i128, + crate::number::Endianness::Little => le_i128, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_i128, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_i128, + } } /// Recognizes a big endian 4 bytes floating point number. @@ -1308,18 +1308,18 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::be_f32`][crate::number::be_f32] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::be_f32` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::be_f32` with input wrapped in `winnow::input::Streaming`" )] pub fn be_f32>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match be_u32(input) { - Err(e) => Err(e), - Ok((i, o)) => Ok((i, f32::from_bits(o))), - } + match be_u32(input) { + Err(e) => Err(e), + Ok((i, o)) => Ok((i, f32::from_bits(o))), + } } /// Recognizes a big endian 8 bytes floating point number. @@ -1340,18 +1340,18 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::be_f64`][crate::number::be_f64] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::be_f64` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::be_f64` with input wrapped in `winnow::input::Streaming`" )] pub fn be_f64>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match be_u64(input) { - Err(e) => Err(e), - Ok((i, o)) => Ok((i, f64::from_bits(o))), - } + match be_u64(input) { + Err(e) => Err(e), + Ok((i, o)) => Ok((i, f64::from_bits(o))), + } } /// Recognizes a little endian 4 bytes floating point number. @@ -1372,18 +1372,18 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::le_f32`][crate::number::le_f32] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::le_f32` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::le_f32` with input wrapped in `winnow::input::Streaming`" )] pub fn le_f32>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match le_u32(input) { - Err(e) => Err(e), - Ok((i, o)) => Ok((i, f32::from_bits(o))), - } + match le_u32(input) { + Err(e) => Err(e), + Ok((i, o)) => Ok((i, f32::from_bits(o))), + } } /// Recognizes a little endian 8 bytes floating point number. @@ -1404,18 +1404,18 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::le_f64`][crate::number::le_f64] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::le_f64` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::le_f64` with input wrapped in `winnow::input::Streaming`" )] pub fn le_f64>(input: I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match le_u64(input) { - Err(e) => Err(e), - Ok((i, o)) => Ok((i, f64::from_bits(o))), - } + match le_u64(input) { + Err(e) => Err(e), + Ok((i, o)) => Ok((i, f64::from_bits(o))), + } } /// Recognizes a 4 byte floating point number @@ -1446,22 +1446,22 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::f32`][crate::number::f32] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::f32` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::f32` with input wrapped in `winnow::input::Streaming`" )] pub fn f32>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_f32, - crate::number::Endianness::Little => le_f32, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_f32, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_f32, - } + match endian { + crate::number::Endianness::Big => be_f32, + crate::number::Endianness::Little => le_f32, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_f32, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_f32, + } } /// Recognizes an 8 byte floating point number @@ -1492,22 +1492,22 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::number::f64`][crate::number::f64] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::number::f64` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::number::f64` with input wrapped in `winnow::input::Streaming`" )] pub fn f64>(endian: crate::number::Endianness) -> fn(I) -> IResult where - I: Input, - ::Slice: AsBytes, + I: Input, + ::Slice: AsBytes, { - match endian { - crate::number::Endianness::Big => be_f64, - crate::number::Endianness::Little => le_f64, - #[cfg(target_endian = "big")] - crate::number::Endianness::Native => be_f64, - #[cfg(target_endian = "little")] - crate::number::Endianness::Native => le_f64, - } + match endian { + crate::number::Endianness::Big => be_f64, + crate::number::Endianness::Little => le_f64, + #[cfg(target_endian = "big")] + crate::number::Endianness::Native => be_f64, + #[cfg(target_endian = "little")] + crate::number::Endianness::Native => le_f64, + } } /// Recognizes a hex-encoded integer. @@ -1529,184 +1529,186 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::hex_uint`][crate::character::hex_uint] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::hex_uint` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::hex_uint` with input wrapped in `winnow::input::Streaming`" )] pub fn hex_u32>(input: I) -> IResult where - I: Input, - ::Token: AsChar, - ::Slice: AsBStr, + I: Input, + ::Token: AsChar, + ::Slice: AsBStr, { - let invalid_offset = input - .offset_for(|c| { - let c = c.as_char(); - !"0123456789abcdefABCDEF".contains(c) - }) - .unwrap_or_else(|| input.input_len()); - const MAX_DIGITS: usize = 8; - let max_offset = input.offset_at(MAX_DIGITS); - let offset = match max_offset { - Ok(max_offset) => invalid_offset.min(max_offset), - Err(_) => { - if invalid_offset == input.input_len() { - // Only the next byte is guaranteed required - return Err(ErrMode::Incomplete(Needed::new(1))); - } else { - invalid_offset - } + let invalid_offset = input + .offset_for(|c| { + let c = c.as_char(); + !"0123456789abcdefABCDEF".contains(c) + }) + .unwrap_or_else(|| input.input_len()); + const MAX_DIGITS: usize = 8; + let max_offset = input.offset_at(MAX_DIGITS); + let offset = match max_offset { + Ok(max_offset) => invalid_offset.min(max_offset), + Err(_) => { + if invalid_offset == input.input_len() { + // Only the next byte is guaranteed required + return Err(ErrMode::Incomplete(Needed::new(1))); + } else { + invalid_offset + } + } + }; + if offset == 0 { + return Err(ErrMode::from_error_kind(input, ErrorKind::IsA)); } - }; - if offset == 0 { - return Err(ErrMode::from_error_kind(input, ErrorKind::IsA)); - } - let (remaining, parsed) = input.next_slice(offset); - - let res = parsed - .as_bstr() - .iter() - .rev() - .enumerate() - .map(|(k, &v)| { - let digit = v as char; - digit.to_digit(16).unwrap_or(0) << (k * 4) - }) - .sum(); - - Ok((remaining, res)) + let (remaining, parsed) = input.next_slice(offset); + + let res = parsed + .as_bstr() + .iter() + .rev() + .enumerate() + .map(|(k, &v)| { + let digit = v as char; + digit.to_digit(16).unwrap_or(0) << (k * 4) + }) + .sum(); + + Ok((remaining, res)) } /// **WARNING:** Deprecated, no longer supported #[deprecated(since = "0.3.0", note = "No longer supported")] pub fn recognize_float>(input: T) -> IResult::Slice, E> where - T: Input, - T: Offset + Compare<&'static str>, - ::Token: AsChar + Copy, - ::IterOffsets: Clone, - T: AsBStr, + T: Input, + T: Offset + Compare<&'static str>, + ::Token: AsChar + Copy, + ::IterOffsets: Clone, + T: AsBStr, { - tuple(( - opt(alt((char('+'), char('-')))), - alt(( - map(tuple((digit1, opt(pair(char('.'), opt(digit1))))), |_| ()), - map(tuple((char('.'), digit1)), |_| ()), - )), - opt(tuple(( - alt((char('e'), char('E'))), - opt(alt((char('+'), char('-')))), - cut_err(digit1), - ))), - )) - .recognize() - .parse_next(input) + tuple(( + opt(alt((char('+'), char('-')))), + alt(( + map(tuple((digit1, opt(pair(char('.'), opt(digit1))))), |_| ()), + map(tuple((char('.'), digit1)), |_| ()), + )), + opt(tuple(( + alt((char('e'), char('E'))), + opt(alt((char('+'), char('-')))), + cut_err(digit1), + ))), + )) + .recognize() + .parse_next(input) } /// **WARNING:** Deprecated, no longer supported #[deprecated(since = "0.3.0", note = "No longer supported")] pub fn recognize_float_or_exceptions>( - input: T, + input: T, ) -> IResult::Slice, E> where - T: Input, - T: Offset + Compare<&'static str>, - ::Token: AsChar + Copy, - ::IterOffsets: Clone, - T: AsBStr, + T: Input, + T: Offset + Compare<&'static str>, + ::Token: AsChar + Copy, + ::IterOffsets: Clone, + T: AsBStr, { - alt(( - |i: T| { - recognize_float::<_, E>(i.clone()).map_err(|e| match e { - crate::error::ErrMode::Backtrack(_) => { - crate::error::ErrMode::from_error_kind(i, ErrorKind::Float) - } - crate::error::ErrMode::Cut(_) => { - crate::error::ErrMode::Cut(E::from_error_kind(i, ErrorKind::Float)) - } - crate::error::ErrMode::Incomplete(needed) => crate::error::ErrMode::Incomplete(needed), - }) - }, - |i: T| { - crate::bytes::streaming::tag_no_case::<_, _, E>("nan")(i.clone()) - .map_err(|_err| crate::error::ErrMode::from_error_kind(i, ErrorKind::Float)) - }, - |i: T| { - crate::bytes::streaming::tag_no_case::<_, _, E>("inf")(i.clone()) - .map_err(|_err| crate::error::ErrMode::from_error_kind(i, ErrorKind::Float)) - }, - |i: T| { - crate::bytes::streaming::tag_no_case::<_, _, E>("infinity")(i.clone()) - .map_err(|_err| crate::error::ErrMode::from_error_kind(i, ErrorKind::Float)) - }, - ))(input) + alt(( + |i: T| { + recognize_float::<_, E>(i.clone()).map_err(|e| match e { + crate::error::ErrMode::Backtrack(_) => { + crate::error::ErrMode::from_error_kind(i, ErrorKind::Float) + } + crate::error::ErrMode::Cut(_) => { + crate::error::ErrMode::Cut(E::from_error_kind(i, ErrorKind::Float)) + } + crate::error::ErrMode::Incomplete(needed) => { + crate::error::ErrMode::Incomplete(needed) + } + }) + }, + |i: T| { + crate::bytes::streaming::tag_no_case::<_, _, E>("nan")(i.clone()) + .map_err(|_err| crate::error::ErrMode::from_error_kind(i, ErrorKind::Float)) + }, + |i: T| { + crate::bytes::streaming::tag_no_case::<_, _, E>("inf")(i.clone()) + .map_err(|_err| crate::error::ErrMode::from_error_kind(i, ErrorKind::Float)) + }, + |i: T| { + crate::bytes::streaming::tag_no_case::<_, _, E>("infinity")(i.clone()) + .map_err(|_err| crate::error::ErrMode::from_error_kind(i, ErrorKind::Float)) + }, + ))(input) } /// **WARNING:** Deprecated, no longer supported #[allow(clippy::type_complexity)] #[deprecated(since = "0.3.0", note = "No longer supported")] pub fn recognize_float_parts>( - input: T, + input: T, ) -> IResult::Slice, ::Slice, i32), E> where - T: Input + Compare<&'static [u8]> + AsBStr, - ::Token: AsChar + Copy, - ::Slice: SliceLen, + T: Input + Compare<&'static [u8]> + AsBStr, + ::Token: AsChar + Copy, + ::Slice: SliceLen, { - let (i, sign) = sign(input.clone())?; - - let (i, integer) = match i.offset_for(|c| !c.is_dec_digit()) { - Some(offset) => i.next_slice(offset), - None => i.next_slice(i.input_len()), - }; - - let (i, opt_dot) = opt(tag(&b"."[..]))(i)?; - let (i, fraction) = if opt_dot.is_none() { - i.next_slice(0) - } else { - // match number - let mut zero_count = 0usize; - let mut offset = None; - for (pos, c) in i.as_bstr().iter().enumerate() { - if *c >= b'0' && *c <= b'9' { - if *c == b'0' { - zero_count += 1; - } else { - zero_count = 0; - } - } else { - offset = Some(pos); - break; - } - } + let (i, sign) = sign(input.clone())?; - let offset = offset.ok_or_else(|| ErrMode::Incomplete(Needed::new(1)))?; + let (i, integer) = match i.offset_for(|c| !c.is_dec_digit()) { + Some(offset) => i.next_slice(offset), + None => i.next_slice(i.input_len()), + }; - // trim right zeroes - let trimmed_offset = (offset - zero_count).max(1); + let (i, opt_dot) = opt(tag(&b"."[..]))(i)?; + let (i, fraction) = if opt_dot.is_none() { + i.next_slice(0) + } else { + // match number + let mut zero_count = 0usize; + let mut offset = None; + for (pos, c) in i.as_bstr().iter().enumerate() { + if *c >= b'0' && *c <= b'9' { + if *c == b'0' { + zero_count += 1; + } else { + zero_count = 0; + } + } else { + offset = Some(pos); + break; + } + } - let (_, frac) = i.next_slice(trimmed_offset); - let (i, _) = i.next_slice(offset); - (i, frac) - }; + let offset = offset.ok_or_else(|| ErrMode::Incomplete(Needed::new(1)))?; - if integer.slice_len() == 0 && fraction.slice_len() == 0 { - return Err(ErrMode::from_error_kind(input, ErrorKind::Float)); - } + // trim right zeroes + let trimmed_offset = (offset - zero_count).max(1); - let i2 = i.clone(); - let (i, e) = i - .next_token() - .filter(|(_, t)| t.as_char() == 'e' || t.as_char() == 'E') - .map(|(i, _)| (i, true)) - .unwrap_or((i, false)); + let (_, frac) = i.next_slice(trimmed_offset); + let (i, _) = i.next_slice(offset); + (i, frac) + }; - let (i, exp) = if e { - cut_err(crate::character::streaming::i32)(i)? - } else { - (i2, 0) - }; + if integer.slice_len() == 0 && fraction.slice_len() == 0 { + return Err(ErrMode::from_error_kind(input, ErrorKind::Float)); + } + + let i2 = i.clone(); + let (i, e) = i + .next_token() + .filter(|(_, t)| t.as_char() == 'e' || t.as_char() == 'E') + .map(|(i, _)| (i, true)) + .unwrap_or((i, false)); + + let (i, exp) = if e { + cut_err(crate::character::streaming::i32)(i)? + } else { + (i2, 0) + }; - Ok((i, (sign, integer, fraction, exp))) + Ok((i, (sign, integer, fraction, exp))) } /// Recognizes floating point number in text format and returns a f32. @@ -1730,26 +1732,26 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::float`][crate::character::float] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::float` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::float` with input wrapped in `winnow::input::Streaming`" )] pub fn float>(input: T) -> IResult where - T: Input, - T: Offset + Compare<&'static str>, - ::Slice: ParseSlice, - ::Token: AsChar + Copy, - ::IterOffsets: Clone, - T: AsBStr, + T: Input, + T: Offset + Compare<&'static str>, + ::Slice: ParseSlice, + ::Token: AsChar + Copy, + ::IterOffsets: Clone, + T: AsBStr, { - let (i, s) = recognize_float_or_exceptions(input)?; - match s.parse_slice() { - Some(f) => Ok((i, f)), - None => Err(crate::error::ErrMode::from_error_kind( - i, - crate::error::ErrorKind::Float, - )), - } + let (i, s) = recognize_float_or_exceptions(input)?; + match s.parse_slice() { + Some(f) => Ok((i, f)), + None => Err(crate::error::ErrMode::from_error_kind( + i, + crate::error::ErrorKind::Float, + )), + } } /// Recognizes floating point number in text format and returns a f64. @@ -1773,636 +1775,643 @@ where /// /// **WARNING:** Deprecated, replaced with [`winnow::character::float`][crate::character::float] with input wrapped in [`winnow::input::Streaming`][crate::input::Streaming] #[deprecated( - since = "0.1.0", - note = "Replaced with `winnow::character::float` with input wrapped in `winnow::input::Streaming`" + since = "0.1.0", + note = "Replaced with `winnow::character::float` with input wrapped in `winnow::input::Streaming`" )] pub fn double>(input: T) -> IResult where - T: Input, - T: Offset + Compare<&'static str>, - ::Slice: ParseSlice, - ::Token: AsChar + Copy, - ::IterOffsets: Clone, - T: AsBStr, + T: Input, + T: Offset + Compare<&'static str>, + ::Slice: ParseSlice, + ::Token: AsChar + Copy, + ::IterOffsets: Clone, + T: AsBStr, { - let (i, s) = recognize_float_or_exceptions(input)?; - match s.parse_slice() { - Some(f) => Ok((i, f)), - None => Err(crate::error::ErrMode::from_error_kind( - i, - crate::error::ErrorKind::Float, - )), - } + let (i, s) = recognize_float_or_exceptions(input)?; + match s.parse_slice() { + Some(f) => Ok((i, f)), + None => Err(crate::error::ErrMode::from_error_kind( + i, + crate::error::ErrorKind::Float, + )), + } } #[cfg(test)] mod tests { - use super::*; - use crate::error::Error; - use crate::error::ErrorKind; - use crate::error::{ErrMode, Needed}; - use proptest::prelude::*; + use super::*; + use crate::error::Error; + use crate::error::ErrorKind; + use crate::error::{ErrMode, Needed}; + use proptest::prelude::*; - macro_rules! assert_parse( + macro_rules! assert_parse( ($left: expr, $right: expr) => { let res: $crate::IResult<_, _, Error<_>> = $left; assert_eq!(res, $right); }; ); - #[test] - fn i8_tests() { - assert_parse!(be_i8(&[0x00][..]), Ok((&b""[..], 0))); - assert_parse!(be_i8(&[0x7f][..]), Ok((&b""[..], 127))); - assert_parse!(be_i8(&[0xff][..]), Ok((&b""[..], -1))); - assert_parse!(be_i8(&[0x80][..]), Ok((&b""[..], -128))); - assert_parse!(be_i8(&[][..]), Err(ErrMode::Incomplete(Needed::new(1)))); - } - - #[test] - fn i16_tests() { - assert_parse!(be_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0))); - assert_parse!(be_i16(&[0x7f, 0xff][..]), Ok((&b""[..], 32_767_i16))); - assert_parse!(be_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1))); - assert_parse!(be_i16(&[0x80, 0x00][..]), Ok((&b""[..], -32_768_i16))); - assert_parse!(be_i16(&[][..]), Err(ErrMode::Incomplete(Needed::new(2)))); - assert_parse!( - be_i16(&[0x00][..]), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - } - - #[test] - fn u24_tests() { - assert_parse!(be_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); - assert_parse!(be_u24(&[0x00, 0xFF, 0xFF][..]), Ok((&b""[..], 65_535_u32))); - assert_parse!( - be_u24(&[0x12, 0x34, 0x56][..]), - Ok((&b""[..], 1_193_046_u32)) - ); - assert_parse!(be_u24(&[][..]), Err(ErrMode::Incomplete(Needed::new(3)))); - assert_parse!( - be_u24(&[0x00][..]), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_parse!( - be_u24(&[0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - } - - #[test] - fn i24_tests() { - assert_parse!(be_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32))); - assert_parse!(be_i24(&[0xFF, 0x00, 0x00][..]), Ok((&b""[..], -65_536_i32))); - assert_parse!( - be_i24(&[0xED, 0xCB, 0xAA][..]), - Ok((&b""[..], -1_193_046_i32)) - ); - assert_parse!(be_i24(&[][..]), Err(ErrMode::Incomplete(Needed::new(3)))); - assert_parse!( - be_i24(&[0x00][..]), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_parse!( - be_i24(&[0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - } - - #[test] - fn i32_tests() { - assert_parse!(be_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); - assert_parse!( - be_i32(&[0x7f, 0xff, 0xff, 0xff][..]), - Ok((&b""[..], 2_147_483_647_i32)) - ); - assert_parse!(be_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1))); - assert_parse!( - be_i32(&[0x80, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], -2_147_483_648_i32)) - ); - assert_parse!(be_i32(&[][..]), Err(ErrMode::Incomplete(Needed::new(4)))); - assert_parse!( - be_i32(&[0x00][..]), - Err(ErrMode::Incomplete(Needed::new(3))) - ); - assert_parse!( - be_i32(&[0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_parse!( - be_i32(&[0x00, 0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - } - - #[test] - fn i64_tests() { - assert_parse!( - be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], 0)) - ); - assert_parse!( - be_i64(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), - Ok((&b""[..], 9_223_372_036_854_775_807_i64)) - ); - assert_parse!( - be_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), - Ok((&b""[..], -1)) - ); - assert_parse!( - be_i64(&[0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], -9_223_372_036_854_775_808_i64)) - ); - assert_parse!(be_i64(&[][..]), Err(ErrMode::Incomplete(Needed::new(8)))); - assert_parse!( - be_i64(&[0x00][..]), - Err(ErrMode::Incomplete(Needed::new(7))) - ); - assert_parse!( - be_i64(&[0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(6))) - ); - assert_parse!( - be_i64(&[0x00, 0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(5))) - ); - assert_parse!( - be_i64(&[0x00, 0x00, 0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(4))) - ); - assert_parse!( - be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(3))) - ); - assert_parse!( - be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_parse!( - be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - } - - #[test] - fn i128_tests() { - assert_parse!( - be_i128( - &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 - ][..] - ), - Ok((&b""[..], 0)) - ); - assert_parse!( - be_i128( - &[ - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff - ][..] - ), - Ok(( - &b""[..], - 170_141_183_460_469_231_731_687_303_715_884_105_727_i128 - )) - ); - assert_parse!( - be_i128( - &[ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff - ][..] - ), - Ok((&b""[..], -1)) - ); - assert_parse!( - be_i128( - &[ - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 - ][..] - ), - Ok(( - &b""[..], - -170_141_183_460_469_231_731_687_303_715_884_105_728_i128 - )) - ); - assert_parse!(be_i128(&[][..]), Err(ErrMode::Incomplete(Needed::new(16)))); - assert_parse!( - be_i128(&[0x00][..]), - Err(ErrMode::Incomplete(Needed::new(15))) - ); - assert_parse!( - be_i128(&[0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(14))) - ); - assert_parse!( - be_i128(&[0x00, 0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(13))) - ); - assert_parse!( - be_i128(&[0x00, 0x00, 0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(12))) - ); - assert_parse!( - be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(11))) - ); - assert_parse!( - be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(10))) - ); - assert_parse!( - be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(9))) - ); - assert_parse!( - be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(8))) - ); - assert_parse!( - be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(7))) - ); - assert_parse!( - be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(6))) - ); - assert_parse!( - be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(5))) - ); - assert_parse!( - be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(4))) - ); - assert_parse!( - be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Err(ErrMode::Incomplete(Needed::new(3))) - ); - assert_parse!( - be_i128( - &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] - ), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_parse!( - be_i128( - &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] - [..] - ), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - } - - #[test] - fn le_i8_tests() { - assert_parse!(le_i8(&[0x00][..]), Ok((&b""[..], 0))); - assert_parse!(le_i8(&[0x7f][..]), Ok((&b""[..], 127))); - assert_parse!(le_i8(&[0xff][..]), Ok((&b""[..], -1))); - assert_parse!(le_i8(&[0x80][..]), Ok((&b""[..], -128))); - } - - #[test] - fn le_i16_tests() { - assert_parse!(le_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0))); - assert_parse!(le_i16(&[0xff, 0x7f][..]), Ok((&b""[..], 32_767_i16))); - assert_parse!(le_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1))); - assert_parse!(le_i16(&[0x00, 0x80][..]), Ok((&b""[..], -32_768_i16))); - } - - #[test] - fn le_u24_tests() { - assert_parse!(le_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); - assert_parse!(le_u24(&[0xFF, 0xFF, 0x00][..]), Ok((&b""[..], 65_535_u32))); - assert_parse!( - le_u24(&[0x56, 0x34, 0x12][..]), - Ok((&b""[..], 1_193_046_u32)) - ); - } - - #[test] - fn le_i24_tests() { - assert_parse!(le_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32))); - assert_parse!(le_i24(&[0x00, 0x00, 0xFF][..]), Ok((&b""[..], -65_536_i32))); - assert_parse!( - le_i24(&[0xAA, 0xCB, 0xED][..]), - Ok((&b""[..], -1_193_046_i32)) - ); - } - - #[test] - fn le_i32_tests() { - assert_parse!(le_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); - assert_parse!( - le_i32(&[0xff, 0xff, 0xff, 0x7f][..]), - Ok((&b""[..], 2_147_483_647_i32)) - ); - assert_parse!(le_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1))); - assert_parse!( - le_i32(&[0x00, 0x00, 0x00, 0x80][..]), - Ok((&b""[..], -2_147_483_648_i32)) - ); - } - - #[test] - fn le_i64_tests() { - assert_parse!( - le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], 0)) - ); - assert_parse!( - le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f][..]), - Ok((&b""[..], 9_223_372_036_854_775_807_i64)) - ); - assert_parse!( - le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), - Ok((&b""[..], -1)) - ); - assert_parse!( - le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80][..]), - Ok((&b""[..], -9_223_372_036_854_775_808_i64)) - ); - } - - #[test] - fn le_i128_tests() { - assert_parse!( - le_i128( - &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 - ][..] - ), - Ok((&b""[..], 0)) - ); - assert_parse!( - le_i128( - &[ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x7f - ][..] - ), - Ok(( - &b""[..], - 170_141_183_460_469_231_731_687_303_715_884_105_727_i128 - )) - ); - assert_parse!( - le_i128( - &[ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff - ][..] - ), - Ok((&b""[..], -1)) - ); - assert_parse!( - le_i128( - &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80 - ][..] - ), - Ok(( - &b""[..], - -170_141_183_460_469_231_731_687_303_715_884_105_728_i128 - )) - ); - } - - #[test] - fn be_f32_tests() { - assert_parse!(be_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32))); - assert_parse!( - be_f32(&[0x4d, 0x31, 0x1f, 0xd8][..]), - Ok((&b""[..], 185_728_380_f32)) - ); - } - - #[test] - fn be_f64_tests() { - assert_parse!( - be_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], 0_f64)) - ); - assert_parse!( - be_f64(&[0x41, 0xa6, 0x23, 0xfb, 0x10, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], 185_728_392_f64)) - ); - } - - #[test] - fn le_f32_tests() { - assert_parse!(le_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32))); - assert_parse!( - le_f32(&[0xd8, 0x1f, 0x31, 0x4d][..]), - Ok((&b""[..], 185_728_380_f32)) - ); - } - - #[test] - fn le_f64_tests() { - assert_parse!( - le_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], 0_f64)) - ); - assert_parse!( - le_f64(&[0x00, 0x00, 0x00, 0x10, 0xfb, 0x23, 0xa6, 0x41][..]), - Ok((&b""[..], 185_728_392_f64)) - ); - } - - #[test] - fn hex_u32_tests() { - assert_parse!( - hex_u32(&b";"[..]), - Err(ErrMode::Backtrack(error_position!( - &b";"[..], - ErrorKind::IsA - ))) - ); - assert_parse!(hex_u32(&b"ff;"[..]), Ok((&b";"[..], 255))); - assert_parse!(hex_u32(&b"1be2;"[..]), Ok((&b";"[..], 7138))); - assert_parse!(hex_u32(&b"c5a31be2;"[..]), Ok((&b";"[..], 3_315_801_058))); - assert_parse!(hex_u32(&b"C5A31be2;"[..]), Ok((&b";"[..], 3_315_801_058))); - assert_parse!(hex_u32(&b"00c5a31be2;"[..]), Ok((&b"e2;"[..], 12_952_347))); - assert_parse!( - hex_u32(&b"c5a31be201;"[..]), - Ok((&b"01;"[..], 3_315_801_058)) - ); - assert_parse!(hex_u32(&b"ffffffff;"[..]), Ok((&b";"[..], 4_294_967_295))); - assert_parse!(hex_u32(&b"0x1be2;"[..]), Ok((&b"x1be2;"[..], 0))); - assert_parse!( - hex_u32(&b"12af"[..]), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - } - - #[test] - #[cfg(feature = "std")] - fn float_test() { - let mut test_cases = vec![ - "+3.14", - "3.14", - "-3.14", - "0", - "0.0", - "1.", - ".789", - "-.5", - "1e7", - "-1E-7", - ".3e-2", - "1.e4", - "1.2e4", - "12.34", - "-1.234E-12", - "-1.234e-12", - "0.00000000000000000087", - ]; - - for test in test_cases.drain(..) { - let expected32 = str::parse::(test).unwrap(); - let expected64 = str::parse::(test).unwrap(); - - println!("now parsing: {} -> {}", test, expected32); - - let larger = format!("{};", test); - assert_parse!(recognize_float(&larger[..]), Ok((";", test))); - - assert_parse!(float(larger.as_bytes()), Ok((&b";"[..], expected32))); - assert_parse!(float(&larger[..]), Ok((";", expected32))); - - assert_parse!(double(larger.as_bytes()), Ok((&b";"[..], expected64))); - assert_parse!(double(&larger[..]), Ok((";", expected64))); + #[test] + fn i8_tests() { + assert_parse!(be_i8(&[0x00][..]), Ok((&b""[..], 0))); + assert_parse!(be_i8(&[0x7f][..]), Ok((&b""[..], 127))); + assert_parse!(be_i8(&[0xff][..]), Ok((&b""[..], -1))); + assert_parse!(be_i8(&[0x80][..]), Ok((&b""[..], -128))); + assert_parse!(be_i8(&[][..]), Err(ErrMode::Incomplete(Needed::new(1)))); } - let remaining_exponent = "-1.234E-"; - assert_parse!( - recognize_float(remaining_exponent), - Err(ErrMode::Incomplete(Needed::new(1))) - ); + #[test] + fn i16_tests() { + assert_parse!(be_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!(be_i16(&[0x7f, 0xff][..]), Ok((&b""[..], 32_767_i16))); + assert_parse!(be_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1))); + assert_parse!(be_i16(&[0x80, 0x00][..]), Ok((&b""[..], -32_768_i16))); + assert_parse!(be_i16(&[][..]), Err(ErrMode::Incomplete(Needed::new(2)))); + assert_parse!( + be_i16(&[0x00][..]), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + } + + #[test] + fn u24_tests() { + assert_parse!(be_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!(be_u24(&[0x00, 0xFF, 0xFF][..]), Ok((&b""[..], 65_535_u32))); + assert_parse!( + be_u24(&[0x12, 0x34, 0x56][..]), + Ok((&b""[..], 1_193_046_u32)) + ); + assert_parse!(be_u24(&[][..]), Err(ErrMode::Incomplete(Needed::new(3)))); + assert_parse!( + be_u24(&[0x00][..]), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_parse!( + be_u24(&[0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + } + + #[test] + fn i24_tests() { + assert_parse!(be_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32))); + assert_parse!(be_i24(&[0xFF, 0x00, 0x00][..]), Ok((&b""[..], -65_536_i32))); + assert_parse!( + be_i24(&[0xED, 0xCB, 0xAA][..]), + Ok((&b""[..], -1_193_046_i32)) + ); + assert_parse!(be_i24(&[][..]), Err(ErrMode::Incomplete(Needed::new(3)))); + assert_parse!( + be_i24(&[0x00][..]), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_parse!( + be_i24(&[0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + } + + #[test] + fn i32_tests() { + assert_parse!(be_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!( + be_i32(&[0x7f, 0xff, 0xff, 0xff][..]), + Ok((&b""[..], 2_147_483_647_i32)) + ); + assert_parse!(be_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1))); + assert_parse!( + be_i32(&[0x80, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], -2_147_483_648_i32)) + ); + assert_parse!(be_i32(&[][..]), Err(ErrMode::Incomplete(Needed::new(4)))); + assert_parse!( + be_i32(&[0x00][..]), + Err(ErrMode::Incomplete(Needed::new(3))) + ); + assert_parse!( + be_i32(&[0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_parse!( + be_i32(&[0x00, 0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + } - let (_i, nan) = float::<_, ()>("NaN").unwrap(); - assert!(nan.is_nan()); + #[test] + fn i64_tests() { + assert_parse!( + be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 0)) + ); + assert_parse!( + be_i64(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), + Ok((&b""[..], 9_223_372_036_854_775_807_i64)) + ); + assert_parse!( + be_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), + Ok((&b""[..], -1)) + ); + assert_parse!( + be_i64(&[0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], -9_223_372_036_854_775_808_i64)) + ); + assert_parse!(be_i64(&[][..]), Err(ErrMode::Incomplete(Needed::new(8)))); + assert_parse!( + be_i64(&[0x00][..]), + Err(ErrMode::Incomplete(Needed::new(7))) + ); + assert_parse!( + be_i64(&[0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(6))) + ); + assert_parse!( + be_i64(&[0x00, 0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(5))) + ); + assert_parse!( + be_i64(&[0x00, 0x00, 0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(4))) + ); + assert_parse!( + be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(3))) + ); + assert_parse!( + be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_parse!( + be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + } - let (_i, inf) = float::<_, ()>("inf").unwrap(); - assert!(inf.is_infinite()); - let (_i, inf) = float::<_, ()>("infinite").unwrap(); - assert!(inf.is_infinite()); - } + #[test] + fn i128_tests() { + assert_parse!( + be_i128( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 + ][..] + ), + Ok((&b""[..], 0)) + ); + assert_parse!( + be_i128( + &[ + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff + ][..] + ), + Ok(( + &b""[..], + 170_141_183_460_469_231_731_687_303_715_884_105_727_i128 + )) + ); + assert_parse!( + be_i128( + &[ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff + ][..] + ), + Ok((&b""[..], -1)) + ); + assert_parse!( + be_i128( + &[ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 + ][..] + ), + Ok(( + &b""[..], + -170_141_183_460_469_231_731_687_303_715_884_105_728_i128 + )) + ); + assert_parse!(be_i128(&[][..]), Err(ErrMode::Incomplete(Needed::new(16)))); + assert_parse!( + be_i128(&[0x00][..]), + Err(ErrMode::Incomplete(Needed::new(15))) + ); + assert_parse!( + be_i128(&[0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(14))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(13))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(12))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(11))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(10))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(9))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(8))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(7))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(6))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(5))) + ); + assert_parse!( + be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Err(ErrMode::Incomplete(Needed::new(4))) + ); + assert_parse!( + be_i128( + &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] + ), + Err(ErrMode::Incomplete(Needed::new(3))) + ); + assert_parse!( + be_i128( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 + ][..] + ), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_parse!( + be_i128( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 + ][..] + ), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + } - #[test] - fn configurable_endianness() { - use crate::number::Endianness; + #[test] + fn le_i8_tests() { + assert_parse!(le_i8(&[0x00][..]), Ok((&b""[..], 0))); + assert_parse!(le_i8(&[0x7f][..]), Ok((&b""[..], 127))); + assert_parse!(le_i8(&[0xff][..]), Ok((&b""[..], -1))); + assert_parse!(le_i8(&[0x80][..]), Ok((&b""[..], -128))); + } - fn be_tst16(i: &[u8]) -> IResult<&[u8], u16> { - u16(Endianness::Big)(i) + #[test] + fn le_i16_tests() { + assert_parse!(le_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!(le_i16(&[0xff, 0x7f][..]), Ok((&b""[..], 32_767_i16))); + assert_parse!(le_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1))); + assert_parse!(le_i16(&[0x00, 0x80][..]), Ok((&b""[..], -32_768_i16))); } - fn le_tst16(i: &[u8]) -> IResult<&[u8], u16> { - u16(Endianness::Little)(i) + + #[test] + fn le_u24_tests() { + assert_parse!(le_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!(le_u24(&[0xFF, 0xFF, 0x00][..]), Ok((&b""[..], 65_535_u32))); + assert_parse!( + le_u24(&[0x56, 0x34, 0x12][..]), + Ok((&b""[..], 1_193_046_u32)) + ); } - assert_eq!(be_tst16(&[0x80, 0x00]), Ok((&b""[..], 32_768_u16))); - assert_eq!(le_tst16(&[0x80, 0x00]), Ok((&b""[..], 128_u16))); - fn be_tst32(i: &[u8]) -> IResult<&[u8], u32> { - u32(Endianness::Big)(i) + #[test] + fn le_i24_tests() { + assert_parse!(le_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32))); + assert_parse!(le_i24(&[0x00, 0x00, 0xFF][..]), Ok((&b""[..], -65_536_i32))); + assert_parse!( + le_i24(&[0xAA, 0xCB, 0xED][..]), + Ok((&b""[..], -1_193_046_i32)) + ); } - fn le_tst32(i: &[u8]) -> IResult<&[u8], u32> { - u32(Endianness::Little)(i) + + #[test] + fn le_i32_tests() { + assert_parse!(le_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!( + le_i32(&[0xff, 0xff, 0xff, 0x7f][..]), + Ok((&b""[..], 2_147_483_647_i32)) + ); + assert_parse!(le_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1))); + assert_parse!( + le_i32(&[0x00, 0x00, 0x00, 0x80][..]), + Ok((&b""[..], -2_147_483_648_i32)) + ); } - assert_eq!( - be_tst32(&[0x12, 0x00, 0x60, 0x00]), - Ok((&b""[..], 302_014_464_u32)) - ); - assert_eq!( - le_tst32(&[0x12, 0x00, 0x60, 0x00]), - Ok((&b""[..], 6_291_474_u32)) - ); - - fn be_tst64(i: &[u8]) -> IResult<&[u8], u64> { - u64(Endianness::Big)(i) + + #[test] + fn le_i64_tests() { + assert_parse!( + le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 0)) + ); + assert_parse!( + le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f][..]), + Ok((&b""[..], 9_223_372_036_854_775_807_i64)) + ); + assert_parse!( + le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), + Ok((&b""[..], -1)) + ); + assert_parse!( + le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80][..]), + Ok((&b""[..], -9_223_372_036_854_775_808_i64)) + ); } - fn le_tst64(i: &[u8]) -> IResult<&[u8], u64> { - u64(Endianness::Little)(i) + + #[test] + fn le_i128_tests() { + assert_parse!( + le_i128( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 + ][..] + ), + Ok((&b""[..], 0)) + ); + assert_parse!( + le_i128( + &[ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f + ][..] + ), + Ok(( + &b""[..], + 170_141_183_460_469_231_731_687_303_715_884_105_727_i128 + )) + ); + assert_parse!( + le_i128( + &[ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff + ][..] + ), + Ok((&b""[..], -1)) + ); + assert_parse!( + le_i128( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80 + ][..] + ), + Ok(( + &b""[..], + -170_141_183_460_469_231_731_687_303_715_884_105_728_i128 + )) + ); } - assert_eq!( - be_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), - Ok((&b""[..], 1_297_142_246_100_992_000_u64)) - ); - assert_eq!( - le_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), - Ok((&b""[..], 36_028_874_334_666_770_u64)) - ); - - fn be_tsti16(i: &[u8]) -> IResult<&[u8], i16> { - i16(Endianness::Big)(i) + + #[test] + fn be_f32_tests() { + assert_parse!(be_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32))); + assert_parse!( + be_f32(&[0x4d, 0x31, 0x1f, 0xd8][..]), + Ok((&b""[..], 185_728_380_f32)) + ); } - fn le_tsti16(i: &[u8]) -> IResult<&[u8], i16> { - i16(Endianness::Little)(i) + + #[test] + fn be_f64_tests() { + assert_parse!( + be_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 0_f64)) + ); + assert_parse!( + be_f64(&[0x41, 0xa6, 0x23, 0xfb, 0x10, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 185_728_392_f64)) + ); } - assert_eq!(be_tsti16(&[0x00, 0x80]), Ok((&b""[..], 128_i16))); - assert_eq!(le_tsti16(&[0x00, 0x80]), Ok((&b""[..], -32_768_i16))); - fn be_tsti32(i: &[u8]) -> IResult<&[u8], i32> { - i32(Endianness::Big)(i) + #[test] + fn le_f32_tests() { + assert_parse!(le_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32))); + assert_parse!( + le_f32(&[0xd8, 0x1f, 0x31, 0x4d][..]), + Ok((&b""[..], 185_728_380_f32)) + ); } - fn le_tsti32(i: &[u8]) -> IResult<&[u8], i32> { - i32(Endianness::Little)(i) + + #[test] + fn le_f64_tests() { + assert_parse!( + le_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 0_f64)) + ); + assert_parse!( + le_f64(&[0x00, 0x00, 0x00, 0x10, 0xfb, 0x23, 0xa6, 0x41][..]), + Ok((&b""[..], 185_728_392_f64)) + ); } - assert_eq!( - be_tsti32(&[0x00, 0x12, 0x60, 0x00]), - Ok((&b""[..], 1_204_224_i32)) - ); - assert_eq!( - le_tsti32(&[0x00, 0x12, 0x60, 0x00]), - Ok((&b""[..], 6_296_064_i32)) - ); - - fn be_tsti64(i: &[u8]) -> IResult<&[u8], i64> { - i64(Endianness::Big)(i) + + #[test] + fn hex_u32_tests() { + assert_parse!( + hex_u32(&b";"[..]), + Err(ErrMode::Backtrack(error_position!( + &b";"[..], + ErrorKind::IsA + ))) + ); + assert_parse!(hex_u32(&b"ff;"[..]), Ok((&b";"[..], 255))); + assert_parse!(hex_u32(&b"1be2;"[..]), Ok((&b";"[..], 7138))); + assert_parse!(hex_u32(&b"c5a31be2;"[..]), Ok((&b";"[..], 3_315_801_058))); + assert_parse!(hex_u32(&b"C5A31be2;"[..]), Ok((&b";"[..], 3_315_801_058))); + assert_parse!(hex_u32(&b"00c5a31be2;"[..]), Ok((&b"e2;"[..], 12_952_347))); + assert_parse!( + hex_u32(&b"c5a31be201;"[..]), + Ok((&b"01;"[..], 3_315_801_058)) + ); + assert_parse!(hex_u32(&b"ffffffff;"[..]), Ok((&b";"[..], 4_294_967_295))); + assert_parse!(hex_u32(&b"0x1be2;"[..]), Ok((&b"x1be2;"[..], 0))); + assert_parse!( + hex_u32(&b"12af"[..]), + Err(ErrMode::Incomplete(Needed::new(1))) + ); } - fn le_tsti64(i: &[u8]) -> IResult<&[u8], i64> { - i64(Endianness::Little)(i) + + #[test] + #[cfg(feature = "std")] + fn float_test() { + let mut test_cases = vec![ + "+3.14", + "3.14", + "-3.14", + "0", + "0.0", + "1.", + ".789", + "-.5", + "1e7", + "-1E-7", + ".3e-2", + "1.e4", + "1.2e4", + "12.34", + "-1.234E-12", + "-1.234e-12", + "0.00000000000000000087", + ]; + + for test in test_cases.drain(..) { + let expected32 = str::parse::(test).unwrap(); + let expected64 = str::parse::(test).unwrap(); + + println!("now parsing: {} -> {}", test, expected32); + + let larger = format!("{};", test); + assert_parse!(recognize_float(&larger[..]), Ok((";", test))); + + assert_parse!(float(larger.as_bytes()), Ok((&b";"[..], expected32))); + assert_parse!(float(&larger[..]), Ok((";", expected32))); + + assert_parse!(double(larger.as_bytes()), Ok((&b";"[..], expected64))); + assert_parse!(double(&larger[..]), Ok((";", expected64))); + } + + let remaining_exponent = "-1.234E-"; + assert_parse!( + recognize_float(remaining_exponent), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + + let (_i, nan) = float::<_, ()>("NaN").unwrap(); + assert!(nan.is_nan()); + + let (_i, inf) = float::<_, ()>("inf").unwrap(); + assert!(inf.is_infinite()); + let (_i, inf) = float::<_, ()>("infinite").unwrap(); + assert!(inf.is_infinite()); } - assert_eq!( - be_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), - Ok((&b""[..], 71_881_672_479_506_432_i64)) - ); - assert_eq!( - le_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), - Ok((&b""[..], 36_028_874_334_732_032_i64)) - ); - } - - #[cfg(feature = "std")] - fn parse_f64(i: &str) -> IResult<&str, f64, ()> { - match recognize_float_or_exceptions(i) { - Err(e) => Err(e), - Ok((i, s)) => { - if s.is_empty() { - return Err(ErrMode::Backtrack(())); + + #[test] + fn configurable_endianness() { + use crate::number::Endianness; + + fn be_tst16(i: &[u8]) -> IResult<&[u8], u16> { + u16(Endianness::Big)(i) } - match s.parse_slice() { - Some(n) => Ok((i, n)), - None => Err(ErrMode::Backtrack(())), + fn le_tst16(i: &[u8]) -> IResult<&[u8], u16> { + u16(Endianness::Little)(i) } - } + assert_eq!(be_tst16(&[0x80, 0x00]), Ok((&b""[..], 32_768_u16))); + assert_eq!(le_tst16(&[0x80, 0x00]), Ok((&b""[..], 128_u16))); + + fn be_tst32(i: &[u8]) -> IResult<&[u8], u32> { + u32(Endianness::Big)(i) + } + fn le_tst32(i: &[u8]) -> IResult<&[u8], u32> { + u32(Endianness::Little)(i) + } + assert_eq!( + be_tst32(&[0x12, 0x00, 0x60, 0x00]), + Ok((&b""[..], 302_014_464_u32)) + ); + assert_eq!( + le_tst32(&[0x12, 0x00, 0x60, 0x00]), + Ok((&b""[..], 6_291_474_u32)) + ); + + fn be_tst64(i: &[u8]) -> IResult<&[u8], u64> { + u64(Endianness::Big)(i) + } + fn le_tst64(i: &[u8]) -> IResult<&[u8], u64> { + u64(Endianness::Little)(i) + } + assert_eq!( + be_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), + Ok((&b""[..], 1_297_142_246_100_992_000_u64)) + ); + assert_eq!( + le_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), + Ok((&b""[..], 36_028_874_334_666_770_u64)) + ); + + fn be_tsti16(i: &[u8]) -> IResult<&[u8], i16> { + i16(Endianness::Big)(i) + } + fn le_tsti16(i: &[u8]) -> IResult<&[u8], i16> { + i16(Endianness::Little)(i) + } + assert_eq!(be_tsti16(&[0x00, 0x80]), Ok((&b""[..], 128_i16))); + assert_eq!(le_tsti16(&[0x00, 0x80]), Ok((&b""[..], -32_768_i16))); + + fn be_tsti32(i: &[u8]) -> IResult<&[u8], i32> { + i32(Endianness::Big)(i) + } + fn le_tsti32(i: &[u8]) -> IResult<&[u8], i32> { + i32(Endianness::Little)(i) + } + assert_eq!( + be_tsti32(&[0x00, 0x12, 0x60, 0x00]), + Ok((&b""[..], 1_204_224_i32)) + ); + assert_eq!( + le_tsti32(&[0x00, 0x12, 0x60, 0x00]), + Ok((&b""[..], 6_296_064_i32)) + ); + + fn be_tsti64(i: &[u8]) -> IResult<&[u8], i64> { + i64(Endianness::Big)(i) + } + fn le_tsti64(i: &[u8]) -> IResult<&[u8], i64> { + i64(Endianness::Little)(i) + } + assert_eq!( + be_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), + Ok((&b""[..], 71_881_672_479_506_432_i64)) + ); + assert_eq!( + le_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), + Ok((&b""[..], 36_028_874_334_732_032_i64)) + ); } - } - proptest! { - #[test] #[cfg(feature = "std")] - fn floats(s in "\\PC*") { - println!("testing {}", s); - let res1 = parse_f64(&s); - let res2 = double::<_, ()>(s.as_str()); - assert_eq!(res1, res2); + fn parse_f64(i: &str) -> IResult<&str, f64, ()> { + match recognize_float_or_exceptions(i) { + Err(e) => Err(e), + Ok((i, s)) => { + if s.is_empty() { + return Err(ErrMode::Backtrack(())); + } + match s.parse_slice() { + Some(n) => Ok((i, n)), + None => Err(ErrMode::Backtrack(())), + } + } + } + } + + proptest! { + #[test] + #[cfg(feature = "std")] + fn floats(s in "\\PC*") { + println!("testing {}", s); + let res1 = parse_f64(&s); + let res2 = double::<_, ()>(s.as_str()); + assert_eq!(res1, res2); + } } - } } diff --git a/src/number/tests.rs b/src/number/tests.rs index e92e6459..e1db8056 100644 --- a/src/number/tests.rs +++ b/src/number/tests.rs @@ -1,1029 +1,1034 @@ use super::*; mod complete { - use super::*; - use crate::error::Error; + use super::*; + use crate::error::Error; - macro_rules! assert_parse( + macro_rules! assert_parse( ($left: expr, $right: expr) => { let res: $crate::IResult<_, _, Error<_>> = $left; assert_eq!(res, $right); }; ); - #[test] - fn i8_tests() { - assert_parse!(i8(&[0x00][..]), Ok((&b""[..], 0))); - assert_parse!(i8(&[0x7f][..]), Ok((&b""[..], 127))); - assert_parse!(i8(&[0xff][..]), Ok((&b""[..], -1))); - assert_parse!(i8(&[0x80][..]), Ok((&b""[..], -128))); - } + #[test] + fn i8_tests() { + assert_parse!(i8(&[0x00][..]), Ok((&b""[..], 0))); + assert_parse!(i8(&[0x7f][..]), Ok((&b""[..], 127))); + assert_parse!(i8(&[0xff][..]), Ok((&b""[..], -1))); + assert_parse!(i8(&[0x80][..]), Ok((&b""[..], -128))); + } - #[test] - fn be_i8_tests() { - assert_parse!(be_i8(&[0x00][..]), Ok((&b""[..], 0))); - assert_parse!(be_i8(&[0x7f][..]), Ok((&b""[..], 127))); - assert_parse!(be_i8(&[0xff][..]), Ok((&b""[..], -1))); - assert_parse!(be_i8(&[0x80][..]), Ok((&b""[..], -128))); - } + #[test] + fn be_i8_tests() { + assert_parse!(be_i8(&[0x00][..]), Ok((&b""[..], 0))); + assert_parse!(be_i8(&[0x7f][..]), Ok((&b""[..], 127))); + assert_parse!(be_i8(&[0xff][..]), Ok((&b""[..], -1))); + assert_parse!(be_i8(&[0x80][..]), Ok((&b""[..], -128))); + } - #[test] - fn be_i16_tests() { - assert_parse!(be_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0))); - assert_parse!(be_i16(&[0x7f, 0xff][..]), Ok((&b""[..], 32_767_i16))); - assert_parse!(be_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1))); - assert_parse!(be_i16(&[0x80, 0x00][..]), Ok((&b""[..], -32_768_i16))); - } + #[test] + fn be_i16_tests() { + assert_parse!(be_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!(be_i16(&[0x7f, 0xff][..]), Ok((&b""[..], 32_767_i16))); + assert_parse!(be_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1))); + assert_parse!(be_i16(&[0x80, 0x00][..]), Ok((&b""[..], -32_768_i16))); + } - #[test] - fn be_u24_tests() { - assert_parse!(be_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); - assert_parse!(be_u24(&[0x00, 0xFF, 0xFF][..]), Ok((&b""[..], 65_535_u32))); - assert_parse!( - be_u24(&[0x12, 0x34, 0x56][..]), - Ok((&b""[..], 1_193_046_u32)) - ); - } + #[test] + fn be_u24_tests() { + assert_parse!(be_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!(be_u24(&[0x00, 0xFF, 0xFF][..]), Ok((&b""[..], 65_535_u32))); + assert_parse!( + be_u24(&[0x12, 0x34, 0x56][..]), + Ok((&b""[..], 1_193_046_u32)) + ); + } - #[test] - fn be_i24_tests() { - assert_parse!(be_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32))); - assert_parse!(be_i24(&[0xFF, 0x00, 0x00][..]), Ok((&b""[..], -65_536_i32))); - assert_parse!( - be_i24(&[0xED, 0xCB, 0xAA][..]), - Ok((&b""[..], -1_193_046_i32)) - ); - } + #[test] + fn be_i24_tests() { + assert_parse!(be_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32))); + assert_parse!(be_i24(&[0xFF, 0x00, 0x00][..]), Ok((&b""[..], -65_536_i32))); + assert_parse!( + be_i24(&[0xED, 0xCB, 0xAA][..]), + Ok((&b""[..], -1_193_046_i32)) + ); + } - #[test] - fn be_i32_tests() { - assert_parse!(be_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); - assert_parse!( - be_i32(&[0x7f, 0xff, 0xff, 0xff][..]), - Ok((&b""[..], 2_147_483_647_i32)) - ); - assert_parse!(be_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1))); - assert_parse!( - be_i32(&[0x80, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], -2_147_483_648_i32)) - ); - } + #[test] + fn be_i32_tests() { + assert_parse!(be_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!( + be_i32(&[0x7f, 0xff, 0xff, 0xff][..]), + Ok((&b""[..], 2_147_483_647_i32)) + ); + assert_parse!(be_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1))); + assert_parse!( + be_i32(&[0x80, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], -2_147_483_648_i32)) + ); + } - #[test] - fn be_i64_tests() { - assert_parse!( - be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], 0)) - ); - assert_parse!( - be_i64(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), - Ok((&b""[..], 9_223_372_036_854_775_807_i64)) - ); - assert_parse!( - be_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), - Ok((&b""[..], -1)) - ); - assert_parse!( - be_i64(&[0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], -9_223_372_036_854_775_808_i64)) - ); - } + #[test] + fn be_i64_tests() { + assert_parse!( + be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 0)) + ); + assert_parse!( + be_i64(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), + Ok((&b""[..], 9_223_372_036_854_775_807_i64)) + ); + assert_parse!( + be_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), + Ok((&b""[..], -1)) + ); + assert_parse!( + be_i64(&[0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], -9_223_372_036_854_775_808_i64)) + ); + } - #[test] - fn be_i128_tests() { - assert_parse!( - be_i128( - &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 - ][..] - ), - Ok((&b""[..], 0)) - ); - assert_parse!( - be_i128( - &[ - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff - ][..] - ), - Ok(( - &b""[..], - 170_141_183_460_469_231_731_687_303_715_884_105_727_i128 - )) - ); - assert_parse!( - be_i128( - &[ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff - ][..] - ), - Ok((&b""[..], -1)) - ); - assert_parse!( - be_i128( - &[ - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 - ][..] - ), - Ok(( - &b""[..], - -170_141_183_460_469_231_731_687_303_715_884_105_728_i128 - )) - ); - } + #[test] + fn be_i128_tests() { + assert_parse!( + be_i128( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 + ][..] + ), + Ok((&b""[..], 0)) + ); + assert_parse!( + be_i128( + &[ + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff + ][..] + ), + Ok(( + &b""[..], + 170_141_183_460_469_231_731_687_303_715_884_105_727_i128 + )) + ); + assert_parse!( + be_i128( + &[ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff + ][..] + ), + Ok((&b""[..], -1)) + ); + assert_parse!( + be_i128( + &[ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 + ][..] + ), + Ok(( + &b""[..], + -170_141_183_460_469_231_731_687_303_715_884_105_728_i128 + )) + ); + } - #[test] - fn le_i8_tests() { - assert_parse!(le_i8(&[0x00][..]), Ok((&b""[..], 0))); - assert_parse!(le_i8(&[0x7f][..]), Ok((&b""[..], 127))); - assert_parse!(le_i8(&[0xff][..]), Ok((&b""[..], -1))); - assert_parse!(le_i8(&[0x80][..]), Ok((&b""[..], -128))); - } + #[test] + fn le_i8_tests() { + assert_parse!(le_i8(&[0x00][..]), Ok((&b""[..], 0))); + assert_parse!(le_i8(&[0x7f][..]), Ok((&b""[..], 127))); + assert_parse!(le_i8(&[0xff][..]), Ok((&b""[..], -1))); + assert_parse!(le_i8(&[0x80][..]), Ok((&b""[..], -128))); + } - #[test] - fn le_i16_tests() { - assert_parse!(le_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0))); - assert_parse!(le_i16(&[0xff, 0x7f][..]), Ok((&b""[..], 32_767_i16))); - assert_parse!(le_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1))); - assert_parse!(le_i16(&[0x00, 0x80][..]), Ok((&b""[..], -32_768_i16))); - } + #[test] + fn le_i16_tests() { + assert_parse!(le_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!(le_i16(&[0xff, 0x7f][..]), Ok((&b""[..], 32_767_i16))); + assert_parse!(le_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1))); + assert_parse!(le_i16(&[0x00, 0x80][..]), Ok((&b""[..], -32_768_i16))); + } - #[test] - fn le_u24_tests() { - assert_parse!(le_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); - assert_parse!(le_u24(&[0xFF, 0xFF, 0x00][..]), Ok((&b""[..], 65_535_u32))); - assert_parse!( - le_u24(&[0x56, 0x34, 0x12][..]), - Ok((&b""[..], 1_193_046_u32)) - ); - } + #[test] + fn le_u24_tests() { + assert_parse!(le_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!(le_u24(&[0xFF, 0xFF, 0x00][..]), Ok((&b""[..], 65_535_u32))); + assert_parse!( + le_u24(&[0x56, 0x34, 0x12][..]), + Ok((&b""[..], 1_193_046_u32)) + ); + } - #[test] - fn le_i24_tests() { - assert_parse!(le_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32))); - assert_parse!(le_i24(&[0x00, 0x00, 0xFF][..]), Ok((&b""[..], -65_536_i32))); - assert_parse!( - le_i24(&[0xAA, 0xCB, 0xED][..]), - Ok((&b""[..], -1_193_046_i32)) - ); - } + #[test] + fn le_i24_tests() { + assert_parse!(le_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32))); + assert_parse!(le_i24(&[0x00, 0x00, 0xFF][..]), Ok((&b""[..], -65_536_i32))); + assert_parse!( + le_i24(&[0xAA, 0xCB, 0xED][..]), + Ok((&b""[..], -1_193_046_i32)) + ); + } - #[test] - fn le_i32_tests() { - assert_parse!(le_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); - assert_parse!( - le_i32(&[0xff, 0xff, 0xff, 0x7f][..]), - Ok((&b""[..], 2_147_483_647_i32)) - ); - assert_parse!(le_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1))); - assert_parse!( - le_i32(&[0x00, 0x00, 0x00, 0x80][..]), - Ok((&b""[..], -2_147_483_648_i32)) - ); - } + #[test] + fn le_i32_tests() { + assert_parse!(le_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0))); + assert_parse!( + le_i32(&[0xff, 0xff, 0xff, 0x7f][..]), + Ok((&b""[..], 2_147_483_647_i32)) + ); + assert_parse!(le_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1))); + assert_parse!( + le_i32(&[0x00, 0x00, 0x00, 0x80][..]), + Ok((&b""[..], -2_147_483_648_i32)) + ); + } - #[test] - fn le_i64_tests() { - assert_parse!( - le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], 0)) - ); - assert_parse!( - le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f][..]), - Ok((&b""[..], 9_223_372_036_854_775_807_i64)) - ); - assert_parse!( - le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), - Ok((&b""[..], -1)) - ); - assert_parse!( - le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80][..]), - Ok((&b""[..], -9_223_372_036_854_775_808_i64)) - ); - } + #[test] + fn le_i64_tests() { + assert_parse!( + le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 0)) + ); + assert_parse!( + le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f][..]), + Ok((&b""[..], 9_223_372_036_854_775_807_i64)) + ); + assert_parse!( + le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]), + Ok((&b""[..], -1)) + ); + assert_parse!( + le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80][..]), + Ok((&b""[..], -9_223_372_036_854_775_808_i64)) + ); + } - #[test] - fn le_i128_tests() { - assert_parse!( - le_i128( - &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 - ][..] - ), - Ok((&b""[..], 0)) - ); - assert_parse!( - le_i128( - &[ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x7f - ][..] - ), - Ok(( - &b""[..], - 170_141_183_460_469_231_731_687_303_715_884_105_727_i128 - )) - ); - assert_parse!( - le_i128( - &[ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff - ][..] - ), - Ok((&b""[..], -1)) - ); - assert_parse!( - le_i128( - &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80 - ][..] - ), - Ok(( - &b""[..], - -170_141_183_460_469_231_731_687_303_715_884_105_728_i128 - )) - ); - } + #[test] + fn le_i128_tests() { + assert_parse!( + le_i128( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 + ][..] + ), + Ok((&b""[..], 0)) + ); + assert_parse!( + le_i128( + &[ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f + ][..] + ), + Ok(( + &b""[..], + 170_141_183_460_469_231_731_687_303_715_884_105_727_i128 + )) + ); + assert_parse!( + le_i128( + &[ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff + ][..] + ), + Ok((&b""[..], -1)) + ); + assert_parse!( + le_i128( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80 + ][..] + ), + Ok(( + &b""[..], + -170_141_183_460_469_231_731_687_303_715_884_105_728_i128 + )) + ); + } - #[test] - fn be_f32_tests() { - assert_parse!(be_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32))); - assert_parse!( - be_f32(&[0x4d, 0x31, 0x1f, 0xd8][..]), - Ok((&b""[..], 185_728_380_f32)) - ); - } + #[test] + fn be_f32_tests() { + assert_parse!(be_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32))); + assert_parse!( + be_f32(&[0x4d, 0x31, 0x1f, 0xd8][..]), + Ok((&b""[..], 185_728_380_f32)) + ); + } - #[test] - fn be_f64_tests() { - assert_parse!( - be_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], 0_f64)) - ); - assert_parse!( - be_f64(&[0x41, 0xa6, 0x23, 0xfb, 0x10, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], 185_728_392_f64)) - ); - } + #[test] + fn be_f64_tests() { + assert_parse!( + be_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 0_f64)) + ); + assert_parse!( + be_f64(&[0x41, 0xa6, 0x23, 0xfb, 0x10, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 185_728_392_f64)) + ); + } - #[test] - fn le_f32_tests() { - assert_parse!(le_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32))); - assert_parse!( - le_f32(&[0xd8, 0x1f, 0x31, 0x4d][..]), - Ok((&b""[..], 185_728_380_f32)) - ); - } + #[test] + fn le_f32_tests() { + assert_parse!(le_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32))); + assert_parse!( + le_f32(&[0xd8, 0x1f, 0x31, 0x4d][..]), + Ok((&b""[..], 185_728_380_f32)) + ); + } - #[test] - fn le_f64_tests() { - assert_parse!( - le_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), - Ok((&b""[..], 0_f64)) - ); - assert_parse!( - le_f64(&[0x00, 0x00, 0x00, 0x10, 0xfb, 0x23, 0xa6, 0x41][..]), - Ok((&b""[..], 185_728_392_f64)) - ); - } + #[test] + fn le_f64_tests() { + assert_parse!( + le_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), + Ok((&b""[..], 0_f64)) + ); + assert_parse!( + le_f64(&[0x00, 0x00, 0x00, 0x10, 0xfb, 0x23, 0xa6, 0x41][..]), + Ok((&b""[..], 185_728_392_f64)) + ); + } - #[test] - fn configurable_endianness() { - use crate::number::Endianness; + #[test] + fn configurable_endianness() { + use crate::number::Endianness; - fn be_tst16(i: &[u8]) -> IResult<&[u8], u16> { - u16(Endianness::Big)(i) - } - fn le_tst16(i: &[u8]) -> IResult<&[u8], u16> { - u16(Endianness::Little)(i) - } - assert_eq!(be_tst16(&[0x80, 0x00]), Ok((&b""[..], 32_768_u16))); - assert_eq!(le_tst16(&[0x80, 0x00]), Ok((&b""[..], 128_u16))); + fn be_tst16(i: &[u8]) -> IResult<&[u8], u16> { + u16(Endianness::Big)(i) + } + fn le_tst16(i: &[u8]) -> IResult<&[u8], u16> { + u16(Endianness::Little)(i) + } + assert_eq!(be_tst16(&[0x80, 0x00]), Ok((&b""[..], 32_768_u16))); + assert_eq!(le_tst16(&[0x80, 0x00]), Ok((&b""[..], 128_u16))); - fn be_tst32(i: &[u8]) -> IResult<&[u8], u32> { - u32(Endianness::Big)(i) - } - fn le_tst32(i: &[u8]) -> IResult<&[u8], u32> { - u32(Endianness::Little)(i) - } - assert_eq!( - be_tst32(&[0x12, 0x00, 0x60, 0x00]), - Ok((&b""[..], 302_014_464_u32)) - ); - assert_eq!( - le_tst32(&[0x12, 0x00, 0x60, 0x00]), - Ok((&b""[..], 6_291_474_u32)) - ); + fn be_tst32(i: &[u8]) -> IResult<&[u8], u32> { + u32(Endianness::Big)(i) + } + fn le_tst32(i: &[u8]) -> IResult<&[u8], u32> { + u32(Endianness::Little)(i) + } + assert_eq!( + be_tst32(&[0x12, 0x00, 0x60, 0x00]), + Ok((&b""[..], 302_014_464_u32)) + ); + assert_eq!( + le_tst32(&[0x12, 0x00, 0x60, 0x00]), + Ok((&b""[..], 6_291_474_u32)) + ); - fn be_tst64(i: &[u8]) -> IResult<&[u8], u64> { - u64(Endianness::Big)(i) - } - fn le_tst64(i: &[u8]) -> IResult<&[u8], u64> { - u64(Endianness::Little)(i) - } - assert_eq!( - be_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), - Ok((&b""[..], 1_297_142_246_100_992_000_u64)) - ); - assert_eq!( - le_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), - Ok((&b""[..], 36_028_874_334_666_770_u64)) - ); + fn be_tst64(i: &[u8]) -> IResult<&[u8], u64> { + u64(Endianness::Big)(i) + } + fn le_tst64(i: &[u8]) -> IResult<&[u8], u64> { + u64(Endianness::Little)(i) + } + assert_eq!( + be_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), + Ok((&b""[..], 1_297_142_246_100_992_000_u64)) + ); + assert_eq!( + le_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), + Ok((&b""[..], 36_028_874_334_666_770_u64)) + ); - fn be_tsti16(i: &[u8]) -> IResult<&[u8], i16> { - i16(Endianness::Big)(i) - } - fn le_tsti16(i: &[u8]) -> IResult<&[u8], i16> { - i16(Endianness::Little)(i) - } - assert_eq!(be_tsti16(&[0x00, 0x80]), Ok((&b""[..], 128_i16))); - assert_eq!(le_tsti16(&[0x00, 0x80]), Ok((&b""[..], -32_768_i16))); + fn be_tsti16(i: &[u8]) -> IResult<&[u8], i16> { + i16(Endianness::Big)(i) + } + fn le_tsti16(i: &[u8]) -> IResult<&[u8], i16> { + i16(Endianness::Little)(i) + } + assert_eq!(be_tsti16(&[0x00, 0x80]), Ok((&b""[..], 128_i16))); + assert_eq!(le_tsti16(&[0x00, 0x80]), Ok((&b""[..], -32_768_i16))); - fn be_tsti32(i: &[u8]) -> IResult<&[u8], i32> { - i32(Endianness::Big)(i) - } - fn le_tsti32(i: &[u8]) -> IResult<&[u8], i32> { - i32(Endianness::Little)(i) - } - assert_eq!( - be_tsti32(&[0x00, 0x12, 0x60, 0x00]), - Ok((&b""[..], 1_204_224_i32)) - ); - assert_eq!( - le_tsti32(&[0x00, 0x12, 0x60, 0x00]), - Ok((&b""[..], 6_296_064_i32)) - ); + fn be_tsti32(i: &[u8]) -> IResult<&[u8], i32> { + i32(Endianness::Big)(i) + } + fn le_tsti32(i: &[u8]) -> IResult<&[u8], i32> { + i32(Endianness::Little)(i) + } + assert_eq!( + be_tsti32(&[0x00, 0x12, 0x60, 0x00]), + Ok((&b""[..], 1_204_224_i32)) + ); + assert_eq!( + le_tsti32(&[0x00, 0x12, 0x60, 0x00]), + Ok((&b""[..], 6_296_064_i32)) + ); - fn be_tsti64(i: &[u8]) -> IResult<&[u8], i64> { - i64(Endianness::Big)(i) - } - fn le_tsti64(i: &[u8]) -> IResult<&[u8], i64> { - i64(Endianness::Little)(i) + fn be_tsti64(i: &[u8]) -> IResult<&[u8], i64> { + i64(Endianness::Big)(i) + } + fn le_tsti64(i: &[u8]) -> IResult<&[u8], i64> { + i64(Endianness::Little)(i) + } + assert_eq!( + be_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), + Ok((&b""[..], 71_881_672_479_506_432_i64)) + ); + assert_eq!( + le_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), + Ok((&b""[..], 36_028_874_334_732_032_i64)) + ); } - assert_eq!( - be_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), - Ok((&b""[..], 71_881_672_479_506_432_i64)) - ); - assert_eq!( - le_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), - Ok((&b""[..], 36_028_874_334_732_032_i64)) - ); - } } mod streaming { - use super::*; - use crate::error::ErrMode; - use crate::error::Error; - use crate::error::Needed; - use crate::input::Streaming; + use super::*; + use crate::error::ErrMode; + use crate::error::Error; + use crate::error::Needed; + use crate::input::Streaming; - macro_rules! assert_parse( + macro_rules! assert_parse( ($left: expr, $right: expr) => { let res: $crate::IResult<_, _, Error<_>> = $left; assert_eq!(res, $right); }; ); - #[test] - fn i8_tests() { - assert_parse!(be_i8(Streaming(&[0x00][..])), Ok((Streaming(&b""[..]), 0))); - assert_parse!( - be_i8(Streaming(&[0x7f][..])), - Ok((Streaming(&b""[..]), 127)) - ); - assert_parse!(be_i8(Streaming(&[0xff][..])), Ok((Streaming(&b""[..]), -1))); - assert_parse!( - be_i8(Streaming(&[0x80][..])), - Ok((Streaming(&b""[..]), -128)) - ); - assert_parse!( - be_i8(Streaming(&[][..])), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - } + #[test] + fn i8_tests() { + assert_parse!(be_i8(Streaming(&[0x00][..])), Ok((Streaming(&b""[..]), 0))); + assert_parse!( + be_i8(Streaming(&[0x7f][..])), + Ok((Streaming(&b""[..]), 127)) + ); + assert_parse!(be_i8(Streaming(&[0xff][..])), Ok((Streaming(&b""[..]), -1))); + assert_parse!( + be_i8(Streaming(&[0x80][..])), + Ok((Streaming(&b""[..]), -128)) + ); + assert_parse!( + be_i8(Streaming(&[][..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + } - #[test] - fn i16_tests() { - assert_parse!( - be_i16(Streaming(&[0x00, 0x00][..])), - Ok((Streaming(&b""[..]), 0)) - ); - assert_parse!( - be_i16(Streaming(&[0x7f, 0xff][..])), - Ok((Streaming(&b""[..]), 32_767_i16)) - ); - assert_parse!( - be_i16(Streaming(&[0xff, 0xff][..])), - Ok((Streaming(&b""[..]), -1)) - ); - assert_parse!( - be_i16(Streaming(&[0x80, 0x00][..])), - Ok((Streaming(&b""[..]), -32_768_i16)) - ); - assert_parse!( - be_i16(Streaming(&[][..])), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_parse!( - be_i16(Streaming(&[0x00][..])), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - } + #[test] + fn i16_tests() { + assert_parse!( + be_i16(Streaming(&[0x00, 0x00][..])), + Ok((Streaming(&b""[..]), 0)) + ); + assert_parse!( + be_i16(Streaming(&[0x7f, 0xff][..])), + Ok((Streaming(&b""[..]), 32_767_i16)) + ); + assert_parse!( + be_i16(Streaming(&[0xff, 0xff][..])), + Ok((Streaming(&b""[..]), -1)) + ); + assert_parse!( + be_i16(Streaming(&[0x80, 0x00][..])), + Ok((Streaming(&b""[..]), -32_768_i16)) + ); + assert_parse!( + be_i16(Streaming(&[][..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_parse!( + be_i16(Streaming(&[0x00][..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + } - #[test] - fn u24_tests() { - assert_parse!( - be_u24(Streaming(&[0x00, 0x00, 0x00][..])), - Ok((Streaming(&b""[..]), 0)) - ); - assert_parse!( - be_u24(Streaming(&[0x00, 0xFF, 0xFF][..])), - Ok((Streaming(&b""[..]), 65_535_u32)) - ); - assert_parse!( - be_u24(Streaming(&[0x12, 0x34, 0x56][..])), - Ok((Streaming(&b""[..]), 1_193_046_u32)) - ); - assert_parse!( - be_u24(Streaming(&[][..])), - Err(ErrMode::Incomplete(Needed::new(3))) - ); - assert_parse!( - be_u24(Streaming(&[0x00][..])), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_parse!( - be_u24(Streaming(&[0x00, 0x00][..])), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - } + #[test] + fn u24_tests() { + assert_parse!( + be_u24(Streaming(&[0x00, 0x00, 0x00][..])), + Ok((Streaming(&b""[..]), 0)) + ); + assert_parse!( + be_u24(Streaming(&[0x00, 0xFF, 0xFF][..])), + Ok((Streaming(&b""[..]), 65_535_u32)) + ); + assert_parse!( + be_u24(Streaming(&[0x12, 0x34, 0x56][..])), + Ok((Streaming(&b""[..]), 1_193_046_u32)) + ); + assert_parse!( + be_u24(Streaming(&[][..])), + Err(ErrMode::Incomplete(Needed::new(3))) + ); + assert_parse!( + be_u24(Streaming(&[0x00][..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_parse!( + be_u24(Streaming(&[0x00, 0x00][..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + } - #[test] - fn i24_tests() { - assert_parse!( - be_i24(Streaming(&[0xFF, 0xFF, 0xFF][..])), - Ok((Streaming(&b""[..]), -1_i32)) - ); - assert_parse!( - be_i24(Streaming(&[0xFF, 0x00, 0x00][..])), - Ok((Streaming(&b""[..]), -65_536_i32)) - ); - assert_parse!( - be_i24(Streaming(&[0xED, 0xCB, 0xAA][..])), - Ok((Streaming(&b""[..]), -1_193_046_i32)) - ); - assert_parse!( - be_i24(Streaming(&[][..])), - Err(ErrMode::Incomplete(Needed::new(3))) - ); - assert_parse!( - be_i24(Streaming(&[0x00][..])), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_parse!( - be_i24(Streaming(&[0x00, 0x00][..])), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - } + #[test] + fn i24_tests() { + assert_parse!( + be_i24(Streaming(&[0xFF, 0xFF, 0xFF][..])), + Ok((Streaming(&b""[..]), -1_i32)) + ); + assert_parse!( + be_i24(Streaming(&[0xFF, 0x00, 0x00][..])), + Ok((Streaming(&b""[..]), -65_536_i32)) + ); + assert_parse!( + be_i24(Streaming(&[0xED, 0xCB, 0xAA][..])), + Ok((Streaming(&b""[..]), -1_193_046_i32)) + ); + assert_parse!( + be_i24(Streaming(&[][..])), + Err(ErrMode::Incomplete(Needed::new(3))) + ); + assert_parse!( + be_i24(Streaming(&[0x00][..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_parse!( + be_i24(Streaming(&[0x00, 0x00][..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + } - #[test] - fn i32_tests() { - assert_parse!( - be_i32(Streaming(&[0x00, 0x00, 0x00, 0x00][..])), - Ok((Streaming(&b""[..]), 0)) - ); - assert_parse!( - be_i32(Streaming(&[0x7f, 0xff, 0xff, 0xff][..])), - Ok((Streaming(&b""[..]), 2_147_483_647_i32)) - ); - assert_parse!( - be_i32(Streaming(&[0xff, 0xff, 0xff, 0xff][..])), - Ok((Streaming(&b""[..]), -1)) - ); - assert_parse!( - be_i32(Streaming(&[0x80, 0x00, 0x00, 0x00][..])), - Ok((Streaming(&b""[..]), -2_147_483_648_i32)) - ); - assert_parse!( - be_i32(Streaming(&[][..])), - Err(ErrMode::Incomplete(Needed::new(4))) - ); - assert_parse!( - be_i32(Streaming(&[0x00][..])), - Err(ErrMode::Incomplete(Needed::new(3))) - ); - assert_parse!( - be_i32(Streaming(&[0x00, 0x00][..])), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_parse!( - be_i32(Streaming(&[0x00, 0x00, 0x00][..])), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - } + #[test] + fn i32_tests() { + assert_parse!( + be_i32(Streaming(&[0x00, 0x00, 0x00, 0x00][..])), + Ok((Streaming(&b""[..]), 0)) + ); + assert_parse!( + be_i32(Streaming(&[0x7f, 0xff, 0xff, 0xff][..])), + Ok((Streaming(&b""[..]), 2_147_483_647_i32)) + ); + assert_parse!( + be_i32(Streaming(&[0xff, 0xff, 0xff, 0xff][..])), + Ok((Streaming(&b""[..]), -1)) + ); + assert_parse!( + be_i32(Streaming(&[0x80, 0x00, 0x00, 0x00][..])), + Ok((Streaming(&b""[..]), -2_147_483_648_i32)) + ); + assert_parse!( + be_i32(Streaming(&[][..])), + Err(ErrMode::Incomplete(Needed::new(4))) + ); + assert_parse!( + be_i32(Streaming(&[0x00][..])), + Err(ErrMode::Incomplete(Needed::new(3))) + ); + assert_parse!( + be_i32(Streaming(&[0x00, 0x00][..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_parse!( + be_i32(Streaming(&[0x00, 0x00, 0x00][..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + } - #[test] - fn i64_tests() { - assert_parse!( - be_i64(Streaming( - &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] - )), - Ok((Streaming(&b""[..]), 0)) - ); - assert_parse!( - be_i64(Streaming( - &[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..] - )), - Ok((Streaming(&b""[..]), 9_223_372_036_854_775_807_i64)) - ); - assert_parse!( - be_i64(Streaming( - &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..] - )), - Ok((Streaming(&b""[..]), -1)) - ); - assert_parse!( - be_i64(Streaming( - &[0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] - )), - Ok((Streaming(&b""[..]), -9_223_372_036_854_775_808_i64)) - ); - assert_parse!( - be_i64(Streaming(&[][..])), - Err(ErrMode::Incomplete(Needed::new(8))) - ); - assert_parse!( - be_i64(Streaming(&[0x00][..])), - Err(ErrMode::Incomplete(Needed::new(7))) - ); - assert_parse!( - be_i64(Streaming(&[0x00, 0x00][..])), - Err(ErrMode::Incomplete(Needed::new(6))) - ); - assert_parse!( - be_i64(Streaming(&[0x00, 0x00, 0x00][..])), - Err(ErrMode::Incomplete(Needed::new(5))) - ); - assert_parse!( - be_i64(Streaming(&[0x00, 0x00, 0x00, 0x00][..])), - Err(ErrMode::Incomplete(Needed::new(4))) - ); - assert_parse!( - be_i64(Streaming(&[0x00, 0x00, 0x00, 0x00, 0x00][..])), - Err(ErrMode::Incomplete(Needed::new(3))) - ); - assert_parse!( - be_i64(Streaming(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..])), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_parse!( - be_i64(Streaming(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..])), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - } + #[test] + fn i64_tests() { + assert_parse!( + be_i64(Streaming( + &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] + )), + Ok((Streaming(&b""[..]), 0)) + ); + assert_parse!( + be_i64(Streaming( + &[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..] + )), + Ok((Streaming(&b""[..]), 9_223_372_036_854_775_807_i64)) + ); + assert_parse!( + be_i64(Streaming( + &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..] + )), + Ok((Streaming(&b""[..]), -1)) + ); + assert_parse!( + be_i64(Streaming( + &[0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] + )), + Ok((Streaming(&b""[..]), -9_223_372_036_854_775_808_i64)) + ); + assert_parse!( + be_i64(Streaming(&[][..])), + Err(ErrMode::Incomplete(Needed::new(8))) + ); + assert_parse!( + be_i64(Streaming(&[0x00][..])), + Err(ErrMode::Incomplete(Needed::new(7))) + ); + assert_parse!( + be_i64(Streaming(&[0x00, 0x00][..])), + Err(ErrMode::Incomplete(Needed::new(6))) + ); + assert_parse!( + be_i64(Streaming(&[0x00, 0x00, 0x00][..])), + Err(ErrMode::Incomplete(Needed::new(5))) + ); + assert_parse!( + be_i64(Streaming(&[0x00, 0x00, 0x00, 0x00][..])), + Err(ErrMode::Incomplete(Needed::new(4))) + ); + assert_parse!( + be_i64(Streaming(&[0x00, 0x00, 0x00, 0x00, 0x00][..])), + Err(ErrMode::Incomplete(Needed::new(3))) + ); + assert_parse!( + be_i64(Streaming(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_parse!( + be_i64(Streaming(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + } - #[test] - fn i128_tests() { - assert_parse!( - be_i128(Streaming( - &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 - ][..] - )), - Ok((Streaming(&b""[..]), 0)) - ); - assert_parse!( - be_i128(Streaming( - &[ - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff - ][..] - )), - Ok(( - Streaming(&b""[..]), - 170_141_183_460_469_231_731_687_303_715_884_105_727_i128 - )) - ); - assert_parse!( - be_i128(Streaming( - &[ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff - ][..] - )), - Ok((Streaming(&b""[..]), -1)) - ); - assert_parse!( - be_i128(Streaming( - &[ - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 - ][..] - )), - Ok(( - Streaming(&b""[..]), - -170_141_183_460_469_231_731_687_303_715_884_105_728_i128 - )) - ); - assert_parse!( - be_i128(Streaming(&[][..])), - Err(ErrMode::Incomplete(Needed::new(16))) - ); - assert_parse!( - be_i128(Streaming(&[0x00][..])), - Err(ErrMode::Incomplete(Needed::new(15))) - ); - assert_parse!( - be_i128(Streaming(&[0x00, 0x00][..])), - Err(ErrMode::Incomplete(Needed::new(14))) - ); - assert_parse!( - be_i128(Streaming(&[0x00, 0x00, 0x00][..])), - Err(ErrMode::Incomplete(Needed::new(13))) - ); - assert_parse!( - be_i128(Streaming(&[0x00, 0x00, 0x00, 0x00][..])), - Err(ErrMode::Incomplete(Needed::new(12))) - ); - assert_parse!( - be_i128(Streaming(&[0x00, 0x00, 0x00, 0x00, 0x00][..])), - Err(ErrMode::Incomplete(Needed::new(11))) - ); - assert_parse!( - be_i128(Streaming(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..])), - Err(ErrMode::Incomplete(Needed::new(10))) - ); - assert_parse!( - be_i128(Streaming(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..])), - Err(ErrMode::Incomplete(Needed::new(9))) - ); - assert_parse!( - be_i128(Streaming( - &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] - )), - Err(ErrMode::Incomplete(Needed::new(8))) - ); - assert_parse!( - be_i128(Streaming( - &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] - )), - Err(ErrMode::Incomplete(Needed::new(7))) - ); - assert_parse!( - be_i128(Streaming( - &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] - )), - Err(ErrMode::Incomplete(Needed::new(6))) - ); - assert_parse!( - be_i128(Streaming( - &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] - )), - Err(ErrMode::Incomplete(Needed::new(5))) - ); - assert_parse!( - be_i128(Streaming( - &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] - )), - Err(ErrMode::Incomplete(Needed::new(4))) - ); - assert_parse!( - be_i128(Streaming( - &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] - )), - Err(ErrMode::Incomplete(Needed::new(3))) - ); - assert_parse!( - be_i128(Streaming( - &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] - )), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_parse!( - be_i128(Streaming( - &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] - [..] - )), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - } + #[test] + fn i128_tests() { + assert_parse!( + be_i128(Streaming( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 + ][..] + )), + Ok((Streaming(&b""[..]), 0)) + ); + assert_parse!( + be_i128(Streaming( + &[ + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff + ][..] + )), + Ok(( + Streaming(&b""[..]), + 170_141_183_460_469_231_731_687_303_715_884_105_727_i128 + )) + ); + assert_parse!( + be_i128(Streaming( + &[ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff + ][..] + )), + Ok((Streaming(&b""[..]), -1)) + ); + assert_parse!( + be_i128(Streaming( + &[ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 + ][..] + )), + Ok(( + Streaming(&b""[..]), + -170_141_183_460_469_231_731_687_303_715_884_105_728_i128 + )) + ); + assert_parse!( + be_i128(Streaming(&[][..])), + Err(ErrMode::Incomplete(Needed::new(16))) + ); + assert_parse!( + be_i128(Streaming(&[0x00][..])), + Err(ErrMode::Incomplete(Needed::new(15))) + ); + assert_parse!( + be_i128(Streaming(&[0x00, 0x00][..])), + Err(ErrMode::Incomplete(Needed::new(14))) + ); + assert_parse!( + be_i128(Streaming(&[0x00, 0x00, 0x00][..])), + Err(ErrMode::Incomplete(Needed::new(13))) + ); + assert_parse!( + be_i128(Streaming(&[0x00, 0x00, 0x00, 0x00][..])), + Err(ErrMode::Incomplete(Needed::new(12))) + ); + assert_parse!( + be_i128(Streaming(&[0x00, 0x00, 0x00, 0x00, 0x00][..])), + Err(ErrMode::Incomplete(Needed::new(11))) + ); + assert_parse!( + be_i128(Streaming(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..])), + Err(ErrMode::Incomplete(Needed::new(10))) + ); + assert_parse!( + be_i128(Streaming(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..])), + Err(ErrMode::Incomplete(Needed::new(9))) + ); + assert_parse!( + be_i128(Streaming( + &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] + )), + Err(ErrMode::Incomplete(Needed::new(8))) + ); + assert_parse!( + be_i128(Streaming( + &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] + )), + Err(ErrMode::Incomplete(Needed::new(7))) + ); + assert_parse!( + be_i128(Streaming( + &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] + )), + Err(ErrMode::Incomplete(Needed::new(6))) + ); + assert_parse!( + be_i128(Streaming( + &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] + )), + Err(ErrMode::Incomplete(Needed::new(5))) + ); + assert_parse!( + be_i128(Streaming( + &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] + )), + Err(ErrMode::Incomplete(Needed::new(4))) + ); + assert_parse!( + be_i128(Streaming( + &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] + )), + Err(ErrMode::Incomplete(Needed::new(3))) + ); + assert_parse!( + be_i128(Streaming( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 + ][..] + )), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_parse!( + be_i128(Streaming( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 + ][..] + )), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + } - #[test] - fn le_i8_tests() { - assert_parse!(le_i8(Streaming(&[0x00][..])), Ok((Streaming(&b""[..]), 0))); - assert_parse!( - le_i8(Streaming(&[0x7f][..])), - Ok((Streaming(&b""[..]), 127)) - ); - assert_parse!(le_i8(Streaming(&[0xff][..])), Ok((Streaming(&b""[..]), -1))); - assert_parse!( - le_i8(Streaming(&[0x80][..])), - Ok((Streaming(&b""[..]), -128)) - ); - } + #[test] + fn le_i8_tests() { + assert_parse!(le_i8(Streaming(&[0x00][..])), Ok((Streaming(&b""[..]), 0))); + assert_parse!( + le_i8(Streaming(&[0x7f][..])), + Ok((Streaming(&b""[..]), 127)) + ); + assert_parse!(le_i8(Streaming(&[0xff][..])), Ok((Streaming(&b""[..]), -1))); + assert_parse!( + le_i8(Streaming(&[0x80][..])), + Ok((Streaming(&b""[..]), -128)) + ); + } - #[test] - fn le_i16_tests() { - assert_parse!( - le_i16(Streaming(&[0x00, 0x00][..])), - Ok((Streaming(&b""[..]), 0)) - ); - assert_parse!( - le_i16(Streaming(&[0xff, 0x7f][..])), - Ok((Streaming(&b""[..]), 32_767_i16)) - ); - assert_parse!( - le_i16(Streaming(&[0xff, 0xff][..])), - Ok((Streaming(&b""[..]), -1)) - ); - assert_parse!( - le_i16(Streaming(&[0x00, 0x80][..])), - Ok((Streaming(&b""[..]), -32_768_i16)) - ); - } + #[test] + fn le_i16_tests() { + assert_parse!( + le_i16(Streaming(&[0x00, 0x00][..])), + Ok((Streaming(&b""[..]), 0)) + ); + assert_parse!( + le_i16(Streaming(&[0xff, 0x7f][..])), + Ok((Streaming(&b""[..]), 32_767_i16)) + ); + assert_parse!( + le_i16(Streaming(&[0xff, 0xff][..])), + Ok((Streaming(&b""[..]), -1)) + ); + assert_parse!( + le_i16(Streaming(&[0x00, 0x80][..])), + Ok((Streaming(&b""[..]), -32_768_i16)) + ); + } - #[test] - fn le_u24_tests() { - assert_parse!( - le_u24(Streaming(&[0x00, 0x00, 0x00][..])), - Ok((Streaming(&b""[..]), 0)) - ); - assert_parse!( - le_u24(Streaming(&[0xFF, 0xFF, 0x00][..])), - Ok((Streaming(&b""[..]), 65_535_u32)) - ); - assert_parse!( - le_u24(Streaming(&[0x56, 0x34, 0x12][..])), - Ok((Streaming(&b""[..]), 1_193_046_u32)) - ); - } + #[test] + fn le_u24_tests() { + assert_parse!( + le_u24(Streaming(&[0x00, 0x00, 0x00][..])), + Ok((Streaming(&b""[..]), 0)) + ); + assert_parse!( + le_u24(Streaming(&[0xFF, 0xFF, 0x00][..])), + Ok((Streaming(&b""[..]), 65_535_u32)) + ); + assert_parse!( + le_u24(Streaming(&[0x56, 0x34, 0x12][..])), + Ok((Streaming(&b""[..]), 1_193_046_u32)) + ); + } - #[test] - fn le_i24_tests() { - assert_parse!( - le_i24(Streaming(&[0xFF, 0xFF, 0xFF][..])), - Ok((Streaming(&b""[..]), -1_i32)) - ); - assert_parse!( - le_i24(Streaming(&[0x00, 0x00, 0xFF][..])), - Ok((Streaming(&b""[..]), -65_536_i32)) - ); - assert_parse!( - le_i24(Streaming(&[0xAA, 0xCB, 0xED][..])), - Ok((Streaming(&b""[..]), -1_193_046_i32)) - ); - } + #[test] + fn le_i24_tests() { + assert_parse!( + le_i24(Streaming(&[0xFF, 0xFF, 0xFF][..])), + Ok((Streaming(&b""[..]), -1_i32)) + ); + assert_parse!( + le_i24(Streaming(&[0x00, 0x00, 0xFF][..])), + Ok((Streaming(&b""[..]), -65_536_i32)) + ); + assert_parse!( + le_i24(Streaming(&[0xAA, 0xCB, 0xED][..])), + Ok((Streaming(&b""[..]), -1_193_046_i32)) + ); + } - #[test] - fn le_i32_tests() { - assert_parse!( - le_i32(Streaming(&[0x00, 0x00, 0x00, 0x00][..])), - Ok((Streaming(&b""[..]), 0)) - ); - assert_parse!( - le_i32(Streaming(&[0xff, 0xff, 0xff, 0x7f][..])), - Ok((Streaming(&b""[..]), 2_147_483_647_i32)) - ); - assert_parse!( - le_i32(Streaming(&[0xff, 0xff, 0xff, 0xff][..])), - Ok((Streaming(&b""[..]), -1)) - ); - assert_parse!( - le_i32(Streaming(&[0x00, 0x00, 0x00, 0x80][..])), - Ok((Streaming(&b""[..]), -2_147_483_648_i32)) - ); - } + #[test] + fn le_i32_tests() { + assert_parse!( + le_i32(Streaming(&[0x00, 0x00, 0x00, 0x00][..])), + Ok((Streaming(&b""[..]), 0)) + ); + assert_parse!( + le_i32(Streaming(&[0xff, 0xff, 0xff, 0x7f][..])), + Ok((Streaming(&b""[..]), 2_147_483_647_i32)) + ); + assert_parse!( + le_i32(Streaming(&[0xff, 0xff, 0xff, 0xff][..])), + Ok((Streaming(&b""[..]), -1)) + ); + assert_parse!( + le_i32(Streaming(&[0x00, 0x00, 0x00, 0x80][..])), + Ok((Streaming(&b""[..]), -2_147_483_648_i32)) + ); + } - #[test] - fn le_i64_tests() { - assert_parse!( - le_i64(Streaming( - &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] - )), - Ok((Streaming(&b""[..]), 0)) - ); - assert_parse!( - le_i64(Streaming( - &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f][..] - )), - Ok((Streaming(&b""[..]), 9_223_372_036_854_775_807_i64)) - ); - assert_parse!( - le_i64(Streaming( - &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..] - )), - Ok((Streaming(&b""[..]), -1)) - ); - assert_parse!( - le_i64(Streaming( - &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80][..] - )), - Ok((Streaming(&b""[..]), -9_223_372_036_854_775_808_i64)) - ); - } + #[test] + fn le_i64_tests() { + assert_parse!( + le_i64(Streaming( + &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] + )), + Ok((Streaming(&b""[..]), 0)) + ); + assert_parse!( + le_i64(Streaming( + &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f][..] + )), + Ok((Streaming(&b""[..]), 9_223_372_036_854_775_807_i64)) + ); + assert_parse!( + le_i64(Streaming( + &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..] + )), + Ok((Streaming(&b""[..]), -1)) + ); + assert_parse!( + le_i64(Streaming( + &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80][..] + )), + Ok((Streaming(&b""[..]), -9_223_372_036_854_775_808_i64)) + ); + } - #[test] - fn le_i128_tests() { - assert_parse!( - le_i128(Streaming( - &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 - ][..] - )), - Ok((Streaming(&b""[..]), 0)) - ); - assert_parse!( - le_i128(Streaming( - &[ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x7f - ][..] - )), - Ok(( - Streaming(&b""[..]), - 170_141_183_460_469_231_731_687_303_715_884_105_727_i128 - )) - ); - assert_parse!( - le_i128(Streaming( - &[ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff - ][..] - )), - Ok((Streaming(&b""[..]), -1)) - ); - assert_parse!( - le_i128(Streaming( - &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80 - ][..] - )), - Ok(( - Streaming(&b""[..]), - -170_141_183_460_469_231_731_687_303_715_884_105_728_i128 - )) - ); - } + #[test] + fn le_i128_tests() { + assert_parse!( + le_i128(Streaming( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 + ][..] + )), + Ok((Streaming(&b""[..]), 0)) + ); + assert_parse!( + le_i128(Streaming( + &[ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f + ][..] + )), + Ok(( + Streaming(&b""[..]), + 170_141_183_460_469_231_731_687_303_715_884_105_727_i128 + )) + ); + assert_parse!( + le_i128(Streaming( + &[ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff + ][..] + )), + Ok((Streaming(&b""[..]), -1)) + ); + assert_parse!( + le_i128(Streaming( + &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80 + ][..] + )), + Ok(( + Streaming(&b""[..]), + -170_141_183_460_469_231_731_687_303_715_884_105_728_i128 + )) + ); + } - #[test] - fn be_f32_tests() { - assert_parse!( - be_f32(Streaming(&[0x00, 0x00, 0x00, 0x00][..])), - Ok((Streaming(&b""[..]), 0_f32)) - ); - assert_parse!( - be_f32(Streaming(&[0x4d, 0x31, 0x1f, 0xd8][..])), - Ok((Streaming(&b""[..]), 185_728_380_f32)) - ); - } + #[test] + fn be_f32_tests() { + assert_parse!( + be_f32(Streaming(&[0x00, 0x00, 0x00, 0x00][..])), + Ok((Streaming(&b""[..]), 0_f32)) + ); + assert_parse!( + be_f32(Streaming(&[0x4d, 0x31, 0x1f, 0xd8][..])), + Ok((Streaming(&b""[..]), 185_728_380_f32)) + ); + } - #[test] - fn be_f64_tests() { - assert_parse!( - be_f64(Streaming( - &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] - )), - Ok((Streaming(&b""[..]), 0_f64)) - ); - assert_parse!( - be_f64(Streaming( - &[0x41, 0xa6, 0x23, 0xfb, 0x10, 0x00, 0x00, 0x00][..] - )), - Ok((Streaming(&b""[..]), 185_728_392_f64)) - ); - } + #[test] + fn be_f64_tests() { + assert_parse!( + be_f64(Streaming( + &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] + )), + Ok((Streaming(&b""[..]), 0_f64)) + ); + assert_parse!( + be_f64(Streaming( + &[0x41, 0xa6, 0x23, 0xfb, 0x10, 0x00, 0x00, 0x00][..] + )), + Ok((Streaming(&b""[..]), 185_728_392_f64)) + ); + } - #[test] - fn le_f32_tests() { - assert_parse!( - le_f32(Streaming(&[0x00, 0x00, 0x00, 0x00][..])), - Ok((Streaming(&b""[..]), 0_f32)) - ); - assert_parse!( - le_f32(Streaming(&[0xd8, 0x1f, 0x31, 0x4d][..])), - Ok((Streaming(&b""[..]), 185_728_380_f32)) - ); - } + #[test] + fn le_f32_tests() { + assert_parse!( + le_f32(Streaming(&[0x00, 0x00, 0x00, 0x00][..])), + Ok((Streaming(&b""[..]), 0_f32)) + ); + assert_parse!( + le_f32(Streaming(&[0xd8, 0x1f, 0x31, 0x4d][..])), + Ok((Streaming(&b""[..]), 185_728_380_f32)) + ); + } - #[test] - fn le_f64_tests() { - assert_parse!( - le_f64(Streaming( - &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] - )), - Ok((Streaming(&b""[..]), 0_f64)) - ); - assert_parse!( - le_f64(Streaming( - &[0x00, 0x00, 0x00, 0x10, 0xfb, 0x23, 0xa6, 0x41][..] - )), - Ok((Streaming(&b""[..]), 185_728_392_f64)) - ); - } + #[test] + fn le_f64_tests() { + assert_parse!( + le_f64(Streaming( + &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..] + )), + Ok((Streaming(&b""[..]), 0_f64)) + ); + assert_parse!( + le_f64(Streaming( + &[0x00, 0x00, 0x00, 0x10, 0xfb, 0x23, 0xa6, 0x41][..] + )), + Ok((Streaming(&b""[..]), 185_728_392_f64)) + ); + } - #[test] - fn configurable_endianness() { - use crate::number::Endianness; + #[test] + fn configurable_endianness() { + use crate::number::Endianness; - fn be_tst16(i: Streaming<&[u8]>) -> IResult, u16> { - u16(Endianness::Big)(i) - } - fn le_tst16(i: Streaming<&[u8]>) -> IResult, u16> { - u16(Endianness::Little)(i) - } - assert_eq!( - be_tst16(Streaming(&[0x80, 0x00])), - Ok((Streaming(&b""[..]), 32_768_u16)) - ); - assert_eq!( - le_tst16(Streaming(&[0x80, 0x00])), - Ok((Streaming(&b""[..]), 128_u16)) - ); + fn be_tst16(i: Streaming<&[u8]>) -> IResult, u16> { + u16(Endianness::Big)(i) + } + fn le_tst16(i: Streaming<&[u8]>) -> IResult, u16> { + u16(Endianness::Little)(i) + } + assert_eq!( + be_tst16(Streaming(&[0x80, 0x00])), + Ok((Streaming(&b""[..]), 32_768_u16)) + ); + assert_eq!( + le_tst16(Streaming(&[0x80, 0x00])), + Ok((Streaming(&b""[..]), 128_u16)) + ); - fn be_tst32(i: Streaming<&[u8]>) -> IResult, u32> { - u32(Endianness::Big)(i) - } - fn le_tst32(i: Streaming<&[u8]>) -> IResult, u32> { - u32(Endianness::Little)(i) - } - assert_eq!( - be_tst32(Streaming(&[0x12, 0x00, 0x60, 0x00])), - Ok((Streaming(&b""[..]), 302_014_464_u32)) - ); - assert_eq!( - le_tst32(Streaming(&[0x12, 0x00, 0x60, 0x00])), - Ok((Streaming(&b""[..]), 6_291_474_u32)) - ); + fn be_tst32(i: Streaming<&[u8]>) -> IResult, u32> { + u32(Endianness::Big)(i) + } + fn le_tst32(i: Streaming<&[u8]>) -> IResult, u32> { + u32(Endianness::Little)(i) + } + assert_eq!( + be_tst32(Streaming(&[0x12, 0x00, 0x60, 0x00])), + Ok((Streaming(&b""[..]), 302_014_464_u32)) + ); + assert_eq!( + le_tst32(Streaming(&[0x12, 0x00, 0x60, 0x00])), + Ok((Streaming(&b""[..]), 6_291_474_u32)) + ); - fn be_tst64(i: Streaming<&[u8]>) -> IResult, u64> { - u64(Endianness::Big)(i) - } - fn le_tst64(i: Streaming<&[u8]>) -> IResult, u64> { - u64(Endianness::Little)(i) - } - assert_eq!( - be_tst64(Streaming(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00])), - Ok((Streaming(&b""[..]), 1_297_142_246_100_992_000_u64)) - ); - assert_eq!( - le_tst64(Streaming(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00])), - Ok((Streaming(&b""[..]), 36_028_874_334_666_770_u64)) - ); + fn be_tst64(i: Streaming<&[u8]>) -> IResult, u64> { + u64(Endianness::Big)(i) + } + fn le_tst64(i: Streaming<&[u8]>) -> IResult, u64> { + u64(Endianness::Little)(i) + } + assert_eq!( + be_tst64(Streaming(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00])), + Ok((Streaming(&b""[..]), 1_297_142_246_100_992_000_u64)) + ); + assert_eq!( + le_tst64(Streaming(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00])), + Ok((Streaming(&b""[..]), 36_028_874_334_666_770_u64)) + ); - fn be_tsti16(i: Streaming<&[u8]>) -> IResult, i16> { - i16(Endianness::Big)(i) - } - fn le_tsti16(i: Streaming<&[u8]>) -> IResult, i16> { - i16(Endianness::Little)(i) - } - assert_eq!( - be_tsti16(Streaming(&[0x00, 0x80])), - Ok((Streaming(&b""[..]), 128_i16)) - ); - assert_eq!( - le_tsti16(Streaming(&[0x00, 0x80])), - Ok((Streaming(&b""[..]), -32_768_i16)) - ); + fn be_tsti16(i: Streaming<&[u8]>) -> IResult, i16> { + i16(Endianness::Big)(i) + } + fn le_tsti16(i: Streaming<&[u8]>) -> IResult, i16> { + i16(Endianness::Little)(i) + } + assert_eq!( + be_tsti16(Streaming(&[0x00, 0x80])), + Ok((Streaming(&b""[..]), 128_i16)) + ); + assert_eq!( + le_tsti16(Streaming(&[0x00, 0x80])), + Ok((Streaming(&b""[..]), -32_768_i16)) + ); - fn be_tsti32(i: Streaming<&[u8]>) -> IResult, i32> { - i32(Endianness::Big)(i) - } - fn le_tsti32(i: Streaming<&[u8]>) -> IResult, i32> { - i32(Endianness::Little)(i) - } - assert_eq!( - be_tsti32(Streaming(&[0x00, 0x12, 0x60, 0x00])), - Ok((Streaming(&b""[..]), 1_204_224_i32)) - ); - assert_eq!( - le_tsti32(Streaming(&[0x00, 0x12, 0x60, 0x00])), - Ok((Streaming(&b""[..]), 6_296_064_i32)) - ); + fn be_tsti32(i: Streaming<&[u8]>) -> IResult, i32> { + i32(Endianness::Big)(i) + } + fn le_tsti32(i: Streaming<&[u8]>) -> IResult, i32> { + i32(Endianness::Little)(i) + } + assert_eq!( + be_tsti32(Streaming(&[0x00, 0x12, 0x60, 0x00])), + Ok((Streaming(&b""[..]), 1_204_224_i32)) + ); + assert_eq!( + le_tsti32(Streaming(&[0x00, 0x12, 0x60, 0x00])), + Ok((Streaming(&b""[..]), 6_296_064_i32)) + ); - fn be_tsti64(i: Streaming<&[u8]>) -> IResult, i64> { - i64(Endianness::Big)(i) - } - fn le_tsti64(i: Streaming<&[u8]>) -> IResult, i64> { - i64(Endianness::Little)(i) + fn be_tsti64(i: Streaming<&[u8]>) -> IResult, i64> { + i64(Endianness::Big)(i) + } + fn le_tsti64(i: Streaming<&[u8]>) -> IResult, i64> { + i64(Endianness::Little)(i) + } + assert_eq!( + be_tsti64(Streaming(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00])), + Ok((Streaming(&b""[..]), 71_881_672_479_506_432_i64)) + ); + assert_eq!( + le_tsti64(Streaming(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00])), + Ok((Streaming(&b""[..]), 36_028_874_334_732_032_i64)) + ); } - assert_eq!( - be_tsti64(Streaming(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00])), - Ok((Streaming(&b""[..]), 71_881_672_479_506_432_i64)) - ); - assert_eq!( - le_tsti64(Streaming(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00])), - Ok((Streaming(&b""[..]), 36_028_874_334_732_032_i64)) - ); - } } diff --git a/src/parser.rs b/src/parser.rs index fd491186..63912881 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -39,579 +39,579 @@ use crate::input::{AsChar, Compare, Input, InputIsStreaming, Location}; /// - `u8` and `char`, see [`winnow::character::char`][crate::bytes::one_of] /// - `&[u8]` and `&str`, see [`winnow::character::char`][crate::bytes::tag] pub trait Parser { - /// A parser takes in input type, and returns a `Result` containing - /// either the remaining input and the output value, or an error - #[deprecated(since = "0.3.0", note = "Replaced with `Parser::parse_next`")] - fn parse(&mut self, input: I) -> IResult { - self.parse_next(input) - } - - /// A parser takes in input type, and returns a `Result` containing - /// either the remaining input and the output value, or an error - fn parse_next(&mut self, input: I) -> IResult; - - /// Treat `&mut Self` as a parser - /// - /// This helps when needing to move a `Parser` when all you have is a `&mut Parser`. - /// - /// # Example - /// - /// Because parsers are `FnMut`, they can be called multiple times. This prevents moving `f` - /// into [`length_data`][crate::multi::length_data] and `g` into - /// [`complete`][Parser::complete]: - /// ```rust,compile_fail - /// # use winnow::prelude::*; - /// # use winnow::IResult; - /// # use winnow::Parser; - /// # use winnow::error::ParseError; - /// # use winnow::multi::length_data; - /// pub fn length_value<'i, O, E: ParseError<&'i [u8]>>( - /// mut f: impl Parser<&'i [u8], usize, E>, - /// mut g: impl Parser<&'i [u8], O, E> - /// ) -> impl FnMut(&'i [u8]) -> IResult<&'i [u8], O, E> { - /// move |i: &'i [u8]| { - /// let (i, data) = length_data(f).parse_next(i)?; - /// let (_, o) = g.complete().parse_next(data)?; - /// Ok((i, o)) - /// } - /// } - /// ``` - /// - /// By adding `by_ref`, we can make this work: - /// ```rust - /// # use winnow::prelude::*; - /// # use winnow::IResult; - /// # use winnow::Parser; - /// # use winnow::error::ParseError; - /// # use winnow::multi::length_data; - /// pub fn length_value<'i, O, E: ParseError<&'i [u8]>>( - /// mut f: impl Parser<&'i [u8], usize, E>, - /// mut g: impl Parser<&'i [u8], O, E> - /// ) -> impl FnMut(&'i [u8]) -> IResult<&'i [u8], O, E> { - /// move |i: &'i [u8]| { - /// let (i, data) = length_data(f.by_ref()).parse_next(i)?; - /// let (_, o) = g.by_ref().complete().parse_next(data)?; - /// Ok((i, o)) - /// } - /// } - /// ``` - fn by_ref(&mut self) -> ByRef<'_, Self> - where - Self: core::marker::Sized, - { - ByRef::new(self) - } - - /// Returns the provided value if the child parser succeeds. - /// - /// # Example - /// - /// ```rust - /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult, Parser}; - /// use winnow::character::alpha1; - /// # fn main() { - /// - /// let mut parser = alpha1.value(1234); - /// - /// assert_eq!(parser.parse_next("abcd"), Ok(("", 1234))); - /// assert_eq!(parser.parse_next("123abcd;"), Err(ErrMode::Backtrack(Error::new("123abcd;", ErrorKind::Alpha)))); - /// # } - /// ``` - fn value(self, val: O2) -> Value - where - Self: core::marker::Sized, - O2: Clone, - { - Value::new(self, val) - } - - /// Discards the output of the `Parser` - /// - /// # Example - /// - /// ```rust - /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult, Parser}; - /// use winnow::character::alpha1; - /// # fn main() { - /// - /// let mut parser = alpha1.void(); - /// - /// assert_eq!(parser.parse_next("abcd"), Ok(("", ()))); - /// assert_eq!(parser.parse_next("123abcd;"), Err(ErrMode::Backtrack(Error::new("123abcd;", ErrorKind::Alpha)))); - /// # } - /// ``` - fn void(self) -> Void - where - Self: core::marker::Sized, - { - Void::new(self) - } - - /// Convert the parser's output to another type using [`std::convert::From`] - /// - /// # Example - /// - /// ```rust - /// # use winnow::IResult; - /// # use winnow::Parser; - /// use winnow::character::alpha1; - /// # fn main() { - /// - /// fn parser1(i: &str) -> IResult<&str, &str> { - /// alpha1(i) - /// } - /// - /// let mut parser2 = parser1.output_into(); - /// - /// // the parser converts the &str output of the child parser into a Vec - /// let bytes: IResult<&str, Vec> = parser2.parse_next("abcd"); - /// assert_eq!(bytes, Ok(("", vec![97, 98, 99, 100]))); - /// # } - /// ``` - fn output_into(self) -> OutputInto - where - Self: core::marker::Sized, - O: Into, - { - OutputInto::new(self) - } - - /// If the child parser was successful, return the consumed input as produced value. - /// - /// # Example - /// - /// ```rust - /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult, Parser}; - /// use winnow::character::{alpha1}; - /// use winnow::sequence::separated_pair; - /// # fn main() { - /// - /// let mut parser = separated_pair(alpha1, ',', alpha1).recognize(); - /// - /// assert_eq!(parser.parse_next("abcd,efgh"), Ok(("", "abcd,efgh"))); - /// assert_eq!(parser.parse_next("abcd;"),Err(ErrMode::Backtrack(Error::new(";", ErrorKind::OneOf)))); - /// # } - /// ``` - fn recognize(self) -> Recognize - where - Self: core::marker::Sized, - { - Recognize::new(self) - } - - /// if the child parser was successful, return the consumed input with the output - /// as a tuple. Functions similarly to [recognize](fn.recognize.html) except it - /// returns the parser output as well. - /// - /// This can be useful especially in cases where the output is not the same type - /// as the input, or the input is a user defined type. - /// - /// Returned tuple is of the format `(produced output, consumed input)`. - /// - /// # Example - /// - /// ```rust - /// # use winnow::prelude::*; - /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult}; - /// use winnow::character::{alpha1}; - /// use winnow::bytes::tag; - /// use winnow::sequence::separated_pair; - /// - /// fn inner_parser(input: &str) -> IResult<&str, bool> { - /// tag("1234").value(true).parse_next(input) - /// } - /// - /// # fn main() { - /// - /// let mut consumed_parser = separated_pair(alpha1, ',', alpha1).value(true).with_recognized(); - /// - /// assert_eq!(consumed_parser.parse_next("abcd,efgh1"), Ok(("1", (true, "abcd,efgh")))); - /// assert_eq!(consumed_parser.parse_next("abcd;"),Err(ErrMode::Backtrack(Error::new(";", ErrorKind::OneOf)))); - /// - /// // the second output (representing the consumed input) - /// // should be the same as that of the `recognize` parser. - /// let mut recognize_parser = inner_parser.recognize(); - /// let mut consumed_parser = inner_parser.with_recognized().map(|(output, consumed)| consumed); - /// - /// assert_eq!(recognize_parser.parse_next("1234"), consumed_parser.parse_next("1234")); - /// assert_eq!(recognize_parser.parse_next("abcd"), consumed_parser.parse_next("abcd")); - /// # } - /// ``` - fn with_recognized(self) -> WithRecognized - where - Self: core::marker::Sized, - { - WithRecognized::new(self) - } - - /// If the child parser was successful, return the location of the consumed input as produced value. - /// - /// # Example - /// - /// ```rust - /// # use winnow::prelude::*; - /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, input::Input}; - /// use winnow::input::Located; - /// use winnow::character::alpha1; - /// use winnow::sequence::separated_pair; - /// - /// let mut parser = separated_pair(alpha1.span(), ',', alpha1.span()); - /// - /// assert_eq!(parser.parse_next(Located::new("abcd,efgh")).finish(), Ok((0..4, 5..9))); - /// assert_eq!(parser.parse_next(Located::new("abcd;")),Err(ErrMode::Backtrack(Error::new(Located::new("abcd;").next_slice(4).0, ErrorKind::OneOf)))); - /// ``` - fn span(self) -> Span - where - Self: core::marker::Sized, - I: Location + Clone, - { - Span::new(self) - } - - /// if the child parser was successful, return the location of consumed input with the output - /// as a tuple. Functions similarly to [`Parser::span`] except it - /// returns the parser output as well. - /// - /// This can be useful especially in cases where the output is not the same type - /// as the input, or the input is a user defined type. - /// - /// Returned tuple is of the format `(produced output, consumed input)`. - /// - /// # Example - /// - /// ```rust - /// # use winnow::prelude::*; - /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult, input::Input}; - /// use winnow::input::Located; - /// use winnow::character::alpha1; - /// use winnow::bytes::tag; - /// use winnow::sequence::separated_pair; - /// - /// fn inner_parser(input: Located<&str>) -> IResult, bool> { - /// tag("1234").value(true).parse_next(input) - /// } - /// - /// # fn main() { - /// - /// let mut consumed_parser = separated_pair(alpha1.value(1).with_span(), ',', alpha1.value(2).with_span()); - /// - /// assert_eq!(consumed_parser.parse_next(Located::new("abcd,efgh")).finish(), Ok(((1, 0..4), (2, 5..9)))); - /// assert_eq!(consumed_parser.parse_next(Located::new("abcd;")),Err(ErrMode::Backtrack(Error::new(Located::new("abcd;").next_slice(4).0, ErrorKind::OneOf)))); - /// - /// // the second output (representing the consumed input) - /// // should be the same as that of the `span` parser. - /// let mut recognize_parser = inner_parser.span(); - /// let mut consumed_parser = inner_parser.with_span().map(|(output, consumed)| consumed); - /// - /// assert_eq!(recognize_parser.parse_next(Located::new("1234")), consumed_parser.parse_next(Located::new("1234"))); - /// assert_eq!(recognize_parser.parse_next(Located::new("abcd")), consumed_parser.parse_next(Located::new("abcd"))); - /// # } - /// ``` - fn with_span(self) -> WithSpan - where - Self: core::marker::Sized, - I: Location + Clone, - { - WithSpan::new(self) - } - - /// Maps a function over the result of a parser - /// - /// # Example - /// - /// ```rust - /// use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult,Parser}; - /// use winnow::character::digit1; - /// # fn main() { - /// - /// let mut parser = digit1.map(|s: &str| s.len()); - /// - /// // the parser will count how many characters were returned by digit1 - /// assert_eq!(parser.parse_next("123456"), Ok(("", 6))); - /// - /// // this will fail if digit1 fails - /// assert_eq!(parser.parse_next("abc"), Err(ErrMode::Backtrack(Error::new("abc", ErrorKind::Digit)))); - /// # } - /// ``` - fn map(self, g: G) -> Map - where - G: Fn(O) -> O2, - Self: core::marker::Sized, - { - Map::new(self, g) - } - - /// Applies a function returning a `Result` over the result of a parser. - /// - /// # Example - /// - /// ```rust - /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult, Parser}; - /// use winnow::character::digit1; - /// # fn main() { - /// - /// let mut parse = digit1.map_res(|s: &str| s.parse::()); - /// - /// // the parser will convert the result of digit1 to a number - /// assert_eq!(parse.parse_next("123"), Ok(("", 123))); - /// - /// // this will fail if digit1 fails - /// assert_eq!(parse.parse_next("abc"), Err(ErrMode::Backtrack(Error::new("abc", ErrorKind::Digit)))); - /// - /// // this will fail if the mapped function fails (a `u8` is too small to hold `123456`) - /// assert_eq!(parse.parse_next("123456"), Err(ErrMode::Backtrack(Error::new("123456", ErrorKind::MapRes)))); - /// # } - /// ``` - fn map_res(self, g: G) -> MapRes - where - Self: core::marker::Sized, - G: FnMut(O) -> Result, - { - MapRes::new(self, g) - } - - /// Applies a function returning an `Option` over the result of a parser. - /// - /// # Example - /// - /// ```rust - /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult, Parser}; - /// use winnow::character::digit1; - /// # fn main() { - /// - /// let mut parse = digit1.map_opt(|s: &str| s.parse::().ok()); - /// - /// // the parser will convert the result of digit1 to a number - /// assert_eq!(parse.parse_next("123"), Ok(("", 123))); - /// - /// // this will fail if digit1 fails - /// assert_eq!(parse.parse_next("abc"), Err(ErrMode::Backtrack(Error::new("abc", ErrorKind::Digit)))); - /// - /// // this will fail if the mapped function fails (a `u8` is too small to hold `123456`) - /// assert_eq!(parse.parse_next("123456"), Err(ErrMode::Backtrack(Error::new("123456", ErrorKind::MapOpt)))); - /// # } - /// ``` - fn map_opt(self, g: G) -> MapOpt - where - Self: core::marker::Sized, - G: FnMut(O) -> Option, - { - MapOpt::new(self, g) - } - - /// Creates a second parser from the output of the first one, then apply over the rest of the input - /// - /// # Example - /// - /// ```rust - /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult, Parser}; - /// use winnow::bytes::take; - /// use winnow::number::u8; - /// # fn main() { - /// - /// let mut length_data = u8.flat_map(take); - /// - /// assert_eq!(length_data.parse_next(&[2, 0, 1, 2][..]), Ok((&[2][..], &[0, 1][..]))); - /// assert_eq!(length_data.parse_next(&[4, 0, 1, 2][..]), Err(ErrMode::Backtrack(Error::new(&[0, 1, 2][..], ErrorKind::Eof)))); - /// # } - /// ``` - fn flat_map(self, g: G) -> FlatMap - where - G: FnMut(O) -> H, - H: Parser, - Self: core::marker::Sized, - { - FlatMap::new(self, g) - } - - /// Applies a second parser over the output of the first one - /// - /// # Example - /// - /// ```rust - /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult, Parser}; - /// use winnow::character::digit1; - /// use winnow::bytes::take; - /// # fn main() { - /// - /// let mut digits = take(5u8).and_then(digit1); - /// - /// assert_eq!(digits.parse_next("12345"), Ok(("", "12345"))); - /// assert_eq!(digits.parse_next("123ab"), Ok(("", "123"))); - /// assert_eq!(digits.parse_next("123"), Err(ErrMode::Backtrack(Error::new("123", ErrorKind::Eof)))); - /// # } - /// ``` - fn and_then(self, g: G) -> AndThen - where - G: Parser, - Self: core::marker::Sized, - { - AndThen::new(self, g) - } - - /// Apply [`std::str::FromStr`] to the output of the parser - /// - /// # Example - /// - /// ```rust - /// # use winnow::prelude::*; - /// use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult,Parser}; - /// use winnow::character::digit1; - /// - /// fn parser(input: &str) -> IResult<&str, u64> { - /// digit1.parse_to().parse_next(input) - /// } - /// - /// // the parser will count how many characters were returned by digit1 - /// assert_eq!(parser.parse_next("123456"), Ok(("", 123456))); - /// - /// // this will fail if digit1 fails - /// assert_eq!(parser.parse_next("abc"), Err(ErrMode::Backtrack(Error::new("abc", ErrorKind::Digit)))); - /// ``` - fn parse_to(self) -> ParseTo - where - Self: core::marker::Sized, - O: crate::input::ParseSlice, - { - ParseTo::new(self) - } - - /// Returns the result of the child parser if it satisfies a verification function. - /// - /// The verification function takes as argument a reference to the output of the - /// parser. - /// - /// # Example - /// - /// ```rust - /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult, Parser}; - /// # use winnow::character::alpha1; - /// # fn main() { - /// - /// let mut parser = alpha1.verify(|s: &str| s.len() == 4); - /// - /// assert_eq!(parser.parse_next("abcd"), Ok(("", "abcd"))); - /// assert_eq!(parser.parse_next("abcde"), Err(ErrMode::Backtrack(Error::new("abcde", ErrorKind::Verify)))); - /// assert_eq!(parser.parse_next("123abcd;"),Err(ErrMode::Backtrack(Error::new("123abcd;", ErrorKind::Alpha)))); - /// # } - /// ``` - fn verify(self, second: G) -> Verify - where - Self: core::marker::Sized, - G: Fn(&O2) -> bool, - { - Verify::new(self, second) - } - - /// If parsing fails, add context to the error - /// - /// This is used mainly to add user friendly information - /// to errors when backtracking through a parse tree. - fn context(self, context: C) -> Context - where - Self: core::marker::Sized, - C: Clone, - E: ContextError, - { - Context::new(self, context) - } - - /// Transforms [`Incomplete`][crate::error::ErrMode::Incomplete] into [`Error`][crate::error::ErrMode::Backtrack] - /// - /// # Example - /// - /// ```rust - /// # use winnow::{error::ErrMode, error::ErrorKind, error::Error, IResult, input::Streaming, Parser}; - /// # use winnow::bytes::take; - /// # fn main() { - /// - /// let mut parser = take(5u8).complete(); - /// - /// assert_eq!(parser.parse_next(Streaming("abcdefg")), Ok((Streaming("fg"), "abcde"))); - /// assert_eq!(parser.parse_next(Streaming("abcd")), Err(ErrMode::Backtrack(Error::new(Streaming("abcd"), ErrorKind::Complete)))); - /// # } - /// ``` - fn complete(self) -> Complete - where - Self: core::marker::Sized, - { - Complete::new(self) - } - - /// Convert the parser's error to another type using [`std::convert::From`] - fn err_into(self) -> ErrInto - where - Self: core::marker::Sized, - E: Into, - { - ErrInto::new(self) - } - - /// Prints a message and the input if the parser fails. - /// - /// The message prints the `Error` or `Incomplete` - /// and the parser's calling kind. - /// - /// It also displays the input in hexdump format - /// - /// ```rust - /// use winnow::prelude::*; - /// use winnow::{IResult, bytes::tag}; - /// - /// fn f(i: &[u8]) -> IResult<&[u8], &[u8]> { - /// tag("abcd").dbg_err("alpha tag").parse_next(i) - /// } - /// - /// let a = &b"efghijkl"[..]; - /// f(a); - /// ``` - /// - /// Will print the following message: - /// ```console - /// alpha tag: Error(Position(0, [101, 102, 103, 104, 105, 106, 107, 108])) at: - /// 00000000 65 66 67 68 69 6a 6b 6c efghijkl - /// ``` - #[cfg(feature = "std")] - fn dbg_err(self, context: C) -> DbgErr - where - C: std::fmt::Display, - Self: core::marker::Sized, - { - DbgErr::new(self, context) - } - - /// Applies a second parser after the first one, return their results as a tuple - /// - /// **WARNING:** Deprecated, replaced with [`winnow::sequence::tuple`][crate::sequence::tuple] - #[deprecated(since = "0.1.0", note = "Replaced with `winnow::sequence::tuple")] - fn and(self, g: G) -> And - where - G: Parser, - Self: core::marker::Sized, - { - And::new(self, g) - } - - /// Applies a second parser over the input if the first one failed - /// - /// **WARNING:** Deprecated, replaced with [`winnow::branch::alt`][crate::branch::alt] - #[deprecated(since = "0.1.0", note = "Replaced with `winnow::branch::alt")] - fn or(self, g: G) -> Or - where - G: Parser, - Self: core::marker::Sized, - { - Or::new(self, g) - } + /// A parser takes in input type, and returns a `Result` containing + /// either the remaining input and the output value, or an error + #[deprecated(since = "0.3.0", note = "Replaced with `Parser::parse_next`")] + fn parse(&mut self, input: I) -> IResult { + self.parse_next(input) + } + + /// A parser takes in input type, and returns a `Result` containing + /// either the remaining input and the output value, or an error + fn parse_next(&mut self, input: I) -> IResult; + + /// Treat `&mut Self` as a parser + /// + /// This helps when needing to move a `Parser` when all you have is a `&mut Parser`. + /// + /// # Example + /// + /// Because parsers are `FnMut`, they can be called multiple times. This prevents moving `f` + /// into [`length_data`][crate::multi::length_data] and `g` into + /// [`complete`][Parser::complete]: + /// ```rust,compile_fail + /// # use winnow::prelude::*; + /// # use winnow::IResult; + /// # use winnow::Parser; + /// # use winnow::error::ParseError; + /// # use winnow::multi::length_data; + /// pub fn length_value<'i, O, E: ParseError<&'i [u8]>>( + /// mut f: impl Parser<&'i [u8], usize, E>, + /// mut g: impl Parser<&'i [u8], O, E> + /// ) -> impl FnMut(&'i [u8]) -> IResult<&'i [u8], O, E> { + /// move |i: &'i [u8]| { + /// let (i, data) = length_data(f).parse_next(i)?; + /// let (_, o) = g.complete().parse_next(data)?; + /// Ok((i, o)) + /// } + /// } + /// ``` + /// + /// By adding `by_ref`, we can make this work: + /// ```rust + /// # use winnow::prelude::*; + /// # use winnow::IResult; + /// # use winnow::Parser; + /// # use winnow::error::ParseError; + /// # use winnow::multi::length_data; + /// pub fn length_value<'i, O, E: ParseError<&'i [u8]>>( + /// mut f: impl Parser<&'i [u8], usize, E>, + /// mut g: impl Parser<&'i [u8], O, E> + /// ) -> impl FnMut(&'i [u8]) -> IResult<&'i [u8], O, E> { + /// move |i: &'i [u8]| { + /// let (i, data) = length_data(f.by_ref()).parse_next(i)?; + /// let (_, o) = g.by_ref().complete().parse_next(data)?; + /// Ok((i, o)) + /// } + /// } + /// ``` + fn by_ref(&mut self) -> ByRef<'_, Self> + where + Self: core::marker::Sized, + { + ByRef::new(self) + } + + /// Returns the provided value if the child parser succeeds. + /// + /// # Example + /// + /// ```rust + /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult, Parser}; + /// use winnow::character::alpha1; + /// # fn main() { + /// + /// let mut parser = alpha1.value(1234); + /// + /// assert_eq!(parser.parse_next("abcd"), Ok(("", 1234))); + /// assert_eq!(parser.parse_next("123abcd;"), Err(ErrMode::Backtrack(Error::new("123abcd;", ErrorKind::Alpha)))); + /// # } + /// ``` + fn value(self, val: O2) -> Value + where + Self: core::marker::Sized, + O2: Clone, + { + Value::new(self, val) + } + + /// Discards the output of the `Parser` + /// + /// # Example + /// + /// ```rust + /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult, Parser}; + /// use winnow::character::alpha1; + /// # fn main() { + /// + /// let mut parser = alpha1.void(); + /// + /// assert_eq!(parser.parse_next("abcd"), Ok(("", ()))); + /// assert_eq!(parser.parse_next("123abcd;"), Err(ErrMode::Backtrack(Error::new("123abcd;", ErrorKind::Alpha)))); + /// # } + /// ``` + fn void(self) -> Void + where + Self: core::marker::Sized, + { + Void::new(self) + } + + /// Convert the parser's output to another type using [`std::convert::From`] + /// + /// # Example + /// + /// ```rust + /// # use winnow::IResult; + /// # use winnow::Parser; + /// use winnow::character::alpha1; + /// # fn main() { + /// + /// fn parser1(i: &str) -> IResult<&str, &str> { + /// alpha1(i) + /// } + /// + /// let mut parser2 = parser1.output_into(); + /// + /// // the parser converts the &str output of the child parser into a Vec + /// let bytes: IResult<&str, Vec> = parser2.parse_next("abcd"); + /// assert_eq!(bytes, Ok(("", vec![97, 98, 99, 100]))); + /// # } + /// ``` + fn output_into(self) -> OutputInto + where + Self: core::marker::Sized, + O: Into, + { + OutputInto::new(self) + } + + /// If the child parser was successful, return the consumed input as produced value. + /// + /// # Example + /// + /// ```rust + /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult, Parser}; + /// use winnow::character::{alpha1}; + /// use winnow::sequence::separated_pair; + /// # fn main() { + /// + /// let mut parser = separated_pair(alpha1, ',', alpha1).recognize(); + /// + /// assert_eq!(parser.parse_next("abcd,efgh"), Ok(("", "abcd,efgh"))); + /// assert_eq!(parser.parse_next("abcd;"),Err(ErrMode::Backtrack(Error::new(";", ErrorKind::OneOf)))); + /// # } + /// ``` + fn recognize(self) -> Recognize + where + Self: core::marker::Sized, + { + Recognize::new(self) + } + + /// if the child parser was successful, return the consumed input with the output + /// as a tuple. Functions similarly to [recognize](fn.recognize.html) except it + /// returns the parser output as well. + /// + /// This can be useful especially in cases where the output is not the same type + /// as the input, or the input is a user defined type. + /// + /// Returned tuple is of the format `(produced output, consumed input)`. + /// + /// # Example + /// + /// ```rust + /// # use winnow::prelude::*; + /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult}; + /// use winnow::character::{alpha1}; + /// use winnow::bytes::tag; + /// use winnow::sequence::separated_pair; + /// + /// fn inner_parser(input: &str) -> IResult<&str, bool> { + /// tag("1234").value(true).parse_next(input) + /// } + /// + /// # fn main() { + /// + /// let mut consumed_parser = separated_pair(alpha1, ',', alpha1).value(true).with_recognized(); + /// + /// assert_eq!(consumed_parser.parse_next("abcd,efgh1"), Ok(("1", (true, "abcd,efgh")))); + /// assert_eq!(consumed_parser.parse_next("abcd;"),Err(ErrMode::Backtrack(Error::new(";", ErrorKind::OneOf)))); + /// + /// // the second output (representing the consumed input) + /// // should be the same as that of the `recognize` parser. + /// let mut recognize_parser = inner_parser.recognize(); + /// let mut consumed_parser = inner_parser.with_recognized().map(|(output, consumed)| consumed); + /// + /// assert_eq!(recognize_parser.parse_next("1234"), consumed_parser.parse_next("1234")); + /// assert_eq!(recognize_parser.parse_next("abcd"), consumed_parser.parse_next("abcd")); + /// # } + /// ``` + fn with_recognized(self) -> WithRecognized + where + Self: core::marker::Sized, + { + WithRecognized::new(self) + } + + /// If the child parser was successful, return the location of the consumed input as produced value. + /// + /// # Example + /// + /// ```rust + /// # use winnow::prelude::*; + /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, input::Input}; + /// use winnow::input::Located; + /// use winnow::character::alpha1; + /// use winnow::sequence::separated_pair; + /// + /// let mut parser = separated_pair(alpha1.span(), ',', alpha1.span()); + /// + /// assert_eq!(parser.parse_next(Located::new("abcd,efgh")).finish(), Ok((0..4, 5..9))); + /// assert_eq!(parser.parse_next(Located::new("abcd;")),Err(ErrMode::Backtrack(Error::new(Located::new("abcd;").next_slice(4).0, ErrorKind::OneOf)))); + /// ``` + fn span(self) -> Span + where + Self: core::marker::Sized, + I: Location + Clone, + { + Span::new(self) + } + + /// if the child parser was successful, return the location of consumed input with the output + /// as a tuple. Functions similarly to [`Parser::span`] except it + /// returns the parser output as well. + /// + /// This can be useful especially in cases where the output is not the same type + /// as the input, or the input is a user defined type. + /// + /// Returned tuple is of the format `(produced output, consumed input)`. + /// + /// # Example + /// + /// ```rust + /// # use winnow::prelude::*; + /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult, input::Input}; + /// use winnow::input::Located; + /// use winnow::character::alpha1; + /// use winnow::bytes::tag; + /// use winnow::sequence::separated_pair; + /// + /// fn inner_parser(input: Located<&str>) -> IResult, bool> { + /// tag("1234").value(true).parse_next(input) + /// } + /// + /// # fn main() { + /// + /// let mut consumed_parser = separated_pair(alpha1.value(1).with_span(), ',', alpha1.value(2).with_span()); + /// + /// assert_eq!(consumed_parser.parse_next(Located::new("abcd,efgh")).finish(), Ok(((1, 0..4), (2, 5..9)))); + /// assert_eq!(consumed_parser.parse_next(Located::new("abcd;")),Err(ErrMode::Backtrack(Error::new(Located::new("abcd;").next_slice(4).0, ErrorKind::OneOf)))); + /// + /// // the second output (representing the consumed input) + /// // should be the same as that of the `span` parser. + /// let mut recognize_parser = inner_parser.span(); + /// let mut consumed_parser = inner_parser.with_span().map(|(output, consumed)| consumed); + /// + /// assert_eq!(recognize_parser.parse_next(Located::new("1234")), consumed_parser.parse_next(Located::new("1234"))); + /// assert_eq!(recognize_parser.parse_next(Located::new("abcd")), consumed_parser.parse_next(Located::new("abcd"))); + /// # } + /// ``` + fn with_span(self) -> WithSpan + where + Self: core::marker::Sized, + I: Location + Clone, + { + WithSpan::new(self) + } + + /// Maps a function over the result of a parser + /// + /// # Example + /// + /// ```rust + /// use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult,Parser}; + /// use winnow::character::digit1; + /// # fn main() { + /// + /// let mut parser = digit1.map(|s: &str| s.len()); + /// + /// // the parser will count how many characters were returned by digit1 + /// assert_eq!(parser.parse_next("123456"), Ok(("", 6))); + /// + /// // this will fail if digit1 fails + /// assert_eq!(parser.parse_next("abc"), Err(ErrMode::Backtrack(Error::new("abc", ErrorKind::Digit)))); + /// # } + /// ``` + fn map(self, g: G) -> Map + where + G: Fn(O) -> O2, + Self: core::marker::Sized, + { + Map::new(self, g) + } + + /// Applies a function returning a `Result` over the result of a parser. + /// + /// # Example + /// + /// ```rust + /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult, Parser}; + /// use winnow::character::digit1; + /// # fn main() { + /// + /// let mut parse = digit1.map_res(|s: &str| s.parse::()); + /// + /// // the parser will convert the result of digit1 to a number + /// assert_eq!(parse.parse_next("123"), Ok(("", 123))); + /// + /// // this will fail if digit1 fails + /// assert_eq!(parse.parse_next("abc"), Err(ErrMode::Backtrack(Error::new("abc", ErrorKind::Digit)))); + /// + /// // this will fail if the mapped function fails (a `u8` is too small to hold `123456`) + /// assert_eq!(parse.parse_next("123456"), Err(ErrMode::Backtrack(Error::new("123456", ErrorKind::MapRes)))); + /// # } + /// ``` + fn map_res(self, g: G) -> MapRes + where + Self: core::marker::Sized, + G: FnMut(O) -> Result, + { + MapRes::new(self, g) + } + + /// Applies a function returning an `Option` over the result of a parser. + /// + /// # Example + /// + /// ```rust + /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult, Parser}; + /// use winnow::character::digit1; + /// # fn main() { + /// + /// let mut parse = digit1.map_opt(|s: &str| s.parse::().ok()); + /// + /// // the parser will convert the result of digit1 to a number + /// assert_eq!(parse.parse_next("123"), Ok(("", 123))); + /// + /// // this will fail if digit1 fails + /// assert_eq!(parse.parse_next("abc"), Err(ErrMode::Backtrack(Error::new("abc", ErrorKind::Digit)))); + /// + /// // this will fail if the mapped function fails (a `u8` is too small to hold `123456`) + /// assert_eq!(parse.parse_next("123456"), Err(ErrMode::Backtrack(Error::new("123456", ErrorKind::MapOpt)))); + /// # } + /// ``` + fn map_opt(self, g: G) -> MapOpt + where + Self: core::marker::Sized, + G: FnMut(O) -> Option, + { + MapOpt::new(self, g) + } + + /// Creates a second parser from the output of the first one, then apply over the rest of the input + /// + /// # Example + /// + /// ```rust + /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult, Parser}; + /// use winnow::bytes::take; + /// use winnow::number::u8; + /// # fn main() { + /// + /// let mut length_data = u8.flat_map(take); + /// + /// assert_eq!(length_data.parse_next(&[2, 0, 1, 2][..]), Ok((&[2][..], &[0, 1][..]))); + /// assert_eq!(length_data.parse_next(&[4, 0, 1, 2][..]), Err(ErrMode::Backtrack(Error::new(&[0, 1, 2][..], ErrorKind::Eof)))); + /// # } + /// ``` + fn flat_map(self, g: G) -> FlatMap + where + G: FnMut(O) -> H, + H: Parser, + Self: core::marker::Sized, + { + FlatMap::new(self, g) + } + + /// Applies a second parser over the output of the first one + /// + /// # Example + /// + /// ```rust + /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult, Parser}; + /// use winnow::character::digit1; + /// use winnow::bytes::take; + /// # fn main() { + /// + /// let mut digits = take(5u8).and_then(digit1); + /// + /// assert_eq!(digits.parse_next("12345"), Ok(("", "12345"))); + /// assert_eq!(digits.parse_next("123ab"), Ok(("", "123"))); + /// assert_eq!(digits.parse_next("123"), Err(ErrMode::Backtrack(Error::new("123", ErrorKind::Eof)))); + /// # } + /// ``` + fn and_then(self, g: G) -> AndThen + where + G: Parser, + Self: core::marker::Sized, + { + AndThen::new(self, g) + } + + /// Apply [`std::str::FromStr`] to the output of the parser + /// + /// # Example + /// + /// ```rust + /// # use winnow::prelude::*; + /// use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult,Parser}; + /// use winnow::character::digit1; + /// + /// fn parser(input: &str) -> IResult<&str, u64> { + /// digit1.parse_to().parse_next(input) + /// } + /// + /// // the parser will count how many characters were returned by digit1 + /// assert_eq!(parser.parse_next("123456"), Ok(("", 123456))); + /// + /// // this will fail if digit1 fails + /// assert_eq!(parser.parse_next("abc"), Err(ErrMode::Backtrack(Error::new("abc", ErrorKind::Digit)))); + /// ``` + fn parse_to(self) -> ParseTo + where + Self: core::marker::Sized, + O: crate::input::ParseSlice, + { + ParseTo::new(self) + } + + /// Returns the result of the child parser if it satisfies a verification function. + /// + /// The verification function takes as argument a reference to the output of the + /// parser. + /// + /// # Example + /// + /// ```rust + /// # use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult, Parser}; + /// # use winnow::character::alpha1; + /// # fn main() { + /// + /// let mut parser = alpha1.verify(|s: &str| s.len() == 4); + /// + /// assert_eq!(parser.parse_next("abcd"), Ok(("", "abcd"))); + /// assert_eq!(parser.parse_next("abcde"), Err(ErrMode::Backtrack(Error::new("abcde", ErrorKind::Verify)))); + /// assert_eq!(parser.parse_next("123abcd;"),Err(ErrMode::Backtrack(Error::new("123abcd;", ErrorKind::Alpha)))); + /// # } + /// ``` + fn verify(self, second: G) -> Verify + where + Self: core::marker::Sized, + G: Fn(&O2) -> bool, + { + Verify::new(self, second) + } + + /// If parsing fails, add context to the error + /// + /// This is used mainly to add user friendly information + /// to errors when backtracking through a parse tree. + fn context(self, context: C) -> Context + where + Self: core::marker::Sized, + C: Clone, + E: ContextError, + { + Context::new(self, context) + } + + /// Transforms [`Incomplete`][crate::error::ErrMode::Incomplete] into [`Error`][crate::error::ErrMode::Backtrack] + /// + /// # Example + /// + /// ```rust + /// # use winnow::{error::ErrMode, error::ErrorKind, error::Error, IResult, input::Streaming, Parser}; + /// # use winnow::bytes::take; + /// # fn main() { + /// + /// let mut parser = take(5u8).complete(); + /// + /// assert_eq!(parser.parse_next(Streaming("abcdefg")), Ok((Streaming("fg"), "abcde"))); + /// assert_eq!(parser.parse_next(Streaming("abcd")), Err(ErrMode::Backtrack(Error::new(Streaming("abcd"), ErrorKind::Complete)))); + /// # } + /// ``` + fn complete(self) -> Complete + where + Self: core::marker::Sized, + { + Complete::new(self) + } + + /// Convert the parser's error to another type using [`std::convert::From`] + fn err_into(self) -> ErrInto + where + Self: core::marker::Sized, + E: Into, + { + ErrInto::new(self) + } + + /// Prints a message and the input if the parser fails. + /// + /// The message prints the `Error` or `Incomplete` + /// and the parser's calling kind. + /// + /// It also displays the input in hexdump format + /// + /// ```rust + /// use winnow::prelude::*; + /// use winnow::{IResult, bytes::tag}; + /// + /// fn f(i: &[u8]) -> IResult<&[u8], &[u8]> { + /// tag("abcd").dbg_err("alpha tag").parse_next(i) + /// } + /// + /// let a = &b"efghijkl"[..]; + /// f(a); + /// ``` + /// + /// Will print the following message: + /// ```console + /// alpha tag: Error(Position(0, [101, 102, 103, 104, 105, 106, 107, 108])) at: + /// 00000000 65 66 67 68 69 6a 6b 6c efghijkl + /// ``` + #[cfg(feature = "std")] + fn dbg_err(self, context: C) -> DbgErr + where + C: std::fmt::Display, + Self: core::marker::Sized, + { + DbgErr::new(self, context) + } + + /// Applies a second parser after the first one, return their results as a tuple + /// + /// **WARNING:** Deprecated, replaced with [`winnow::sequence::tuple`][crate::sequence::tuple] + #[deprecated(since = "0.1.0", note = "Replaced with `winnow::sequence::tuple")] + fn and(self, g: G) -> And + where + G: Parser, + Self: core::marker::Sized, + { + And::new(self, g) + } + + /// Applies a second parser over the input if the first one failed + /// + /// **WARNING:** Deprecated, replaced with [`winnow::branch::alt`][crate::branch::alt] + #[deprecated(since = "0.1.0", note = "Replaced with `winnow::branch::alt")] + fn or(self, g: G) -> Or + where + G: Parser, + Self: core::marker::Sized, + { + Or::new(self, g) + } } impl<'a, I, O, E, F> Parser for F where - F: FnMut(I) -> IResult + 'a, + F: FnMut(I) -> IResult + 'a, { - fn parse_next(&mut self, i: I) -> IResult { - self(i) - } + fn parse_next(&mut self, i: I) -> IResult { + self(i) + } } /// This is a shortcut for [`one_of`][crate::bytes::one_of]. @@ -631,13 +631,13 @@ where /// ``` impl Parser for u8 where - I: InputIsStreaming, - I: Input, - E: ParseError, + I: InputIsStreaming, + I: Input, + E: ParseError, { - fn parse_next(&mut self, i: I) -> IResult { - crate::bytes::one_of(*self).parse_next(i) - } + fn parse_next(&mut self, i: I) -> IResult { + crate::bytes::one_of(*self).parse_next(i) + } } /// This is a shortcut for [`one_of`][crate::bytes::one_of]. @@ -657,14 +657,14 @@ where /// ``` impl Parser::Token, E> for char where - I: InputIsStreaming, - I: Input, - ::Token: AsChar + Copy, - E: ParseError, + I: InputIsStreaming, + I: Input, + ::Token: AsChar + Copy, + E: ParseError, { - fn parse_next(&mut self, i: I) -> IResult::Token, E> { - crate::bytes::one_of(*self).parse_next(i) - } + fn parse_next(&mut self, i: I) -> IResult::Token, E> { + crate::bytes::one_of(*self).parse_next(i) + } } /// This is a shortcut for [`tag`][crate::bytes::tag]. @@ -687,12 +687,12 @@ where /// ``` impl<'s, I, E: ParseError> Parser::Slice, E> for &'s [u8] where - I: Compare<&'s [u8]> + InputIsStreaming, - I: Input, + I: Compare<&'s [u8]> + InputIsStreaming, + I: Input, { - fn parse_next(&mut self, i: I) -> IResult::Slice, E> { - crate::bytes::tag(*self).parse_next(i) - } + fn parse_next(&mut self, i: I) -> IResult::Slice, E> { + crate::bytes::tag(*self).parse_next(i) + } } /// This is a shortcut for [`tag`][crate::bytes::tag]. @@ -715,12 +715,12 @@ where /// ``` impl<'s, I, E: ParseError, const N: usize> Parser::Slice, E> for &'s [u8; N] where - I: Compare<&'s [u8; N]> + InputIsStreaming, - I: Input, + I: Compare<&'s [u8; N]> + InputIsStreaming, + I: Input, { - fn parse_next(&mut self, i: I) -> IResult::Slice, E> { - crate::bytes::tag(*self).parse_next(i) - } + fn parse_next(&mut self, i: I) -> IResult::Slice, E> { + crate::bytes::tag(*self).parse_next(i) + } } /// This is a shortcut for [`tag`][crate::bytes::tag]. @@ -743,18 +743,18 @@ where /// ``` impl<'s, I, E: ParseError> Parser::Slice, E> for &'s str where - I: Compare<&'s str> + InputIsStreaming, - I: Input, + I: Compare<&'s str> + InputIsStreaming, + I: Input, { - fn parse_next(&mut self, i: I) -> IResult::Slice, E> { - crate::bytes::tag(*self).parse_next(i) - } + fn parse_next(&mut self, i: I) -> IResult::Slice, E> { + crate::bytes::tag(*self).parse_next(i) + } } impl> Parser for () { - fn parse_next(&mut self, i: I) -> IResult { - Ok((i, ())) - } + fn parse_next(&mut self, i: I) -> IResult { + Ok((i, ())) + } } macro_rules! impl_parser_for_tuple { @@ -817,97 +817,97 @@ use alloc::boxed::Box; #[cfg(feature = "alloc")] impl<'a, I, O, E> Parser for Box + 'a> { - fn parse_next(&mut self, input: I) -> IResult { - (**self).parse_next(input) - } + fn parse_next(&mut self, input: I) -> IResult { + (**self).parse_next(input) + } } #[cfg(test)] mod tests { - use super::*; - use crate::bytes::{tag, take}; - use crate::error::ErrMode; - use crate::error::Error; - use crate::error::ErrorKind; - use crate::error::Needed; - use crate::input::Streaming; - use crate::number::be_u16; - - #[doc(hidden)] - #[macro_export] - macro_rules! assert_size ( + use super::*; + use crate::bytes::{tag, take}; + use crate::error::ErrMode; + use crate::error::Error; + use crate::error::ErrorKind; + use crate::error::Needed; + use crate::input::Streaming; + use crate::number::be_u16; + + #[doc(hidden)] + #[macro_export] + macro_rules! assert_size ( ($t:ty, $sz:expr) => ( assert!($crate::lib::std::mem::size_of::<$t>() <= $sz, "{} <= {} failed", $crate::lib::std::mem::size_of::<$t>(), $sz); ); ); - #[test] - #[cfg(target_pointer_width = "64")] - fn size_test() { - assert_size!(IResult<&[u8], &[u8], (&[u8], u32)>, 40); - assert_size!(IResult<&str, &str, u32>, 40); - assert_size!(Needed, 8); - assert_size!(ErrMode, 16); - assert_size!(ErrorKind, 1); - } - - #[test] - fn err_map_test() { - let e = ErrMode::Backtrack(1); - assert_eq!(e.map(|v| v + 1), ErrMode::Backtrack(2)); - } - - #[test] - fn single_element_tuples() { - use crate::character::alpha1; - use crate::error::ErrorKind; + #[test] + #[cfg(target_pointer_width = "64")] + fn size_test() { + assert_size!(IResult<&[u8], &[u8], (&[u8], u32)>, 40); + assert_size!(IResult<&str, &str, u32>, 40); + assert_size!(Needed, 8); + assert_size!(ErrMode, 16); + assert_size!(ErrorKind, 1); + } - let mut parser = (alpha1,); - assert_eq!(parser.parse_next("abc123def"), Ok(("123def", ("abc",)))); - assert_eq!( - parser.parse_next("123def"), - Err(ErrMode::Backtrack(Error { - input: "123def", - kind: ErrorKind::Alpha - })) - ); - } + #[test] + fn err_map_test() { + let e = ErrMode::Backtrack(1); + assert_eq!(e.map(|v| v + 1), ErrMode::Backtrack(2)); + } - #[test] - fn tuple_test() { - #[allow(clippy::type_complexity)] - fn tuple_3(i: Streaming<&[u8]>) -> IResult, (u16, &[u8], &[u8])> { - (be_u16, take(3u8), tag("fg")).parse_next(i) + #[test] + fn single_element_tuples() { + use crate::character::alpha1; + use crate::error::ErrorKind; + + let mut parser = (alpha1,); + assert_eq!(parser.parse_next("abc123def"), Ok(("123def", ("abc",)))); + assert_eq!( + parser.parse_next("123def"), + Err(ErrMode::Backtrack(Error { + input: "123def", + kind: ErrorKind::Alpha + })) + ); } - assert_eq!( - tuple_3(Streaming(&b"abcdefgh"[..])), - Ok((Streaming(&b"h"[..]), (0x6162u16, &b"cde"[..], &b"fg"[..]))) - ); - assert_eq!( - tuple_3(Streaming(&b"abcd"[..])), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - tuple_3(Streaming(&b"abcde"[..])), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_eq!( - tuple_3(Streaming(&b"abcdejk"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"jk"[..]), - ErrorKind::Tag - ))) - ); - } + #[test] + fn tuple_test() { + #[allow(clippy::type_complexity)] + fn tuple_3(i: Streaming<&[u8]>) -> IResult, (u16, &[u8], &[u8])> { + (be_u16, take(3u8), tag("fg")).parse_next(i) + } + + assert_eq!( + tuple_3(Streaming(&b"abcdefgh"[..])), + Ok((Streaming(&b"h"[..]), (0x6162u16, &b"cde"[..], &b"fg"[..]))) + ); + assert_eq!( + tuple_3(Streaming(&b"abcd"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + tuple_3(Streaming(&b"abcde"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_eq!( + tuple_3(Streaming(&b"abcdejk"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"jk"[..]), + ErrorKind::Tag + ))) + ); + } - #[test] - fn unit_type() { - fn parser(i: &str) -> IResult<&str, ()> { - ().parse_next(i) + #[test] + fn unit_type() { + fn parser(i: &str) -> IResult<&str, ()> { + ().parse_next(i) + } + assert_eq!(parser.parse_next("abxsbsh"), Ok(("abxsbsh", ()))); + assert_eq!(parser.parse_next("sdfjakdsas"), Ok(("sdfjakdsas", ()))); + assert_eq!(parser.parse_next(""), Ok(("", ()))); } - assert_eq!(parser.parse_next("abxsbsh"), Ok(("abxsbsh", ()))); - assert_eq!(parser.parse_next("sdfjakdsas"), Ok(("sdfjakdsas", ()))); - assert_eq!(parser.parse_next(""), Ok(("", ()))); - } } diff --git a/src/sequence/mod.rs b/src/sequence/mod.rs index 3a770c6e..d048daa1 100644 --- a/src/sequence/mod.rs +++ b/src/sequence/mod.rs @@ -30,17 +30,17 @@ use crate::{IResult, Parser}; /// ``` #[deprecated(since = "0.1.0", note = "`Parser` is directly implemented for tuples")] pub fn pair, F, G>( - mut first: F, - mut second: G, + mut first: F, + mut second: G, ) -> impl FnMut(I) -> IResult where - F: Parser, - G: Parser, + F: Parser, + G: Parser, { - move |input: I| { - let (input, o1) = first.parse_next(input)?; - second.parse_next(input).map(|(i, o2)| (i, (o1, o2))) - } + move |input: I| { + let (input, o1) = first.parse_next(input)?; + second.parse_next(input).map(|(i, o2)| (i, (o1, o2))) + } } /// Matches an object from the first parser and discards it, @@ -64,17 +64,17 @@ where /// assert_eq!(parser("123"), Err(ErrMode::Backtrack(Error::new("123", ErrorKind::Tag)))); /// ``` pub fn preceded, F, G>( - mut first: F, - mut second: G, + mut first: F, + mut second: G, ) -> impl FnMut(I) -> IResult where - F: Parser, - G: Parser, + F: Parser, + G: Parser, { - move |input: I| { - let (input, _) = first.parse_next(input)?; - second.parse_next(input) - } + move |input: I| { + let (input, _) = first.parse_next(input)?; + second.parse_next(input) + } } /// Gets an object from the first parser, @@ -98,17 +98,17 @@ where /// assert_eq!(parser("123"), Err(ErrMode::Backtrack(Error::new("123", ErrorKind::Tag)))); /// ``` pub fn terminated, F, G>( - mut first: F, - mut second: G, + mut first: F, + mut second: G, ) -> impl FnMut(I) -> IResult where - F: Parser, - G: Parser, + F: Parser, + G: Parser, { - move |input: I| { - let (input, o1) = first.parse_next(input)?; - second.parse_next(input).map(|(i, _)| (i, o1)) - } + move |input: I| { + let (input, o1) = first.parse_next(input)?; + second.parse_next(input).map(|(i, _)| (i, o1)) + } } /// Gets an object from the first parser, @@ -134,20 +134,20 @@ where /// assert_eq!(parser("123"), Err(ErrMode::Backtrack(Error::new("123", ErrorKind::Tag)))); /// ``` pub fn separated_pair, F, G, H>( - mut first: F, - mut sep: G, - mut second: H, + mut first: F, + mut sep: G, + mut second: H, ) -> impl FnMut(I) -> IResult where - F: Parser, - G: Parser, - H: Parser, + F: Parser, + G: Parser, + H: Parser, { - move |input: I| { - let (input, o1) = first.parse_next(input)?; - let (input, _) = sep.parse_next(input)?; - second.parse_next(input).map(|(i, o2)| (i, (o1, o2))) - } + move |input: I| { + let (input, o1) = first.parse_next(input)?; + let (input, _) = sep.parse_next(input)?; + second.parse_next(input).map(|(i, o2)| (i, (o1, o2))) + } } /// Matches an object from the first parser and discards it, @@ -173,20 +173,20 @@ where /// assert_eq!(parser("123"), Err(ErrMode::Backtrack(Error::new("123", ErrorKind::Tag)))); /// ``` pub fn delimited, F, G, H>( - mut first: F, - mut second: G, - mut third: H, + mut first: F, + mut second: G, + mut third: H, ) -> impl FnMut(I) -> IResult where - F: Parser, - G: Parser, - H: Parser, + F: Parser, + G: Parser, + H: Parser, { - move |input: I| { - let (input, _) = first.parse_next(input)?; - let (input, o2) = second.parse_next(input)?; - third.parse_next(input).map(|(i, _)| (i, o2)) - } + move |input: I| { + let (input, _) = first.parse_next(input)?; + let (input, o2) = second.parse_next(input)?; + third.parse_next(input).map(|(i, _)| (i, o2)) + } } /// Helper trait for the tuple combinator. @@ -194,15 +194,15 @@ where /// This trait is implemented for tuples of parsers of up to 21 elements. #[deprecated(since = "0.1.0", note = "Replaced with `Parser`")] pub trait Tuple { - /// Parses the input and returns a tuple of results of each parser. - fn parse(&mut self, input: I) -> IResult; + /// Parses the input and returns a tuple of results of each parser. + fn parse(&mut self, input: I) -> IResult; } #[allow(deprecated)] impl, F: Parser> Tuple for (F,) { - fn parse(&mut self, input: I) -> IResult { - self.0.parse_next(input).map(|(i, o)| (i, (o,))) - } + fn parse(&mut self, input: I) -> IResult { + self.0.parse_next(input).map(|(i, o)| (i, (o,))) + } } macro_rules! tuple_trait( @@ -282,9 +282,9 @@ tuple_trait!( // Literally, `()` is an empty tuple, so it should simply parse nothing. #[allow(deprecated)] impl> Tuple for () { - fn parse(&mut self, input: I) -> IResult { - Ok((input, ())) - } + fn parse(&mut self, input: I) -> IResult { + Ok((input, ())) + } } ///Applies a tuple of parsers one by one and returns their results as a tuple. @@ -304,7 +304,7 @@ impl> Tuple for () { #[deprecated(since = "0.1.0", note = "`Parser` is directly implemented for tuples")] #[allow(deprecated)] pub fn tuple, List: Tuple>( - mut l: List, + mut l: List, ) -> impl FnMut(I) -> IResult { - move |i: I| l.parse(i) + move |i: I| l.parse(i) } diff --git a/src/sequence/tests.rs b/src/sequence/tests.rs index 217fb32f..1b336acf 100644 --- a/src/sequence/tests.rs +++ b/src/sequence/tests.rs @@ -7,313 +7,313 @@ use crate::IResult; #[test] fn single_element_tuples() { - #![allow(deprecated)] - use crate::character::alpha1; - use crate::error::ErrorKind; + #![allow(deprecated)] + use crate::character::alpha1; + use crate::error::ErrorKind; - let mut parser = tuple((alpha1,)); - assert_eq!(parser("abc123def"), Ok(("123def", ("abc",)))); - assert_eq!( - parser("123def"), - Err(ErrMode::Backtrack(Error { - input: "123def", - kind: ErrorKind::Alpha - })) - ); + let mut parser = tuple((alpha1,)); + assert_eq!(parser("abc123def"), Ok(("123def", ("abc",)))); + assert_eq!( + parser("123def"), + Err(ErrMode::Backtrack(Error { + input: "123def", + kind: ErrorKind::Alpha + })) + ); } #[derive(PartialEq, Eq, Debug)] struct B { - a: u8, - b: u8, + a: u8, + b: u8, } #[derive(PartialEq, Eq, Debug)] struct C { - a: u8, - b: Option, + a: u8, + b: Option, } #[test] fn complete() { - use crate::bytes::tag; - fn err_test(i: &[u8]) -> IResult<&[u8], &[u8]> { - let (i, _) = tag("ijkl")(i)?; - tag("mnop")(i) - } - let a = &b"ijklmn"[..]; + use crate::bytes::tag; + fn err_test(i: &[u8]) -> IResult<&[u8], &[u8]> { + let (i, _) = tag("ijkl")(i)?; + tag("mnop")(i) + } + let a = &b"ijklmn"[..]; - let res_a = err_test(a); - assert_eq!( - res_a, - Err(ErrMode::Backtrack(error_position!( - &b"mn"[..], - ErrorKind::Tag - ))) - ); + let res_a = err_test(a); + assert_eq!( + res_a, + Err(ErrMode::Backtrack(error_position!( + &b"mn"[..], + ErrorKind::Tag + ))) + ); } #[test] fn pair_test() { - #![allow(deprecated)] - #[allow(clippy::type_complexity)] - fn pair_abc_def(i: Streaming<&[u8]>) -> IResult, (&[u8], &[u8])> { - pair(tag("abc"), tag("def"))(i) - } + #![allow(deprecated)] + #[allow(clippy::type_complexity)] + fn pair_abc_def(i: Streaming<&[u8]>) -> IResult, (&[u8], &[u8])> { + pair(tag("abc"), tag("def"))(i) + } - assert_eq!( - pair_abc_def(Streaming(&b"abcdefghijkl"[..])), - Ok((Streaming(&b"ghijkl"[..]), (&b"abc"[..], &b"def"[..]))) - ); - assert_eq!( - pair_abc_def(Streaming(&b"ab"[..])), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - pair_abc_def(Streaming(&b"abcd"[..])), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_eq!( - pair_abc_def(Streaming(&b"xxx"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxx"[..]), - ErrorKind::Tag - ))) - ); - assert_eq!( - pair_abc_def(Streaming(&b"xxxdef"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxxdef"[..]), - ErrorKind::Tag - ))) - ); - assert_eq!( - pair_abc_def(Streaming(&b"abcxxx"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxx"[..]), - ErrorKind::Tag - ))) - ); + assert_eq!( + pair_abc_def(Streaming(&b"abcdefghijkl"[..])), + Ok((Streaming(&b"ghijkl"[..]), (&b"abc"[..], &b"def"[..]))) + ); + assert_eq!( + pair_abc_def(Streaming(&b"ab"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + pair_abc_def(Streaming(&b"abcd"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_eq!( + pair_abc_def(Streaming(&b"xxx"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + pair_abc_def(Streaming(&b"xxxdef"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxxdef"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + pair_abc_def(Streaming(&b"abcxxx"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); } #[test] fn separated_pair_test() { - #[allow(clippy::type_complexity)] - fn sep_pair_abc_def(i: Streaming<&[u8]>) -> IResult, (&[u8], &[u8])> { - separated_pair(tag("abc"), tag(","), tag("def"))(i) - } + #[allow(clippy::type_complexity)] + fn sep_pair_abc_def(i: Streaming<&[u8]>) -> IResult, (&[u8], &[u8])> { + separated_pair(tag("abc"), tag(","), tag("def"))(i) + } - assert_eq!( - sep_pair_abc_def(Streaming(&b"abc,defghijkl"[..])), - Ok((Streaming(&b"ghijkl"[..]), (&b"abc"[..], &b"def"[..]))) - ); - assert_eq!( - sep_pair_abc_def(Streaming(&b"ab"[..])), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - sep_pair_abc_def(Streaming(&b"abc,d"[..])), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_eq!( - sep_pair_abc_def(Streaming(&b"xxx"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxx"[..]), - ErrorKind::Tag - ))) - ); - assert_eq!( - sep_pair_abc_def(Streaming(&b"xxx,def"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxx,def"[..]), - ErrorKind::Tag - ))) - ); - assert_eq!( - sep_pair_abc_def(Streaming(&b"abc,xxx"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxx"[..]), - ErrorKind::Tag - ))) - ); + assert_eq!( + sep_pair_abc_def(Streaming(&b"abc,defghijkl"[..])), + Ok((Streaming(&b"ghijkl"[..]), (&b"abc"[..], &b"def"[..]))) + ); + assert_eq!( + sep_pair_abc_def(Streaming(&b"ab"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + sep_pair_abc_def(Streaming(&b"abc,d"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_eq!( + sep_pair_abc_def(Streaming(&b"xxx"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + sep_pair_abc_def(Streaming(&b"xxx,def"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxx,def"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + sep_pair_abc_def(Streaming(&b"abc,xxx"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); } #[test] fn preceded_test() { - fn preceded_abcd_efgh(i: Streaming<&[u8]>) -> IResult, &[u8]> { - preceded(tag("abcd"), tag("efgh"))(i) - } + fn preceded_abcd_efgh(i: Streaming<&[u8]>) -> IResult, &[u8]> { + preceded(tag("abcd"), tag("efgh"))(i) + } - assert_eq!( - preceded_abcd_efgh(Streaming(&b"abcdefghijkl"[..])), - Ok((Streaming(&b"ijkl"[..]), &b"efgh"[..])) - ); - assert_eq!( - preceded_abcd_efgh(Streaming(&b"ab"[..])), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_eq!( - preceded_abcd_efgh(Streaming(&b"abcde"[..])), - Err(ErrMode::Incomplete(Needed::new(3))) - ); - assert_eq!( - preceded_abcd_efgh(Streaming(&b"xxx"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxx"[..]), - ErrorKind::Tag - ))) - ); - assert_eq!( - preceded_abcd_efgh(Streaming(&b"xxxxdef"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxxxdef"[..]), - ErrorKind::Tag - ))) - ); - assert_eq!( - preceded_abcd_efgh(Streaming(&b"abcdxxx"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxx"[..]), - ErrorKind::Tag - ))) - ); + assert_eq!( + preceded_abcd_efgh(Streaming(&b"abcdefghijkl"[..])), + Ok((Streaming(&b"ijkl"[..]), &b"efgh"[..])) + ); + assert_eq!( + preceded_abcd_efgh(Streaming(&b"ab"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_eq!( + preceded_abcd_efgh(Streaming(&b"abcde"[..])), + Err(ErrMode::Incomplete(Needed::new(3))) + ); + assert_eq!( + preceded_abcd_efgh(Streaming(&b"xxx"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + preceded_abcd_efgh(Streaming(&b"xxxxdef"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxxxdef"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + preceded_abcd_efgh(Streaming(&b"abcdxxx"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); } #[test] fn terminated_test() { - fn terminated_abcd_efgh(i: Streaming<&[u8]>) -> IResult, &[u8]> { - terminated(tag("abcd"), tag("efgh"))(i) - } + fn terminated_abcd_efgh(i: Streaming<&[u8]>) -> IResult, &[u8]> { + terminated(tag("abcd"), tag("efgh"))(i) + } - assert_eq!( - terminated_abcd_efgh(Streaming(&b"abcdefghijkl"[..])), - Ok((Streaming(&b"ijkl"[..]), &b"abcd"[..])) - ); - assert_eq!( - terminated_abcd_efgh(Streaming(&b"ab"[..])), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_eq!( - terminated_abcd_efgh(Streaming(&b"abcde"[..])), - Err(ErrMode::Incomplete(Needed::new(3))) - ); - assert_eq!( - terminated_abcd_efgh(Streaming(&b"xxx"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxx"[..]), - ErrorKind::Tag - ))) - ); - assert_eq!( - terminated_abcd_efgh(Streaming(&b"xxxxdef"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxxxdef"[..]), - ErrorKind::Tag - ))) - ); - assert_eq!( - terminated_abcd_efgh(Streaming(&b"abcdxxxx"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxxx"[..]), - ErrorKind::Tag - ))) - ); + assert_eq!( + terminated_abcd_efgh(Streaming(&b"abcdefghijkl"[..])), + Ok((Streaming(&b"ijkl"[..]), &b"abcd"[..])) + ); + assert_eq!( + terminated_abcd_efgh(Streaming(&b"ab"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_eq!( + terminated_abcd_efgh(Streaming(&b"abcde"[..])), + Err(ErrMode::Incomplete(Needed::new(3))) + ); + assert_eq!( + terminated_abcd_efgh(Streaming(&b"xxx"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + terminated_abcd_efgh(Streaming(&b"xxxxdef"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxxxdef"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + terminated_abcd_efgh(Streaming(&b"abcdxxxx"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxxx"[..]), + ErrorKind::Tag + ))) + ); } #[test] fn delimited_test() { - fn delimited_abc_def_ghi(i: Streaming<&[u8]>) -> IResult, &[u8]> { - delimited(tag("abc"), tag("def"), tag("ghi"))(i) - } + fn delimited_abc_def_ghi(i: Streaming<&[u8]>) -> IResult, &[u8]> { + delimited(tag("abc"), tag("def"), tag("ghi"))(i) + } - assert_eq!( - delimited_abc_def_ghi(Streaming(&b"abcdefghijkl"[..])), - Ok((Streaming(&b"jkl"[..]), &b"def"[..])) - ); - assert_eq!( - delimited_abc_def_ghi(Streaming(&b"ab"[..])), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - delimited_abc_def_ghi(Streaming(&b"abcde"[..])), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - delimited_abc_def_ghi(Streaming(&b"abcdefgh"[..])), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - delimited_abc_def_ghi(Streaming(&b"xxx"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxx"[..]), - ErrorKind::Tag - ))) - ); - assert_eq!( - delimited_abc_def_ghi(Streaming(&b"xxxdefghi"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxxdefghi"[..]), - ErrorKind::Tag - ),)) - ); - assert_eq!( - delimited_abc_def_ghi(Streaming(&b"abcxxxghi"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxxghi"[..]), - ErrorKind::Tag - ))) - ); - assert_eq!( - delimited_abc_def_ghi(Streaming(&b"abcdefxxx"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"xxx"[..]), - ErrorKind::Tag - ))) - ); + assert_eq!( + delimited_abc_def_ghi(Streaming(&b"abcdefghijkl"[..])), + Ok((Streaming(&b"jkl"[..]), &b"def"[..])) + ); + assert_eq!( + delimited_abc_def_ghi(Streaming(&b"ab"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + delimited_abc_def_ghi(Streaming(&b"abcde"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + delimited_abc_def_ghi(Streaming(&b"abcdefgh"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + delimited_abc_def_ghi(Streaming(&b"xxx"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + delimited_abc_def_ghi(Streaming(&b"xxxdefghi"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxxdefghi"[..]), + ErrorKind::Tag + ),)) + ); + assert_eq!( + delimited_abc_def_ghi(Streaming(&b"abcxxxghi"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxxghi"[..]), + ErrorKind::Tag + ))) + ); + assert_eq!( + delimited_abc_def_ghi(Streaming(&b"abcdefxxx"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"xxx"[..]), + ErrorKind::Tag + ))) + ); } #[test] fn tuple_test() { - #![allow(deprecated)] - #[allow(clippy::type_complexity)] - fn tuple_3(i: Streaming<&[u8]>) -> IResult, (u16, &[u8], &[u8])> { - tuple((be_u16, take(3u8), tag("fg")))(i) - } + #![allow(deprecated)] + #[allow(clippy::type_complexity)] + fn tuple_3(i: Streaming<&[u8]>) -> IResult, (u16, &[u8], &[u8])> { + tuple((be_u16, take(3u8), tag("fg")))(i) + } - assert_eq!( - tuple_3(Streaming(&b"abcdefgh"[..])), - Ok((Streaming(&b"h"[..]), (0x6162u16, &b"cde"[..], &b"fg"[..]))) - ); - assert_eq!( - tuple_3(Streaming(&b"abcd"[..])), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - tuple_3(Streaming(&b"abcde"[..])), - Err(ErrMode::Incomplete(Needed::new(2))) - ); - assert_eq!( - tuple_3(Streaming(&b"abcdejk"[..])), - Err(ErrMode::Backtrack(error_position!( - Streaming(&b"jk"[..]), - ErrorKind::Tag - ))) - ); + assert_eq!( + tuple_3(Streaming(&b"abcdefgh"[..])), + Ok((Streaming(&b"h"[..]), (0x6162u16, &b"cde"[..], &b"fg"[..]))) + ); + assert_eq!( + tuple_3(Streaming(&b"abcd"[..])), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + tuple_3(Streaming(&b"abcde"[..])), + Err(ErrMode::Incomplete(Needed::new(2))) + ); + assert_eq!( + tuple_3(Streaming(&b"abcdejk"[..])), + Err(ErrMode::Backtrack(error_position!( + Streaming(&b"jk"[..]), + ErrorKind::Tag + ))) + ); } #[test] fn unit_type() { - #![allow(deprecated)] - assert_eq!( - tuple::<&'static str, (), Error<&'static str>, ()>(())("abxsbsh"), - Ok(("abxsbsh", ())) - ); - assert_eq!( - tuple::<&'static str, (), Error<&'static str>, ()>(())("sdfjakdsas"), - Ok(("sdfjakdsas", ())) - ); - assert_eq!( - tuple::<&'static str, (), Error<&'static str>, ()>(())(""), - Ok(("", ())) - ); + #![allow(deprecated)] + assert_eq!( + tuple::<&'static str, (), Error<&'static str>, ()>(())("abxsbsh"), + Ok(("abxsbsh", ())) + ); + assert_eq!( + tuple::<&'static str, (), Error<&'static str>, ()>(())("sdfjakdsas"), + Ok(("sdfjakdsas", ())) + ); + assert_eq!( + tuple::<&'static str, (), Error<&'static str>, ()>(())(""), + Ok(("", ())) + ); } diff --git a/tests/testsuite/custom_errors.rs b/tests/testsuite/custom_errors.rs index e9ad3dd1..24804bca 100644 --- a/tests/testsuite/custom_errors.rs +++ b/tests/testsuite/custom_errors.rs @@ -14,38 +14,38 @@ use winnow::IResult; pub struct CustomError(String); impl<'a> From<(&'a str, ErrorKind)> for CustomError { - fn from(error: (&'a str, ErrorKind)) -> Self { - CustomError(format!("error code was: {:?}", error)) - } + fn from(error: (&'a str, ErrorKind)) -> Self { + CustomError(format!("error code was: {:?}", error)) + } } impl<'a> ParseError> for CustomError { - fn from_error_kind(_: Streaming<&'a str>, kind: ErrorKind) -> Self { - CustomError(format!("error code was: {:?}", kind)) - } + fn from_error_kind(_: Streaming<&'a str>, kind: ErrorKind) -> Self { + CustomError(format!("error code was: {:?}", kind)) + } - fn append(self, _: Streaming<&'a str>, kind: ErrorKind) -> Self { - CustomError(format!("{:?}\nerror code was: {:?}", self, kind)) - } + fn append(self, _: Streaming<&'a str>, kind: ErrorKind) -> Self { + CustomError(format!("{:?}\nerror code was: {:?}", self, kind)) + } } fn test1(input: Streaming<&str>) -> IResult, &str, CustomError> { - //fix_error!(input, CustomError, tag!("abcd")) - tag("abcd")(input) + //fix_error!(input, CustomError, tag!("abcd")) + tag("abcd")(input) } fn test2(input: Streaming<&str>) -> IResult, &str, CustomError> { - //terminated!(input, test1, fix_error!(CustomError, digit)) - terminated(test1, digit)(input) + //terminated!(input, test1, fix_error!(CustomError, digit)) + terminated(test1, digit)(input) } fn test3(input: Streaming<&str>) -> IResult, &str, CustomError> { - test1 - .verify(|s: &str| s.starts_with("abcd")) - .parse_next(input) + test1 + .verify(|s: &str| s.starts_with("abcd")) + .parse_next(input) } #[cfg(feature = "alloc")] fn test4(input: Streaming<&str>) -> IResult, Vec<&str>, CustomError> { - count(test1, 4)(input) + count(test1, 4)(input) } diff --git a/tests/testsuite/float.rs b/tests/testsuite/float.rs index b06ab418..951f0121 100644 --- a/tests/testsuite/float.rs +++ b/tests/testsuite/float.rs @@ -9,38 +9,37 @@ use std::str; use std::str::FromStr; fn unsigned_float(i: &[u8]) -> IResult<&[u8], f32> { - let float_bytes = alt(( - delimited(digit, ".", opt(digit)), - delimited(opt(digit), ".", digit), - )) - .recognize(); - let float_str = float_bytes.map_res(str::from_utf8); - float_str.map_res(FromStr::from_str).parse_next(i) + let float_bytes = alt(( + delimited(digit, ".", opt(digit)), + delimited(opt(digit), ".", digit), + )) + .recognize(); + let float_str = float_bytes.map_res(str::from_utf8); + float_str.map_res(FromStr::from_str).parse_next(i) } fn float(i: &[u8]) -> IResult<&[u8], f32> { - (opt(alt(("+", "-"))), unsigned_float) - .map(|(sign, value)| { - sign - .and_then(|s| if s[0] == b'-' { Some(-1f32) } else { None }) - .unwrap_or(1f32) - * value - }) - .parse_next(i) + (opt(alt(("+", "-"))), unsigned_float) + .map(|(sign, value)| { + sign.and_then(|s| if s[0] == b'-' { Some(-1f32) } else { None }) + .unwrap_or(1f32) + * value + }) + .parse_next(i) } #[test] fn unsigned_float_test() { - assert_eq!(unsigned_float(&b"123.456;"[..]), Ok((&b";"[..], 123.456))); - assert_eq!(unsigned_float(&b"0.123;"[..]), Ok((&b";"[..], 0.123))); - assert_eq!(unsigned_float(&b"123.0;"[..]), Ok((&b";"[..], 123.0))); - assert_eq!(unsigned_float(&b"123.;"[..]), Ok((&b";"[..], 123.0))); - assert_eq!(unsigned_float(&b".123;"[..]), Ok((&b";"[..], 0.123))); + assert_eq!(unsigned_float(&b"123.456;"[..]), Ok((&b";"[..], 123.456))); + assert_eq!(unsigned_float(&b"0.123;"[..]), Ok((&b";"[..], 0.123))); + assert_eq!(unsigned_float(&b"123.0;"[..]), Ok((&b";"[..], 123.0))); + assert_eq!(unsigned_float(&b"123.;"[..]), Ok((&b";"[..], 123.0))); + assert_eq!(unsigned_float(&b".123;"[..]), Ok((&b";"[..], 0.123))); } #[test] fn float_test() { - assert_eq!(float(&b"123.456;"[..]), Ok((&b";"[..], 123.456))); - assert_eq!(float(&b"+123.456;"[..]), Ok((&b";"[..], 123.456))); - assert_eq!(float(&b"-123.456;"[..]), Ok((&b";"[..], -123.456))); + assert_eq!(float(&b"123.456;"[..]), Ok((&b";"[..], 123.456))); + assert_eq!(float(&b"+123.456;"[..]), Ok((&b";"[..], 123.456))); + assert_eq!(float(&b"-123.456;"[..]), Ok((&b";"[..], -123.456))); } diff --git a/tests/testsuite/fnmut.rs b/tests/testsuite/fnmut.rs index 90edc617..e2e62dc1 100644 --- a/tests/testsuite/fnmut.rs +++ b/tests/testsuite/fnmut.rs @@ -6,35 +6,35 @@ use winnow::multi::many0; #[test] #[cfg(feature = "std")] fn parse() { - let mut counter = 0; + let mut counter = 0; - let res = { - let mut parser = many0::<_, _, Vec<_>, (), _>(|i| { - counter += 1; - tag("abc")(i) - }); + let res = { + let mut parser = many0::<_, _, Vec<_>, (), _>(|i| { + counter += 1; + tag("abc")(i) + }); - parser("abcabcabcabc").unwrap() - }; + parser("abcabcabcabc").unwrap() + }; - println!("res: {:?}", res); - assert_eq!(counter, 5); + println!("res: {:?}", res); + assert_eq!(counter, 5); } #[test] fn accumulate() { - let mut v = Vec::new(); - - let (_, count) = { - let mut parser = many0::<_, _, usize, (), _>(|i| { - let (i, o) = tag("abc")(i)?; - v.push(o); - Ok((i, ())) - }); - parser("abcabcabcabc").unwrap() - }; - - println!("v: {:?}", v); - assert_eq!(count, 4); - assert_eq!(v.len(), 4); + let mut v = Vec::new(); + + let (_, count) = { + let mut parser = many0::<_, _, usize, (), _>(|i| { + let (i, o) = tag("abc")(i)?; + v.push(o); + Ok((i, ())) + }); + parser("abcabcabcabc").unwrap() + }; + + println!("v: {:?}", v); + assert_eq!(count, 4); + assert_eq!(v.len(), 4); } diff --git a/tests/testsuite/issues.rs b/tests/testsuite/issues.rs index d11f4328..8effda33 100644 --- a/tests/testsuite/issues.rs +++ b/tests/testsuite/issues.rs @@ -8,281 +8,281 @@ use winnow::{error::ErrMode, error::ErrorKind, error::Needed, IResult}; #[allow(dead_code)] struct Range { - start: char, - end: char, + start: char, + end: char, } pub fn take_char(input: &[u8]) -> IResult<&[u8], char> { - if !input.is_empty() { - Ok((&input[1..], input[0] as char)) - } else { - Err(ErrMode::Incomplete(Needed::new(1))) - } + if !input.is_empty() { + Ok((&input[1..], input[0] as char)) + } else { + Err(ErrMode::Incomplete(Needed::new(1))) + } } #[cfg(feature = "std")] mod parse_int { - use std::str; - use winnow::input::HexDisplay; - use winnow::input::Streaming; - use winnow::prelude::*; - use winnow::{ - character::{digit1 as digit, space1 as space}, - combinator::opt, - multi::many0, - IResult, - }; - - fn parse_ints(input: Streaming<&[u8]>) -> IResult, Vec> { - many0(spaces_or_int)(input) - } - - fn spaces_or_int(input: Streaming<&[u8]>) -> IResult, i32> { - println!("{}", input.to_hex(8)); - let (i, _) = opt(space.complete())(input)?; - let (i, res) = digit - .complete() - .map(|x| { - println!("x: {:?}", x); - let result = str::from_utf8(x).unwrap(); - println!("Result: {}", result); - println!("int is empty?: {}", x.is_empty()); - match result.parse() { - Ok(i) => i, - Err(e) => panic!("UH OH! NOT A DIGIT! {:?}", e), - } - }) - .parse_next(i)?; - - Ok((i, res)) - } - - #[test] - fn issue_142() { - let subject = parse_ints(Streaming(&b"12 34 5689a"[..])); - let expected = Ok((Streaming(&b"a"[..]), vec![12, 34, 5689])); - assert_eq!(subject, expected); - - let subject = parse_ints(Streaming(&b"12 34 5689 "[..])); - let expected = Ok((Streaming(&b" "[..]), vec![12, 34, 5689])); - assert_eq!(subject, expected); - } + use std::str; + use winnow::input::HexDisplay; + use winnow::input::Streaming; + use winnow::prelude::*; + use winnow::{ + character::{digit1 as digit, space1 as space}, + combinator::opt, + multi::many0, + IResult, + }; + + fn parse_ints(input: Streaming<&[u8]>) -> IResult, Vec> { + many0(spaces_or_int)(input) + } + + fn spaces_or_int(input: Streaming<&[u8]>) -> IResult, i32> { + println!("{}", input.to_hex(8)); + let (i, _) = opt(space.complete())(input)?; + let (i, res) = digit + .complete() + .map(|x| { + println!("x: {:?}", x); + let result = str::from_utf8(x).unwrap(); + println!("Result: {}", result); + println!("int is empty?: {}", x.is_empty()); + match result.parse() { + Ok(i) => i, + Err(e) => panic!("UH OH! NOT A DIGIT! {:?}", e), + } + }) + .parse_next(i)?; + + Ok((i, res)) + } + + #[test] + fn issue_142() { + let subject = parse_ints(Streaming(&b"12 34 5689a"[..])); + let expected = Ok((Streaming(&b"a"[..]), vec![12, 34, 5689])); + assert_eq!(subject, expected); + + let subject = parse_ints(Streaming(&b"12 34 5689 "[..])); + let expected = Ok((Streaming(&b" "[..]), vec![12, 34, 5689])); + assert_eq!(subject, expected); + } } #[test] fn usize_length_bytes_issue() { - use winnow::multi::length_data; - use winnow::number::be_u16; - #[allow(clippy::type_complexity)] - let _: IResult, &[u8]> = length_data(be_u16)(Streaming(b"012346")); + use winnow::multi::length_data; + use winnow::number::be_u16; + #[allow(clippy::type_complexity)] + let _: IResult, &[u8]> = length_data(be_u16)(Streaming(b"012346")); } #[test] fn take_till0_issue() { - use winnow::bytes::take_till0; - - fn nothing(i: Streaming<&[u8]>) -> IResult, &[u8]> { - take_till0(|_| true)(i) - } - - assert_eq!( - nothing(Streaming(b"")), - Err(ErrMode::Incomplete(Needed::new(1))) - ); - assert_eq!( - nothing(Streaming(b"abc")), - Ok((Streaming(&b"abc"[..]), &b""[..])) - ); + use winnow::bytes::take_till0; + + fn nothing(i: Streaming<&[u8]>) -> IResult, &[u8]> { + take_till0(|_| true)(i) + } + + assert_eq!( + nothing(Streaming(b"")), + Err(ErrMode::Incomplete(Needed::new(1))) + ); + assert_eq!( + nothing(Streaming(b"abc")), + Ok((Streaming(&b"abc"[..]), &b""[..])) + ); } #[test] fn issue_655() { - use winnow::character::{line_ending, not_line_ending}; - fn twolines(i: Streaming<&str>) -> IResult, (&str, &str)> { - let (i, l1) = not_line_ending(i)?; - let (i, _) = line_ending(i)?; - let (i, l2) = not_line_ending(i)?; - let (i, _) = line_ending(i)?; - - Ok((i, (l1, l2))) - } - - assert_eq!( - twolines(Streaming("foo\nbar\n")), - Ok((Streaming(""), ("foo", "bar"))) - ); - assert_eq!( - twolines(Streaming("féo\nbar\n")), - Ok((Streaming(""), ("féo", "bar"))) - ); - assert_eq!( - twolines(Streaming("foé\nbar\n")), - Ok((Streaming(""), ("foé", "bar"))) - ); - assert_eq!( - twolines(Streaming("foé\r\nbar\n")), - Ok((Streaming(""), ("foé", "bar"))) - ); + use winnow::character::{line_ending, not_line_ending}; + fn twolines(i: Streaming<&str>) -> IResult, (&str, &str)> { + let (i, l1) = not_line_ending(i)?; + let (i, _) = line_ending(i)?; + let (i, l2) = not_line_ending(i)?; + let (i, _) = line_ending(i)?; + + Ok((i, (l1, l2))) + } + + assert_eq!( + twolines(Streaming("foo\nbar\n")), + Ok((Streaming(""), ("foo", "bar"))) + ); + assert_eq!( + twolines(Streaming("féo\nbar\n")), + Ok((Streaming(""), ("féo", "bar"))) + ); + assert_eq!( + twolines(Streaming("foé\nbar\n")), + Ok((Streaming(""), ("foé", "bar"))) + ); + assert_eq!( + twolines(Streaming("foé\r\nbar\n")), + Ok((Streaming(""), ("foé", "bar"))) + ); } #[cfg(feature = "alloc")] fn issue_717(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { - use winnow::bytes::{tag, take_till1}; - use winnow::multi::separated_list0; + use winnow::bytes::{tag, take_till1}; + use winnow::multi::separated_list0; - separated_list0(tag([0x0]), take_till1([0x0u8]))(i) + separated_list0(tag([0x0]), take_till1([0x0u8]))(i) } mod issue_647 { - use winnow::bytes::tag; - use winnow::multi::separated_list0; - use winnow::prelude::*; - use winnow::{error::ErrMode, error::Error, number::be_f64, IResult}; - pub type Input<'a> = winnow::input::Streaming<&'a [u8]>; - - #[derive(PartialEq, Debug, Clone)] - struct Data { - c: f64, - v: Vec, - } - - #[allow(clippy::type_complexity)] - fn list<'a>( - input: Input<'a>, - _cs: &f64, - ) -> Result<(Input<'a>, Vec), ErrMode>>> { - separated_list0(tag(",").complete(), be_f64.complete())(input) - } - - fn data(input: Input<'_>) -> IResult, Data> { - let (i, c) = be_f64(input)?; - let (i, _) = tag("\n")(i)?; - let (i, v) = list(i, &c)?; - Ok((i, Data { c, v })) - } + use winnow::bytes::tag; + use winnow::multi::separated_list0; + use winnow::prelude::*; + use winnow::{error::ErrMode, error::Error, number::be_f64, IResult}; + pub type Input<'a> = winnow::input::Streaming<&'a [u8]>; + + #[derive(PartialEq, Debug, Clone)] + struct Data { + c: f64, + v: Vec, + } + + #[allow(clippy::type_complexity)] + fn list<'a>( + input: Input<'a>, + _cs: &f64, + ) -> Result<(Input<'a>, Vec), ErrMode>>> { + separated_list0(tag(",").complete(), be_f64.complete())(input) + } + + fn data(input: Input<'_>) -> IResult, Data> { + let (i, c) = be_f64(input)?; + let (i, _) = tag("\n")(i)?; + let (i, v) = list(i, &c)?; + Ok((i, Data { c, v })) + } } #[test] fn issue_848_overflow_incomplete_bits_to_bytes() { - fn take(i: Streaming<&[u8]>) -> IResult, &[u8]> { - use winnow::bytes::take; - take(0x2000000000000000_usize)(i) - } - fn parser(i: Streaming<&[u8]>) -> IResult, &[u8]> { - use winnow::bits::{bits, bytes}; - - bits(bytes(take))(i) - } - assert_eq!( - parser(Streaming(&b""[..])), - Err(ErrMode::Cut(winnow::error::Error { - input: Streaming(&b""[..]), - kind: ErrorKind::TooLarge - })) - ); + fn take(i: Streaming<&[u8]>) -> IResult, &[u8]> { + use winnow::bytes::take; + take(0x2000000000000000_usize)(i) + } + fn parser(i: Streaming<&[u8]>) -> IResult, &[u8]> { + use winnow::bits::{bits, bytes}; + + bits(bytes(take))(i) + } + assert_eq!( + parser(Streaming(&b""[..])), + Err(ErrMode::Cut(winnow::error::Error { + input: Streaming(&b""[..]), + kind: ErrorKind::TooLarge + })) + ); } #[test] fn issue_942() { - use winnow::error::{ContextError, ParseError}; - pub fn parser<'a, E: ParseError<&'a str> + ContextError<&'a str, &'static str>>( - i: &'a str, - ) -> IResult<&'a str, usize, E> { - use winnow::{bytes::one_of, multi::many0}; - many0(one_of('a').context("char_a"))(i) - } - assert_eq!(parser::<()>("aaa"), Ok(("", 3))); + use winnow::error::{ContextError, ParseError}; + pub fn parser<'a, E: ParseError<&'a str> + ContextError<&'a str, &'static str>>( + i: &'a str, + ) -> IResult<&'a str, usize, E> { + use winnow::{bytes::one_of, multi::many0}; + many0(one_of('a').context("char_a"))(i) + } + assert_eq!(parser::<()>("aaa"), Ok(("", 3))); } #[test] #[cfg(feature = "std")] fn issue_many_m_n_with_zeros() { - use winnow::multi::many_m_n; - let mut parser = many_m_n::<_, _, Vec<_>, (), _>(0, 0, 'a'); - assert_eq!(parser("aaa"), Ok(("aaa", vec![]))); + use winnow::multi::many_m_n; + let mut parser = many_m_n::<_, _, Vec<_>, (), _>(0, 0, 'a'); + assert_eq!(parser("aaa"), Ok(("aaa", vec![]))); } #[test] fn issue_1027_convert_error_panic_nonempty() { - use winnow::error::{convert_error, VerboseError}; + use winnow::error::{convert_error, VerboseError}; - let input = "a"; + let input = "a"; - let result: IResult<_, _, VerboseError<&str>> = ('a', 'b').parse_next(input); - let err = match result.unwrap_err() { - ErrMode::Backtrack(e) => e, - _ => unreachable!(), - }; + let result: IResult<_, _, VerboseError<&str>> = ('a', 'b').parse_next(input); + let err = match result.unwrap_err() { + ErrMode::Backtrack(e) => e, + _ => unreachable!(), + }; - let msg = convert_error(input, err); - assert_eq!(msg, "0: at line 1, in OneOf:\na\n ^\n\n",); + let msg = convert_error(input, err); + assert_eq!(msg, "0: at line 1, in OneOf:\na\n ^\n\n",); } #[test] fn issue_1231_bits_expect_fn_closure() { - use winnow::bits::{bits, take}; - use winnow::error::Error; - pub fn example(input: &[u8]) -> IResult<&[u8], (u8, u8)> { - bits::<_, _, Error<_>, _, _>((take(1usize), take(1usize)))(input) - } - assert_eq!(example(&[0xff]), Ok((&b""[..], (1, 1)))); + use winnow::bits::{bits, take}; + use winnow::error::Error; + pub fn example(input: &[u8]) -> IResult<&[u8], (u8, u8)> { + bits::<_, _, Error<_>, _, _>((take(1usize), take(1usize)))(input) + } + assert_eq!(example(&[0xff]), Ok((&b""[..], (1, 1)))); } #[test] fn issue_1282_findtoken_char() { - use winnow::bytes::one_of; - use winnow::error::Error; - let parser = one_of::<_, _, Error<_>, false>(&['a', 'b', 'c'][..]); - assert_eq!(parser("aaa"), Ok(("aa", 'a'))); + use winnow::bytes::one_of; + use winnow::error::Error; + let parser = one_of::<_, _, Error<_>, false>(&['a', 'b', 'c'][..]); + assert_eq!(parser("aaa"), Ok(("aa", 'a'))); } #[test] fn issue_x_looser_fill_bounds() { - use winnow::{bytes::tag, character::digit1, multi::fill, sequence::terminated}; - - fn fill_pair(i: &[u8]) -> IResult<&[u8], [&[u8]; 2]> { - let mut buf = [&[][..], &[][..]]; - let (i, _) = fill(terminated(digit1, tag(",")), &mut buf)(i)?; - Ok((i, buf)) - } - - assert_eq!( - fill_pair(b"123,456,"), - Ok((&b""[..], [&b"123"[..], &b"456"[..]])) - ); - assert_eq!( - fill_pair(b"123,456,789"), - Ok((&b"789"[..], [&b"123"[..], &b"456"[..]])) - ); - assert_eq!( - fill_pair(b"123,,"), - Err(ErrMode::Backtrack(winnow::error::Error { - input: &b","[..], - kind: ErrorKind::Digit - })) - ); + use winnow::{bytes::tag, character::digit1, multi::fill, sequence::terminated}; + + fn fill_pair(i: &[u8]) -> IResult<&[u8], [&[u8]; 2]> { + let mut buf = [&[][..], &[][..]]; + let (i, _) = fill(terminated(digit1, tag(",")), &mut buf)(i)?; + Ok((i, buf)) + } + + assert_eq!( + fill_pair(b"123,456,"), + Ok((&b""[..], [&b"123"[..], &b"456"[..]])) + ); + assert_eq!( + fill_pair(b"123,456,789"), + Ok((&b"789"[..], [&b"123"[..], &b"456"[..]])) + ); + assert_eq!( + fill_pair(b"123,,"), + Err(ErrMode::Backtrack(winnow::error::Error { + input: &b","[..], + kind: ErrorKind::Digit + })) + ); } #[cfg(feature = "std")] fn issue_1459_clamp_capacity() { - // shouldn't panic - use winnow::multi::many_m_n; - let mut parser = many_m_n::<_, _, Vec<_>, (), _>(usize::MAX, usize::MAX, 'a'); - assert_eq!(parser("a"), Err(winnow::error::ErrMode::Backtrack(()))); - - // shouldn't panic - use winnow::multi::count; - let mut parser = count::<_, _, Vec<_>, (), _>('a', usize::MAX); - assert_eq!(parser("a"), Err(winnow::error::ErrMode::Backtrack(()))); + // shouldn't panic + use winnow::multi::many_m_n; + let mut parser = many_m_n::<_, _, Vec<_>, (), _>(usize::MAX, usize::MAX, 'a'); + assert_eq!(parser("a"), Err(winnow::error::ErrMode::Backtrack(()))); + + // shouldn't panic + use winnow::multi::count; + let mut parser = count::<_, _, Vec<_>, (), _>('a', usize::MAX); + assert_eq!(parser("a"), Err(winnow::error::ErrMode::Backtrack(()))); } #[test] fn issue_1617_count_parser_returning_zero_size() { - use winnow::{bytes::tag, error::Error, multi::count}; + use winnow::{bytes::tag, error::Error, multi::count}; - // previously, `count()` panicked if the parser had type `O = ()` - let parser = tag::<_, _, Error<&str>, false>("abc").map(|_| ()); - // shouldn't panic - let result = count(parser, 3)("abcabcabcdef").expect("parsing should succeed"); - assert_eq!(result, ("def", vec![(), (), ()])); + // previously, `count()` panicked if the parser had type `O = ()` + let parser = tag::<_, _, Error<&str>, false>("abc").map(|_| ()); + // shouldn't panic + let result = count(parser, 3)("abcabcabcdef").expect("parsing should succeed"); + assert_eq!(result, ("def", vec![(), (), ()])); } diff --git a/tests/testsuite/multiline.rs b/tests/testsuite/multiline.rs index 79639e3d..2d96950f 100644 --- a/tests/testsuite/multiline.rs +++ b/tests/testsuite/multiline.rs @@ -1,33 +1,33 @@ #![cfg(feature = "alloc")] use winnow::{ - character::{alphanumeric1 as alphanumeric, line_ending as eol}, - multi::many0, - sequence::terminated, - IResult, + character::{alphanumeric1 as alphanumeric, line_ending as eol}, + multi::many0, + sequence::terminated, + IResult, }; pub fn end_of_line(input: &str) -> IResult<&str, &str> { - if input.is_empty() { - Ok((input, input)) - } else { - eol(input) - } + if input.is_empty() { + Ok((input, input)) + } else { + eol(input) + } } pub fn read_line(input: &str) -> IResult<&str, &str> { - terminated(alphanumeric, end_of_line)(input) + terminated(alphanumeric, end_of_line)(input) } pub fn read_lines(input: &str) -> IResult<&str, Vec<&str>> { - many0(read_line)(input) + many0(read_line)(input) } #[cfg(feature = "alloc")] #[test] fn read_lines_test() { - let res = Ok(("", vec!["Duck", "Dog", "Cow"])); + let res = Ok(("", vec!["Duck", "Dog", "Cow"])); - assert_eq!(read_lines("Duck\nDog\nCow\n"), res); - assert_eq!(read_lines("Duck\nDog\nCow"), res); + assert_eq!(read_lines("Duck\nDog\nCow\n"), res); + assert_eq!(read_lines("Duck\nDog\nCow"), res); } diff --git a/tests/testsuite/overflow.rs b/tests/testsuite/overflow.rs index 14ecc2d4..bc66b579 100644 --- a/tests/testsuite/overflow.rs +++ b/tests/testsuite/overflow.rs @@ -15,150 +15,150 @@ use winnow::prelude::*; // We request a length that would trigger an overflow if computing consumed + requested #[allow(clippy::type_complexity)] fn parser02(i: Streaming<&[u8]>) -> IResult, (&[u8], &[u8])> { - (take(1_usize), take(18446744073709551615_usize)).parse_next(i) + (take(1_usize), take(18446744073709551615_usize)).parse_next(i) } #[test] fn overflow_incomplete_tuple() { - assert_eq!( - parser02(Streaming(&b"3"[..])), - Err(ErrMode::Incomplete(Needed::new(18446744073709551615))) - ); + assert_eq!( + parser02(Streaming(&b"3"[..])), + Err(ErrMode::Incomplete(Needed::new(18446744073709551615))) + ); } #[test] #[cfg(feature = "alloc")] fn overflow_incomplete_length_bytes() { - fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - many0(length_data(be_u64))(i) - } - - // Trigger an overflow in length_data - assert_eq!( - multi(Streaming( - &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xff"[..] - )), - Err(ErrMode::Incomplete(Needed::new(18446744073709551615))) - ); + fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + many0(length_data(be_u64))(i) + } + + // Trigger an overflow in length_data + assert_eq!( + multi(Streaming( + &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xff"[..] + )), + Err(ErrMode::Incomplete(Needed::new(18446744073709551615))) + ); } #[test] #[cfg(feature = "alloc")] fn overflow_incomplete_many0() { - fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - many0(length_data(be_u64))(i) - } - - // Trigger an overflow in many0 - assert_eq!( - multi(Streaming( - &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..] - )), - Err(ErrMode::Incomplete(Needed::new(18446744073709551599))) - ); + fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + many0(length_data(be_u64))(i) + } + + // Trigger an overflow in many0 + assert_eq!( + multi(Streaming( + &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..] + )), + Err(ErrMode::Incomplete(Needed::new(18446744073709551599))) + ); } #[test] #[cfg(feature = "alloc")] fn overflow_incomplete_many1() { - use winnow::multi::many1; - - fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - many1(length_data(be_u64))(i) - } - - // Trigger an overflow in many1 - assert_eq!( - multi(Streaming( - &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..] - )), - Err(ErrMode::Incomplete(Needed::new(18446744073709551599))) - ); + use winnow::multi::many1; + + fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + many1(length_data(be_u64))(i) + } + + // Trigger an overflow in many1 + assert_eq!( + multi(Streaming( + &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..] + )), + Err(ErrMode::Incomplete(Needed::new(18446744073709551599))) + ); } #[test] #[cfg(feature = "alloc")] fn overflow_incomplete_many_till0() { - use winnow::{bytes::tag, multi::many_till0}; - - #[allow(clippy::type_complexity)] - fn multi(i: Streaming<&[u8]>) -> IResult, (Vec<&[u8]>, &[u8])> { - many_till0(length_data(be_u64), tag("abc"))(i) - } - - // Trigger an overflow in many_till0 - assert_eq!( - multi(Streaming( - &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..] - )), - Err(ErrMode::Incomplete(Needed::new(18446744073709551599))) - ); + use winnow::{bytes::tag, multi::many_till0}; + + #[allow(clippy::type_complexity)] + fn multi(i: Streaming<&[u8]>) -> IResult, (Vec<&[u8]>, &[u8])> { + many_till0(length_data(be_u64), tag("abc"))(i) + } + + // Trigger an overflow in many_till0 + assert_eq!( + multi(Streaming( + &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..] + )), + Err(ErrMode::Incomplete(Needed::new(18446744073709551599))) + ); } #[test] #[cfg(feature = "alloc")] fn overflow_incomplete_many_m_n() { - use winnow::multi::many_m_n; - - fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - many_m_n(2, 4, length_data(be_u64))(i) - } - - // Trigger an overflow in many_m_n - assert_eq!( - multi(Streaming( - &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..] - )), - Err(ErrMode::Incomplete(Needed::new(18446744073709551599))) - ); + use winnow::multi::many_m_n; + + fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + many_m_n(2, 4, length_data(be_u64))(i) + } + + // Trigger an overflow in many_m_n + assert_eq!( + multi(Streaming( + &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..] + )), + Err(ErrMode::Incomplete(Needed::new(18446744073709551599))) + ); } #[test] #[cfg(feature = "alloc")] fn overflow_incomplete_count() { - use winnow::multi::count; - - fn counter(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - count(length_data(be_u64), 2)(i) - } - - assert_eq!( - counter(Streaming( - &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..] - )), - Err(ErrMode::Incomplete(Needed::new(18446744073709551599))) - ); + use winnow::multi::count; + + fn counter(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + count(length_data(be_u64), 2)(i) + } + + assert_eq!( + counter(Streaming( + &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..] + )), + Err(ErrMode::Incomplete(Needed::new(18446744073709551599))) + ); } #[test] #[cfg(feature = "alloc")] fn overflow_incomplete_length_count() { - use winnow::multi::length_count; - use winnow::number::be_u8; - - fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - length_count(be_u8, length_data(be_u64))(i) - } - - assert_eq!( - multi(Streaming( - &b"\x04\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xee"[..] - )), - Err(ErrMode::Incomplete(Needed::new(18446744073709551598))) - ); + use winnow::multi::length_count; + use winnow::number::be_u8; + + fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + length_count(be_u8, length_data(be_u64))(i) + } + + assert_eq!( + multi(Streaming( + &b"\x04\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xee"[..] + )), + Err(ErrMode::Incomplete(Needed::new(18446744073709551598))) + ); } #[test] #[cfg(feature = "alloc")] fn overflow_incomplete_length_data() { - fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { - many0(length_data(be_u64))(i) - } - - assert_eq!( - multi(Streaming( - &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xff"[..] - )), - Err(ErrMode::Incomplete(Needed::new(18446744073709551615))) - ); + fn multi(i: Streaming<&[u8]>) -> IResult, Vec<&[u8]>> { + many0(length_data(be_u64))(i) + } + + assert_eq!( + multi(Streaming( + &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xff"[..] + )), + Err(ErrMode::Incomplete(Needed::new(18446744073709551615))) + ); } diff --git a/tests/testsuite/reborrow_fold.rs b/tests/testsuite/reborrow_fold.rs index cee9b0f6..3faf2a07 100644 --- a/tests/testsuite/reborrow_fold.rs +++ b/tests/testsuite/reborrow_fold.rs @@ -10,22 +10,22 @@ use winnow::sequence::delimited; use winnow::IResult; fn atom(_tomb: &mut ()) -> impl for<'a> FnMut(&'a [u8]) -> IResult<&'a [u8], String> { - move |input| { - take_till1(" \t\r\n") - .map_res(str::from_utf8) - .map(ToString::to_string) - .parse_next(input) - } + move |input| { + take_till1(" \t\r\n") + .map_res(str::from_utf8) + .map(ToString::to_string) + .parse_next(input) + } } // FIXME: should we support the use case of borrowing data mutably in a parser? fn list<'a>(i: &'a [u8], tomb: &mut ()) -> IResult<&'a [u8], String> { - delimited( - '(', - fold_many0(atom(tomb), String::new, |mut acc: String, next: String| { - acc.push_str(next.as_str()); - acc - }), - ')', - )(i) + delimited( + '(', + fold_many0(atom(tomb), String::new, |mut acc: String, next: String| { + acc.push_str(next.as_str()); + acc + }), + ')', + )(i) } diff --git a/tests/testsuite/utf8.rs b/tests/testsuite/utf8.rs index af804c85..7f176add 100644 --- a/tests/testsuite/utf8.rs +++ b/tests/testsuite/utf8.rs @@ -1,529 +1,529 @@ #[cfg(test)] mod test { - use winnow::input::Streaming; - #[cfg(feature = "alloc")] - use winnow::{branch::alt, bytes::tag_no_case, multi::many1}; - use winnow::{ - bytes::{tag, take, take_till0, take_till1, take_until0, take_while1}, - error::ErrMode, - error::{self, Error, ErrorKind}, - IResult, - }; - - #[test] - fn tag_succeed_str() { - const INPUT: &str = "Hello World!"; - const TAG: &str = "Hello"; - fn test(input: &str) -> IResult<&str, &str> { - tag(TAG)(input) - } + use winnow::input::Streaming; + #[cfg(feature = "alloc")] + use winnow::{branch::alt, bytes::tag_no_case, multi::many1}; + use winnow::{ + bytes::{tag, take, take_till0, take_till1, take_until0, take_while1}, + error::ErrMode, + error::{self, Error, ErrorKind}, + IResult, + }; - match test(INPUT) { - Ok((extra, output)) => { - assert!(extra == " World!", "Parser `tag` consumed leftover input."); - assert!( - output == TAG, - "Parser `tag` doesn't return the tag it matched on success. \ + #[test] + fn tag_succeed_str() { + const INPUT: &str = "Hello World!"; + const TAG: &str = "Hello"; + fn test(input: &str) -> IResult<&str, &str> { + tag(TAG)(input) + } + + match test(INPUT) { + Ok((extra, output)) => { + assert!(extra == " World!", "Parser `tag` consumed leftover input."); + assert!( + output == TAG, + "Parser `tag` doesn't return the tag it matched on success. \ Expected `{}`, got `{}`.", - TAG, - output - ); - } - other => panic!( - "Parser `tag` didn't succeed when it should have. \ + TAG, + output + ); + } + other => panic!( + "Parser `tag` didn't succeed when it should have. \ Got `{:?}`.", - other - ), - }; - } + other + ), + }; + } - #[test] - fn tag_incomplete_str() { - use winnow::bytes::tag; + #[test] + fn tag_incomplete_str() { + use winnow::bytes::tag; - const INPUT: &str = "Hello"; - const TAG: &str = "Hello World!"; + const INPUT: &str = "Hello"; + const TAG: &str = "Hello World!"; - let res: IResult<_, _, error::Error<_>> = tag(TAG)(Streaming(INPUT)); - match res { - Err(ErrMode::Incomplete(_)) => (), - other => { - panic!( - "Parser `tag` didn't require more input when it should have. \ + let res: IResult<_, _, error::Error<_>> = tag(TAG)(Streaming(INPUT)); + match res { + Err(ErrMode::Incomplete(_)) => (), + other => { + panic!( + "Parser `tag` didn't require more input when it should have. \ Got `{:?}`.", - other - ); - } - }; - } - - #[test] - fn tag_error_str() { - const INPUT: &str = "Hello World!"; - const TAG: &str = "Random"; // TAG must be closer than INPUT. - - let res: IResult<_, _, error::Error<_>> = tag(TAG)(INPUT); - match res { - Err(ErrMode::Backtrack(_)) => (), - other => { - panic!( - "Parser `tag` didn't fail when it should have. Got `{:?}`.`", - other - ); - } - }; - } + other + ); + } + }; + } - #[cfg(feature = "alloc")] - #[test] - fn tag_case_insensitive_str() { - fn test(i: &str) -> IResult<&str, &str> { - tag_no_case("ABcd")(i) + #[test] + fn tag_error_str() { + const INPUT: &str = "Hello World!"; + const TAG: &str = "Random"; // TAG must be closer than INPUT. + + let res: IResult<_, _, error::Error<_>> = tag(TAG)(INPUT); + match res { + Err(ErrMode::Backtrack(_)) => (), + other => { + panic!( + "Parser `tag` didn't fail when it should have. Got `{:?}`.`", + other + ); + } + }; } - assert_eq!(test("aBCdefgh"), Ok(("efgh", "aBCd"))); - assert_eq!(test("abcdefgh"), Ok(("efgh", "abcd"))); - assert_eq!(test("ABCDefgh"), Ok(("efgh", "ABCD"))); - } - - #[test] - fn take_succeed_str() { - const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; - const CONSUMED: &str = "βèƒôřèÂßÇ"; - const LEFTOVER: &str = "áƒƭèř"; - - let res: IResult<_, _, error::Error<_>> = take(9_usize)(INPUT); - match res { - Ok((extra, output)) => { - assert!( - extra == LEFTOVER, - "Parser `take_s` consumed leftover input. Leftover `{}`.", - extra - ); - assert!( + + #[cfg(feature = "alloc")] + #[test] + fn tag_case_insensitive_str() { + fn test(i: &str) -> IResult<&str, &str> { + tag_no_case("ABcd")(i) + } + assert_eq!(test("aBCdefgh"), Ok(("efgh", "aBCd"))); + assert_eq!(test("abcdefgh"), Ok(("efgh", "abcd"))); + assert_eq!(test("ABCDefgh"), Ok(("efgh", "ABCD"))); + } + + #[test] + fn take_succeed_str() { + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + const CONSUMED: &str = "βèƒôřèÂßÇ"; + const LEFTOVER: &str = "áƒƭèř"; + + let res: IResult<_, _, error::Error<_>> = take(9_usize)(INPUT); + match res { + Ok((extra, output)) => { + assert!( + extra == LEFTOVER, + "Parser `take_s` consumed leftover input. Leftover `{}`.", + extra + ); + assert!( output == CONSUMED, "Parser `take_s` doesn't return the string it consumed on success. Expected `{}`, got `{}`.", CONSUMED, output ); - } - other => panic!( - "Parser `take_s` didn't succeed when it should have. \ + } + other => panic!( + "Parser `take_s` didn't succeed when it should have. \ Got `{:?}`.", - other - ), - }; - } + other + ), + }; + } - #[test] - fn take_incomplete_str() { - use winnow::bytes::take; + #[test] + fn take_incomplete_str() { + use winnow::bytes::take; - const INPUT: &str = "βèƒôřèÂßÇá"; + const INPUT: &str = "βèƒôřèÂßÇá"; - let res: IResult<_, _, Error<_>> = take(13_usize)(Streaming(INPUT)); - match res { - Err(ErrMode::Incomplete(_)) => (), - other => panic!( - "Parser `take` didn't require more input when it should have. \ + let res: IResult<_, _, Error<_>> = take(13_usize)(Streaming(INPUT)); + match res { + Err(ErrMode::Incomplete(_)) => (), + other => panic!( + "Parser `take` didn't require more input when it should have. \ Got `{:?}`.", - other - ), + other + ), + } } - } - - #[test] - fn take_until_succeed_str() { - const INPUT: &str = "βèƒôřèÂßÇ∂áƒƭèř"; - const FIND: &str = "ÂßÇ∂"; - const CONSUMED: &str = "βèƒôřè"; - const LEFTOVER: &str = "ÂßÇ∂áƒƭèř"; - - let res: IResult<_, _, Error<_>> = take_until0(FIND)(INPUT); - match res { - Ok((extra, output)) => { - assert!( - extra == LEFTOVER, - "Parser `take_until0`\ + + #[test] + fn take_until_succeed_str() { + const INPUT: &str = "βèƒôřèÂßÇ∂áƒƭèř"; + const FIND: &str = "ÂßÇ∂"; + const CONSUMED: &str = "βèƒôřè"; + const LEFTOVER: &str = "ÂßÇ∂áƒƭèř"; + + let res: IResult<_, _, Error<_>> = take_until0(FIND)(INPUT); + match res { + Ok((extra, output)) => { + assert!( + extra == LEFTOVER, + "Parser `take_until0`\ consumed leftover input. Leftover `{}`.", - extra - ); - assert!( - output == CONSUMED, - "Parser `take_until0`\ + extra + ); + assert!( + output == CONSUMED, + "Parser `take_until0`\ doesn't return the string it consumed on success. Expected `{}`, got `{}`.", - CONSUMED, - output - ); - } - other => panic!( - "Parser `take_until0` didn't succeed when it should have. \ + CONSUMED, + output + ); + } + other => panic!( + "Parser `take_until0` didn't succeed when it should have. \ Got `{:?}`.", - other - ), - }; - } + other + ), + }; + } - #[test] - fn take_until_incomplete_str() { - use winnow::bytes::take_until0; + #[test] + fn take_until_incomplete_str() { + use winnow::bytes::take_until0; - const INPUT: &str = "βèƒôřè"; - const FIND: &str = "βèƒôřèÂßÇ"; + const INPUT: &str = "βèƒôřè"; + const FIND: &str = "βèƒôřèÂßÇ"; - let res: IResult<_, _, Error<_>> = take_until0(FIND)(Streaming(INPUT)); - match res { - Err(ErrMode::Incomplete(_)) => (), - other => panic!( - "Parser `take_until0` didn't require more input when it should have. \ + let res: IResult<_, _, Error<_>> = take_until0(FIND)(Streaming(INPUT)); + match res { + Err(ErrMode::Incomplete(_)) => (), + other => panic!( + "Parser `take_until0` didn't require more input when it should have. \ Got `{:?}`.", - other - ), - }; - } + other + ), + }; + } - #[test] - fn take_until_error_str() { - use winnow::bytes::take_until0; + #[test] + fn take_until_error_str() { + use winnow::bytes::take_until0; - const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; - const FIND: &str = "Ráñδô₥"; + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + const FIND: &str = "Ráñδô₥"; - let res: IResult<_, _, Error<_>> = take_until0(FIND)(Streaming(INPUT)); - match res { - Err(ErrMode::Incomplete(_)) => (), - other => panic!( - "Parser `take_until0` didn't fail when it should have. \ + let res: IResult<_, _, Error<_>> = take_until0(FIND)(Streaming(INPUT)); + match res { + Err(ErrMode::Incomplete(_)) => (), + other => panic!( + "Parser `take_until0` didn't fail when it should have. \ Got `{:?}`.", - other - ), - }; - } + other + ), + }; + } - fn is_alphabetic(c: char) -> bool { - (c as u8 >= 0x41 && c as u8 <= 0x5A) || (c as u8 >= 0x61 && c as u8 <= 0x7A) - } + fn is_alphabetic(c: char) -> bool { + (c as u8 >= 0x41 && c as u8 <= 0x5A) || (c as u8 >= 0x61 && c as u8 <= 0x7A) + } - #[test] - fn take_while_str() { - use winnow::error::Needed; + #[test] + fn take_while_str() { + use winnow::error::Needed; - use winnow::bytes::take_while0; + use winnow::bytes::take_while0; - fn f(i: Streaming<&str>) -> IResult, &str> { - take_while0(is_alphabetic)(i) - } - let a = ""; - let b = "abcd"; - let c = "abcd123"; - let d = "123"; - - assert_eq!(f(Streaming(a)), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(f(Streaming(b)), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(f(Streaming(c)), Ok((Streaming(d), b))); - assert_eq!(f(Streaming(d)), Ok((Streaming(d), a))); - } - - #[test] - fn take_while_succeed_none_str() { - use winnow::bytes::take_while0; - - const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; - const CONSUMED: &str = ""; - const LEFTOVER: &str = "βèƒôřèÂßÇáƒƭèř"; - fn while_s(c: char) -> bool { - c == '9' - } - fn test(input: &str) -> IResult<&str, &str> { - take_while0(while_s)(input) + fn f(i: Streaming<&str>) -> IResult, &str> { + take_while0(is_alphabetic)(i) + } + let a = ""; + let b = "abcd"; + let c = "abcd123"; + let d = "123"; + + assert_eq!(f(Streaming(a)), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(f(Streaming(b)), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(f(Streaming(c)), Ok((Streaming(d), b))); + assert_eq!(f(Streaming(d)), Ok((Streaming(d), a))); } - match test(INPUT) { - Ok((extra, output)) => { - assert!( - extra == LEFTOVER, - "Parser `take_while0` consumed leftover input." - ); - assert!( - output == CONSUMED, - "Parser `take_while0` doesn't return the string it consumed on success. \ + + #[test] + fn take_while_succeed_none_str() { + use winnow::bytes::take_while0; + + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + const CONSUMED: &str = ""; + const LEFTOVER: &str = "βèƒôřèÂßÇáƒƭèř"; + fn while_s(c: char) -> bool { + c == '9' + } + fn test(input: &str) -> IResult<&str, &str> { + take_while0(while_s)(input) + } + match test(INPUT) { + Ok((extra, output)) => { + assert!( + extra == LEFTOVER, + "Parser `take_while0` consumed leftover input." + ); + assert!( + output == CONSUMED, + "Parser `take_while0` doesn't return the string it consumed on success. \ Expected `{}`, got `{}`.", - CONSUMED, - output - ); - } - other => panic!( - "Parser `take_while0` didn't succeed when it should have. \ + CONSUMED, + output + ); + } + other => panic!( + "Parser `take_while0` didn't succeed when it should have. \ Got `{:?}`.", - other - ), - }; - } - - #[test] - fn take_while_succeed_some_str() { - use winnow::bytes::take_while0; - - const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; - const CONSUMED: &str = "βèƒôřèÂßÇ"; - const LEFTOVER: &str = "áƒƭèř"; - fn while_s(c: char) -> bool { - matches!(c, 'β' | 'è' | 'ƒ' | 'ô' | 'ř' | 'Â' | 'ß' | 'Ç') + other + ), + }; } - fn test(input: &str) -> IResult<&str, &str> { - take_while0(while_s)(input) - } - match test(INPUT) { - Ok((extra, output)) => { - assert!( - extra == LEFTOVER, - "Parser `take_while0` consumed leftover input." - ); - assert!( - output == CONSUMED, - "Parser `take_while0` doesn't return the string it consumed on success. \ + + #[test] + fn take_while_succeed_some_str() { + use winnow::bytes::take_while0; + + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + const CONSUMED: &str = "βèƒôřèÂßÇ"; + const LEFTOVER: &str = "áƒƭèř"; + fn while_s(c: char) -> bool { + matches!(c, 'β' | 'è' | 'ƒ' | 'ô' | 'ř' | 'Â' | 'ß' | 'Ç') + } + fn test(input: &str) -> IResult<&str, &str> { + take_while0(while_s)(input) + } + match test(INPUT) { + Ok((extra, output)) => { + assert!( + extra == LEFTOVER, + "Parser `take_while0` consumed leftover input." + ); + assert!( + output == CONSUMED, + "Parser `take_while0` doesn't return the string it consumed on success. \ Expected `{}`, got `{}`.", - CONSUMED, - output - ); - } - other => panic!( - "Parser `take_while0` didn't succeed when it should have. \ + CONSUMED, + output + ); + } + other => panic!( + "Parser `take_while0` didn't succeed when it should have. \ Got `{:?}`.", - other - ), - }; - } - - #[test] - fn test_take_while1_str() { - use winnow::error::Needed; - - fn f(i: Streaming<&str>) -> IResult, &str> { - take_while1(is_alphabetic)(i) - } - let a = ""; - let b = "abcd"; - let c = "abcd123"; - let d = "123"; - - assert_eq!(f(Streaming(a)), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(f(Streaming(b)), Err(ErrMode::Incomplete(Needed::new(1)))); - assert_eq!(f(Streaming(c)), Ok((Streaming("123"), b))); - assert_eq!( - f(Streaming(d)), - Err(ErrMode::Backtrack(winnow::error::Error { - input: Streaming(d), - kind: ErrorKind::TakeWhile1 - })) - ); - } - - #[test] - fn take_while1_fn_succeed_str() { - use winnow::bytes::take_while1; - - const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; - const CONSUMED: &str = "βèƒôřèÂßÇ"; - const LEFTOVER: &str = "áƒƭèř"; - fn while1_s(c: char) -> bool { - matches!(c, 'β' | 'è' | 'ƒ' | 'ô' | 'ř' | 'Â' | 'ß' | 'Ç') + other + ), + }; } - fn test(input: &str) -> IResult<&str, &str> { - take_while1(while1_s)(input) - } - match test(INPUT) { - Ok((extra, output)) => { - assert!( - extra == LEFTOVER, - "Parser `take_while1` consumed leftover input." + + #[test] + fn test_take_while1_str() { + use winnow::error::Needed; + + fn f(i: Streaming<&str>) -> IResult, &str> { + take_while1(is_alphabetic)(i) + } + let a = ""; + let b = "abcd"; + let c = "abcd123"; + let d = "123"; + + assert_eq!(f(Streaming(a)), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(f(Streaming(b)), Err(ErrMode::Incomplete(Needed::new(1)))); + assert_eq!(f(Streaming(c)), Ok((Streaming("123"), b))); + assert_eq!( + f(Streaming(d)), + Err(ErrMode::Backtrack(winnow::error::Error { + input: Streaming(d), + kind: ErrorKind::TakeWhile1 + })) ); - assert!( - output == CONSUMED, - "Parser `take_while1` doesn't return the string it consumed on success. \ + } + + #[test] + fn take_while1_fn_succeed_str() { + use winnow::bytes::take_while1; + + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + const CONSUMED: &str = "βèƒôřèÂßÇ"; + const LEFTOVER: &str = "áƒƭèř"; + fn while1_s(c: char) -> bool { + matches!(c, 'β' | 'è' | 'ƒ' | 'ô' | 'ř' | 'Â' | 'ß' | 'Ç') + } + fn test(input: &str) -> IResult<&str, &str> { + take_while1(while1_s)(input) + } + match test(INPUT) { + Ok((extra, output)) => { + assert!( + extra == LEFTOVER, + "Parser `take_while1` consumed leftover input." + ); + assert!( + output == CONSUMED, + "Parser `take_while1` doesn't return the string it consumed on success. \ Expected `{}`, got `{}`.", - CONSUMED, - output - ); - } - other => panic!( - "Parser `take_while1` didn't succeed when it should have. \ + CONSUMED, + output + ); + } + other => panic!( + "Parser `take_while1` didn't succeed when it should have. \ Got `{:?}`.", - other - ), - }; - } - - #[test] - fn take_while1_set_succeed_str() { - const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; - const MATCH: &str = "βèƒôřèÂßÇ"; - const CONSUMED: &str = "βèƒôřèÂßÇ"; - const LEFTOVER: &str = "áƒƭèř"; - fn test(input: &str) -> IResult<&str, &str> { - take_while1(MATCH)(input) + other + ), + }; } - match test(INPUT) { - Ok((extra, output)) => { - assert!( - extra == LEFTOVER, - "Parser `is_a` consumed leftover input. Leftover `{}`.", - extra - ); - assert!( + + #[test] + fn take_while1_set_succeed_str() { + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + const MATCH: &str = "βèƒôřèÂßÇ"; + const CONSUMED: &str = "βèƒôřèÂßÇ"; + const LEFTOVER: &str = "áƒƭèř"; + fn test(input: &str) -> IResult<&str, &str> { + take_while1(MATCH)(input) + } + match test(INPUT) { + Ok((extra, output)) => { + assert!( + extra == LEFTOVER, + "Parser `is_a` consumed leftover input. Leftover `{}`.", + extra + ); + assert!( output == CONSUMED, "Parser `is_a` doesn't return the string it consumed on success. Expected `{}`, got `{}`.", CONSUMED, output ); - } - other => panic!( - "Parser `is_a` didn't succeed when it should have. \ + } + other => panic!( + "Parser `is_a` didn't succeed when it should have. \ Got `{:?}`.", - other - ), - }; - } - - #[test] - fn take_while1_fn_fail_str() { - use winnow::bytes::take_while1; - - const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; - fn while1_s(c: char) -> bool { - c == '9' - } - fn test(input: &str) -> IResult<&str, &str> { - take_while1(while1_s)(input) + other + ), + }; } - match test(INPUT) { - Err(ErrMode::Backtrack(_)) => (), - other => panic!( - "Parser `take_while1` didn't fail when it should have. \ + + #[test] + fn take_while1_fn_fail_str() { + use winnow::bytes::take_while1; + + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + fn while1_s(c: char) -> bool { + c == '9' + } + fn test(input: &str) -> IResult<&str, &str> { + take_while1(while1_s)(input) + } + match test(INPUT) { + Err(ErrMode::Backtrack(_)) => (), + other => panic!( + "Parser `take_while1` didn't fail when it should have. \ Got `{:?}`.", - other - ), - }; - } - - #[test] - fn take_while1_set_fail_str() { - const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; - const MATCH: &str = "Ûñℓúçƙ¥"; - fn test(input: &str) -> IResult<&str, &str> { - take_while1(MATCH)(input) - } - match test(INPUT) { - Err(ErrMode::Backtrack(_)) => (), - other => panic!( - "Parser `is_a` didn't fail when it should have. Got `{:?}`.", - other - ), - }; - } - - #[test] - fn take_till0_succeed_str() { - const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; - const CONSUMED: &str = "βèƒôřèÂßÇ"; - const LEFTOVER: &str = "áƒƭèř"; - fn till_s(c: char) -> bool { - c == 'á' + other + ), + }; } - fn test(input: &str) -> IResult<&str, &str> { - take_till0(till_s)(input) + + #[test] + fn take_while1_set_fail_str() { + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + const MATCH: &str = "Ûñℓúçƙ¥"; + fn test(input: &str) -> IResult<&str, &str> { + take_while1(MATCH)(input) + } + match test(INPUT) { + Err(ErrMode::Backtrack(_)) => (), + other => panic!( + "Parser `is_a` didn't fail when it should have. Got `{:?}`.", + other + ), + }; } - match test(INPUT) { - Ok((extra, output)) => { - assert!( - extra == LEFTOVER, - "Parser `take_till0` consumed leftover input." - ); - assert!( - output == CONSUMED, - "Parser `take_till0` doesn't return the string it consumed on success. \ + + #[test] + fn take_till0_succeed_str() { + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + const CONSUMED: &str = "βèƒôřèÂßÇ"; + const LEFTOVER: &str = "áƒƭèř"; + fn till_s(c: char) -> bool { + c == 'á' + } + fn test(input: &str) -> IResult<&str, &str> { + take_till0(till_s)(input) + } + match test(INPUT) { + Ok((extra, output)) => { + assert!( + extra == LEFTOVER, + "Parser `take_till0` consumed leftover input." + ); + assert!( + output == CONSUMED, + "Parser `take_till0` doesn't return the string it consumed on success. \ Expected `{}`, got `{}`.", - CONSUMED, - output - ); - } - other => panic!( - "Parser `take_till0` didn't succeed when it should have. \ + CONSUMED, + output + ); + } + other => panic!( + "Parser `take_till0` didn't succeed when it should have. \ Got `{:?}`.", - other - ), - }; - } - - #[test] - fn take_till1_succeed_str() { - const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; - const AVOID: &str = "£úçƙ¥á"; - const CONSUMED: &str = "βèƒôřèÂßÇ"; - const LEFTOVER: &str = "áƒƭèř"; - fn test(input: &str) -> IResult<&str, &str> { - take_till1(AVOID)(input) + other + ), + }; } - match test(INPUT) { - Ok((extra, output)) => { - assert!( - extra == LEFTOVER, - "Parser `take_till1` consumed leftover input. Leftover `{}`.", - extra - ); - assert!( + + #[test] + fn take_till1_succeed_str() { + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + const AVOID: &str = "£úçƙ¥á"; + const CONSUMED: &str = "βèƒôřèÂßÇ"; + const LEFTOVER: &str = "áƒƭèř"; + fn test(input: &str) -> IResult<&str, &str> { + take_till1(AVOID)(input) + } + match test(INPUT) { + Ok((extra, output)) => { + assert!( + extra == LEFTOVER, + "Parser `take_till1` consumed leftover input. Leftover `{}`.", + extra + ); + assert!( output == CONSUMED, "Parser `take_till1` doesn't return the string it consumed on success. Expected `{}`, got `{}`.", CONSUMED, output ); - } - other => panic!( - "Parser `take_till1` didn't succeed when it should have. \ + } + other => panic!( + "Parser `take_till1` didn't succeed when it should have. \ Got `{:?}`.", - other - ), - }; - } - - #[test] - fn take_till1_failed_str() { - const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; - const AVOID: &str = "βúçƙ¥"; - fn test(input: &str) -> IResult<&str, &str> { - take_till1(AVOID)(input) + other + ), + }; } - match test(INPUT) { - Err(ErrMode::Backtrack(_)) => (), - other => panic!( - "Parser `is_not` didn't fail when it should have. Got `{:?}`.", - other - ), - }; - } - #[test] - #[cfg(feature = "alloc")] - fn recognize_is_a_str() { - use winnow::prelude::*; + #[test] + fn take_till1_failed_str() { + const INPUT: &str = "βèƒôřèÂßÇáƒƭèř"; + const AVOID: &str = "βúçƙ¥"; + fn test(input: &str) -> IResult<&str, &str> { + take_till1(AVOID)(input) + } + match test(INPUT) { + Err(ErrMode::Backtrack(_)) => (), + other => panic!( + "Parser `is_not` didn't fail when it should have. Got `{:?}`.", + other + ), + }; + } - let a = "aabbab"; - let b = "ababcd"; + #[test] + #[cfg(feature = "alloc")] + fn recognize_is_a_str() { + use winnow::prelude::*; - fn f(i: &str) -> IResult<&str, &str> { - many1::<_, _, (), _, _>(alt((tag("a"), tag("b")))) - .recognize() - .parse_next(i) - } + let a = "aabbab"; + let b = "ababcd"; - assert_eq!(f(a), Ok((&a[6..], a))); - assert_eq!(f(b), Ok((&b[4..], &b[..4]))); - } + fn f(i: &str) -> IResult<&str, &str> { + many1::<_, _, (), _, _>(alt((tag("a"), tag("b")))) + .recognize() + .parse_next(i) + } - #[test] - fn utf8_indexing_str() { - fn dot(i: &str) -> IResult<&str, &str> { - tag(".")(i) + assert_eq!(f(a), Ok((&a[6..], a))); + assert_eq!(f(b), Ok((&b[4..], &b[..4]))); } - let _ = dot("點"); - } + #[test] + fn utf8_indexing_str() { + fn dot(i: &str) -> IResult<&str, &str> { + tag(".")(i) + } + + let _ = dot("點"); + } }