//! Byte level parsers and combinators
//!
#[allow(unused_variables)]

/// `tag!(&[T]: nom::AsBytes) => &[T] -> IResult<&[T], &[T]>`
/// declares a byte array as a suite to recognize.
///
/// Consumes the recognized characters.
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # fn main() {
///  named!(x, tag!("abcd"));
///  let r = x(&b"abcdefgh"[..]);
///  assert_eq!(r, Ok((&b"efgh"[..], &b"abcd"[..])));
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! tag (
  ($i:expr, $tag: expr) => ({
    $crate::bytes::streaming::tag($tag)($i)
  });
);

/// `tag_no_case!(&[T]) => &[T] -> IResult<&[T], &[T]>`
/// declares a case insensitive ascii string as a suite to recognize.
///
/// Consumes the recognized characters.
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # fn main() {
///  named!(test, tag_no_case!("ABcd"));
///
///  let r = test(&b"aBCdefgh"[..]);
///  assert_eq!(r, Ok((&b"efgh"[..], &b"aBCd"[..])));
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! tag_no_case (
  ($i:expr, $tag: expr) => ({
    $crate::bytes::streaming::tag_no_case($tag)($i)
  });
);

/// `is_not!(&[T:AsBytes]) => &[T] -> IResult<&[T], &[T]>`
/// returns the longest list of bytes that do not appear in the provided array.
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # fn main() {
///  named!( not_space, is_not!( " \t\r\n" ) );
///
///  let r = not_space(&b"abcdefgh\nijkl"[..]);
///  assert_eq!(r, Ok((&b"\nijkl"[..], &b"abcdefgh"[..])));
///  # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! is_not (
  ($input:expr, $arr:expr) => ({
    $crate::bytes::streaming::is_not($arr)($input)
  });
);

/// `is_a!(&[T]) => &[T] -> IResult<&[T], &[T]>`
/// returns the longest list of bytes that appear in the provided array.
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # fn main() {
///  named!(abcd, is_a!( "abcd" ));
///
///  let r1 = abcd(&b"aaaaefgh"[..]);
///  assert_eq!(r1, Ok((&b"efgh"[..], &b"aaaa"[..])));
///
///  let r2 = abcd(&b"dcbaefgh"[..]);
///  assert_eq!(r2, Ok((&b"efgh"[..], &b"dcba"[..])));
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! is_a (
  ($input:expr, $arr:expr) => ({
    $crate::bytes::streaming::is_a($arr)($input)
  });
);

/// `escaped!(T -> IResult<T, T>, U, T -> IResult<T, T>) => T -> IResult<T, T> where T: InputIter,
/// U: AsChar`
/// matches a byte string with escaped characters.
///
/// * The first argument matches the normal characters (it must not accept the control character)
/// * The second argument is the control character (like `\` in most languages)
/// * The third argument matches the escaped characters
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::character::complete::digit1;
/// # fn main() {
///  named!(esc, escaped!(call!(digit1), '\\', one_of!("\"n\\")));
///  assert_eq!(esc(&b"123;"[..]), Ok((&b";"[..], &b"123"[..])));
///  assert_eq!(esc(&b"12\\\"34;"[..]), Ok((&b";"[..], &b"12\\\"34"[..])));
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! escaped (
  ($i:expr, $submac1:ident!( $($args:tt)* ), $control_char: expr, $submac2:ident!( $($args2:tt)*) ) => (
    {
     escaped!($i, |i| $submac1!(i, $($args)*), $control_char,  |i| $submac2!(i, $($args2)*))
    }
  );
  ($i:expr, $normal:expr, $control_char: expr, $submac2:ident!( $($args2:tt)*) ) => (
    {
     escaped!($i, $normal, $control_char,  |i| $submac2!(i, $($args2)*))
    }
  );
  ($i:expr, $submac1:ident!( $($args:tt)* ), $control_char: expr, $escapable:expr ) => (
    {
     escaped!($i, |i| $submac1!(i, $($args)*), $control_char,  $escapable)
    }
  );
  ($i:expr, $normal:expr, $control_char: expr, $escapable:expr) => (
    {
      $crate::bytes::complete::escapedc($i, $normal, $control_char, $escapable)
    }
  );
);

