#[macro_export(local_inner_macros)]
macro_rules! alt (
  (__impl $i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)* ) => (
    compile_error!("alt uses '|' as separator, not ',':
      alt!(
        tag!(\"abcd\") |
        tag!(\"efgh\") |
        tag!(\"ijkl\")
      )
    ");
  );
  (__impl $i:expr, $e:path, $($rest:tt)* ) => (
    alt!(__impl $i, call!($e) , $($rest)*);
  );
  (__impl $i:expr, $e:path | $($rest:tt)*) => (
    alt!(__impl $i, call!($e) | $($rest)*);
  );
  (__impl $i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => (
    {
      use $crate::lib::std::result::Result::*;
      use $crate::Err;
      let i_ = $i.clone();
      let res = $subrule!(i_, $($args)*);
      match res {
        Ok(o) => Ok(o),
        Err(Err::Error(e))      => {
          let out = alt!(__impl $i, $($rest)*);
          
          
          #[allow(dead_code)]
          fn unify_types<T>(_: &T, _: &T) {}
          if let Err(Err::Error(ref e2)) = out {
            unify_types(&e, e2);
          }
          out
        },
        Err(e) => Err(e),
      }
    }
  );
  (__impl $i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)*) => (
    {
      use $crate::lib::std::result::Result::*;
      use $crate::Err;
      let i_ = $i.clone();
      match $subrule!(i_, $($args)* ) {
        Ok((i,o))         => Ok((i,$gen(o))),
        Err(Err::Error(e)) => {
          let out = alt!(__impl $i, $($rest)*);
          
          
          fn unify_types<T>(_: &T, _: &T) {}
          if let Err(Err::Error(ref e2)) = out {
            unify_types(&e, e2);
          }
          out
        },
        Err(e) => Err(e),
      }
    }
  );
  (__impl $i:expr, $e:path => { $gen:expr } | $($rest:tt)*) => (
    alt!(__impl $i, call!($e) => { $gen } | $($rest)*);
  );
  (__impl $i:expr, __end) => (
    {
      use $crate::{Err,ErrorKind};
      let e2 = ErrorKind::Alt;
      let err = Err::Error(error_position!($i, e2));
      Err(err)
    }
  );
  ($i:expr, $($rest:tt)*) => (
    {
      alt!(__impl $i, $($rest)* | __end)
    }
  );
);
#[macro_export(local_inner_macros)]
macro_rules! alt_complete (
  
  ($i:expr, $e:path | $($rest:tt)*) => (
    alt_complete!($i, complete!(call!($e)) | $($rest)*);
  );
  ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => (
    {
      use $crate::lib::std::result::Result::*;
      use $crate::Err;
      let i_ = $i.clone();
      let res = complete!(i_, $subrule!($($args)*));
      match res {
        Ok((_,_)) => res,
        Err(Err::Failure(e)) => Err(Err::Failure(e)),
        e => {
          let out = alt_complete!($i, $($rest)*);
          if let (&Err(Err::Error(ref e1)), &Err(Err::Error(ref e2))) = (&e, &out) {
            
            
            fn unify_types<T>(_: &T, _: &T) {}
            unify_types(e1, e2);
          }
          out
        },
      }
    }
  );
  ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => (
    {
      use $crate::lib::std::result::Result::*;
      use $crate::Err;
      let i_ = $i.clone();
      match complete!(i_, $subrule!($($args)*)) {
        Ok((i,o)) => Ok((i,$gen(o))),
        Err(Err::Failure(e)) => Err(Err::Failure(e)),
        e => {
          let out = alt_complete!($i, $($rest)*);
          if let (&Err(Err::Error(ref e1)), &Err(Err::Error(ref e2))) = (&e, &out) {
            
            
            fn unify_types<T>(_: &T, _: &T) {}
            unify_types(e1, e2);
          }
          out
        },
      }
    }
  );
  ($i:expr, $e:path => { $gen:expr } | $($rest:tt)*) => (
    alt_complete!($i, complete!(call!($e)) => { $gen } | $($rest)*);
  );
  
  ($i:expr, $e:path => { $gen:expr }) => (
    alt_complete!($i, call!($e) => { $gen });
  );
  ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => (
    alt!(__impl $i, complete!($subrule!($($args)*)) => { $gen } | __end)
  );
  ($i:expr, $e:path) => (
    alt_complete!($i, call!($e));
  );
  ($i:expr, $subrule:ident!( $($args:tt)*)) => (
    alt!(__impl $i, complete!($subrule!($($args)*)) | __end)
  );
);
#[macro_export(local_inner_macros)]
macro_rules! switch (
  (__impl $i:expr, $submac:ident!( $($args:tt)* ), $( $($p:pat)|+ => $subrule:ident!( $($args2:tt)* ))|* ) => (
    {
      use $crate::lib::std::result::Result::*;
      use $crate::lib::std::option::Option::*;
      use $crate::{Err,Convert,ErrorKind};
      let i_ = $i.clone();
      match map!(i_, $submac!($($args)*), Some) {
        Err(Err::Error(err))      => {
          fn unify_types<T>(_: &T, _: &T) {}
          let e1 = ErrorKind::Switch;
          let e2 = error_position!($i, e1.clone());
          unify_types(&err, &e2);
          Err(Err::Error(error_node_position!($i, e1, err)))
        },
        Err(e) => Err(e),
        Ok((i, o))    => {
          match o {
            $($(Some($p) )|+ => match $subrule!(i, $($args2)*) {
              Err(Err::Error(err)) => {
                fn unify_types<T>(_: &T, _: &T) {}
                let e1 = ErrorKind::Switch;
                let e2 = error_position!($i, e1.clone());
                unify_types(&err, &e2);
                Err(Err::Error(error_node_position!($i, e1, err)))
              },
              Ok(o) => Ok(o),
              Err(e) => Err(e),
            }),*,
            _    => Err(Err::convert(Err::Error(error_position!($i, ErrorKind::Switch::<u32>))))
          }
        }
      }
    }
  );
  ($i:expr, $submac:ident!( $($args:tt)*), $($rest:tt)*) => (
    {
      switch!(__impl $i, $submac!($($args)*), $($rest)*)
    }
  );
  ($i:expr, $e:path, $($rest:tt)*) => (
    {
      switch!(__impl $i, call!($e), $($rest)*)
    }
  );
);
#[macro_export(local_inner_macros)]
macro_rules! permutation (
  ($i:expr, $($rest:tt)*) => (
    {
      use $crate::lib::std::result::Result::*;
      use $crate::lib::std::option::Option::*;
      use $crate::{Err,Convert,ErrorKind};
      let mut res    = permutation_init!((), $($rest)*);
      let mut input  = $i;
      let mut error  = None;
      let mut needed = None;
      loop {
        let mut all_done = true;
        permutation_iterator!(0, input, all_done, needed, res, $($rest)*);
        
        if !all_done {
          
          error = Some(error_position!(input, ErrorKind::Permutation));
        }
        break;
      }
      if let Some(need) = needed {
        Err(Err::convert(need))
      } else {
        if let Some(unwrapped_res) = { permutation_unwrap!(0, (), res, $($rest)*) } {
          Ok((input, unwrapped_res))
        } else {
          if let Some(e) = error {
            Err(Err::Error(error_node_position!($i, ErrorKind::Permutation, e)))
          } else {
            Err(Err::Error(error_position!($i, ErrorKind::Permutation)))
          }
        }
      }
    }
  );
);
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! permutation_init (
  ((), $e:ident?, $($rest:tt)*) => (
    permutation_init!(($crate::lib::std::option::Option::None), $($rest)*)
  );
  ((), $e:ident, $($rest:tt)*) => (
    permutation_init!(($crate::lib::std::option::Option::None), $($rest)*)
  );
  ((), $submac:ident!( $($args:tt)* )?, $($rest:tt)*) => (
    permutation_init!(($crate::lib::std::option::Option::None), $($rest)*)
  );
  ((), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => (
    permutation_init!(($crate::lib::std::option::Option::None), $($rest)*)
  );
  (($($parsed:expr),*), $e:ident?, $($rest:tt)*) => (
    permutation_init!(($($parsed),* , $crate::lib::std::option::Option::None), $($rest)*);
  );
  (($($parsed:expr),*), $e:ident, $($rest:tt)*) => (
    permutation_init!(($($parsed),* , $crate::lib::std::option::Option::None), $($rest)*);
  );
  (($($parsed:expr),*), $submac:ident!( $($args:tt)* )?, $($rest:tt)*) => (
    permutation_init!(($($parsed),* , $crate::lib::std::option::Option::None), $($rest)*);
  );
  (($($parsed:expr),*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => (
    permutation_init!(($($parsed),* , $crate::lib::std::option::Option::None), $($rest)*);
  );
  (($($parsed:expr),*), $e:ident) => (
    ($($parsed),* , $crate::lib::std::option::Option::None)
  );
  (($($parsed:expr),*), $e:ident?) => (
    ($($parsed),* , $crate::lib::std::option::Option::None)
  );
  (($($parsed:expr),*), $submac:ident!( $($args:tt)* )?) => (
    ($($parsed),* , $crate::lib::std::option::Option::None)
  );
  (($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => (
    ($($parsed),* , $crate::lib::std::option::Option::None)
  );
  (($($parsed:expr),*),) => (
    ($($parsed),*)
  );
);
#[doc(hidden)]
#[macro_export(local_inner_macros)]
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)*));
);
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! acc (
  (0, $tup:expr) => ($tup.0);
  (1, $tup:expr) => ($tup.1);
  (2, $tup:expr) => ($tup.2);
  (3, $tup:expr) => ($tup.3);
  (4, $tup:expr) => ($tup.4);
  (5, $tup:expr) => ($tup.5);
  (6, $tup:expr) => ($tup.6);
  (7, $tup:expr) => ($tup.7);
  (8, $tup:expr) => ($tup.8);
  (9, $tup:expr) => ($tup.9);
  (10, $tup:expr) => ($tup.10);
  (11, $tup:expr) => ($tup.11);
  (12, $tup:expr) => ($tup.12);
  (13, $tup:expr) => ($tup.13);
  (14, $tup:expr) => ($tup.14);
  (15, $tup:expr) => ($tup.15);
  (16, $tup:expr) => ($tup.16);
  (17, $tup:expr) => ($tup.17);
  (18, $tup:expr) => ($tup.18);
  (19, $tup:expr) => ($tup.19);
  (20, $tup:expr) => ($tup.20);
);
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! permutation_unwrap (
  ($it:tt,  (), $res:ident, $e:ident?, $($rest:tt)*) => (
    succ!($it, permutation_unwrap!((acc!($it, $res)), $res, $($rest)*));
  );
  ($it:tt,  (), $res:ident, $e:ident, $($rest:tt)*) => ({
    let res = acc!($it, $res);
    if res.is_some() {
      succ!($it, permutation_unwrap!((res.unwrap()), $res, $($rest)*))
    } else {
      $crate::lib::std::option::Option::None
    }
  });
  ($it:tt,  (), $res:ident, $submac:ident!( $($args:tt)* )?, $($rest:tt)*) => (
    succ!($it, permutation_unwrap!((acc!($it, $res)), $res, $($rest)*));
  );
  ($it:tt,  (), $res:ident, $submac:ident!( $($args:tt)* ), $($rest:tt)*) => ({
    let res = acc!($it, $res);
    if res.is_some() {
      succ!($it, permutation_unwrap!((res.unwrap()), $res, $($rest)*))
    } else {
      $crate::lib::std::option::Option::None
    }
  });
  ($it:tt, ($($parsed:expr),*), $res:ident, $e:ident?, $($rest:tt)*) => (
    succ!($it, permutation_unwrap!(($($parsed),* , acc!($it, $res)), $res, $($rest)*));
  );
  ($it:tt, ($($parsed:expr),*), $res:ident, $e:ident, $($rest:tt)*) => ({
    let res = acc!($it, $res);
    if res.is_some() {
      succ!($it, permutation_unwrap!(($($parsed),* , res.unwrap()), $res, $($rest)*))
    } else {
      $crate::lib::std::option::Option::None
    }
  });
  ($it:tt, ($($parsed:expr),*), $res:ident, $submac:ident!( $($args:tt)* )?, $($rest:tt)*) => (
    succ!($it, permutation_unwrap!(($($parsed),* , acc!($it, $res)), $res, $($rest)*));
  );
  ($it:tt, ($($parsed:expr),*), $res:ident, $submac:ident!( $($args:tt)* ), $($rest:tt)*) => ({
    let res = acc!($it, $res);
    if res.is_some() {
      succ!($it, permutation_unwrap!(($($parsed),* , res.unwrap()), $res, $($rest)*))
    } else {
      $crate::lib::std::option::Option::None
    }
  });
  ($it:tt, ($($parsed:expr),*), $res:ident?, $e:ident) => (
    $crate::lib::std::option::Option::Some(($($parsed),* , { acc!($it, $res) }))
  );
  ($it:tt, ($($parsed:expr),*), $res:ident, $e:ident) => ({
    let res = acc!($it, $res);
    if res.is_some() {
      $crate::lib::std::option::Option::Some(($($parsed),* , res.unwrap() ))
    } else {
      $crate::lib::std::option::Option::None
    }
  });
  ($it:tt, ($($parsed:expr),*), $res:ident, $submac:ident!( $($args:tt)* )?) => (
    $crate::lib::std::option::Option::Some(($($parsed),* , { acc!($it, $res) }))
  );
  ($it:tt, ($($parsed:expr),*), $res:ident, $submac:ident!( $($args:tt)* )) => ({
    let res = acc!($it, $res);
    if res.is_some() {
      $crate::lib::std::option::Option::Some(($($parsed),* , res.unwrap() ))
    } else {
      $crate::lib::std::option::Option::None
    }
  });
);
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! permutation_iterator (
  ($it:tt,$i:expr, $all_done:expr, $needed:expr, $res:expr, $e:ident?, $($rest:tt)*) => (
    permutation_iterator!($it, $i, $all_done, $needed, $res, call!($e), $($rest)*);
  );
  ($it:tt,$i:expr, $all_done:expr, $needed:expr, $res:expr, $e:ident, $($rest:tt)*) => (
    permutation_iterator!($it, $i, $all_done, $needed, $res, call!($e), $($rest)*);
  );
  ($it:tt, $i:expr, $all_done:expr, $needed:expr, $res:expr, $submac:ident!( $($args:tt)* )?, $($rest:tt)*) => {
    permutation_iterator!($it, $i, $all_done, $needed, $res, $submac!($($args)*) , $($rest)*);
  };
  ($it:tt, $i:expr, $all_done:expr, $needed:expr, $res:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)*) => ({
    use $crate::lib::std::result::Result::*;
    use $crate::lib::std::option::Option::*;
    use $crate::Err;
    if acc!($it, $res).is_none() {
      match $submac!($i, $($args)*) {
        Ok((i,o))     => {
          $i = i;
          acc!($it, $res) = Some(o);
          continue;
        },
        Err(Err::Error(_)) => {
          $all_done = false;
        },
        Err(e) => {
          $needed = Some(e);
          break;
        }
      };
    }
    succ!($it, permutation_iterator!($i, $all_done, $needed, $res, $($rest)*));
  });
  ($it:tt,$i:expr, $all_done:expr, $needed:expr, $res:expr, $e:ident?) => (
    permutation_iterator!($it, $i, $all_done, $needed, $res, call!($e));
  );
  ($it:tt,$i:expr, $all_done:expr, $needed:expr, $res:expr, $e:ident) => (
    permutation_iterator!($it, $i, $all_done, $needed, $res, call!($e));
  );
  ($it:tt, $i:expr, $all_done:expr, $needed:expr, $res:expr, $submac:ident!( $($args:tt)* )?) => {
    permutation_iterator!($it, $i, $all_done, $needed, $res, $submac!($($args)*));
  };
  ($it:tt, $i:expr, $all_done:expr, $needed:expr, $res:expr, $submac:ident!( $($args:tt)* )) => ({
    use $crate::lib::std::result::Result::*;
    use $crate::lib::std::option::Option::*;
    use $crate::Err;
    if acc!($it, $res).is_none() {
      match $submac!($i, $($args)*) {
        Ok((i,o))     => {
          $i = i;
          acc!($it, $res) = Some(o);
          continue;
        },
        Err(Err::Error(_)) => {
          $all_done = false;
        },
        Err(e) => {
          $needed = Some(e);
          break;
        }
      };
    }
  });
);
#[cfg(test)]
mod tests {
  #[cfg(feature = "alloc")]
  use lib::std::string::{String, ToString};
  use internal::{Err, IResult, Needed};
  use util::ErrorKind;
  
  macro_rules! tag (
    ($i:expr, $inp: expr) => (
      {
        #[inline(always)]
        fn as_bytes<T: $crate::AsBytes>(b: &T) -> &[u8] {
          b.as_bytes()
        }
        let expected = $inp;
        let bytes    = as_bytes(&expected);
        tag_bytes!($i,bytes)
      }
    );
  );
  macro_rules! tag_bytes (
    ($i:expr, $bytes: expr) => (
      {
        use $crate::need_more;
        use $crate::lib::std::cmp::min;
        let len = $i.len();
        let blen = $bytes.len();
        let m   = min(len, blen);
        let reduced = &$i[..m];
        let b       = &$bytes[..m];
        let res: IResult<_,_,u32> = if reduced != b {
          let e: ErrorKind<u32> = ErrorKind::Tag::<u32>;
          Err(Err::Error(error_position!($i, e)))
        } else if m < blen {
          
          
          need_more($i, Needed::Size(blen))
        } else {
          Ok((&$i[blen..], reduced))
        };
        res
      }
    );
  );
  macro_rules! take(
    ($i:expr, $count:expr) => (
      {
        use $crate::need_more;
        let cnt = $count as usize;
        let res:IResult<&[u8],&[u8],u32> = if $i.len() < cnt {
          need_more($i, Needed::Size(cnt))
        } else {
          Ok((&$i[cnt..],&$i[0..cnt]))
        };
        res
      }
    );
  );
  #[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")]
  #[test]
  fn alt() {
    fn work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
      Ok((&b""[..], input))
    }
    #[allow(unused_variables)]
    fn dont_work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
      use Context;
      Err(Err::Error(Context::Code(
        &b""[..],
        ErrorKind::Custom(ErrorStr("abcd".to_string())),
      )))
    }
    fn work2(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
      Ok((input, &b""[..]))
    }
    fn alt1(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
      alt!(i, dont_work | dont_work)
    }
    fn alt2(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
      alt!(i, dont_work | work)
    }
    fn alt3(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
      alt!(i, dont_work | dont_work | work2 | dont_work)
    }
    
    
    
    let a = &b"abcd"[..];
    assert_eq!(alt1(a), Err(Err::Error(error_position!(a, ErrorKind::Alt))));
    assert_eq!(alt2(a), Ok((&b""[..], a)));
    assert_eq!(alt3(a), Ok((a, &b""[..])));
    named!(alt4, alt!(tag!("abcd") | tag!("efgh")));
    let b = &b"efgh"[..];
    assert_eq!(alt4(a), Ok((&b""[..], a)));
    assert_eq!(alt4(b), Ok((&b""[..], b)));
    
    named!(
      alt5<bool>,
      alt!(tag!("abcd") => { |_| false } | tag!("efgh") => { |_| true })
    );
    assert_eq!(alt5(a), Ok((&b""[..], false)));
    assert_eq!(alt5(b), Ok((&b""[..], true)));
    
    named!(alt_eof1, alt!(eof!() | eof!()));
    named!(alt_eof2, alt!(eof!() => {|x| x} | eof!() => {|x| x}));
    let _ = (alt_eof1, alt_eof2);
  }
  #[test]
  fn alt_incomplete() {
    named!(alt1, alt!(tag!("a") | tag!("bc") | tag!("def")));
    let a = &b""[..];
    assert_eq!(alt1(a), Err(Err::Incomplete(Needed::Size(1))));
    let a = &b"b"[..];
    assert_eq!(alt1(a), Err(Err::Incomplete(Needed::Size(2))));
    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::Alt))));
    let a = &b"de"[..];
    assert_eq!(alt1(a), Err(Err::Incomplete(Needed::Size(3))));
    let a = &b"defg"[..];
    assert_eq!(alt1(a), Ok((&b"g"[..], &b"def"[..])));
  }
  #[test]
  fn alt_complete() {
    named!(ac<&[u8], &[u8]>,
      alt_complete!(tag!("abcd") | tag!("ef") | tag!("ghi") | tag!("kl"))
    );
    let a = &b""[..];
    assert_eq!(ac(a), Err(Err::Error(error_position!(a, ErrorKind::Alt))));
    let a = &b"ef"[..];
    assert_eq!(ac(a), Ok((&b""[..], &b"ef"[..])));
    let a = &b"cde"[..];
    assert_eq!(ac(a), Err(Err::Error(error_position!(a, ErrorKind::Alt))));
  }
  #[allow(unused_variables)]
  #[test]
  fn switch() {
    named!(
      sw,
      switch!(take!(4),
        b"abcd" | b"xxxx" => take!(2) |
        b"efgh" => take!(4)
      )
    );
    let a = &b"abcdefgh"[..];
    assert_eq!(sw(a), Ok((&b"gh"[..], &b"ef"[..])));
    let b = &b"efghijkl"[..];
    assert_eq!(sw(b), Ok((&b""[..], &b"ijkl"[..])));
    let c = &b"afghijkl"[..];
    assert_eq!(
      sw(c),
      Err(Err::Error(error_position!(
        &b"afghijkl"[..],
        ErrorKind::Switch
      )))
    );
    let a = &b"xxxxefgh"[..];
    assert_eq!(sw(a), Ok((&b"gh"[..], &b"ef"[..])));
  }
  #[test]
  fn permutation() {
    named!(
      perm<(&[u8], &[u8], &[u8])>,
      permutation!(tag!("abcd"), tag!("efg"), tag!("hi"))
    );
    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::Permutation)
      )))
    );
    let e = &b"efgabc"[..];
    assert_eq!(perm(e), Err(Err::Incomplete(Needed::Size(4))));
  }
  
}