summaryrefslogtreecommitdiffstats
path: root/third_party/rust/nom/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/nom/tests
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/nom/tests')
-rw-r--r--third_party/rust/nom/tests/arithmetic.rs109
-rw-r--r--third_party/rust/nom/tests/arithmetic_ast.rs172
-rw-r--r--third_party/rust/nom/tests/blockbuf-arithmetic.rs321
-rw-r--r--third_party/rust/nom/tests/css.rs51
-rw-r--r--third_party/rust/nom/tests/custom_errors.rs53
-rw-r--r--third_party/rust/nom/tests/escaped.rs25
-rw-r--r--third_party/rust/nom/tests/float.rs46
-rw-r--r--third_party/rust/nom/tests/inference.rs53
-rw-r--r--third_party/rust/nom/tests/ini.rs221
-rw-r--r--third_party/rust/nom/tests/ini_str.rs215
-rw-r--r--third_party/rust/nom/tests/issues.rs318
-rw-r--r--third_party/rust/nom/tests/json.rs105
-rw-r--r--third_party/rust/nom/tests/mp4.rs319
-rw-r--r--third_party/rust/nom/tests/multiline.rs36
-rw-r--r--third_party/rust/nom/tests/named_args.rs161
-rw-r--r--third_party/rust/nom/tests/overflow.rs139
-rw-r--r--third_party/rust/nom/tests/reborrow_fold.rs18
-rw-r--r--third_party/rust/nom/tests/test1.rs44
18 files changed, 2406 insertions, 0 deletions
diff --git a/third_party/rust/nom/tests/arithmetic.rs b/third_party/rust/nom/tests/arithmetic.rs
new file mode 100644
index 0000000000..b3c38931df
--- /dev/null
+++ b/third_party/rust/nom/tests/arithmetic.rs
@@ -0,0 +1,109 @@
+extern crate nom;
+
+
+use nom::{
+ IResult,
+ branch::alt,
+ combinator::map_res,
+ character::complete::char,
+ bytes::complete::tag,
+ character::complete::{digit1 as digit, space0 as space},
+ multi::fold_many0,
+ sequence::{delimited, pair}
+};
+
+// 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(
+ tag("("),
+ expr,
+ tag(")")
+ ),
+ 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((
+ map_res(delimited(space, digit, space), 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(
+ pair(alt((char('*'), char('/'))), factor),
+ 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(
+ pair(alt((char('+'), char('-'))), term),
+ 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/third_party/rust/nom/tests/arithmetic_ast.rs b/third_party/rust/nom/tests/arithmetic_ast.rs
new file mode 100644
index 0000000000..ecb8d40641
--- /dev/null
+++ b/third_party/rust/nom/tests/arithmetic_ast.rs
@@ -0,0 +1,172 @@
+extern crate nom;
+
+use std::fmt;
+use std::fmt::{Debug, Display, Formatter};
+
+use std::str::FromStr;
+
+use nom::{
+ IResult,
+ character::complete::{digit1 as digit, multispace0 as multispace},
+ sequence::{preceded, delimited},
+ combinator::{map, map_res},
+ multi::many0,
+ branch::alt,
+ bytes::complete::tag,
+};
+
+pub enum Expr {
+ Value(i64),
+ Add(Box<Expr>, Box<Expr>),
+ Sub(Box<Expr>, Box<Expr>),
+ Mul(Box<Expr>, Box<Expr>),
+ Div(Box<Expr>, Box<Expr>),
+ Paren(Box<Expr>),
+}
+
+#[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(
+ tag("("),
+ map(expr, |e| Expr::Paren(Box::new(e))),
+ tag(")")
+ ),
+ multispace
+ )(i)
+}
+
+fn factor(i: &str) -> IResult<&str, Expr> {
+ alt((
+ map(
+ map_res(
+ delimited(multispace, digit, multispace),
+ FromStr::from_str
+ ),
+ 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(tag("*"), factor)(i)?;
+ Ok((i,(Oper::Mul, mul)))
+ },
+ |i| {
+ let(i, div) = preceded(tag("/"), 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(tag("+"), term)(i)?;
+ Ok((i,(Oper::Add, add)))
+ },
+ |i| {
+ let(i, sub) = preceded(tag("-"), 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/third_party/rust/nom/tests/blockbuf-arithmetic.rs b/third_party/rust/nom/tests/blockbuf-arithmetic.rs
new file mode 100644
index 0000000000..27a295fc77
--- /dev/null
+++ b/third_party/rust/nom/tests/blockbuf-arithmetic.rs
@@ -0,0 +1,321 @@
+/*
+#[macro_use]
+extern crate nom;
+extern crate bytes;
+
+use nom::{Compare,CompareResult,InputLength,InputIter,Slice,HexDisplay};
+
+use std::str;
+use std::str::FromStr;
+use bytes::{Buf,MutBuf};
+use bytes::buf::{BlockBuf,BlockBufCursor};
+use std::ops::{Range,RangeTo,RangeFrom,RangeFull};
+use std::iter::{Enumerate,Iterator};
+use std::fmt;
+use std::cmp::{min,PartialEq};
+
+#[derive(Clone,Copy)]
+#[repr(C)]
+pub struct BlockSlice<'a> {
+ buf: &'a BlockBuf,
+ start: usize,
+ end: usize,
+}
+
+impl<'a> BlockSlice<'a> {
+ fn cursor(&self) -> WrapCursor<'a> {
+ let mut cur = self.buf.buf();
+ cur.advance(self.start);
+ WrapCursor {
+ cursor: cur,
+ length: self.end - self.start,
+ }
+ }
+}
+
+impl<'a> fmt::Debug for BlockSlice<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "BlockSlice {{ start: {}, end: {}, data:\n{}\n}}", self.start, self.end, self.buf.bytes().unwrap_or(&b""[..]).to_hex(16))
+ }
+}
+
+impl<'a> PartialEq for BlockSlice<'a> {
+ fn eq(&self, other: &BlockSlice<'a>) -> bool {
+ let bufs = (self.buf as *const BlockBuf) == (other.buf as *const BlockBuf);
+ self.start == other.start && self.end == other.end && bufs
+ }
+}
+
+impl<'a> Slice<Range<usize>> for BlockSlice<'a> {
+ fn slice(&self, range:Range<usize>) -> Self {
+ BlockSlice {
+ buf: self.buf,
+ start: self.start + range.start,
+ //FIXME: check for valid end here
+ end: self.start + range.end,
+ }
+ }
+}
+
+impl<'a> Slice<RangeTo<usize>> for BlockSlice<'a> {
+ fn slice(&self, range:RangeTo<usize>) -> Self {
+ self.slice(0..range.end)
+ }
+}
+
+impl<'a> Slice<RangeFrom<usize>> for BlockSlice<'a> {
+ fn slice(&self, range:RangeFrom<usize>) -> Self {
+ self.slice(range.start..self.end - self.start)
+ }
+}
+
+impl<'a> Slice<RangeFull> for BlockSlice<'a> {
+ fn slice(&self, _:RangeFull) -> Self {
+ BlockSlice {
+ buf: self.buf,
+ start: self.start,
+ end: self.end,
+ }
+ }
+}
+
+
+impl<'a> InputIter for BlockSlice<'a> {
+ type Item = u8;
+ type RawItem = u8;
+ type Iter = Enumerate<WrapCursor<'a>>;
+ type IterElem = WrapCursor<'a>;
+
+ fn iter_indices(&self) -> Self::Iter {
+ self.cursor().enumerate()
+ }
+ fn iter_elements(&self) -> Self::IterElem {
+ self.cursor()
+ }
+ fn position<P>(&self, predicate: P) -> Option<usize> where P: Fn(Self::RawItem) -> bool {
+ self.cursor().position(|b| predicate(b))
+ }
+ fn slice_index(&self, count:usize) -> Option<usize> {
+ if self.end - self.start >= count {
+ Some(count)
+ } else {
+ None
+ }
+ }
+}
+
+
+impl<'a> InputLength for BlockSlice<'a> {
+ fn input_len(&self) -> usize {
+ self.end - self.start
+ }
+}
+
+impl<'a,'b> Compare<&'b[u8]> for BlockSlice<'a> {
+ fn compare(&self, t: &'b[u8]) -> CompareResult {
+ let len = self.end - self.start;
+ let blen = t.len();
+ let m = if len < blen { len } else { blen };
+ let reduced = self.slice(..m);
+ let b = &t[..m];
+
+ for (a,b) in reduced.cursor().zip(b.iter()) {
+ if a != *b {
+ return CompareResult::Error;
+ }
+ }
+ if m < blen {
+ CompareResult::Incomplete
+ } else {
+ CompareResult::Ok
+ }
+ }
+
+
+ #[inline(always)]
+ fn compare_no_case(&self, t: &'b[u8]) -> CompareResult {
+ let len = self.end - self.start;
+ let blen = t.len();
+ let m = if len < blen { len } else { blen };
+ let reduced = self.slice(..m);
+ let other = &t[..m];
+
+ if !reduced.cursor().zip(other).all(|(a, b)| {
+ match (a,*b) {
+ (0...64, 0...64) | (91...96, 91...96) | (123...255, 123...255) => a == *b,
+ (65...90, 65...90) | (97...122, 97...122) | (65...90, 97...122 ) |(97...122, 65...90) => {
+ a & 0b01000000 == *b & 0b01000000
+ }
+ _ => false
+ }
+ }) {
+ CompareResult::Error
+ } else if m < blen {
+ CompareResult::Incomplete
+ } else {
+ CompareResult::Ok
+ }
+ }
+}
+
+impl<'a,'b> Compare<&'b str> for BlockSlice<'a> {
+ fn compare(&self, t: &'b str) -> CompareResult {
+ self.compare(str::as_bytes(t))
+ }
+ fn compare_no_case(&self, t: &'b str) -> CompareResult {
+ self.compare_no_case(str::as_bytes(t))
+ }
+}
+
+//Wrapper to implement Iterator on BlockBufCursor
+pub struct WrapCursor<'a> {
+ pub cursor: BlockBufCursor<'a>,
+ pub length: usize,
+}
+
+impl<'a> Iterator for WrapCursor<'a> {
+ type Item = u8;
+ fn next(&mut self) -> Option<u8> {
+ //println!("NEXT: length={}, remaining={}", self.length, self.cursor.remaining());
+ if min(self.length, self.cursor.remaining()) > 0 {
+ self.length -=1;
+ Some(self.cursor.read_u8())
+ } else {
+ None
+ }
+ }
+}
+
+//Reimplement eat_separator instead of fixing iterators
+#[macro_export]
+macro_rules! block_eat_separator (
+ ($i:expr, $arr:expr) => (
+ {
+ use nom::{InputLength,InputIter,Slice};
+ if ($i).input_len() == 0 {
+ Ok(($i, ($i).slice(0..0)))
+ } else {
+ match ($i).iter_indices().position(|(_, item)| {
+ for (_,c) in ($arr).iter_indices() {
+ if *c == item { return false; }
+ }
+ true
+ }) {
+ Some(index) => {
+ Ok((($i).slice(index..), ($i).slice(..index)))
+ },
+ None => {
+ Ok((($i).slice(($i).input_len()..), $i))
+ }
+ }
+ }
+ }
+ )
+);
+
+#[macro_export]
+macro_rules! block_named (
+ ($name:ident, $submac:ident!( $($args:tt)* )) => (
+ fn $name<'a>( i: BlockSlice<'a> ) -> nom::IResult<BlockSlice<'a>, BlockSlice<'a>, u32> {
+ $submac!(i, $($args)*)
+ }
+ );
+ ($name:ident<$o:ty>, $submac:ident!( $($args:tt)* )) => (
+ fn $name<'a>( i: BlockSlice<'a> ) -> nom::IResult<BlockSlice<'a>, $o, u32> {
+ $submac!(i, $($args)*)
+ }
+ );
+);
+
+block_named!(sp, block_eat_separator!(&b" \t\r\n"[..]));
+
+macro_rules! block_ws (
+ ($i:expr, $($args:tt)*) => (
+ {
+ sep!($i, sp, $($args)*)
+ }
+ )
+);
+
+block_named!(digit, is_a!("0123456789"));
+
+block_named!(parens<i64>, block_ws!(delimited!( tag!("("), expr, tag!(")") )) );
+
+
+block_named!(factor<i64>, alt!(
+ map_res!(
+ block_ws!(digit),
+ to_i64
+ )
+ | parens
+ )
+);
+
+block_named!(term <i64>, do_parse!(
+ init: factor >>
+ res: fold_many0!(
+ pair!(alt!(tag!("*") | tag!("/")), factor),
+ init,
+ |acc, (op, val): (BlockSlice, i64)| {
+ if (op.cursor().next().unwrap() as char) == '*' { acc * val } else { acc / val }
+ }
+ ) >>
+ (res)
+ )
+);
+
+block_named!(expr <i64>, do_parse!(
+ init: term >>
+ res: fold_many0!(
+ pair!(alt!(tag!("+") | tag!("-")), term),
+ init,
+ |acc, (op, val): (BlockSlice, i64)| {
+ if (op.cursor().next().unwrap() as char) == '+' { acc + val } else { acc - val }
+ }
+ ) >>
+ (res)
+ )
+);
+
+
+fn blockbuf_from(input: &[u8]) -> BlockBuf {
+ let mut b = BlockBuf::new(2, 100);
+ b.copy_from(input);
+ b
+}
+
+
+fn sl<'a>(input: &'a BlockBuf) -> BlockSlice<'a> {
+ BlockSlice {
+ buf: input,
+ start: 0,
+ end: input.len(),
+ }
+}
+
+fn to_i64<'a>(input: BlockSlice<'a>) -> Result<i64, ()> {
+ let v: Vec<u8> = input.cursor().collect();
+
+ match str::from_utf8(&v) {
+ Err(_) => Err(()),
+ Ok(s) => match FromStr::from_str(s) {
+ Err(_) => Err(()),
+ Ok(i) => Ok(i)
+ }
+ }
+}
+
+#[test]
+fn factor_test() {
+ let a = blockbuf_from(&b"3"[..]);
+ println!("calculated: {:?}", factor(sl(&a)));
+}
+
+#[test]
+fn parens_test() {
+ let input1 = blockbuf_from(&b" 2* ( 3 + 4 ) "[..]);
+ println!("calculated 1: {:?}", expr(sl(&input1)));
+ let input2 = blockbuf_from(&b" 2*2 / ( 5 - 1) + 3"[..]);
+ println!("calculated 2: {:?}", expr(sl(&input2)));
+}
+*/
diff --git a/third_party/rust/nom/tests/css.rs b/third_party/rust/nom/tests/css.rs
new file mode 100644
index 0000000000..0ce7e77b05
--- /dev/null
+++ b/third_party/rust/nom/tests/css.rs
@@ -0,0 +1,51 @@
+extern crate nom;
+
+use nom::IResult;
+use nom::bytes::complete::{tag, take_while_m_n};
+use nom::combinator::map_res;
+use nom::sequence::tuple;
+
+#[derive(Debug, PartialEq)]
+pub struct Color {
+ pub red: u8,
+ pub green: u8,
+ pub blue: u8,
+}
+
+fn from_hex(input: &str) -> Result<u8, std::num::ParseIntError> {
+ 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> {
+ map_res(
+ take_while_m_n(2, 2, is_hex_digit),
+ from_hex
+ )(input)
+}
+
+fn hex_color(input: &str) -> IResult<&str, Color> {
+ let (input, _) = tag("#")(input)?;
+ let (input, (red, green, blue)) = tuple((hex_primary, hex_primary, hex_primary))(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/third_party/rust/nom/tests/custom_errors.rs b/third_party/rust/nom/tests/custom_errors.rs
new file mode 100644
index 0000000000..89366dc9e1
--- /dev/null
+++ b/third_party/rust/nom/tests/custom_errors.rs
@@ -0,0 +1,53 @@
+#![allow(dead_code)]
+#![cfg_attr(feature = "cargo-clippy", allow(block_in_if_condition_stmt))]
+
+#[macro_use]
+extern crate nom;
+
+use nom::IResult;
+use nom::error::{ErrorKind,ParseError};
+use nom::character::streaming::digit1 as digit;
+
+use std::convert::From;
+
+#[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<&'a str> for CustomError {
+ fn from_error_kind(_: &'a str, kind: ErrorKind) -> Self {
+ CustomError(format!("error code was: {:?}", kind))
+ }
+
+ fn append(_: &'a str, kind: ErrorKind, other: CustomError) -> Self {
+ CustomError(format!("{:?}\nerror code was: {:?}", other, kind))
+
+ }
+
+}
+
+fn test1(input: &str) -> IResult<&str, &str, CustomError> {
+ //fix_error!(input, CustomError, tag!("abcd"))
+ tag!(input, "abcd")
+}
+
+fn test2(input: &str) -> IResult<&str, &str, CustomError> {
+ //terminated!(input, test1, fix_error!(CustomError, digit))
+ terminated!(input, test1, digit)
+}
+
+fn test3(input: &str) -> IResult<&str, &str, CustomError> {
+ verify!(input, test1, |s: &str| {
+ s.starts_with("abcd")
+ })
+}
+
+#[cfg(feature = "alloc")]
+fn test4(input: &str) -> IResult<&str, Vec<&str>, CustomError> {
+ count!(input, test1, 4)
+}
diff --git a/third_party/rust/nom/tests/escaped.rs b/third_party/rust/nom/tests/escaped.rs
new file mode 100644
index 0000000000..19c1ed70a4
--- /dev/null
+++ b/third_party/rust/nom/tests/escaped.rs
@@ -0,0 +1,25 @@
+use nom::{Err, error::ErrorKind, IResult};
+use nom::character::complete::digit1;
+use nom::bytes::complete::escaped;
+use nom::character::complete::one_of;
+
+fn esc(s: &str) -> IResult<&str, &str> {
+ escaped(digit1, '\\', one_of("\"n\\"))(s)
+}
+
+#[cfg(feature="alloc")]
+fn esc_trans(s: &str) -> IResult<&str, String> {
+ use nom::bytes::complete::{escaped_transform, tag};
+ escaped_transform(digit1, '\\', |i: &str| tag("n")(i))(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/third_party/rust/nom/tests/float.rs b/third_party/rust/nom/tests/float.rs
new file mode 100644
index 0000000000..eb82804f29
--- /dev/null
+++ b/third_party/rust/nom/tests/float.rs
@@ -0,0 +1,46 @@
+#[macro_use]
+extern crate nom;
+
+use nom::character::streaming::digit1 as digit;
+
+use std::str;
+use std::str::FromStr;
+
+named!(
+ unsigned_float<f32>,
+ map_res!(
+ map_res!(
+ recognize!(alt!(
+ delimited!(digit, tag!("."), opt!(digit)) | delimited!(opt!(digit), tag!("."), digit)
+ )),
+ str::from_utf8
+ ),
+ FromStr::from_str
+ )
+);
+
+named!(
+ float<f32>,
+ map!(
+ pair!(opt!(alt!(tag!("+") | tag!("-"))), unsigned_float),
+ |(sign, value): (Option<&[u8]>, f32)| sign
+ .and_then(|s| if s[0] == b'-' { Some(-1f32) } else { None })
+ .unwrap_or(1f32) * value
+ )
+);
+
+#[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/third_party/rust/nom/tests/inference.rs b/third_party/rust/nom/tests/inference.rs
new file mode 100644
index 0000000000..851c1382c9
--- /dev/null
+++ b/third_party/rust/nom/tests/inference.rs
@@ -0,0 +1,53 @@
+//! test type inference issues in parsee compilation
+//#![feature(trace_macros)]
+#![allow(dead_code)]
+#![allow(unused_comparisons)]
+#![allow(unused_variables)]
+#![allow(unused_imports)]
+
+#[macro_use]
+extern crate nom;
+
+use std::str;
+use nom::character::{streaming::alpha1 as alpha, is_digit};
+
+// issue #617
+named!(multi<&[u8], () >, fold_many0!( take_while1!( is_digit ), (), |_, _| {}));
+
+// issue #561
+#[cfg(feature = "alloc")]
+named!(
+ value<Vec<Vec<&str>>>,
+ do_parse!(
+ first_line: map_res!(is_not!("\n"), std::str::from_utf8)
+ >> rest:
+ many_m_n!(
+ 0,
+ 1,
+ separated_list!(
+ tag!("\n\t"),
+ map_res!(take_while!(call!(|c| c != b'\n')), std::str::from_utf8)
+ )
+ ) >> (rest)
+ )
+);
+
+// issue #534
+#[cfg(feature = "alloc")]
+fn wrap_suffix(input: &Option<Vec<&[u8]>>) -> Option<String> {
+ if input.is_some() {
+ // I've tried both of the lines below individually and get the same error.
+ Some("hello".to_string())
+ //Some(str::from_utf8(u).expect("Found invalid UTF-8").to_string())
+ } else {
+ None
+ }
+}
+
+#[cfg(feature = "alloc")]
+named!(parse_suffix<&[u8],Option<String>>,do_parse!(
+ u: opt!(many1!(alt!(
+ complete!(tag!("%")) | complete!(tag!("#")) | complete!(tag!("@")) | complete!(alpha)
+ ))) >>
+ (wrap_suffix(&u))
+));
diff --git a/third_party/rust/nom/tests/ini.rs b/third_party/rust/nom/tests/ini.rs
new file mode 100644
index 0000000000..c3f9b750d7
--- /dev/null
+++ b/third_party/rust/nom/tests/ini.rs
@@ -0,0 +1,221 @@
+#[macro_use]
+extern crate nom;
+
+use nom::{
+ IResult,
+ bytes::complete::take_while,
+ sequence::delimited,
+ combinator::map_res,
+ character::complete::{char, alphanumeric1 as alphanumeric, multispace0 as multispace, space0 as space}
+};
+
+use std::str;
+use std::collections::HashMap;
+
+fn category(i: &[u8]) -> IResult<&[u8], &str> {
+ map_res(delimited(char('['), take_while(|c| c != b']'), char(']')), str::from_utf8)(i)
+}
+
+fn complete_byte_slice_to_str<'a>(s: &'a[u8]) -> Result<&'a str, str::Utf8Error> {
+ str::from_utf8(s)
+}
+
+named!(key_value <&[u8],(&str,&str)>,
+ do_parse!(
+ key: map_res!(alphanumeric, complete_byte_slice_to_str)
+ >> opt!(space)
+ >> char!('=')
+ >> opt!(space)
+ >> val: map_res!(
+ take_while!(call!(|c| c != b'\n' && c != b';')),
+ complete_byte_slice_to_str
+ )
+ >> opt!(pair!(char!(';'), take_while!(call!(|c| c != b'\n'))))
+ >> (key, val)
+ )
+);
+
+named!(keys_and_values<&[u8], HashMap<&str, &str> >,
+ map!(
+ many0!(terminated!(key_value, opt!(multispace))),
+ |vec: Vec<_>| vec.into_iter().collect()
+ )
+);
+
+named!(category_and_keys<&[u8],(&str,HashMap<&str,&str>)>,
+ do_parse!(
+ category: category >>
+ opt!(multispace) >>
+ keys: keys_and_values >>
+ (category, keys)
+ )
+);
+
+named!(categories<&[u8], HashMap<&str, HashMap<&str,&str> > >,
+ map!(
+ many0!(
+ separated_pair!(
+ category,
+ opt!(multispace),
+ map!(
+ many0!(terminated!(key_value, opt!(multispace))),
+ |vec: Vec<_>| vec.into_iter().collect()
+ )
+ )
+ ),
+ |vec: Vec<_>| vec.into_iter().collect()
+ )
+);
+
+#[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/third_party/rust/nom/tests/ini_str.rs b/third_party/rust/nom/tests/ini_str.rs
new file mode 100644
index 0000000000..d778918c40
--- /dev/null
+++ b/third_party/rust/nom/tests/ini_str.rs
@@ -0,0 +1,215 @@
+#[macro_use]
+extern crate nom;
+
+use nom::{
+ IResult,
+ combinator::opt,
+ bytes::complete::{take_while, is_a},
+ sequence::{delimited, terminated},
+ character::complete::{char, alphanumeric1 as alphanumeric, space0 as space}
+};
+
+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> {
+ is_a(" \r\n")(i)
+}
+
+fn category(i: &str) -> IResult<&str, &str> {
+ terminated(delimited(char('['), take_while(|c| c != ']'), char(']')), opt(is_a(" \r\n")))(i)
+}
+
+named!(key_value <&str,(&str,&str)>,
+ do_parse!(
+ key: alphanumeric >>
+ opt!(space) >>
+ tag!("=") >>
+ opt!(space) >>
+ val: take_till!(is_line_ending_or_comment) >>
+ opt!(space) >>
+ opt!(pair!(tag!(";"), not_line_ending)) >>
+ opt!(space_or_line_ending) >>
+ (key, val)
+ )
+);
+
+named!(keys_and_values_aggregator<&str, Vec<(&str, &str)> >, many0!(key_value));
+
+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),
+ }
+}
+
+named!(category_and_keys<&str,(&str,HashMap<&str,&str>)>,
+ pair!(category, keys_and_values)
+);
+
+named!(categories_aggregator<&str, Vec<(&str, HashMap<&str,&str>)> >, many0!(category_and_keys));
+
+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/third_party/rust/nom/tests/issues.rs b/third_party/rust/nom/tests/issues.rs
new file mode 100644
index 0000000000..62a1a01bc5
--- /dev/null
+++ b/third_party/rust/nom/tests/issues.rs
@@ -0,0 +1,318 @@
+//#![feature(trace_macros)]
+#![allow(dead_code)]
+#![cfg_attr(feature = "cargo-clippy", allow(redundant_closure))]
+
+#[macro_use]
+extern crate nom;
+
+use nom::{character::{is_digit, streaming::space1 as space}, Err, IResult, Needed, error::ErrorKind, number::streaming::le_u64};
+
+#[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::Size(1)))
+ }
+}
+
+//trace_macros!(true);
+
+#[allow(dead_code)]
+named!(range<&[u8], Range>,
+ alt!(
+ do_parse!(
+ start: take_char >>
+ tag!("-") >>
+ end: take_char >>
+ (Range {
+ start: start,
+ end: end,
+ })
+ ) |
+ map!(
+ take_char,
+ |c| {
+ Range {
+ start: c,
+ end: c,
+ }
+ }
+ )
+ )
+);
+
+#[allow(dead_code)]
+named!(literal<&[u8], Vec<char> >,
+ map!(
+ many1!(take_char),
+ |cs| {
+ cs
+ }
+ )
+);
+
+#[test]
+fn issue_58() {
+ let _ = range(&b"abcd"[..]);
+ let _ = literal(&b"abcd"[..]);
+}
+
+//trace_macros!(false);
+
+#[cfg(feature = "std")]
+mod parse_int {
+ use nom::HexDisplay;
+ use nom::{IResult, character::streaming::{digit1 as digit, space1 as space}};
+ use std::str;
+
+ named!(parse_ints<Vec<i32>>, many0!(spaces_or_int));
+
+ fn spaces_or_int(input: &[u8]) -> IResult<&[u8], i32> {
+ println!("{}", input.to_hex(8));
+ do_parse!(
+ input,
+ opt!(complete!(space)) >> res: map!(complete!(digit), |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),
+ }
+ }) >> (res)
+ )
+ }
+
+ #[test]
+ fn issue_142() {
+ let subject = parse_ints(&b"12 34 5689a"[..]);
+ let expected = Ok((&b"a"[..], vec![12, 34, 5689]));
+ assert_eq!(subject, expected);
+
+ let subject = parse_ints(&b"12 34 5689 "[..]);
+ let expected = Ok((&b" "[..], vec![12, 34, 5689]));
+ assert_eq!(subject, expected)
+ }
+}
+
+#[test]
+fn usize_length_bytes_issue() {
+ use nom::number::streaming::be_u16;
+ let _: IResult<&[u8], &[u8], (&[u8], ErrorKind)> = length_data!(b"012346", be_u16);
+}
+
+/*
+ DOES NOT COMPILE
+#[test]
+fn issue_152() {
+ named!(take4, take!(4));
+ named!(xyz, tag!("XYZ"));
+ named!(abc, tag!("abc"));
+
+
+ named!(sw,
+ switch!(take4,
+ b"abcd" => xyz |
+ b"efgh" => abc
+ )
+ );
+}
+*/
+
+#[test]
+fn take_till_issue() {
+ named!(nothing, take_till!(call!(|_| true)));
+
+ assert_eq!(nothing(b""), Err(Err::Incomplete(Needed::Size(1))));
+ assert_eq!(nothing(b"abc"), Ok((&b"abc"[..], &b""[..])));
+}
+
+named!(
+ issue_498<Vec<&[u8]>>,
+ separated_nonempty_list!(opt!(space), tag!("abcd"))
+);
+
+named!(issue_308(&str) -> bool,
+ do_parse! (
+ tag! ("foo") >>
+ b: alt! (
+ complete!(map! (tag! ("1"), |_: &str|->bool {true})) |
+ value! (false)
+ ) >>
+ (b) ));
+
+#[cfg(feature = "alloc")]
+fn issue_302(input: &[u8]) -> IResult<&[u8], Option<Vec<u64>>> {
+ do_parse!(input, entries: cond!(true, count!(le_u64, 3)) >> (entries))
+}
+
+#[test]
+fn issue_655() {
+ use nom::character::streaming::{line_ending, not_line_ending};
+ named!(twolines(&str) -> (&str, &str),
+ do_parse!(
+ l1 : not_line_ending >>
+ line_ending >>
+ l2 : not_line_ending >>
+ line_ending >>
+ ((l1, l2))
+ )
+ );
+
+ assert_eq!(twolines("foo\nbar\n"), Ok(("", ("foo", "bar"))));
+ assert_eq!(twolines("féo\nbar\n"), Ok(("", ("féo", "bar"))));
+ assert_eq!(twolines("foé\nbar\n"), Ok(("", ("foé", "bar"))));
+ assert_eq!(twolines("foé\r\nbar\n"), Ok(("", ("foé", "bar"))));
+}
+
+#[test]
+fn issue_721() {
+ named!(f1<&str, u16>, parse_to!(u16));
+ named!(f2<&str, String>, parse_to!(String));
+ assert_eq!(f1("1234"), Ok(("", 1234)));
+ assert_eq!(f2("foo"), Ok(("", "foo".to_string())));
+ //assert_eq!(parse_to!("1234", u16), Ok(("", 1234)));
+ //assert_eq!(parse_to!("foo", String), Ok(("", "foo".to_string())));
+}
+
+#[cfg(feature = "alloc")]
+named!(issue_717<&[u8], Vec<&[u8]> >,
+ separated_list!(tag!([0x0]), is_not!([0x0u8]))
+);
+
+struct NoPartialEq {
+ value: i32,
+}
+
+named!(issue_724<&str, i32>,
+ do_parse!(
+ metadata: permutation!(
+ map!(tag!("hello"), |_| NoPartialEq { value: 1 }),
+ map!(tag!("world"), |_| NoPartialEq { value: 2 })
+ ) >>
+ (metadata.0.value + metadata.1.value)
+ )
+);
+
+#[test]
+fn issue_752() {
+ assert_eq!(
+ Err::Error(("ab", nom::error::ErrorKind::ParseTo)),
+ parse_to!("ab", usize).unwrap_err()
+ )
+}
+
+fn atom_specials(c: u8) -> bool {
+ c == b'q'
+}
+
+named!(
+ capability<&str>,
+ do_parse!(tag!(" ") >> _atom: map_res!(take_till1!(atom_specials), std::str::from_utf8) >> ("a"))
+);
+
+#[test]
+fn issue_759() {
+ assert_eq!(capability(b" abcqd"), Ok((&b"qd"[..], "a")));
+}
+
+named_args!(issue_771(count: usize)<Vec<u32>>,
+ length_count!(value!(count), call!(nom::number::streaming::be_u32))
+);
+
+/// This test is in a separate module to check that all required symbols are imported in
+/// `escaped_transform!()`. Without the module, the `use`-es of the current module would
+/// mask the error ('"Use of undeclared type or module `Needed`" in escaped_transform!').
+mod issue_780 {
+ named!(issue_780<&str, String>,
+ escaped_transform!(call!(::nom::character::streaming::alpha1), '\\', tag!("n"))
+ );
+}
+
+// issue 617
+named!(digits, take_while1!( is_digit ));
+named!(multi_617<&[u8], () >, fold_many0!( digits, (), |_, _| {}));
+
+// Sad :(
+named!(multi_617_fails<&[u8], () >, fold_many0!( take_while1!( is_digit ), (), |_, _| {}));
+
+mod issue_647 {
+ use nom::{Err, number::streaming::be_f64, error::ErrorKind};
+ pub type Input<'a> = &'a [u8];
+
+ #[derive(PartialEq, Debug, Clone)]
+ struct Data {
+ c: f64,
+ v: Vec<f64>
+ }
+
+ fn list<'a,'b>(input: Input<'a>, _cs: &'b f64) -> Result<(Input<'a>,Vec<f64>), Err<(&'a [u8], ErrorKind)>> {
+ separated_list!(input, complete!(tag!(",")), complete!(be_f64))
+ }
+
+ named!(data<Input,Data>, map!(
+ do_parse!(
+ c: be_f64 >>
+ tag!("\n") >>
+ v: call!(list,&c) >>
+ (c,v)
+ ), |(c,v)| {
+ Data {
+ c: c,
+ v: v
+ }
+ }
+ ));
+}
+
+named!(issue_775, take_till1!(|_| true));
+
+#[test]
+fn issue_848_overflow_incomplete_bits_to_bytes() {
+ named!(take, take!(0x2000000000000000));
+ named!(parser<&[u8], &[u8]>, bits!(bytes!(take)));
+ assert_eq!(parser(&b""[..]), Err(Err::Failure(error_position!(&b""[..], ErrorKind::TooLarge))));
+}
+
+#[test]
+fn issue_942() {
+ use nom::error::ParseError;
+ pub fn parser<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, usize, E> {
+ use nom::{character::complete::char, error::context, multi::many0_count};
+ many0_count(context("char_a", char('a')))(i)
+ }
+ assert_eq!(parser::<()>("aaa"), Ok(("", 3)));
+}
+
+#[test]
+fn issue_many_m_n_with_zeros() {
+ use nom::multi::many_m_n;
+ use nom::character::complete::char;
+ let parser = many_m_n::<_, _, (), _>(0, 0, char('a'));
+ assert_eq!(parser("aaa"), Ok(("aaa", vec!())));
+}
+
+#[test]
+fn issue_1027_convert_error_panic_nonempty() {
+ use nom::error::{VerboseError, convert_error};
+ use nom::sequence::pair;
+ use nom::character::complete::char;
+
+ let input = "a";
+
+ let result: IResult<_, _, VerboseError<&str>> = pair(char('a'), char('b'))(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:\na\n ^\nexpected \'b\', got end of input\n\n");
+}
diff --git a/third_party/rust/nom/tests/json.rs b/third_party/rust/nom/tests/json.rs
new file mode 100644
index 0000000000..14329a16ae
--- /dev/null
+++ b/third_party/rust/nom/tests/json.rs
@@ -0,0 +1,105 @@
+#![cfg(feature = "alloc")]
+//#![feature(trace_macros)]
+
+#[macro_use]
+extern crate nom;
+
+use nom::{character::is_alphanumeric, number::complete::recognize_float};
+
+use std::str;
+use std::collections::HashMap;
+
+#[derive(Debug, PartialEq)]
+pub enum JsonValue {
+ Str(String),
+ Num(f32),
+ Array(Vec<JsonValue>),
+ Object(HashMap<String, JsonValue>),
+}
+
+named!(float<f32>, flat_map!(recognize_float, parse_to!(f32)));
+
+//FIXME: verify how json strings are formatted
+named!(
+ string<&str>,
+ delimited!(
+ char!('"'),
+ //map_res!(escaped!(call!(alphanumeric), '\\', is_a!("\"n\\")), str::from_utf8),
+ map_res!(
+ escaped!(take_while1!(is_alphanumeric), '\\', one_of!("\"n\\")),
+ str::from_utf8
+ ),
+ char!('"')
+ )
+);
+
+named!(
+ array<Vec<JsonValue>>,
+ ws!(delimited!(
+ char!('['),
+ separated_list!(char!(','), value),
+ char!(']')
+ ))
+);
+
+named!(
+ key_value<(&str, JsonValue)>,
+ ws!(separated_pair!(string, char!(':'), value))
+);
+
+named!(
+ hash<HashMap<String, JsonValue>>,
+ ws!(map!(
+ delimited!(char!('{'), separated_list!(char!(','), key_value), char!('}')),
+ |tuple_vec| {
+ let mut h: HashMap<String, JsonValue> = HashMap::new();
+ for (k, v) in tuple_vec {
+ h.insert(String::from(k), v);
+ }
+ h
+ }
+ ))
+);
+
+named!(
+ value<JsonValue>,
+ ws!(alt!(
+ hash => { |h| JsonValue::Object(h) } |
+ array => { |v| JsonValue::Array(v) } |
+ string => { |s| JsonValue::Str(String::from(s)) } |
+ float => { |num| JsonValue::Num(num) }
+ ))
+);
+
+#[test]
+fn json_object() {
+ let input =
+ r#"{
+ "a": 42,
+ "b": "x"
+ }\0"#;
+
+ let mut expected_map = HashMap::new();
+ expected_map.insert(String::from("a"), JsonValue::Num(42f32));
+ expected_map.insert(String::from("b"), JsonValue::Str(String::from("x")));
+ let expected = JsonValue::Object(expected_map);
+
+ assert_eq!(expected, value(input.as_bytes()).unwrap().1);
+}
+
+#[test]
+fn json_array() {
+ let input =
+ r#"[
+ 42,
+ "x"
+ ]\0"#;
+
+ let expected_vec = vec![
+ JsonValue::Num(42f32),
+ JsonValue::Str(String::from("x"))
+ ];
+ let expected = JsonValue::Array(expected_vec);
+
+ assert_eq!(expected, value(input.as_bytes()).unwrap().1);
+}
diff --git a/third_party/rust/nom/tests/mp4.rs b/third_party/rust/nom/tests/mp4.rs
new file mode 100644
index 0000000000..1432621611
--- /dev/null
+++ b/third_party/rust/nom/tests/mp4.rs
@@ -0,0 +1,319 @@
+#![allow(dead_code)]
+
+#[macro_use]
+extern crate nom;
+
+use nom::{
+ IResult, Needed, Err,
+ error::ErrorKind,
+ number::streaming::{be_u16, be_u32, be_u64, be_f32}
+};
+
+use std::str;
+
+fn mp4_box(input: &[u8]) -> IResult<&[u8], &[u8]> {
+ match be_u32(input) {
+ Ok((i, offset)) => {
+ let sz: usize = offset as usize;
+ if i.len() >= sz - 4 {
+ Ok((&i[(sz - 4)..], &i[0..(sz - 4)]))
+ } else {
+ Err(Err::Incomplete(Needed::Size(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
+}
+
+#[allow(non_snake_case)]
+named!(mvhd32 <&[u8], MvhdBox>,
+ do_parse!(
+ version_flags: be_u32 >>
+ created_date: be_u32 >>
+ modified_date: be_u32 >>
+ scale: be_u32 >>
+ duration: be_u32 >>
+ speed: be_f32 >>
+ volume: be_u16 >> // actually a 2 bytes decimal
+ take!(10) >>
+ scale_a: be_f32 >>
+ rotate_b: be_f32 >>
+ angle_u: be_f32 >>
+ rotate_c: be_f32 >>
+ scale_d: be_f32 >>
+ angle_v: be_f32 >>
+ position_x: be_f32 >>
+ position_y: be_f32 >>
+ scale_w: be_f32 >>
+ preview: be_u64 >>
+ poster: be_u32 >>
+ selection: be_u64 >>
+ current_time: be_u32 >>
+ track_id: be_u32 >>
+ (
+ MvhdBox::M32(Mvhd32 {
+ version_flags: version_flags,
+ created_date: created_date,
+ modified_date: modified_date,
+ scale: scale,
+ duration: duration,
+ speed: speed,
+ volume: 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: preview,
+ poster: poster,
+ selection: selection,
+ current_time: current_time,
+ track_id: track_id
+ })
+ ))
+);
+
+#[allow(non_snake_case)]
+named!(mvhd64 <&[u8], MvhdBox>,
+ do_parse!(
+ version_flags: be_u32 >>
+ created_date: be_u64 >>
+ modified_date: be_u64 >>
+ scale: be_u32 >>
+ duration: be_u64 >>
+ speed: be_f32 >>
+ volume: be_u16 >> // actually a 2 bytes decimal
+ take!(10) >>
+ scale_a: be_f32 >>
+ rotate_b: be_f32 >>
+ angle_u: be_f32 >>
+ rotate_c: be_f32 >>
+ scale_d: be_f32 >>
+ angle_v: be_f32 >>
+ position_x: be_f32 >>
+ position_y: be_f32 >>
+ scale_w: be_f32 >>
+ preview: be_u64 >>
+ poster: be_u32 >>
+ selection: be_u64 >>
+ current_time: be_u32 >>
+ track_id: be_u32 >>
+ (
+ MvhdBox::M64(Mvhd64 {
+ version_flags: version_flags,
+ created_date: created_date,
+ modified_date: modified_date,
+ scale: scale,
+ duration: duration,
+ speed: speed,
+ volume: 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: preview,
+ poster: poster,
+ selection: selection,
+ current_time: current_time,
+ track_id: track_id
+ })
+ ))
+);
+
+#[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,
+}
+
+named!(brand_name<&[u8],&str>, map_res!(take!(4), str::from_utf8));
+
+named!(filetype_parser<&[u8], FileType>,
+ do_parse!(
+ m: brand_name >>
+ v: take!(4) >>
+ c: many0!(brand_name) >>
+ (FileType{ major_brand: m, major_brand_version:v, compatible_brands: c })
+ )
+);
+
+fn mvhd_box(input: &[u8]) -> IResult<&[u8], MvhdBox> {
+ let res = if input.len() < 100 {
+ Err(Err::Incomplete(Needed::Size(100)))
+ } else if input.len() == 100 {
+ mvhd32(input)
+ } else if input.len() == 112 {
+ mvhd64(input)
+ } else {
+ Err(Err::Error(error_position!(input, ErrorKind::TooLarge)))
+ };
+ println!("res: {:?}", res);
+ res
+}
+
+fn unknown_box_type(input: &[u8]) -> IResult<&[u8], MP4BoxType> {
+ Ok((input, MP4BoxType::Unknown))
+}
+
+//named!(box_type<&[u8], MP4BoxType>,
+fn box_type(input: &[u8]) -> IResult<&[u8], MP4BoxType> {
+ alt!(input,
+ tag!("ftyp") => { |_| MP4BoxType::Ftyp } |
+ tag!("moov") => { |_| MP4BoxType::Moov } |
+ tag!("mdat") => { |_| MP4BoxType::Mdat } |
+ tag!("free") => { |_| MP4BoxType::Free } |
+ tag!("skip") => { |_| MP4BoxType::Skip } |
+ tag!("wide") => { |_| MP4BoxType::Wide } |
+ unknown_box_type
+ )
+}
+
+// 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
+named!(moov_type<&[u8], MP4BoxType>,
+ alt!(
+ tag!("mdra") => { |_| MP4BoxType::Mdra } |
+ tag!("dref") => { |_| MP4BoxType::Dref } |
+ tag!("cmov") => { |_| MP4BoxType::Cmov } |
+ tag!("rmra") => { |_| MP4BoxType::Rmra } |
+ tag!("iods") => { |_| MP4BoxType::Iods } |
+ tag!("mvhd") => { |_| MP4BoxType::Mvhd } |
+ tag!("clip") => { |_| MP4BoxType::Clip } |
+ tag!("trak") => { |_| MP4BoxType::Trak } |
+ tag!("udta") => { |_| MP4BoxType::Udta }
+ )
+);
+
+named!(box_header<&[u8],MP4BoxHeader>,
+ do_parse!(
+ length: be_u32 >>
+ tag: box_type >>
+ (MP4BoxHeader{ length: length, tag: tag})
+ )
+);
+
+named!(moov_header<&[u8],MP4BoxHeader>,
+ do_parse!(
+ length: be_u32 >>
+ tag: moov_type >>
+ (MP4BoxHeader{ length: length, tag: tag})
+ )
+);
+
diff --git a/third_party/rust/nom/tests/multiline.rs b/third_party/rust/nom/tests/multiline.rs
new file mode 100644
index 0000000000..cca19ecbad
--- /dev/null
+++ b/third_party/rust/nom/tests/multiline.rs
@@ -0,0 +1,36 @@
+extern crate nom;
+
+use nom::{
+ IResult,
+ multi::many0,
+ sequence::terminated,
+ character::complete::{alphanumeric1 as alphanumeric, line_ending as eol}
+};
+
+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/third_party/rust/nom/tests/named_args.rs b/third_party/rust/nom/tests/named_args.rs
new file mode 100644
index 0000000000..811b0a0dce
--- /dev/null
+++ b/third_party/rust/nom/tests/named_args.rs
@@ -0,0 +1,161 @@
+#[macro_use]
+extern crate nom;
+
+use nom::{
+ branch::alt,
+ sequence::{delimited, pair, preceded},
+ character::complete::{digit1 as digit, space0 as space},
+ bytes::complete::tag
+};
+
+// Parser definition
+
+use std::str;
+use std::str::FromStr;
+
+use self::Operator::*;
+
+enum Operator {
+ Slash,
+ Star,
+}
+
+impl Operator {
+ fn to_str(&self) -> &'static str {
+ match *self {
+ Slash => "/",
+ Star => "*",
+ }
+ }
+}
+
+// Parse the specified `Operator`.
+named_args!(operator(op: Operator) <&[u8], &[u8]>,
+ call!(tag(op.to_str()))
+);
+
+// We parse any expr surrounded by the tags `open_tag` and `close_tag`, ignoring all whitespaces around those
+named_args!(brackets<'a>(open_tag: &str, close_tag: &str) <&'a[u8], i64>,
+ call!(delimited(
+ space,
+ delimited(tag(open_tag), preceded(space, expr), preceded(space, tag(close_tag))),
+ space
+ ))
+);
+
+fn byte_slice_to_str<'a>(s: &'a[u8]) -> Result<&'a str, str::Utf8Error> {
+ str::from_utf8(s)
+}
+
+// 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 brackets parser defined above
+named!(factor<&[u8], i64>, alt!(
+ map_res!(
+ map_res!(
+ call!(delimited(space, digit, space)),
+ byte_slice_to_str
+ ),
+ FromStr::from_str
+ )
+ | call!(brackets, "(", ")")
+ )
+);
+
+// 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
+named!(term <&[u8], i64>, do_parse!(
+ init: factor >>
+ res: fold_many0!(
+ pair!(alt!(call!(operator, Star) | call!(operator, Slash)), factor),
+ init,
+ |acc, (op, val): (&[u8], i64)| {
+ if (op[0] as char) == '*' { acc * val } else { acc / val }
+ }
+ ) >>
+ (res)
+ )
+);
+
+named!(expr <&[u8], i64>, do_parse!(
+ init: term >>
+ res: fold_many0!(
+ call!(pair(alt((tag("+"), tag("-"))), term)),
+ init,
+ |acc, (op, val): (&[u8], i64)| {
+ if (op[0] as char) == '+' { acc + val } else { acc - val }
+ }
+ ) >>
+ (res)
+ )
+);
+
+#[test]
+fn factor_test() {
+ assert_eq!(
+ factor(&b"3"[..]),
+ Ok((&b""[..], 3))
+ );
+ assert_eq!(
+ factor(&b" 12"[..]),
+ Ok((&b""[..], 12))
+ );
+ assert_eq!(
+ factor(&b"537 "[..]),
+ Ok((&b""[..], 537))
+ );
+ assert_eq!(
+ factor(&b" 24 "[..]),
+ Ok((&b""[..], 24))
+ );
+}
+
+#[test]
+fn term_test() {
+ assert_eq!(
+ term(&b" 12 *2 / 3"[..]),
+ Ok((&b""[..], 8))
+ );
+ assert_eq!(
+ term(&b" 2* 3 *2 *2 / 3"[..]),
+ Ok((&b""[..], 8))
+ );
+ assert_eq!(
+ term(&b" 48 / 3/2"[..]),
+ Ok((&b""[..], 8))
+ );
+}
+
+#[test]
+fn expr_test() {
+ assert_eq!(
+ expr(&b" 1 + 2 "[..]),
+ Ok((&b""[..], 3))
+ );
+ assert_eq!(
+ expr(&b" 12 + 6 - 4+ 3"[..]),
+ Ok((&b""[..], 17))
+ );
+ assert_eq!(
+ expr(&b" 1 + 2*3 + 4"[..]),
+ Ok((&b""[..], 11))
+ );
+}
+
+#[test]
+fn parens_test() {
+ assert_eq!(
+ expr(&b" ( 2 )"[..]),
+ Ok((&b""[..], 2))
+ );
+ assert_eq!(
+ expr(&b" 2* ( 3 + 4 ) "[..]),
+ Ok((&b""[..], 14))
+ );
+ assert_eq!(
+ expr(&b" 2*2 / ( 5 - 1) + 3"[..]),
+ Ok((&b""[..], 4))
+ );
+}
diff --git a/third_party/rust/nom/tests/overflow.rs b/third_party/rust/nom/tests/overflow.rs
new file mode 100644
index 0000000000..2f4a87f34a
--- /dev/null
+++ b/third_party/rust/nom/tests/overflow.rs
@@ -0,0 +1,139 @@
+#![cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))]
+#![cfg(target_pointer_width = "64")]
+
+#[macro_use]
+extern crate nom;
+
+use nom::{Err, Needed};
+#[cfg(feature = "alloc")]
+use nom::number::streaming::be_u64;
+
+// Parser definition
+
+// We request a length that would trigger an overflow if computing consumed + requested
+named!(parser01<&[u8],()>,
+ do_parse!(
+ hdr: take!(1) >>
+ data: take!(18446744073709551615) >>
+ ({
+ let _ = hdr;
+ let _ = data;
+ ()
+ })
+ )
+);
+
+// We request a length that would trigger an overflow if computing consumed + requested
+named!(parser02<&[u8],(&[u8],&[u8])>,
+ tuple!(take!(1),take!(18446744073709551615))
+);
+
+#[test]
+fn overflow_incomplete_do_parse() {
+ assert_eq!(
+ parser01(&b"3"[..]),
+ Err(Err::Incomplete(Needed::Size(18446744073709551615)))
+ );
+}
+
+#[test]
+fn overflow_incomplete_tuple() {
+ assert_eq!(
+ parser02(&b"3"[..]),
+ Err(Err::Incomplete(Needed::Size(18446744073709551615)))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn overflow_incomplete_length_bytes() {
+ named!(multi<&[u8], Vec<&[u8]> >, many0!( length_data!(be_u64) ) );
+
+ // Trigger an overflow in length_data
+ assert_eq!(
+ multi(&b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xff\xaa"[..]),
+ Err(Err::Incomplete(Needed::Size(18446744073709551615)))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn overflow_incomplete_many0() {
+ named!(multi<&[u8], Vec<&[u8]> >, many0!( length_data!(be_u64) ) );
+
+ // Trigger an overflow in many0
+ assert_eq!(
+ multi(&b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef\xaa"[..]),
+ Err(Err::Incomplete(Needed::Size(18446744073709551599)))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn overflow_incomplete_many1() {
+ named!(multi<&[u8], Vec<&[u8]> >, many1!( length_data!(be_u64) ) );
+
+ // Trigger an overflow in many1
+ assert_eq!(
+ multi(&b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef\xaa"[..]),
+ Err(Err::Incomplete(Needed::Size(18446744073709551599)))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn overflow_incomplete_many_till() {
+ named!(multi<&[u8], (Vec<&[u8]>, &[u8]) >, many_till!( length_data!(be_u64), tag!("abc") ) );
+
+ // Trigger an overflow in many_till
+ assert_eq!(
+ multi(&b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef\xaa"[..]),
+ Err(Err::Incomplete(Needed::Size(18446744073709551599)))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn overflow_incomplete_many_m_n() {
+ named!(multi<&[u8], Vec<&[u8]> >, many_m_n!(2, 4, length_data!(be_u64) ) );
+
+ // Trigger an overflow in many_m_n
+ assert_eq!(
+ multi(&b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef\xaa"[..]),
+ Err(Err::Incomplete(Needed::Size(18446744073709551599)))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn overflow_incomplete_count() {
+ named!(counter<&[u8], Vec<&[u8]> >, count!( length_data!(be_u64), 2 ) );
+
+ assert_eq!(
+ counter(&b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef\xaa"[..]),
+ Err(Err::Incomplete(Needed::Size(18446744073709551599)))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn overflow_incomplete_length_count() {
+ use nom::number::streaming::be_u8;
+ named!(multi<&[u8], Vec<&[u8]> >, length_count!( be_u8, length_data!(be_u64) ) );
+
+ assert_eq!(
+ multi(&b"\x04\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xee\xaa"[..]),
+ Err(Err::Incomplete(Needed::Size(18446744073709551598)))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn overflow_incomplete_length_data() {
+ named!(multi<&[u8], Vec<&[u8]> >, many0!( length_data!(be_u64) ) );
+
+ assert_eq!(
+ multi(&b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xff\xaa"[..]),
+ Err(Err::Incomplete(Needed::Size(18446744073709551615)))
+ );
+}
diff --git a/third_party/rust/nom/tests/reborrow_fold.rs b/third_party/rust/nom/tests/reborrow_fold.rs
new file mode 100644
index 0000000000..b53555b074
--- /dev/null
+++ b/third_party/rust/nom/tests/reborrow_fold.rs
@@ -0,0 +1,18 @@
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+#[macro_use]
+extern crate nom;
+
+use std::str;
+
+named_args!(atom<'a>(tomb: &'a mut ())<String>,
+ map!(map_res!(is_not!(" \t\r\n()"), str::from_utf8), ToString::to_string));
+
+/*FIXME: should we support the use case of borrowing data mutably in a parser?
+named_args!(list<'a>(tomb: &'a mut ())<String>,
+ delimited!(
+ char!('('),
+ fold_many0!(call!(atom, tomb), "".to_string(), |acc: String, next: String| acc + next.as_str()),
+ char!(')')));
+*/
diff --git a/third_party/rust/nom/tests/test1.rs b/third_party/rust/nom/tests/test1.rs
new file mode 100644
index 0000000000..85c442fe84
--- /dev/null
+++ b/third_party/rust/nom/tests/test1.rs
@@ -0,0 +1,44 @@
+#![cfg(feature = "stream")]
+
+#[macro_use]
+extern crate nom;
+
+use nom::{not_line_ending, IResult};
+
+use std::fmt::Debug;
+
+/*
+#[test]
+#[allow(unused_must_use)]
+fn tag() {
+ FileProducer::new("assets/links.txt", 20).map(|producer: FileProducer| {
+ let mut p = producer;
+ p.refill();
+
+ consumer_from_parser!(PrintConsumer<()>, flat_map!(map_res!(tag!("https!"), str::from_utf8), print));
+ let mut cs = PrintConsumer::new();
+ for _ in 1..4 {
+ p.apply(&mut cs);
+ }
+ });
+}
+*/
+
+pub fn print<T: Debug>(input: T) -> IResult<T, ()> {
+ println!("{:?}", input);
+ Ok((input, ()))
+}
+
+#[test]
+fn is_not() {
+ //is_not!(foo b"\r\n");
+ named!(foo<&[u8],&[u8]>, is_not!(&b"\r\n"[..]));
+ let a = &b"ab12cd\nefgh"[..];
+ assert_eq!(foo(a), Ok((&b"\nefgh"[..], &b"ab12cd"[..])));
+}
+
+#[test]
+fn exported_public_method_defined_by_macro() {
+ let a = &b"ab12cd\nefgh"[..];
+ assert_eq!(not_line_ending(a), Ok((&b"\nefgh"[..], &b"ab12cd"[..])));
+}