/// `escaped_transform!(&[T] -> IResult<&[T], &[T]>, T, &[T] -> IResult<&[T], &[T]>) => &[T] -> IResult<&[T], Vec<T>>`
/// matches a byte string with escaped characters.
///
/// * The first argument matches the normal characters (it must not match the control character)
/// * The second argument is the control character (like `\` in most languages)
/// * The third argument matches the escaped characters and transforms them
///
/// As an example, the chain `abc\tdef` could be `abc    def` (it also consumes the control character).
/// # Example
/// ```rust
/// # #[macro_use] extern crate nom;
/// # use nom::character::complete::alpha1;
/// # use nom::lib::std::str::from_utf8;
/// # fn main() {
/// fn to_s(i:Vec<u8>) -> String {
///   String::from_utf8_lossy(&i).into_owned()
/// }
///
///  named!(transform < String >,
///    map!(
///      escaped_transform!(call!(alpha1), '\\',
///        alt!(
///            tag!("\\")       => { |_| &b"\\"[..] }
///          | tag!("\"")       => { |_| &b"\""[..] }
///          | tag!("n")        => { |_| &b"\n"[..] }
///        )
///      ), to_s
///    )
///  );
///  assert_eq!(transform(&b"ab\\\"cd"[..]), Ok((&b""[..], String::from("ab\"cd"))));
/// # }
/// ```
#[cfg(feature = "alloc")]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
#[macro_export(local_inner_macros)]
macro_rules! escaped_transform (
  ($i:expr, $submac1:ident!( $($args:tt)* ), $control_char: expr, $submac2:ident!( $($args2:tt)*) ) => (
    {
     escaped_transform!($i, |i| $submac1!(i, $($args)*), $control_char,  |i| $submac2!(i, $($args2)*))
    }
  );
  ($i:expr, $normal:expr, $control_char: expr, $submac2:ident!( $($args2:tt)*) ) => (
    {
     escaped_transform!($i, $normal, $control_char,  |i| $submac2!(i, $($args2)*))
    }
  );
  ($i:expr, $submac1:ident!( $($args:tt)* ), $control_char: expr, $transform:expr ) => (
    {
     escaped_transform!($i, |i| $submac1!(i, $($args)*), $control_char,  $transform)
    }
  );
  ($i:expr, $normal:expr, $control_char: expr, $transform:expr) => (
    {
      $crate::bytes::complete::escaped_transformc($i, $normal, $control_char, $transform)
    }
  );
);

/// `take_while!(T -> bool) => &[T] -> IResult<&[T], &[T]>`
/// returns the longest list of bytes until the provided function fails.
///
/// The argument is either a function `T -> bool` or a macro returning a `bool`.
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::character::is_alphanumeric;
/// # fn main() {
///  named!( alpha, take_while!( is_alphanumeric ) );
///
///  let r = alpha(&b"abcd\nefgh"[..]);
///  assert_eq!(r, Ok((&b"\nefgh"[..], &b"abcd"[..])));
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! take_while (
  ($input:expr, $submac:ident!( $($args:tt)* )) => ({
    let res: $crate::IResult<_, _, _> = take_while!($input, (|c| $submac!(c, $($args)*)));
    res
  });
  ($input:expr, $f:expr) => (
    $crate::bytes::streaming::take_while($f)($input)
  );
);

/// `take_while1!(T -> bool) => &[T] -> IResult<&[T], &[T]>`
/// returns the longest (non empty) list of bytes until the provided function fails.
///
/// The argument is either a function `&[T] -> bool` or a macro returning a `bool`.
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::{Err,error::ErrorKind};
/// # use nom::character::is_alphanumeric;
/// # fn main() {
///  named!( alpha, take_while1!( is_alphanumeric ) );
///
///  let r = alpha(&b"abcd\nefgh"[..]);
///  assert_eq!(r, Ok((&b"\nefgh"[..], &b"abcd"[..])));
///  let r = alpha(&b"\nefgh"[..]);
///  assert_eq!(r, Err(Err::Error(error_position!(&b"\nefgh"[..], ErrorKind::TakeWhile1))));
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! take_while1 (
  ($input:expr, $submac:ident!( $($args:tt)* )) => ({
    let res: $crate::IResult<_, _, _> = take_while1!($input, (|c| $submac!(c, $($args)*)));
    res
  });
  ($input:expr, $f:expr) => (
    $crate::bytes::streaming::take_while1($f)($input)
  );
);

/// `take_while_m_n!(m: usize, n: usize, T -> bool) => &[T] -> IResult<&[T], &[T]>`
/// returns a list of bytes or characters for which the provided function returns true.
/// The returned list's size will be at least m, and at most n.
///
/// The argument is either a function `T -> bool` or a macro returning a `bool`.
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::character::is_alphanumeric;
/// # fn main() {
///  named!( alpha, take_while_m_n!(3, 6, is_alphanumeric ) );
///
///  let r = alpha(&b"abcd\nefgh"[..]);
///  assert_eq!(r, Ok((&b"\nefgh"[..], &b"abcd"[..])));
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! take_while_m_n (
  ($input:expr, $m:expr, $n: expr, $submac:ident!( $($args:tt)* )) => ({
    let res: $crate::IResult<_, _, _> = take_while_m_n!($input, $m, $n, (|c| $submac!(c, $($args)*)));
    res
  });
  ($input:expr, $m:expr, $n:expr, $f:expr) => (
    $crate::bytes::streaming::take_while_m_n($m, $n, $f)($input)
  );
);

