summaryrefslogtreecommitdiffstats
path: root/third_party/rust/nom/src/branch
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/rust/nom/src/branch
parentInitial commit. (diff)
downloadfirefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz
firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/nom/src/branch')
-rw-r--r--third_party/rust/nom/src/branch/mod.rs291
-rw-r--r--third_party/rust/nom/src/branch/tests.rs142
2 files changed, 433 insertions, 0 deletions
diff --git a/third_party/rust/nom/src/branch/mod.rs b/third_party/rust/nom/src/branch/mod.rs
new file mode 100644
index 0000000000..9df5a2941a
--- /dev/null
+++ b/third_party/rust/nom/src/branch/mod.rs
@@ -0,0 +1,291 @@
+//! Choice combinators
+
+macro_rules! succ (
+ (0, $submac:ident ! ($($rest:tt)*)) => ($submac!(1, $($rest)*));
+ (1, $submac:ident ! ($($rest:tt)*)) => ($submac!(2, $($rest)*));
+ (2, $submac:ident ! ($($rest:tt)*)) => ($submac!(3, $($rest)*));
+ (3, $submac:ident ! ($($rest:tt)*)) => ($submac!(4, $($rest)*));
+ (4, $submac:ident ! ($($rest:tt)*)) => ($submac!(5, $($rest)*));
+ (5, $submac:ident ! ($($rest:tt)*)) => ($submac!(6, $($rest)*));
+ (6, $submac:ident ! ($($rest:tt)*)) => ($submac!(7, $($rest)*));
+ (7, $submac:ident ! ($($rest:tt)*)) => ($submac!(8, $($rest)*));
+ (8, $submac:ident ! ($($rest:tt)*)) => ($submac!(9, $($rest)*));
+ (9, $submac:ident ! ($($rest:tt)*)) => ($submac!(10, $($rest)*));
+ (10, $submac:ident ! ($($rest:tt)*)) => ($submac!(11, $($rest)*));
+ (11, $submac:ident ! ($($rest:tt)*)) => ($submac!(12, $($rest)*));
+ (12, $submac:ident ! ($($rest:tt)*)) => ($submac!(13, $($rest)*));
+ (13, $submac:ident ! ($($rest:tt)*)) => ($submac!(14, $($rest)*));
+ (14, $submac:ident ! ($($rest:tt)*)) => ($submac!(15, $($rest)*));
+ (15, $submac:ident ! ($($rest:tt)*)) => ($submac!(16, $($rest)*));
+ (16, $submac:ident ! ($($rest:tt)*)) => ($submac!(17, $($rest)*));
+ (17, $submac:ident ! ($($rest:tt)*)) => ($submac!(18, $($rest)*));
+ (18, $submac:ident ! ($($rest:tt)*)) => ($submac!(19, $($rest)*));
+ (19, $submac:ident ! ($($rest:tt)*)) => ($submac!(20, $($rest)*));
+ (20, $submac:ident ! ($($rest:tt)*)) => ($submac!(21, $($rest)*));
+);
+
+#[cfg(test)]
+mod tests;
+
+use crate::error::ErrorKind;
+use crate::error::ParseError;
+use crate::internal::{Err, IResult, Parser};
+
+/// Helper trait for the [alt()] combinator.
+///
+/// This trait is implemented for tuples of up to 21 elements
+pub trait Alt<I, O, E> {
+ /// Tests each parser in the tuple and returns the result of the first one that succeeds
+ fn choice(&mut self, input: I) -> IResult<I, O, E>;
+}
+
+/// Tests a list of parsers one by one until one succeeds.
+///
+/// It takes as argument a tuple of parsers. There is a maximum of 21
+/// parsers. If you need more, it is possible to nest them in other `alt` calls,
+/// like this: `alt(parser_a, alt(parser_b, parser_c))`
+///
+/// ```rust
+/// # use nom::error_position;
+/// # use nom::{Err,error::ErrorKind, Needed, IResult};
+/// use nom::character::complete::{alpha1, digit1};
+/// use nom::branch::alt;
+/// # fn main() {
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// alt((alpha1, digit1))(input)
+/// };
+///
+/// // the first parser, alpha1, recognizes the input
+/// assert_eq!(parser("abc"), Ok(("", "abc")));
+///
+/// // the first parser returns an error, so alt tries the second one
+/// assert_eq!(parser("123456"), Ok(("", "123456")));
+///
+/// // both parsers failed, and with the default error type, alt will return the last error
+/// assert_eq!(parser(" "), Err(Err::Error(error_position!(" ", ErrorKind::Digit))));
+/// # }
+/// ```
+///
+/// With a custom error type, it is possible to have alt return the error of the parser
+/// that went the farthest in the input data
+pub fn alt<I: Clone, O, E: ParseError<I>, List: Alt<I, O, E>>(
+ mut l: List,
+) -> impl FnMut(I) -> IResult<I, O, E> {
+ move |i: I| l.choice(i)
+}
+
+/// Helper trait for the [permutation()] combinator.
+///
+/// This trait is implemented for tuples of up to 21 elements
+pub trait Permutation<I, O, E> {
+ /// Tries to apply all parsers in the tuple in various orders until all of them succeed
+ fn permutation(&mut self, input: I) -> IResult<I, O, E>;
+}
+
+/// Applies a list of parsers in any order.
+///
+/// Permutation will succeed if all of the child parsers succeeded.
+/// It takes as argument a tuple of parsers, and returns a
+/// tuple of the parser results.
+///
+/// ```rust
+/// # use nom::{Err,error::{Error, ErrorKind}, Needed, IResult};
+/// use nom::character::complete::{alpha1, digit1};
+/// use nom::branch::permutation;
+/// # fn main() {
+/// fn parser(input: &str) -> IResult<&str, (&str, &str)> {
+/// permutation((alpha1, digit1))(input)
+/// }
+///
+/// // permutation recognizes alphabetic characters then digit
+/// assert_eq!(parser("abc123"), Ok(("", ("abc", "123"))));
+///
+/// // but also in inverse order
+/// assert_eq!(parser("123abc"), Ok(("", ("abc", "123"))));
+///
+/// // it will fail if one of the parsers failed
+/// assert_eq!(parser("abc;"), Err(Err::Error(Error::new(";", ErrorKind::Digit))));
+/// # }
+/// ```
+///
+/// The parsers are applied greedily: if there are multiple unapplied parsers
+/// that could parse the next slice of input, the first one is used.
+/// ```rust
+/// # use nom::{Err, error::{Error, ErrorKind}, IResult};
+/// use nom::branch::permutation;
+/// use nom::character::complete::{anychar, char};
+///
+/// fn parser(input: &str) -> IResult<&str, (char, char)> {
+/// permutation((anychar, char('a')))(input)
+/// }
+///
+/// // anychar parses 'b', then char('a') parses 'a'
+/// assert_eq!(parser("ba"), Ok(("", ('b', 'a'))));
+///
+/// // anychar parses 'a', then char('a') fails on 'b',
+/// // even though char('a') followed by anychar would succeed
+/// assert_eq!(parser("ab"), Err(Err::Error(Error::new("b", ErrorKind::Char))));
+/// ```
+///
+pub fn permutation<I: Clone, O, E: ParseError<I>, List: Permutation<I, O, E>>(
+ mut l: List,
+) -> impl FnMut(I) -> IResult<I, O, E> {
+ move |i: I| l.permutation(i)
+}
+
+macro_rules! alt_trait(
+ ($first:ident $second:ident $($id: ident)+) => (
+ alt_trait!(__impl $first $second; $($id)+);
+ );
+ (__impl $($current:ident)*; $head:ident $($id: ident)+) => (
+ alt_trait_impl!($($current)*);
+
+ alt_trait!(__impl $($current)* $head; $($id)+);
+ );
+ (__impl $($current:ident)*; $head:ident) => (
+ alt_trait_impl!($($current)*);
+ alt_trait_impl!($($current)* $head);
+ );
+);
+
+macro_rules! alt_trait_impl(
+ ($($id:ident)+) => (
+ impl<
+ Input: Clone, Output, Error: ParseError<Input>,
+ $($id: Parser<Input, Output, Error>),+
+ > Alt<Input, Output, Error> for ( $($id),+ ) {
+
+ fn choice(&mut self, input: Input) -> IResult<Input, Output, Error> {
+ match self.0.parse(input.clone()) {
+ Err(Err::Error(e)) => alt_trait_inner!(1, self, input, e, $($id)+),
+ res => res,
+ }
+ }
+ }
+ );
+);
+
+macro_rules! alt_trait_inner(
+ ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident $($id:ident)+) => (
+ match $self.$it.parse($input.clone()) {
+ Err(Err::Error(e)) => {
+ let err = $err.or(e);
+ succ!($it, alt_trait_inner!($self, $input, err, $($id)+))
+ }
+ res => res,
+ }
+ );
+ ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident) => (
+ Err(Err::Error(Error::append($input, ErrorKind::Alt, $err)))
+ );
+);
+
+alt_trait!(A B C D E F G H I J K L M N O P Q R S T U);
+
+// Manually implement Alt for (A,), the 1-tuple type
+impl<Input, Output, Error: ParseError<Input>, A: Parser<Input, Output, Error>>
+ Alt<Input, Output, Error> for (A,)
+{
+ fn choice(&mut self, input: Input) -> IResult<Input, Output, Error> {
+ self.0.parse(input)
+ }
+}
+
+macro_rules! permutation_trait(
+ (
+ $name1:ident $ty1:ident $item1:ident
+ $name2:ident $ty2:ident $item2:ident
+ $($name3:ident $ty3:ident $item3:ident)*
+ ) => (
+ permutation_trait!(__impl $name1 $ty1 $item1, $name2 $ty2 $item2; $($name3 $ty3 $item3)*);
+ );
+ (
+ __impl $($name:ident $ty:ident $item:ident),+;
+ $name1:ident $ty1:ident $item1:ident $($name2:ident $ty2:ident $item2:ident)*
+ ) => (
+ permutation_trait_impl!($($name $ty $item),+);
+ permutation_trait!(__impl $($name $ty $item),+ , $name1 $ty1 $item1; $($name2 $ty2 $item2)*);
+ );
+ (__impl $($name:ident $ty:ident $item:ident),+;) => (
+ permutation_trait_impl!($($name $ty $item),+);
+ );
+);
+
+macro_rules! permutation_trait_impl(
+ ($($name:ident $ty:ident $item:ident),+) => (
+ impl<
+ Input: Clone, $($ty),+ , Error: ParseError<Input>,
+ $($name: Parser<Input, $ty, Error>),+
+ > Permutation<Input, ( $($ty),+ ), Error> for ( $($name),+ ) {
+
+ fn permutation(&mut self, mut input: Input) -> IResult<Input, ( $($ty),+ ), Error> {
+ let mut res = ($(Option::<$ty>::None),+);
+
+ loop {
+ let mut err: Option<Error> = None;
+ permutation_trait_inner!(0, self, input, res, err, $($name)+);
+
+ // If we reach here, every iterator has either been applied before,
+ // or errored on the remaining input
+ if let Some(err) = err {
+ // There are remaining parsers, and all errored on the remaining input
+ return Err(Err::Error(Error::append(input, ErrorKind::Permutation, err)));
+ }
+
+ // All parsers were applied
+ match res {
+ ($(Some($item)),+) => return Ok((input, ($($item),+))),
+ _ => unreachable!(),
+ }
+ }
+ }
+ }
+ );
+);
+
+macro_rules! permutation_trait_inner(
+ ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr, $head:ident $($id:ident)*) => (
+ if $res.$it.is_none() {
+ match $self.$it.parse($input.clone()) {
+ Ok((i, o)) => {
+ $input = i;
+ $res.$it = Some(o);
+ continue;
+ }
+ Err(Err::Error(e)) => {
+ $err = Some(match $err {
+ Some(err) => err.or(e),
+ None => e,
+ });
+ }
+ Err(e) => return Err(e),
+ };
+ }
+ succ!($it, permutation_trait_inner!($self, $input, $res, $err, $($id)*));
+ );
+ ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr,) => ();
+);
+
+permutation_trait!(
+ FnA A a
+ FnB B b
+ FnC C c
+ FnD D d
+ FnE E e
+ FnF F f
+ FnG G g
+ FnH H h
+ FnI I i
+ FnJ J j
+ FnK K k
+ FnL L l
+ FnM M m
+ FnN N n
+ FnO O o
+ FnP P p
+ FnQ Q q
+ FnR R r
+ FnS S s
+ FnT T t
+ FnU U u
+);
diff --git a/third_party/rust/nom/src/branch/tests.rs b/third_party/rust/nom/src/branch/tests.rs
new file mode 100644
index 0000000000..ecd44407e9
--- /dev/null
+++ b/third_party/rust/nom/src/branch/tests.rs
@@ -0,0 +1,142 @@
+use crate::branch::{alt, permutation};
+use crate::bytes::streaming::tag;
+use crate::error::ErrorKind;
+use crate::internal::{Err, IResult, Needed};
+#[cfg(feature = "alloc")]
+use crate::{
+ error::ParseError,
+ lib::std::{
+ fmt::Debug,
+ string::{String, ToString},
+ },
+};
+
+#[cfg(feature = "alloc")]
+#[derive(Debug, Clone, PartialEq)]
+pub struct ErrorStr(String);
+
+#[cfg(feature = "alloc")]
+impl From<u32> for ErrorStr {
+ fn from(i: u32) -> Self {
+ ErrorStr(format!("custom error code: {}", i))
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl<'a> From<&'a str> for ErrorStr {
+ fn from(i: &'a str) -> Self {
+ ErrorStr(format!("custom error message: {}", i))
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl<I: Debug> ParseError<I> for ErrorStr {
+ fn from_error_kind(input: I, kind: ErrorKind) -> Self {
+ ErrorStr(format!("custom error message: ({:?}, {:?})", input, kind))
+ }
+
+ fn append(input: I, kind: ErrorKind, other: Self) -> Self {
+ ErrorStr(format!(
+ "custom error message: ({:?}, {:?}) - {:?}",
+ input, kind, other
+ ))
+ }
+}
+
+#[cfg(feature = "alloc")]
+#[test]
+fn alt_test() {
+ fn work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+ Ok((&b""[..], input))
+ }
+
+ #[allow(unused_variables)]
+ fn dont_work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+ Err(Err::Error(ErrorStr("abcd".to_string())))
+ }
+
+ fn work2(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+ Ok((input, &b""[..]))
+ }
+
+ fn alt1(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+ alt((dont_work, dont_work))(i)
+ }
+ fn alt2(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+ alt((dont_work, work))(i)
+ }
+ fn alt3(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+ alt((dont_work, dont_work, work2, dont_work))(i)
+ }
+ //named!(alt1, alt!(dont_work | dont_work));
+ //named!(alt2, alt!(dont_work | work));
+ //named!(alt3, alt!(dont_work | dont_work | work2 | dont_work));
+
+ let a = &b"abcd"[..];
+ assert_eq!(
+ alt1(a),
+ Err(Err::Error(error_node_position!(
+ a,
+ ErrorKind::Alt,
+ ErrorStr("abcd".to_string())
+ )))
+ );
+ assert_eq!(alt2(a), Ok((&b""[..], a)));
+ assert_eq!(alt3(a), Ok((a, &b""[..])));
+
+ fn alt4(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ alt((tag("abcd"), tag("efgh")))(i)
+ }
+ let b = &b"efgh"[..];
+ assert_eq!(alt4(a), Ok((&b""[..], a)));
+ assert_eq!(alt4(b), Ok((&b""[..], b)));
+}
+
+#[test]
+fn alt_incomplete() {
+ fn alt1(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ alt((tag("a"), tag("bc"), tag("def")))(i)
+ }
+
+ let a = &b""[..];
+ assert_eq!(alt1(a), Err(Err::Incomplete(Needed::new(1))));
+ let a = &b"b"[..];
+ assert_eq!(alt1(a), Err(Err::Incomplete(Needed::new(1))));
+ let a = &b"bcd"[..];
+ assert_eq!(alt1(a), Ok((&b"d"[..], &b"bc"[..])));
+ let a = &b"cde"[..];
+ assert_eq!(alt1(a), Err(Err::Error(error_position!(a, ErrorKind::Tag))));
+ let a = &b"de"[..];
+ assert_eq!(alt1(a), Err(Err::Incomplete(Needed::new(1))));
+ let a = &b"defg"[..];
+ assert_eq!(alt1(a), Ok((&b"g"[..], &b"def"[..])));
+}
+
+#[test]
+fn permutation_test() {
+ fn perm(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8], &[u8])> {
+ permutation((tag("abcd"), tag("efg"), tag("hi")))(i)
+ }
+
+ let expected = (&b"abcd"[..], &b"efg"[..], &b"hi"[..]);
+
+ let a = &b"abcdefghijk"[..];
+ assert_eq!(perm(a), Ok((&b"jk"[..], expected)));
+ let b = &b"efgabcdhijk"[..];
+ assert_eq!(perm(b), Ok((&b"jk"[..], expected)));
+ let c = &b"hiefgabcdjk"[..];
+ assert_eq!(perm(c), Ok((&b"jk"[..], expected)));
+
+ let d = &b"efgxyzabcdefghi"[..];
+ assert_eq!(
+ perm(d),
+ Err(Err::Error(error_node_position!(
+ &b"efgxyzabcdefghi"[..],
+ ErrorKind::Permutation,
+ error_position!(&b"xyzabcdefghi"[..], ErrorKind::Tag)
+ )))
+ );
+
+ let e = &b"efgabc"[..];
+ assert_eq!(perm(e), Err(Err::Incomplete(Needed::new(1))));
+}