From 7e5d7eea9c580ef4b41a765bde624af431942b96 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 4 May 2024 14:41:35 +0200 Subject: Merging upstream version 1.70.0+dfsg2. Signed-off-by: Daniel Baumann --- vendor/nom8/tests/arithmetic.rs | 92 ++++++++++ vendor/nom8/tests/arithmetic_ast.rs | 159 ++++++++++++++++++ vendor/nom8/tests/css.rs | 45 +++++ vendor/nom8/tests/custom_errors.rs | 49 ++++++ vendor/nom8/tests/escaped.rs | 28 ++++ vendor/nom8/tests/float.rs | 46 +++++ vendor/nom8/tests/fnmut.rs | 39 +++++ vendor/nom8/tests/ini.rs | 202 ++++++++++++++++++++++ vendor/nom8/tests/ini_str.rs | 217 ++++++++++++++++++++++++ vendor/nom8/tests/issues.rs | 248 +++++++++++++++++++++++++++ vendor/nom8/tests/json.rs | 228 +++++++++++++++++++++++++ vendor/nom8/tests/mp4.rs | 324 ++++++++++++++++++++++++++++++++++++ vendor/nom8/tests/multiline.rs | 31 ++++ vendor/nom8/tests/overflow.rs | 162 ++++++++++++++++++ vendor/nom8/tests/reborrow_fold.rs | 30 ++++ 15 files changed, 1900 insertions(+) create mode 100644 vendor/nom8/tests/arithmetic.rs create mode 100644 vendor/nom8/tests/arithmetic_ast.rs create mode 100644 vendor/nom8/tests/css.rs create mode 100644 vendor/nom8/tests/custom_errors.rs create mode 100644 vendor/nom8/tests/escaped.rs create mode 100644 vendor/nom8/tests/float.rs create mode 100644 vendor/nom8/tests/fnmut.rs create mode 100644 vendor/nom8/tests/ini.rs create mode 100644 vendor/nom8/tests/ini_str.rs create mode 100644 vendor/nom8/tests/issues.rs create mode 100644 vendor/nom8/tests/json.rs create mode 100644 vendor/nom8/tests/mp4.rs create mode 100644 vendor/nom8/tests/multiline.rs create mode 100644 vendor/nom8/tests/overflow.rs create mode 100644 vendor/nom8/tests/reborrow_fold.rs (limited to 'vendor/nom8/tests') diff --git a/vendor/nom8/tests/arithmetic.rs b/vendor/nom8/tests/arithmetic.rs new file mode 100644 index 000000000..35e1bf1cc --- /dev/null +++ b/vendor/nom8/tests/arithmetic.rs @@ -0,0 +1,92 @@ +use nom8::prelude::*; +use nom8::{ + branch::alt, + character::{digit1 as digit, space0 as space}, + multi::fold_many0, + sequence::delimited, + IResult, +}; + +// Parser definition + +use std::str::FromStr; + +// We parse any expr surrounded by parens, ignoring all whitespaces around those +fn parens(i: &str) -> IResult<&str, i64> { + delimited(space, delimited("(", expr, ")"), space)(i) +} + +// We transform an integer string into a i64, ignoring surrounding whitespaces +// We look for a digit suite, and try to convert it. +// If either str::from_utf8 or FromStr::from_str fail, +// we fallback to the parens parser defined above +fn factor(i: &str) -> IResult<&str, i64> { + alt(( + delimited(space, digit, space).map_res(FromStr::from_str), + parens, + ))(i) +} + +// We read an initial factor and for each time we find +// a * or / operator followed by another factor, we do +// the math by folding everything +fn term(i: &str) -> IResult<&str, i64> { + let (i, init) = factor(i)?; + + fold_many0( + (alt(('*', '/')), factor), + move || init, + |acc, (op, val): (char, i64)| { + if op == '*' { + acc * val + } else { + acc / val + } + }, + )(i) +} + +fn expr(i: &str) -> IResult<&str, i64> { + let (i, init) = term(i)?; + + fold_many0( + (alt(('+', '-')), term), + move || init, + |acc, (op, val): (char, i64)| { + if op == '+' { + acc + val + } else { + acc - val + } + }, + )(i) +} + +#[test] +fn factor_test() { + assert_eq!(factor("3"), Ok(("", 3))); + assert_eq!(factor(" 12"), Ok(("", 12))); + assert_eq!(factor("537 "), Ok(("", 537))); + assert_eq!(factor(" 24 "), Ok(("", 24))); +} + +#[test] +fn term_test() { + assert_eq!(term(" 12 *2 / 3"), Ok(("", 8))); + assert_eq!(term(" 2* 3 *2 *2 / 3"), Ok(("", 8))); + assert_eq!(term(" 48 / 3/2"), Ok(("", 8))); +} + +#[test] +fn expr_test() { + assert_eq!(expr(" 1 + 2 "), Ok(("", 3))); + assert_eq!(expr(" 12 + 6 - 4+ 3"), Ok(("", 17))); + assert_eq!(expr(" 1 + 2*3 + 4"), Ok(("", 11))); +} + +#[test] +fn parens_test() { + assert_eq!(expr(" ( 2 )"), Ok(("", 2))); + assert_eq!(expr(" 2* ( 3 + 4 ) "), Ok(("", 14))); + assert_eq!(expr(" 2*2 / ( 5 - 1) + 3"), Ok(("", 4))); +} diff --git a/vendor/nom8/tests/arithmetic_ast.rs b/vendor/nom8/tests/arithmetic_ast.rs new file mode 100644 index 000000000..3e49dd2a1 --- /dev/null +++ b/vendor/nom8/tests/arithmetic_ast.rs @@ -0,0 +1,159 @@ +use std::fmt; +use std::fmt::{Debug, Display, Formatter}; + +use std::str::FromStr; + +use nom8::prelude::*; +use nom8::{ + 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), +} + +#[derive(Debug)] +pub enum Oper { + Add, + Sub, + Mul, + Div, +} + +impl Display for Expr { + fn fmt(&self, format: &mut Formatter<'_>) -> fmt::Result { + use self::Expr::*; + 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::*; + 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 parens(i: &str) -> IResult<&str, Expr> { + delimited( + multispace, + delimited("(", expr.map(|e| Expr::Paren(Box::new(e))), ")"), + multispace, + )(i) +} + +fn factor(i: &str) -> IResult<&str, Expr> { + alt(( + delimited(multispace, digit, multispace) + .map_res(FromStr::from_str) + .map(Expr::Value), + parens, + ))(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)), + } + }) +} + +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))) +} + +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))) +} + +#[test] +fn factor_test() { + 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)"))) + ); +} + +#[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)"))) + ); +} + +#[test] +fn parens_test() { + assert_eq!( + expr(" ( 1 + 2 ) * 3 ").map(|(i, x)| (i, format!("{:?}", x))), + Ok(("", String::from("([(1 + 2)] * 3)"))) + ); +} diff --git a/vendor/nom8/tests/css.rs b/vendor/nom8/tests/css.rs new file mode 100644 index 000000000..b3b308804 --- /dev/null +++ b/vendor/nom8/tests/css.rs @@ -0,0 +1,45 @@ +use nom8::bytes::{tag, take_while_m_n}; +use nom8::prelude::*; + +#[derive(Debug, PartialEq)] +pub struct Color { + pub red: u8, + pub green: u8, + pub blue: u8, +} + +fn from_hex(input: &str) -> Result { + u8::from_str_radix(input, 16) +} + +fn is_hex_digit(c: char) -> bool { + c.is_digit(16) +} + +fn hex_primary(input: &str) -> IResult<&str, u8> { + take_while_m_n(2, 2, is_hex_digit) + .map_res(from_hex) + .parse(input) +} + +fn hex_color(input: &str) -> IResult<&str, Color> { + let (input, _) = tag("#")(input)?; + let (input, (red, green, blue)) = (hex_primary, hex_primary, hex_primary).parse(input)?; + + Ok((input, Color { red, green, blue })) +} + +#[test] +fn parse_color() { + assert_eq!( + hex_color("#2F14DF"), + Ok(( + "", + Color { + red: 47, + green: 20, + blue: 223, + } + )) + ); +} diff --git a/vendor/nom8/tests/custom_errors.rs b/vendor/nom8/tests/custom_errors.rs new file mode 100644 index 000000000..8ca0d7b2d --- /dev/null +++ b/vendor/nom8/tests/custom_errors.rs @@ -0,0 +1,49 @@ +#![allow(dead_code)] + +use nom8::bytes::tag; +use nom8::character::digit1 as digit; +use nom8::error::{ErrorKind, ParseError}; +use nom8::input::Streaming; +#[cfg(feature = "alloc")] +use nom8::multi::count; +use nom8::prelude::*; +use nom8::sequence::terminated; +use nom8::IResult; + +#[derive(Debug)] +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)) + } +} + +impl<'a> ParseError> for CustomError { + fn from_error_kind(_: Streaming<&'a str>, kind: ErrorKind) -> Self { + CustomError(format!("error code was: {:?}", kind)) + } + + fn append(_: Streaming<&'a str>, kind: ErrorKind, other: CustomError) -> Self { + CustomError(format!("{:?}\nerror code was: {:?}", other, kind)) + } +} + +fn test1(input: Streaming<&str>) -> IResult, &str, CustomError> { + //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) +} + +fn test3(input: Streaming<&str>) -> IResult, &str, CustomError> { + test1.verify(|s: &str| s.starts_with("abcd")).parse(input) +} + +#[cfg(feature = "alloc")] +fn test4(input: Streaming<&str>) -> IResult, Vec<&str>, CustomError> { + count(test1, 4)(input) +} diff --git a/vendor/nom8/tests/escaped.rs b/vendor/nom8/tests/escaped.rs new file mode 100644 index 000000000..ed99128d3 --- /dev/null +++ b/vendor/nom8/tests/escaped.rs @@ -0,0 +1,28 @@ +use nom8::bytes::escaped; +use nom8::bytes::one_of; +use nom8::character::digit1; +use nom8::{error::ErrorKind, Err, IResult}; + +fn esc(s: &str) -> IResult<&str, &str, (&str, ErrorKind)> { + escaped(digit1, '\\', one_of("\"n\\"))(s) +} + +#[cfg(feature = "alloc")] +fn esc_trans(s: &str) -> IResult<&str, String, (&str, ErrorKind)> { + use nom8::bytes::escaped_transform; + escaped_transform(digit1, '\\', "n")(s) +} + +#[test] +fn test_escaped() { + assert_eq!(esc("abcd"), Err(Err::Error(("abcd", ErrorKind::Escaped)))); +} + +#[test] +#[cfg(feature = "alloc")] +fn test_escaped_transform() { + assert_eq!( + esc_trans("abcd"), + Err(Err::Error(("abcd", ErrorKind::EscapedTransform))) + ); +} diff --git a/vendor/nom8/tests/float.rs b/vendor/nom8/tests/float.rs new file mode 100644 index 000000000..270db3001 --- /dev/null +++ b/vendor/nom8/tests/float.rs @@ -0,0 +1,46 @@ +use nom8::branch::alt; +use nom8::character::digit1 as digit; +use nom8::combinator::opt; +use nom8::prelude::*; +use nom8::sequence::delimited; +use nom8::IResult; + +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(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(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))); +} + +#[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))); +} diff --git a/vendor/nom8/tests/fnmut.rs b/vendor/nom8/tests/fnmut.rs new file mode 100644 index 000000000..f96730420 --- /dev/null +++ b/vendor/nom8/tests/fnmut.rs @@ -0,0 +1,39 @@ +use nom8::{ + bytes::tag, + multi::{many0, many0_count}, +}; + +#[test] +fn parse() { + let mut counter = 0; + + let res = { + let mut parser = many0::<_, _, (), _>(|i| { + counter += 1; + tag("abc")(i) + }); + + parser("abcabcabcabc").unwrap() + }; + + println!("res: {:?}", res); + assert_eq!(counter, 5); +} + +#[test] +fn accumulate() { + let mut v = Vec::new(); + + let (_, count) = { + let mut parser = many0_count::<_, _, (), _>(|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/vendor/nom8/tests/ini.rs b/vendor/nom8/tests/ini.rs new file mode 100644 index 000000000..21c75aaa4 --- /dev/null +++ b/vendor/nom8/tests/ini.rs @@ -0,0 +1,202 @@ +use nom8::prelude::*; +use nom8::{ + bytes::take_while, + character::{alphanumeric1 as alphanumeric, multispace0 as multispace, space0 as space}, + combinator::opt, + multi::many0, + sequence::{delimited, separated_pair, terminated}, +}; + +use std::collections::HashMap; +use std::str; + +fn category(i: &[u8]) -> IResult<&[u8], &str> { + delimited('[', take_while(|c| c != b']'), ']') + .map_res(str::from_utf8) + .parse(i) +} + +fn key_value(i: &[u8]) -> IResult<&[u8], (&str, &str)> { + let (i, key) = alphanumeric.map_res(str::from_utf8).parse(i)?; + let (i, _) = (opt(space), '=', opt(space)).parse(i)?; + let (i, val) = take_while(|c| c != b'\n' && c != b';') + .map_res(str::from_utf8) + .parse(i)?; + let (i, _) = opt((';', take_while(|c| c != b'\n')))(i)?; + Ok((i, (key, val))) +} + +fn keys_and_values(i: &[u8]) -> IResult<&[u8], HashMap<&str, &str>> { + many0(terminated(key_value, opt(multispace))) + .map(|vec| vec.into_iter().collect()) + .parse(i) +} + +fn category_and_keys(i: &[u8]) -> IResult<&[u8], (&str, HashMap<&str, &str>)> { + let (i, category) = terminated(category, opt(multispace))(i)?; + let (i, keys) = keys_and_values(i)?; + Ok((i, (category, keys))) +} + +fn categories(i: &[u8]) -> IResult<&[u8], HashMap<&str, HashMap<&str, &str>>> { + many0(separated_pair( + category, + opt(multispace), + many0(terminated(key_value, opt(multispace))).map(|vec: Vec<_>| vec.into_iter().collect()), + )) + .map(|vec: Vec<_>| vec.into_iter().collect()) + .parse(i) +} + +#[test] +fn parse_category_test() { + let ini_file = &b"[category] + +parameter=value +key = value2"[..]; + + let ini_without_category = &b"\n\nparameter=value +key = value2"[..]; + + let res = category(ini_file); + println!("{:?}", res); + match res { + Ok((i, o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_category, "category"))); +} + +#[test] +fn parse_key_value_test() { + let ini_file = &b"parameter=value +key = value2"[..]; + + let ini_without_key_value = &b"\nkey = value2"[..]; + + let res = key_value(ini_file); + println!("{:?}", res); + match res { + Ok((i, (o1, o2))) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); +} + +#[test] +fn parse_key_value_with_space_test() { + let ini_file = &b"parameter = value +key = value2"[..]; + + let ini_without_key_value = &b"\nkey = value2"[..]; + + let res = key_value(ini_file); + println!("{:?}", res); + match res { + Ok((i, (o1, o2))) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); +} + +#[test] +fn parse_key_value_with_comment_test() { + let ini_file = &b"parameter=value;abc +key = value2"[..]; + + let ini_without_key_value = &b"\nkey = value2"[..]; + + let res = key_value(ini_file); + println!("{:?}", res); + match res { + Ok((i, (o1, o2))) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); +} + +#[test] +fn parse_multiple_keys_and_values_test() { + let ini_file = &b"parameter=value;abc + +key = value2 + +[category]"[..]; + + let ini_without_key_value = &b"[category]"[..]; + + let res = keys_and_values(ini_file); + println!("{:?}", res); + match res { + Ok((i, ref o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o), + _ => println!("error"), + } + + let mut expected: HashMap<&str, &str> = HashMap::new(); + expected.insert("parameter", "value"); + expected.insert("key", "value2"); + assert_eq!(res, Ok((ini_without_key_value, expected))); +} + +#[test] +fn parse_category_then_multiple_keys_and_values_test() { + //FIXME: there can be an empty line or a comment line after a category + let ini_file = &b"[abcd] +parameter=value;abc + +key = value2 + +[category]"[..]; + + let ini_after_parser = &b"[category]"[..]; + + let res = category_and_keys(ini_file); + println!("{:?}", res); + match res { + Ok((i, ref o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o), + _ => println!("error"), + } + + let mut expected_h: HashMap<&str, &str> = HashMap::new(); + expected_h.insert("parameter", "value"); + expected_h.insert("key", "value2"); + assert_eq!(res, Ok((ini_after_parser, ("abcd", expected_h)))); +} + +#[test] +fn parse_multiple_categories_test() { + let ini_file = &b"[abcd] + +parameter=value;abc + +key = value2 + +[category] +parameter3=value3 +key4 = value4 +"[..]; + + let ini_after_parser = &b""[..]; + + let res = categories(ini_file); + //println!("{:?}", res); + match res { + Ok((i, ref o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o), + _ => println!("error"), + } + + let mut expected_1: HashMap<&str, &str> = HashMap::new(); + expected_1.insert("parameter", "value"); + expected_1.insert("key", "value2"); + let mut expected_2: HashMap<&str, &str> = HashMap::new(); + expected_2.insert("parameter3", "value3"); + expected_2.insert("key4", "value4"); + let mut expected_h: HashMap<&str, HashMap<&str, &str>> = HashMap::new(); + expected_h.insert("abcd", expected_1); + expected_h.insert("category", expected_2); + assert_eq!(res, Ok((ini_after_parser, expected_h))); +} diff --git a/vendor/nom8/tests/ini_str.rs b/vendor/nom8/tests/ini_str.rs new file mode 100644 index 000000000..d46013881 --- /dev/null +++ b/vendor/nom8/tests/ini_str.rs @@ -0,0 +1,217 @@ +use nom8::prelude::*; +use nom8::{ + bytes::{take_till, take_while, take_while1}, + character::{alphanumeric1 as alphanumeric, space0 as space}, + combinator::opt, + multi::many0, + sequence::{delimited, terminated}, +}; + +use std::collections::HashMap; + +fn is_line_ending_or_comment(chr: char) -> bool { + chr == ';' || chr == '\n' +} + +fn not_line_ending(i: &str) -> IResult<&str, &str> { + take_while(|c| c != '\r' && c != '\n')(i) +} + +fn space_or_line_ending(i: &str) -> IResult<&str, &str> { + take_while1(" \r\n")(i) +} + +fn category(i: &str) -> IResult<&str, &str> { + terminated( + delimited('[', take_while(|c| c != ']'), ']'), + opt(take_while1(" \r\n")), + )(i) +} + +fn key_value(i: &str) -> IResult<&str, (&str, &str)> { + let (i, key) = alphanumeric(i)?; + let (i, _) = (opt(space), "=", opt(space)).parse(i)?; + let (i, val) = take_till(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 keys_and_values_aggregator(i: &str) -> IResult<&str, Vec<(&str, &str)>> { + many0(key_value)(i) +} + +fn keys_and_values(input: &str) -> IResult<&str, HashMap<&str, &str>> { + match keys_and_values_aggregator(input) { + Ok((i, tuple_vec)) => Ok((i, tuple_vec.into_iter().collect())), + Err(e) => Err(e), + } +} + +fn category_and_keys(i: &str) -> IResult<&str, (&str, HashMap<&str, &str>)> { + (category, keys_and_values).parse(i) +} + +fn categories_aggregator(i: &str) -> IResult<&str, Vec<(&str, HashMap<&str, &str>)>> { + many0(category_and_keys)(i) +} + +fn categories(input: &str) -> IResult<&str, HashMap<&str, HashMap<&str, &str>>> { + match categories_aggregator(input) { + Ok((i, tuple_vec)) => Ok((i, tuple_vec.into_iter().collect())), + Err(e) => Err(e), + } +} + +#[test] +fn parse_category_test() { + let ini_file = "[category] + +parameter=value +key = value2"; + + let ini_without_category = "parameter=value +key = value2"; + + let res = category(ini_file); + println!("{:?}", res); + match res { + Ok((i, o)) => println!("i: {} | o: {:?}", i, o), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_category, "category"))); +} + +#[test] +fn parse_key_value_test() { + let ini_file = "parameter=value +key = value2"; + + let ini_without_key_value = "key = value2"; + + let res = key_value(ini_file); + println!("{:?}", res); + match res { + Ok((i, (o1, o2))) => println!("i: {} | o: ({:?},{:?})", i, o1, o2), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); +} + +#[test] +fn parse_key_value_with_space_test() { + let ini_file = "parameter = value +key = value2"; + + let ini_without_key_value = "key = value2"; + + let res = key_value(ini_file); + println!("{:?}", res); + match res { + Ok((i, (o1, o2))) => println!("i: {} | o: ({:?},{:?})", i, o1, o2), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); +} + +#[test] +fn parse_key_value_with_comment_test() { + let ini_file = "parameter=value;abc +key = value2"; + + let ini_without_key_value = "key = value2"; + + let res = key_value(ini_file); + println!("{:?}", res); + match res { + Ok((i, (o1, o2))) => println!("i: {} | o: ({:?},{:?})", i, o1, o2), + _ => println!("error"), + } + + assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value")))); +} + +#[test] +fn parse_multiple_keys_and_values_test() { + let ini_file = "parameter=value;abc + +key = value2 + +[category]"; + + let ini_without_key_value = "[category]"; + + let res = keys_and_values(ini_file); + println!("{:?}", res); + match res { + Ok((i, ref o)) => println!("i: {} | o: {:?}", i, o), + _ => println!("error"), + } + + let mut expected: HashMap<&str, &str> = HashMap::new(); + expected.insert("parameter", "value"); + expected.insert("key", "value2"); + assert_eq!(res, Ok((ini_without_key_value, expected))); +} + +#[test] +fn parse_category_then_multiple_keys_and_values_test() { + //FIXME: there can be an empty line or a comment line after a category + let ini_file = "[abcd] +parameter=value;abc + +key = value2 + +[category]"; + + let ini_after_parser = "[category]"; + + let res = category_and_keys(ini_file); + println!("{:?}", res); + match res { + Ok((i, ref o)) => println!("i: {} | o: {:?}", i, o), + _ => println!("error"), + } + + let mut expected_h: HashMap<&str, &str> = HashMap::new(); + expected_h.insert("parameter", "value"); + expected_h.insert("key", "value2"); + assert_eq!(res, Ok((ini_after_parser, ("abcd", expected_h)))); +} + +#[test] +fn parse_multiple_categories_test() { + let ini_file = "[abcd] + +parameter=value;abc + +key = value2 + +[category] +parameter3=value3 +key4 = value4 +"; + + let res = categories(ini_file); + //println!("{:?}", res); + match res { + Ok((i, ref o)) => println!("i: {} | o: {:?}", i, o), + _ => println!("error"), + } + + let mut expected_1: HashMap<&str, &str> = HashMap::new(); + expected_1.insert("parameter", "value"); + expected_1.insert("key", "value2"); + let mut expected_2: HashMap<&str, &str> = HashMap::new(); + expected_2.insert("parameter3", "value3"); + expected_2.insert("key4", "value4"); + let mut expected_h: HashMap<&str, HashMap<&str, &str>> = HashMap::new(); + expected_h.insert("abcd", expected_1); + expected_h.insert("category", expected_2); + assert_eq!(res, Ok(("", expected_h))); +} diff --git a/vendor/nom8/tests/issues.rs b/vendor/nom8/tests/issues.rs new file mode 100644 index 000000000..7ac0f0b6c --- /dev/null +++ b/vendor/nom8/tests/issues.rs @@ -0,0 +1,248 @@ +//#![feature(trace_macros)] +#![allow(dead_code)] +#![cfg_attr(feature = "cargo-clippy", allow(redundant_closure))] + +use nom8::input::Streaming; +use nom8::prelude::*; +use nom8::{error::ErrorKind, Err, IResult, Needed}; + +#[allow(dead_code)] +struct Range { + 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(Err::Incomplete(Needed::new(1))) + } +} + +#[cfg(feature = "std")] +mod parse_int { + use nom8::input::HexDisplay; + use nom8::input::Streaming; + use nom8::prelude::*; + use nom8::{ + character::{digit1 as digit, space1 as space}, + combinator::opt, + multi::many0, + IResult, + }; + use std::str; + + 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(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 nom8::multi::length_data; + use nom8::number::be_u16; + let _: IResult, &[u8], (Streaming<&[u8]>, ErrorKind)> = + length_data(be_u16)(Streaming(b"012346")); +} + +#[test] +fn take_till_issue() { + use nom8::bytes::take_till; + + fn nothing(i: Streaming<&[u8]>) -> IResult, &[u8]> { + take_till(|_| true)(i) + } + + assert_eq!( + nothing(Streaming(b"")), + Err(Err::Incomplete(Needed::new(1))) + ); + assert_eq!( + nothing(Streaming(b"abc")), + Ok((Streaming(&b"abc"[..]), &b""[..])) + ); +} + +#[test] +fn issue_655() { + use nom8::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 nom8::bytes::{tag, take_till1}; + use nom8::multi::separated_list0; + + separated_list0(tag([0x0]), take_till1([0x0u8]))(i) +} + +mod issue_647 { + use nom8::bytes::tag; + use nom8::multi::separated_list0; + use nom8::prelude::*; + use nom8::{error::Error, number::be_f64, Err, IResult}; + pub type Input<'a> = nom8::input::Streaming<&'a [u8]>; + + #[derive(PartialEq, Debug, Clone)] + struct Data { + c: f64, + v: Vec, + } + + fn list<'a, 'b>( + input: Input<'a>, + _cs: &'b f64, + ) -> Result<(Input<'a>, Vec), Err>>> { + 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 nom8::bytes::take; + take(0x2000000000000000_usize)(i) + } + fn parser(i: Streaming<&[u8]>) -> IResult, &[u8]> { + use nom8::bits::{bits, bytes}; + + bits(bytes(take))(i) + } + assert_eq!( + parser(Streaming(&b""[..])), + Err(Err::Failure(nom8::error_position!( + Streaming(&b""[..]), + ErrorKind::TooLarge + ))) + ); +} + +#[test] +fn issue_942() { + use nom8::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 nom8::{bytes::one_of, multi::many0_count}; + many0_count(one_of('a').context("char_a"))(i) + } + assert_eq!(parser::<()>("aaa"), Ok(("", 3))); +} + +#[test] +fn issue_many_m_n_with_zeros() { + use nom8::multi::many_m_n; + let mut parser = many_m_n::<_, _, (), _>(0, 0, 'a'); + assert_eq!(parser("aaa"), Ok(("aaa", vec![]))); +} + +#[test] +fn issue_1027_convert_error_panic_nonempty() { + use nom8::error::{convert_error, VerboseError}; + + let input = "a"; + + let result: IResult<_, _, VerboseError<&str>> = ('a', 'b').parse(input); + let err = match result.unwrap_err() { + Err::Error(e) => e, + _ => unreachable!(), + }; + + 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 nom8::bits::{bits, take}; + use nom8::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 nom8::bytes::one_of; + use nom8::error::Error; + let parser = one_of::<_, _, Error<_>, false>(&['a', 'b', 'c'][..]); + assert_eq!(parser("aaa"), Ok(("aa", 'a'))); +} + +#[test] +fn issue_1459_clamp_capacity() { + // shouldn't panic + use nom8::multi::many_m_n; + let mut parser = many_m_n::<_, _, (), _>(usize::MAX, usize::MAX, 'a'); + assert_eq!(parser("a"), Err(nom8::Err::Error(()))); + + // shouldn't panic + use nom8::multi::count; + let mut parser = count::<_, _, (), _>('a', usize::MAX); + assert_eq!(parser("a"), Err(nom8::Err::Error(()))); +} diff --git a/vendor/nom8/tests/json.rs b/vendor/nom8/tests/json.rs new file mode 100644 index 000000000..086b59c13 --- /dev/null +++ b/vendor/nom8/tests/json.rs @@ -0,0 +1,228 @@ +#![cfg(feature = "alloc")] + +use nom8::{ + branch::alt, + bytes::{any, none_of, tag, take}, + character::{f64, multispace0}, + error::ParseError, + multi::{fold_many0, separated_list0}, + sequence::{delimited, preceded, separated_pair}, + IResult, Parser, +}; + +use std::collections::HashMap; + +#[derive(Debug, PartialEq, Clone)] +pub enum JsonValue { + Null, + Bool(bool), + Str(String), + Num(f64), + Array(Vec), + Object(HashMap), +} + +fn boolean(input: &str) -> IResult<&str, bool> { + alt((tag("false").value(false), tag("true").value(true)))(input) +} + +fn u16_hex(input: &str) -> IResult<&str, u16> { + take(4usize) + .map_res(|s| u16::from_str_radix(s, 16)) + .parse(input) +} + +fn unicode_escape(input: &str) -> IResult<&str, char> { + 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(input) +} + +fn character(input: &str) -> IResult<&str, char> { + let (input, c) = none_of("\"")(input)?; + if c == '\\' { + alt(( + any.map_res(|c| { + Ok(match c { + '"' | '\\' | '/' => c, + 'b' => '\x08', + 'f' => '\x0C', + 'n' => '\n', + 'r' => '\r', + 't' => '\t', + _ => return Err(()), + }) + }), + preceded('u', unicode_escape), + ))(input) + } else { + Ok((input, c)) + } +} + +fn string(input: &str) -> IResult<&str, String> { + delimited( + '"', + fold_many0(character, String::new, |mut string, c| { + string.push(c); + string + }), + '"', + )(input) +} + +fn ws<'a, O, E: ParseError<&'a str>, F: Parser<&'a str, O, E>>(f: F) -> impl Parser<&'a str, O, E> { + delimited(multispace0, f, multispace0) +} + +fn array(input: &str) -> IResult<&str, Vec> { + delimited('[', ws(separated_list0(ws(','), json_value)), ']')(input) +} + +fn object(input: &str) -> IResult<&str, HashMap> { + delimited( + '{', + ws(separated_list0( + ws(','), + separated_pair(string, ws(':'), json_value), + )), + '}', + ) + .map(|key_values| key_values.into_iter().collect()) + .parse(input) +} + +fn json_value(input: &str) -> IResult<&str, JsonValue> { + use JsonValue::*; + + alt(( + tag("null").value(Null), + boolean.map(Bool), + string.map(Str), + f64.map(Num), + array.map(Array), + object.map(Object), + ))(input) +} + +fn json(input: &str) -> IResult<&str, JsonValue> { + ws(json_value).parse(input) +} + +#[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::*; + + 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::*; + + 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::*; + + let input = r#" + { + "null" : null, + "true" :true , + "false": false , + "number" : 123e4 , + "string" : " abc 123 " , + "array" : [ false , 1 , "two" ] , + "object" : { "a" : 1.0 , "b" : "c" } , + "empty_array" : [ ] , + "empty_object" : { } + } + "#; + + assert_eq!( + json(input), + Ok(( + "", + Object( + vec![ + ("null".to_string(), Null), + ("true".to_string(), Bool(true)), + ("false".to_string(), Bool(false)), + ("number".to_string(), Num(123e4)), + ("string".to_string(), Str(" abc 123 ".to_string())), + ( + "array".to_string(), + Array(vec![Bool(false), Num(1.0), Str("two".to_string())]) + ), + ( + "object".to_string(), + Object( + vec![ + ("a".to_string(), Num(1.0)), + ("b".to_string(), Str("c".to_string())), + ] + .into_iter() + .collect() + ) + ), + ("empty_array".to_string(), Array(vec![]),), + ("empty_object".to_string(), Object(HashMap::new()),), + ] + .into_iter() + .collect() + ) + )) + ); +} diff --git a/vendor/nom8/tests/mp4.rs b/vendor/nom8/tests/mp4.rs new file mode 100644 index 000000000..076b1161c --- /dev/null +++ b/vendor/nom8/tests/mp4.rs @@ -0,0 +1,324 @@ +#![allow(dead_code)] + +use nom8::input::Streaming; +use nom8::prelude::*; +use nom8::{ + branch::alt, + bytes::{tag, take}, + error::ErrorKind, + multi::many0, + number::{be_f32, be_u16, be_u32, be_u64}, + Err, IResult, Needed, +}; + +use std::str; + +fn mp4_box(input: Streaming<&[u8]>) -> IResult, &[u8]> { + match be_u32(input) { + Ok((i, offset)) => { + let sz: usize = offset as usize; + if i.len() >= sz - 4 { + Ok((Streaming(&i[(sz - 4)..]), &i[0..(sz - 4)])) + } else { + Err(Err::Incomplete(Needed::new(offset as usize + 4))) + } + } + Err(e) => Err(e), + } +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +#[derive(PartialEq,Eq,Debug)] +struct FileType<'a> { + major_brand: &'a str, + major_brand_version: &'a [u8], + compatible_brands: Vec<&'a str> +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +#[allow(non_snake_case)] +#[derive(Debug,Clone)] +pub struct Mvhd32 { + version_flags: u32, // actually: + // version: u8, + // flags: u24 // 3 bytes + created_date: u32, + modified_date: u32, + scale: u32, + duration: u32, + speed: f32, + volume: u16, // actually a 2 bytes decimal + /* 10 bytes reserved */ + scaleA: f32, + rotateB: f32, + angleU: f32, + rotateC: f32, + scaleD: f32, + angleV: f32, + positionX: f32, + positionY: f32, + scaleW: f32, + preview: u64, + poster: u32, + selection: u64, + current_time: u32, + track_id: u32 +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +#[allow(non_snake_case)] +#[derive(Debug,Clone)] +pub struct Mvhd64 { + version_flags: u32, // actually: + // version: u8, + // flags: u24 // 3 bytes + created_date: u64, + modified_date: u64, + scale: u32, + duration: u64, + speed: f32, + volume: u16, // actually a 2 bytes decimal + /* 10 bytes reserved */ + scaleA: f32, + rotateB: f32, + angleU: f32, + rotateC: f32, + scaleD: f32, + angleV: f32, + positionX: f32, + positionY: f32, + scaleW: f32, + preview: u64, + poster: u32, + selection: u64, + current_time: u32, + track_id: u32 +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +fn mvhd32(i: Streaming<&[u8]>) -> IResult, MvhdBox> { + let (i, version_flags) = be_u32(i)?; + let (i, created_date) = be_u32(i)?; + let (i, modified_date) = be_u32(i)?; + let (i, scale) = be_u32(i)?; + let (i, duration) = be_u32(i)?; + let (i, speed) = be_f32(i)?; + let (i, volume) = be_u16(i)?; // actually a 2 bytes decimal + let (i, _) = take(10_usize)(i)?; + let (i, scale_a) = be_f32(i)?; + let (i, rotate_b) = be_f32(i)?; + let (i, angle_u) = be_f32(i)?; + let (i, rotate_c) = be_f32(i)?; + let (i, scale_d) = be_f32(i)?; + let (i, angle_v) = be_f32(i)?; + let (i, position_x) = be_f32(i)?; + let (i, position_y) = be_f32(i)?; + let (i, scale_w) = be_f32(i)?; + let (i, preview) = be_u64(i)?; + let (i, poster) = be_u32(i)?; + let (i, selection) = be_u64(i)?; + let (i, current_time) = be_u32(i)?; + let (i, track_id) = be_u32(i)?; + + let mvhd_box = MvhdBox::M32(Mvhd32 { + version_flags, + created_date, + modified_date, + scale, + duration, + speed, + volume, + scaleA: scale_a, + rotateB: rotate_b, + angleU: angle_u, + rotateC: rotate_c, + scaleD: scale_d, + angleV: angle_v, + positionX: position_x, + positionY: position_y, + scaleW: scale_w, + preview, + poster, + selection, + current_time, + track_id, + }); + + Ok((i, mvhd_box)) +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +fn mvhd64(i: Streaming<&[u8]>) -> IResult, MvhdBox> { + let (i, version_flags) = be_u32(i)?; + let (i, created_date) = be_u64(i)?; + let (i, modified_date) = be_u64(i)?; + let (i, scale) = be_u32(i)?; + let (i, duration) = be_u64(i)?; + let (i, speed) = be_f32(i)?; + let (i, volume) = be_u16(i)?; // actually a 2 bytes decimal + let (i, _) = take(10_usize)(i)?; + let (i, scale_a) = be_f32(i)?; + let (i, rotate_b) = be_f32(i)?; + let (i, angle_u) = be_f32(i)?; + let (i, rotate_c) = be_f32(i)?; + let (i, scale_d) = be_f32(i)?; + let (i, angle_v) = be_f32(i)?; + let (i, position_x) = be_f32(i)?; + let (i, position_y) = be_f32(i)?; + let (i, scale_w) = be_f32(i)?; + let (i, preview) = be_u64(i)?; + let (i, poster) = be_u32(i)?; + let (i, selection) = be_u64(i)?; + let (i, current_time) = be_u32(i)?; + let (i, track_id) = be_u32(i)?; + + let mvhd_box = MvhdBox::M64(Mvhd64 { + version_flags, + created_date, + modified_date, + scale, + duration, + speed, + volume, + scaleA: scale_a, + rotateB: rotate_b, + angleU: angle_u, + rotateC: rotate_c, + scaleD: scale_d, + angleV: angle_v, + positionX: position_x, + positionY: position_y, + scaleW: scale_w, + preview, + poster, + selection, + current_time, + track_id, + }); + + Ok((i, mvhd_box)) +} + +#[derive(Debug, Clone)] +pub enum MvhdBox { + M32(Mvhd32), + M64(Mvhd64), +} + +#[derive(Debug, Clone)] +pub enum MoovBox { + Mdra, + Dref, + Cmov, + Rmra, + Iods, + Mvhd(MvhdBox), + Clip, + Trak, + Udta, +} + +#[derive(Debug)] +enum MP4BoxType { + Ftyp, + Moov, + Mdat, + Free, + Skip, + Wide, + Mdra, + Dref, + Cmov, + Rmra, + Iods, + Mvhd, + Clip, + Trak, + Udta, + Unknown, +} + +#[derive(Debug)] +struct MP4BoxHeader { + length: u32, + tag: MP4BoxType, +} + +fn brand_name(input: Streaming<&[u8]>) -> IResult, &str> { + take(4_usize).map_res(str::from_utf8).parse(input) +} + +fn filetype_parser(input: Streaming<&[u8]>) -> IResult, FileType<'_>> { + let (i, name) = brand_name(input)?; + let (i, version) = take(4_usize)(i)?; + let (i, brands) = many0(brand_name)(i)?; + + let ft = FileType { + major_brand: name, + major_brand_version: version, + compatible_brands: brands, + }; + Ok((i, ft)) +} + +fn mvhd_box(input: Streaming<&[u8]>) -> IResult, MvhdBox> { + let res = if input.len() < 100 { + Err(Err::Incomplete(Needed::new(100))) + } else if input.len() == 100 { + mvhd32(input) + } else if input.len() == 112 { + mvhd64(input) + } else { + Err(Err::Error(nom8::error_position!( + input, + ErrorKind::TooLarge + ))) + }; + println!("res: {:?}", res); + res +} + +fn unknown_box_type(input: Streaming<&[u8]>) -> IResult, MP4BoxType> { + Ok((input, MP4BoxType::Unknown)) +} + +fn box_type(input: Streaming<&[u8]>) -> IResult, MP4BoxType> { + alt(( + tag("ftyp").map(|_| MP4BoxType::Ftyp), + tag("moov").map(|_| MP4BoxType::Moov), + tag("mdat").map(|_| MP4BoxType::Mdat), + tag("free").map(|_| MP4BoxType::Free), + tag("skip").map(|_| MP4BoxType::Skip), + tag("wide").map(|_| MP4BoxType::Wide), + unknown_box_type, + ))(input) +} + +// warning, an alt combinator with 9 branches containing a tag combinator +// can make the compilation very slow. Use functions as sub parsers, +// or split into multiple alt parsers if it gets slow +fn moov_type(input: Streaming<&[u8]>) -> IResult, MP4BoxType> { + alt(( + tag("mdra").map(|_| MP4BoxType::Mdra), + tag("dref").map(|_| MP4BoxType::Dref), + tag("cmov").map(|_| MP4BoxType::Cmov), + tag("rmra").map(|_| MP4BoxType::Rmra), + tag("iods").map(|_| MP4BoxType::Iods), + tag("mvhd").map(|_| MP4BoxType::Mvhd), + tag("clip").map(|_| MP4BoxType::Clip), + tag("trak").map(|_| MP4BoxType::Trak), + tag("udta").map(|_| MP4BoxType::Udta), + ))(input) +} + +fn box_header(input: Streaming<&[u8]>) -> IResult, MP4BoxHeader> { + let (i, length) = be_u32(input)?; + let (i, tag) = box_type(i)?; + Ok((i, MP4BoxHeader { length, tag })) +} + +fn moov_header(input: Streaming<&[u8]>) -> IResult, MP4BoxHeader> { + let (i, length) = be_u32(input)?; + let (i, tag) = moov_type(i)?; + Ok((i, MP4BoxHeader { length, tag })) +} diff --git a/vendor/nom8/tests/multiline.rs b/vendor/nom8/tests/multiline.rs new file mode 100644 index 000000000..c62ee5915 --- /dev/null +++ b/vendor/nom8/tests/multiline.rs @@ -0,0 +1,31 @@ +use nom8::{ + 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) + } +} + +pub fn read_line(input: &str) -> IResult<&str, &str> { + terminated(alphanumeric, end_of_line)(input) +} + +pub fn read_lines(input: &str) -> IResult<&str, Vec<&str>> { + many0(read_line)(input) +} + +#[cfg(feature = "alloc")] +#[test] +fn read_lines_test() { + let res = Ok(("", vec!["Duck", "Dog", "Cow"])); + + assert_eq!(read_lines("Duck\nDog\nCow\n"), res); + assert_eq!(read_lines("Duck\nDog\nCow"), res); +} diff --git a/vendor/nom8/tests/overflow.rs b/vendor/nom8/tests/overflow.rs new file mode 100644 index 000000000..5a771ea30 --- /dev/null +++ b/vendor/nom8/tests/overflow.rs @@ -0,0 +1,162 @@ +#![cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))] +#![cfg(target_pointer_width = "64")] + +use nom8::bytes::take; +use nom8::input::Streaming; +#[cfg(feature = "alloc")] +use nom8::multi::{length_data, many0}; +#[cfg(feature = "alloc")] +use nom8::number::be_u64; +use nom8::prelude::*; +use nom8::{Err, Needed}; + +// Parser definition + +// We request a length that would trigger an overflow if computing consumed + requested +fn parser02(i: Streaming<&[u8]>) -> IResult, (&[u8], &[u8])> { + (take(1_usize), take(18446744073709551615_usize)).parse(i) +} + +#[test] +fn overflow_incomplete_tuple() { + assert_eq!( + parser02(Streaming(&b"3"[..])), + Err(Err::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(Err::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(Err::Incomplete(Needed::new(18446744073709551599))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn overflow_incomplete_many1() { + use nom8::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(Err::Incomplete(Needed::new(18446744073709551599))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn overflow_incomplete_many_till() { + use nom8::{bytes::tag, multi::many_till}; + + fn multi(i: Streaming<&[u8]>) -> IResult, (Vec<&[u8]>, &[u8])> { + many_till(length_data(be_u64), tag("abc"))(i) + } + + // Trigger an overflow in many_till + assert_eq!( + multi(Streaming( + &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..] + )), + Err(Err::Incomplete(Needed::new(18446744073709551599))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn overflow_incomplete_many_m_n() { + use nom8::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(Err::Incomplete(Needed::new(18446744073709551599))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn overflow_incomplete_count() { + use nom8::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(Err::Incomplete(Needed::new(18446744073709551599))) + ); +} + +#[test] +#[cfg(feature = "alloc")] +fn overflow_incomplete_length_count() { + use nom8::multi::length_count; + use nom8::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(Err::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(Err::Incomplete(Needed::new(18446744073709551615))) + ); +} diff --git a/vendor/nom8/tests/reborrow_fold.rs b/vendor/nom8/tests/reborrow_fold.rs new file mode 100644 index 000000000..9041131fd --- /dev/null +++ b/vendor/nom8/tests/reborrow_fold.rs @@ -0,0 +1,30 @@ +#![allow(dead_code)] +// #![allow(unused_variables)] + +use std::str; + +use nom8::bytes::take_till1; +use nom8::multi::fold_many0; +use nom8::prelude::*; +use nom8::sequence::delimited; +use nom8::IResult; + +fn atom<'a>(_tomb: &'a mut ()) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], String> { + move |input| { + take_till1(" \t\r\n") + .map_res(str::from_utf8) + .map(ToString::to_string) + .parse(input) + } +} + +// FIXME: should we support the use case of borrowing data mutably in a parser? +fn list<'a>(i: &'a [u8], tomb: &'a mut ()) -> IResult<&'a [u8], String> { + delimited( + '(', + fold_many0(atom(tomb), String::new, |acc: String, next: String| { + acc + next.as_str() + }), + ')', + )(i) +} -- cgit v1.2.3