/// `take_till!(T -> bool) => &[T] -> IResult<&[T], &[T]>`
/// returns the longest list of bytes until the provided function succeeds.
///
/// The argument is either a function `&[T] -> bool` or a macro returning a `bool`.
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # fn main() {
///  named!( till_colon, take_till!(|ch| ch == b':') );
///
///  let r = till_colon(&b"abcd:efgh"[..]);
///  assert_eq!(r, Ok((&b":efgh"[..], &b"abcd"[..])));
///  let r2 = till_colon(&b":abcdefgh"[..]); // empty match is allowed
///  assert_eq!(r2, Ok((&b":abcdefgh"[..], &b""[..])));
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! take_till (
  ($input:expr, $submac:ident!( $($args:tt)* )) => ({
    let res: $crate::IResult<_, _, _> = take_till!($input, (|c| $submac!(c, $($args)*)));
    res
  });
  ($input:expr, $f:expr) => (
    $crate::bytes::streaming::take_till($f)($input)
  );
);

/// `take_till1!(T -> bool) => &[T] -> IResult<&[T], &[T]>`
/// returns the longest non empty list of bytes until the provided function succeeds.
///
/// The argument is either a function `&[T] -> bool` or a macro returning a `bool`.
///
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::{Err, error::ErrorKind};
/// # fn main() {
///  named!( till1_colon, take_till1!(|ch| ch == b':') );
///
///  let r = till1_colon(&b"abcd:efgh"[..]);
///  assert_eq!(r, Ok((&b":efgh"[..], &b"abcd"[..])));
///
///  let r2 = till1_colon(&b":abcdefgh"[..]); // empty match is error
///  assert_eq!(r2, Err(Err::Error(error_position!(&b":abcdefgh"[..], ErrorKind::TakeTill1))));
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! take_till1 (
  ($input:expr, $submac:ident!( $($args:tt)* )) => ({
    let res: $crate::IResult<_, _, _> = take_till1!($input, (|c| $submac!(c, $($args)*)));
    res
  });
  ($input:expr, $f:expr) => (
    $crate::bytes::streaming::take_till1($f)($input)
  );
);

/// `take!(nb) => &[T] -> IResult<&[T], &[T]>`
/// generates a parser consuming the specified number of bytes.
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # fn main() {
///  // Desmond parser
///  named!(take5, take!( 5 ) );
///
///  let a = b"abcdefgh";
///
///  assert_eq!(take5(&a[..]), Ok((&b"fgh"[..], &b"abcde"[..])));
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! take (
  ($i:expr, $count:expr) => ({
    let c = $count as usize;
    let res: $crate::IResult<_,_,_> = $crate::bytes::streaming::take(c)($i);
    res
  });
);

/// `take_str!(nb) => &[T] -> IResult<&[T], &str>`
/// same as `take!` but returning a `&str`.
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # fn main() {
///  named!(take5( &[u8] ) -> &str, take_str!( 5 ) );
///
///  let a = b"abcdefgh";
///
///  assert_eq!(take5(&a[..]), Ok((&b"fgh"[..], "abcde")));
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! take_str (
 ( $i:expr, $size:expr ) => (
    {
      let input: &[u8] = $i;

      map_res!(input, take!($size), $crate::lib::std::str::from_utf8)
    }
  );
);

/// `take_until!(tag) => &[T] -> IResult<&[T], &[T]>`
/// consumes data until it finds the specified tag.
///
/// The remainder still contains the tag.
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # fn main() {
///  named!(x, take_until!("foo"));
///  let r = x(&b"abcd foo efgh"[..]);
///  assert_eq!(r, Ok((&b"foo efgh"[..], &b"abcd "[..])));
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! take_until (
  ($i:expr, $substr:expr) => ({
    let res: $crate::IResult<_,_,_> = $crate::bytes::streaming::take_until($substr)($i);
    res
  });
);

