use internal::{IResult, Needed};
use traits::{AsChar, InputIter, InputLength, Slice};
use std::ops::RangeFrom;
use traits::{need_more, AtEof};
#[macro_export]
macro_rules! one_of (
($i:expr, $inp: expr) => (
{
use ::std::result::Result::*;
use ::std::option::Option::*;
use $crate::{Err,Needed};
use $crate::Slice;
use $crate::AsChar;
use $crate::FindToken;
use $crate::InputIter;
match ($i).iter_elements().next().map(|c| {
(c, $inp.find_token(c))
}) {
None => $crate::need_more($i, Needed::Size(1)),
Some((_, false)) => Err(Err::Error(error_position!($i, $crate::ErrorKind::OneOf::<u32>))),
Some((c, true)) => Ok(( $i.slice(c.len()..), $i.iter_elements().next().unwrap().as_char() ))
}
}
);
);
#[macro_export]
macro_rules! none_of (
($i:expr, $inp: expr) => (
{
use ::std::result::Result::*;
use ::std::option::Option::*;
use $crate::{Err,Needed};
use $crate::Slice;
use $crate::AsChar;
use $crate::FindToken;
use $crate::InputIter;
match ($i).iter_elements().next().map(|c| {
(c, !$inp.find_token(c))
}) {
None => $crate::need_more($i, Needed::Size(1)),
Some((_, false)) => Err(Err::Error(error_position!($i, $crate::ErrorKind::NoneOf::<u32>))),
Some((c, true)) => Ok(( $i.slice(c.len()..), $i.iter_elements().next().unwrap().as_char() ))
}
}
);
);
#[macro_export]
macro_rules! char (
($i:expr, $c: expr) => (
{
use ::std::result::Result::*;
use ::std::option::Option::*;
use $crate::{Err,Needed};
use $crate::Slice;
use $crate::AsChar;
use $crate::InputIter;
match ($i).iter_elements().next().map(|c| {
let b = c.as_char() == $c;
b
}) {
None => $crate::need_more($i, Needed::Size(1)),
Some(false) => {
let e: $crate::ErrorKind<u32> = $crate::ErrorKind::Char;
Err(Err::Error($crate::Context::Code($i, e)))
},
Some(true) => Ok(( $i.slice($c.len()..), $i.iter_elements().next().unwrap().as_char() ))
}
}
);
);
named!(#[doc="Matches a newline character '\\n'"], pub newline<char>, char!('\n'));
named!(#[doc="Matches a tab character '\\t'"], pub tab<char>, char!('\t'));
pub fn anychar<T>(input: T) -> IResult<T, char>
where
T: InputIter + InputLength + Slice<RangeFrom<usize>> + AtEof,
<T as InputIter>::Item: AsChar,
{
let mut it = input.iter_indices();
match it.next() {
None => need_more(input, Needed::Size(1)),
Some((_, c)) => match it.next() {
None => Ok((input.slice(input.input_len()..), c.as_char())),
Some((idx, _)) => Ok((input.slice(idx..), c.as_char())),
},
}
}
#[cfg(test)]
mod tests {
use internal::Err;
use util::ErrorKind;
#[test]
fn one_of() {
named!(f<char>, one_of!("ab"));
let a = &b"abcd"[..];
assert_eq!(f(a), Ok((&b"bcd"[..], 'a')));
let b = &b"cde"[..];
assert_eq!(f(b), Err(Err::Error(error_position!(b, ErrorKind::OneOf))));
named!(utf8(&str) -> char,
one_of!("+\u{FF0B}"));
assert!(utf8("+").is_ok());
assert!(utf8("\u{FF0B}").is_ok());
}
#[test]
fn none_of() {
named!(f<char>, none_of!("ab"));
let a = &b"abcd"[..];
assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::NoneOf))));
let b = &b"cde"[..];
assert_eq!(f(b), Ok((&b"de"[..], 'c')));
}
#[test]
fn char() {
named!(f<char>, char!('c'));
let a = &b"abcd"[..];
assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::Char))));
let b = &b"cde"[..];
assert_eq!(f(b), Ok((&b"de"[..], 'c')));
}
#[test]
fn char_str() {
named!(f<&str, char>, char!('c'));
let a = &"abcd"[..];
assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::Char))));
let b = &"cde"[..];
assert_eq!(f(b), Ok((&"de"[..], 'c')));
}
#[test]
fn anychar_str() {
use super::anychar;
assert_eq!(anychar("Ә"), Ok(("", 'Ә')));
}
}