/// `take_until1!(tag) => &[T] -> IResult<&[T], &[T]>`
/// consumes data (at least one byte) until it finds the specified tag.
///
/// The remainder still contains the tag.
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # fn main() {
///  named!(x, take_until1!("foo"));
///
///  let r = x(&b"abcd foo efgh"[..]);
///
///  assert_eq!(r, Ok((&b"foo efgh"[..], &b"abcd "[..])));
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! take_until1 (
  ($i:expr, $substr:expr) => (
    {
      use $crate::lib::std::result::Result::*;
      use $crate::lib::std::option::Option::*;
      use $crate::{Err,Needed,IResult,error::ErrorKind};
      use $crate::InputLength;
      use $crate::FindSubstring;
      use $crate::InputTake;
      let input = $i;

      let res: IResult<_,_> = match input.find_substring($substr) {
        None => {
          Err(Err::Incomplete(Needed::new(1 + $substr.input_len())))
        },
        Some(0) => {
          let e = ErrorKind::TakeUntil;
          Err(Err::Error(error_position!($i, e)))
        },
        Some(index) => {
          Ok($i.take_split(index))
        },
      };
      res
    }
  );
);

#[cfg(test)]
mod tests {
  use crate::character::is_alphabetic;
  use crate::character::streaming::{
    alpha1 as alpha, alphanumeric1 as alphanumeric, digit1 as digit, hex_digit1 as hex_digit,
    multispace1 as multispace, oct_digit1 as oct_digit, space1 as space,
  };
  use crate::error::ErrorKind;
  use crate::internal::{Err, IResult, Needed};
  #[cfg(feature = "alloc")]
  use crate::lib::std::string::String;
  #[cfg(feature = "alloc")]
  use crate::lib::std::vec::Vec;

  #[cfg(feature = "alloc")]
  macro_rules! one_of (
    ($i:expr, $inp: expr) => (
      {
        use $crate::Err;
        use $crate::Slice;
        use $crate::AsChar;
        use $crate::FindToken;
        use $crate::InputIter;

        match ($i).iter_elements().next().map(|c| {
          $inp.find_token(c)
        }) {
          None        => Err::<_,_>(Err::Incomplete(Needed::new(1))),
          Some(false) => Err(Err::Error(error_position!($i, ErrorKind::OneOf))),
          //the unwrap should be safe here
          Some(true)  => Ok(($i.slice(1..), $i.iter_elements().next().unwrap().as_char()))
        }
      }
    );
  );

  #[test]
  fn is_a() {
    named!(a_or_b, is_a!(&b"ab"[..]));

    let a = &b"abcd"[..];
    assert_eq!(a_or_b(a), Ok((&b"cd"[..], &b"ab"[..])));

    let b = &b"bcde"[..];
    assert_eq!(a_or_b(b), Ok((&b"cde"[..], &b"b"[..])));

    let c = &b"cdef"[..];
    assert_eq!(
      a_or_b(c),
      Err(Err::Error(error_position!(c, ErrorKind::IsA)))
    );

    let d = &b"bacdef"[..];
    assert_eq!(a_or_b(d), Ok((&b"cdef"[..], &b"ba"[..])));
  }

  #[test]
  fn is_not() {
    named!(a_or_b, is_not!(&b"ab"[..]));

    let a = &b"cdab"[..];
    assert_eq!(a_or_b(a), Ok((&b"ab"[..], &b"cd"[..])));

    let b = &b"cbde"[..];
    assert_eq!(a_or_b(b), Ok((&b"bde"[..], &b"c"[..])));

    let c = &b"abab"[..];
    assert_eq!(
      a_or_b(c),
      Err(Err::Error(error_position!(c, ErrorKind::IsNot)))
    );

    let d = &b"cdefba"[..];
    assert_eq!(a_or_b(d), Ok((&b"ba"[..], &b"cdef"[..])));

    let e = &b"e"[..];
    assert_eq!(a_or_b(e), Err(Err::Incomplete(Needed::new(1))));
  }

  #[cfg(feature = "alloc")]
  #[allow(unused_variables)]
  #[test]
  fn escaping() {
    named!(esc, escaped!(call!(alpha), '\\', one_of!("\"n\\")));
    assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], &b"abcd"[..])));
    assert_eq!(esc(&b"ab\\\"cd;"[..]), Ok((&b";"[..], &b"ab\\\"cd"[..])));
    assert_eq!(esc(&b"\\\"abcd;"[..]), Ok((&b";"[..], &b"\\\"abcd"[..])));
    assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], &b"\\n"[..])));
    assert_eq!(esc(&b"ab\\\"12"[..]), Ok((&b"12"[..], &b"ab\\\""[..])));
    assert_eq!(
      esc(&b"AB\\"[..]),
      Err(Err::Error(error_position!(
        &b"AB\\"[..],
        ErrorKind::Escaped
      )))
    );
    assert_eq!(
      esc(&b"AB\\A"[..]),
      Err(Err::Error(error_node_position!(
        &b"AB\\A"[..],
        ErrorKind::Escaped,
        error_position!(&b"A"[..], ErrorKind::OneOf)
      )))
    );

    named!(esc2, escaped!(call!(digit), '\\', one_of!("\"n\\")));
    assert_eq!(esc2(&b"12\\nnn34"[..]), Ok((&b"nn34"[..], &b"12\\n"[..])));
  }

  #[cfg(feature = "alloc")]
  #[test]
  fn escaping_str() {
    named!(esc<&str, &str>, escaped!(call!(alpha), '\\', one_of!("\"n\\")));
    assert_eq!(esc("abcd;"), Ok((";", "abcd")));
    assert_eq!(esc("ab\\\"cd;"), Ok((";", "ab\\\"cd")));
    assert_eq!(esc("\\\"abcd;"), Ok((";", "\\\"abcd")));
    assert_eq!(esc("\\n;"), Ok((";", "\\n")));
    assert_eq!(esc("ab\\\"12"), Ok(("12", "ab\\\"")));
    assert_eq!(
      esc("AB\\"),
      Err(Err::Error(error_position!("AB\\", ErrorKind::Escaped)))
    );
    assert_eq!(
      esc("AB\\A"),
      Err(Err::Error(error_node_position!(
        "AB\\A",
        ErrorKind::Escaped,
        error_position!("A", ErrorKind::OneOf)
      )))
    );

    named!(esc2<&str, &str>, escaped!(call!(digit), '\\', one_of!("\"n\\")));
    assert_eq!(esc2("12\\nnn34"), Ok(("nn34", "12\\n")));

    named!(esc3<&str, &str>, escaped!(call!(alpha), '\u{241b}', one_of!("\"n")));
    assert_eq!(esc3("ab␛ncd;"), Ok((";", "ab␛ncd")));
  }

  #[cfg(feature = "alloc")]
  fn to_s(i: Vec<u8>) -> String {
    String::from_utf8_lossy(&i).into_owned()
  }

  #[cfg(feature = "alloc")]
  #[test]
  fn escape_transform() {
    use crate::lib::std::str;

    named!(
      esc<String>,
      map!(
        escaped_transform!(
          alpha,
          '\\',
          alt!(
              tag!("\\")       => { |_| &b"\\"[..] }
            | tag!("\"")       => { |_| &b"\""[..] }
            | tag!("n")        => { |_| &b"\n"[..] }
          )
        ),
        to_s
      )
    );

    assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], String::from("abcd"))));
    assert_eq!(
      esc(&b"ab\\\"cd;"[..]),
      Ok((&b";"[..], String::from("ab\"cd")))
    );
    assert_eq!(
      esc(&b"\\\"abcd;"[..]),
      Ok((&b";"[..], String::from("\"abcd")))
    );
    assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], String::from("\n"))));
    assert_eq!(
      esc(&b"ab\\\"12"[..]),
      Ok((&b"12"[..], String::from("ab\"")))
    );
    assert_eq!(
      esc(&b"AB\\"[..]),
      Err(Err::Error(error_position!(
        &b"\\"[..],
        ErrorKind::EscapedTransform
      )))
    );
    assert_eq!(
      esc(&b"AB\\A"[..]),
      Err(Err::Error(error_node_position!(
        &b"AB\\A"[..],
        ErrorKind::EscapedTransform,
        error_position!(&b"A"[..], ErrorKind::Alt)
      )))
    );

    named!(
      esc2<String>,
      map!(
        escaped_transform!(
          call!(alpha),
          '&',
          alt!(
              tag!("egrave;") => { |_| str::as_bytes("è") }
            | tag!("agrave;") => { |_| str::as_bytes("à") }
          )
        ),
        to_s
      )
    );
    assert_eq!(
      esc2(&b"ab&egrave;DEF;"[..]),
      Ok((&b";"[..], String::from("abèDEF")))
    );
    assert_eq!(
      esc2(&b"ab&egrave;D&agrave;EF;"[..]),
      Ok((&b";"[..], String::from("abèDàEF")))
    );
  }

  #[cfg(feature = "std")]
  #[test]
  fn escape_transform_str() {
    named!(esc<&str, String>, escaped_transform!(alpha, '\\',
      alt!(
          tag!("\\")       => { |_| "\\" }
        | tag!("\"")       => { |_| "\"" }
        | tag!("n")        => { |_| "\n" }
      ))
    );

    assert_eq!(esc("abcd;"), Ok((";", String::from("abcd"))));
    assert_eq!(esc("ab\\\"cd;"), Ok((";", String::from("ab\"cd"))));
    assert_eq!(esc("\\\"abcd;"), Ok((";", String::from("\"abcd"))));
    assert_eq!(esc("\\n;"), Ok((";", String::from("\n"))));
    assert_eq!(esc("ab\\\"12"), Ok(("12", String::from("ab\""))));
    assert_eq!(
      esc("AB\\"),
      Err(Err::Error(error_position!(
        "\\",
        ErrorKind::EscapedTransform
      )))
    );
    assert_eq!(
      esc("AB\\A"),
      Err(Err::Error(error_node_position!(
        "AB\\A",
        ErrorKind::EscapedTransform,
        error_position!("A", ErrorKind::Alt)
      )))
    );

    named!(esc2<&str, String>, escaped_transform!(alpha, '&',
      alt!(
          tag!("egrave;") => { |_| "è" }
        | tag!("agrave;") => { |_| "à" }
      ))
    );
    assert_eq!(esc2("ab&egrave;DEF;"), Ok((";", String::from("abèDEF"))));
    assert_eq!(
      esc2("ab&egrave;D&agrave;EF;"),
      Ok((";", String::from("abèDàEF")))
    );

    named!(esc3<&str, String>, escaped_transform!(alpha, '␛',
      alt!(
        tag!("0") => { |_| "\0" } |
        tag!("n") => { |_| "\n" })));
    assert_eq!(esc3("a␛0bc␛n"), Ok(("", String::from("a\0bc\n"))));
  }

  #[test]
  fn take_str_test() {
    let a = b"omnomnom";

    let res: IResult<_, _, (&[u8], ErrorKind)> = take_str!(&a[..], 5u32);
    assert_eq!(res, Ok((&b"nom"[..], "omnom")));

    let res: IResult<_, _, (&[u8], ErrorKind)> = take_str!(&a[..], 9u32);
    assert_eq!(res, Err(Err::Incomplete(Needed::new(1))));
  }

  #[test]
  fn take_until_incomplete() {
    named!(y, take_until!("end"));
    assert_eq!(y(&b"nd"[..]), Err(Err::Incomplete(Needed::Unknown)));
    assert_eq!(y(&b"123"[..]), Err(Err::Incomplete(Needed::Unknown)));
    assert_eq!(y(&b"123en"[..]), Err(Err::Incomplete(Needed::Unknown)));
  }

  #[test]
  fn take_until_incomplete_s() {
    named!(ys<&str, &str>, take_until!("end"));
    assert_eq!(ys("123en"), Err(Err::Incomplete(Needed::Unknown)));
  }

  #[test]
  fn recognize() {
    named!(
      x,
      recognize!(delimited!(tag!("<!--"), take!(5usize), tag!("-->")))
    );
    let r = x(&b"<!-- abc --> aaa"[..]);
    assert_eq!(r, Ok((&b" aaa"[..], &b"<!-- abc -->"[..])));

    let semicolon = &b";"[..];

    named!(ya, recognize!(alpha));
    let ra = ya(&b"abc;"[..]);
    assert_eq!(ra, Ok((semicolon, &b"abc"[..])));

    named!(yd, recognize!(digit));
    let rd = yd(&b"123;"[..]);
    assert_eq!(rd, Ok((semicolon, &b"123"[..])));

    named!(yhd, recognize!(hex_digit));
    let rhd = yhd(&b"123abcDEF;"[..]);
    assert_eq!(rhd, Ok((semicolon, &b"123abcDEF"[..])));

    named!(yod, recognize!(oct_digit));
    let rod = yod(&b"1234567;"[..]);
    assert_eq!(rod, Ok((semicolon, &b"1234567"[..])));

    named!(yan, recognize!(alphanumeric));
    let ran = yan(&b"123abc;"[..]);
    assert_eq!(ran, Ok((semicolon, &b"123abc"[..])));

    named!(ys, recognize!(space));
    let rs = ys(&b" \t;"[..]);
    assert_eq!(rs, Ok((semicolon, &b" \t"[..])));

    named!(yms, recognize!(multispace));
    let rms = yms(&b" \t\r\n;"[..]);
    assert_eq!(rms, Ok((semicolon, &b" \t\r\n"[..])));
  }

  #[test]
  fn take_while() {
    named!(f, take_while!(is_alphabetic));
    let a = b"";
    let b = b"abcd";
    let c = b"abcd123";
    let d = b"123";

    assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1))));
    assert_eq!(f(&b[..]), Err(Err::Incomplete(Needed::new(1))));
    assert_eq!(f(&c[..]), Ok((&d[..], &b[..])));
    assert_eq!(f(&d[..]), Ok((&d[..], &a[..])));
  }

  #[test]
  fn take_while1() {
    named!(f, take_while1!(is_alphabetic));
    let a = b"";
    let b = b"abcd";
    let c = b"abcd123";
    let d = b"123";

    assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1))));
    assert_eq!(f(&b[..]), Err(Err::Incomplete(Needed::new(1))));
    assert_eq!(f(&c[..]), Ok((&b"123"[..], &b[..])));
    assert_eq!(
      f(&d[..]),
      Err(Err::Error(error_position!(&d[..], ErrorKind::TakeWhile1)))
    );
  }

  #[test]
  fn take_while_m_n() {
    named!(x, take_while_m_n!(2, 4, is_alphabetic));
    let a = b"";
    let b = b"a";
    let c = b"abc";
    let d = b"abc123";
    let e = b"abcde";
    let f = b"123";

    assert_eq!(x(&a[..]), Err(Err::Incomplete(Needed::new(2))));
    assert_eq!(x(&b[..]), Err(Err::Incomplete(Needed::new(1))));
    assert_eq!(x(&c[..]), Err(Err::Incomplete(Needed::new(1))));
    assert_eq!(x(&d[..]), Ok((&b"123"[..], &c[..])));
    assert_eq!(x(&e[..]), Ok((&b"e"[..], &b"abcd"[..])));
    assert_eq!(
      x(&f[..]),
      Err(Err::Error(error_position!(&f[..], ErrorKind::TakeWhileMN)))
    );
  }

  #[test]
  fn take_till() {
    named!(f, take_till!(is_alphabetic));
    let a = b"";
    let b = b"abcd";
    let c = b"123abcd";
    let d = b"123";

    assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1))));
    assert_eq!(f(&b[..]), Ok((&b"abcd"[..], &b""[..])));
    assert_eq!(f(&c[..]), Ok((&b"abcd"[..], &b"123"[..])));
    assert_eq!(f(&d[..]), Err(Err::Incomplete(Needed::new(1))));
  }

  #[test]
  fn take_till1() {
    named!(f, take_till1!(is_alphabetic));
    let a = b"";
    let b = b"abcd";
    let c = b"123abcd";
    let d = b"123";

    assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1))));
    assert_eq!(
      f(&b[..]),
      Err(Err::Error(error_position!(&b[..], ErrorKind::TakeTill1)))
    );
    assert_eq!(f(&c[..]), Ok((&b"abcd"[..], &b"123"[..])));
    assert_eq!(f(&d[..]), Err(Err::Incomplete(Needed::new(1))));
  }

  #[test]
  fn take_while_utf8() {
    named!(f<&str,&str>, take_while!(|c:char| { c != '點' }));

    assert_eq!(f(""), Err(Err::Incomplete(Needed::new(1))));
    assert_eq!(f("abcd"), Err(Err::Incomplete(Needed::new(1))));
    assert_eq!(f("abcd點"), Ok(("點", "abcd")));
    assert_eq!(f("abcd點a"), Ok(("點a", "abcd")));

    named!(g<&str,&str>, take_while!(|c:char| { c == '點' }));

    assert_eq!(g(""), Err(Err::Incomplete(Needed::new(1))));
    assert_eq!(g("點abcd"), Ok(("abcd", "點")));
    assert_eq!(g("點點點a"), Ok(("a", "點點點")));
  }

  #[test]
  fn take_till_utf8() {
    named!(f<&str,&str>, take_till!(|c:char| { c == '點' }));

    assert_eq!(f(""), Err(Err::Incomplete(Needed::new(1))));
    assert_eq!(f("abcd"), Err(Err::Incomplete(Needed::new(1))));
    assert_eq!(f("abcd點"), Ok(("點", "abcd")));
    assert_eq!(f("abcd點a"), Ok(("點a", "abcd")));

    named!(g<&str,&str>, take_till!(|c:char| { c != '點' }));

    assert_eq!(g(""), Err(Err::Incomplete(Needed::new(1))));
    assert_eq!(g("點abcd"), Ok(("abcd", "點")));
    assert_eq!(g("點點點a"), Ok(("a", "點點點")));
  }

  #[test]
  fn take_utf8() {
    named!(f<&str,&str>, take!(3));

    assert_eq!(f(""), Err(Err::Incomplete(Needed::Unknown)));
    assert_eq!(f("ab"), Err(Err::Incomplete(Needed::Unknown)));
    assert_eq!(f("點"), Err(Err::Incomplete(Needed::Unknown)));
    assert_eq!(f("ab點cd"), Ok(("cd", "ab點")));
    assert_eq!(f("a點bcd"), Ok(("cd", "a點b")));
    assert_eq!(f("a點b"), Ok(("", "a點b")));

    named!(g<&str,&str>, take_while!(|c:char| { c == '點' }));

    assert_eq!(g(""), Err(Err::Incomplete(Needed::new(1))));
    assert_eq!(g("點abcd"), Ok(("abcd", "點")));
    assert_eq!(g("點點點a"), Ok(("a", "點點點")));
  }

  #[test]
  fn take_while_m_n_utf8() {
    named!(parser<&str, &str>, take_while_m_n!(1, 1, |c| c == 'A' || c == '😃'));
    assert_eq!(parser("A!"), Ok(("!", "A")));
    assert_eq!(parser("😃!"), Ok(("!", "😃")));
  }

  #[test]
  fn take_while_m_n_utf8_full_match() {
    named!(parser<&str, &str>, take_while_m_n!(1, 1, |c: char| c.is_alphabetic()));
    assert_eq!(parser("øn"), Ok(("n", "ø")));
  }

  #[cfg(nightly)]
  use test::Bencher;

  #[cfg(nightly)]
  #[bench]
  fn take_while_bench(b: &mut Bencher) {
    named!(f, take_while!(is_alphabetic));
    b.iter(|| f(&b"abcdefghijklABCDEejfrfrjgro12aa"[..]));
  }

  #[test]
  #[cfg(feature = "std")]
  fn recognize_take_while() {
    use crate::character::is_alphanumeric;
    named!(x, take_while!(is_alphanumeric));
    named!(y, recognize!(x));
    assert_eq!(x(&b"ab."[..]), Ok((&b"."[..], &b"ab"[..])));
    println!("X: {:?}", x(&b"ab"[..]));
    assert_eq!(y(&b"ab."[..]), Ok((&b"."[..], &b"ab"[..])));
  }

  #[test]
  fn length_bytes() {
    use crate::number::streaming::le_u8;
    named!(x, length_data!(le_u8));
    assert_eq!(x(b"\x02..>>"), Ok((&b">>"[..], &b".."[..])));
    assert_eq!(x(b"\x02.."), Ok((&[][..], &b".."[..])));
    assert_eq!(x(b"\x02."), Err(Err::Incomplete(Needed::new(1))));
    assert_eq!(x(b"\x02"), Err(Err::Incomplete(Needed::new(2))));

    named!(y, do_parse!(tag!("magic") >> b: length_data!(le_u8) >> (b)));
    assert_eq!(y(b"magic\x02..>>"), Ok((&b">>"[..], &b".."[..])));
    assert_eq!(y(b"magic\x02.."), Ok((&[][..], &b".."[..])));
    assert_eq!(y(b"magic\x02."), Err(Err::Incomplete(Needed::new(1))));
    assert_eq!(y(b"magic\x02"), Err(Err::Incomplete(Needed::new(2))));
  }

  #[cfg(feature = "alloc")]
  #[test]
  fn case_insensitive() {
    named!(test, tag_no_case!("ABcd"));
    assert_eq!(test(&b"aBCdefgh"[..]), Ok((&b"efgh"[..], &b"aBCd"[..])));
    assert_eq!(test(&b"abcdefgh"[..]), Ok((&b"efgh"[..], &b"abcd"[..])));
    assert_eq!(test(&b"ABCDefgh"[..]), Ok((&b"efgh"[..], &b"ABCD"[..])));
    assert_eq!(test(&b"ab"[..]), Err(Err::Incomplete(Needed::new(2))));
    assert_eq!(
      test(&b"Hello"[..]),
      Err(Err::Error(error_position!(&b"Hello"[..], ErrorKind::Tag)))
    );
    assert_eq!(
      test(&b"Hel"[..]),
      Err(Err::Error(error_position!(&b"Hel"[..], ErrorKind::Tag)))
    );

    named!(test2<&str, &str>, tag_no_case!("ABcd"));
    assert_eq!(test2("aBCdefgh"), Ok(("efgh", "aBCd")));
    assert_eq!(test2("abcdefgh"), Ok(("efgh", "abcd")));
    assert_eq!(test2("ABCDefgh"), Ok(("efgh", "ABCD")));
    assert_eq!(test2("ab"), Err(Err::Incomplete(Needed::new(2))));
    assert_eq!(
      test2("Hello"),
      Err(Err::Error(error_position!(&"Hello"[..], ErrorKind::Tag)))
    );
    assert_eq!(
      test2("Hel"),
      Err(Err::Error(error_position!(&"Hel"[..], ErrorKind::Tag)))
    );
  }

  #[test]
  fn tag_fixed_size_array() {
    named!(test, tag!([0x42]));
    named!(test2, tag!(&[0x42]));
    let input = [0x42, 0x00];
    assert_eq!(test(&input), Ok((&b"\x00"[..], &b"\x42"[..])));
    assert_eq!(test2(&input), Ok((&b"\x00"[..], &b"\x42"[..])));
  }
}
