#[macro_export]
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);
if bytes.len() > $i.len() {
$crate::IResult::Incomplete($crate::Needed::Size(bytes.len()))
} else if &$i[0..bytes.len()] == bytes {
$crate::IResult::Done(&$i[bytes.len()..], &$i[0..bytes.len()])
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorCode::Tag as u32, $i))
}
}
);
);
#[macro_export]
macro_rules! is_not(
($input:expr, $arr:expr) => (
{
#[inline(always)]
fn as_bytes<T: $crate::AsBytes>(b: &T) -> &[u8] {
b.as_bytes()
}
let expected = $arr;
let bytes = as_bytes(&expected);
match $input.iter().position(|c| {
for &i in bytes.iter() {
if *c == i { return true }
}
false
}) {
Some(0) => $crate::IResult::Error($crate::Err::Position($crate::ErrorCode::IsNot as u32,$input)),
Some(n) => {
let res = $crate::IResult::Done(&$input[n..], &$input[..n]);
res
},
None => {
$crate::IResult::Done(&b""[..], $input)
}
}
}
);
);
#[macro_export]
macro_rules! is_a(
($input:expr, $arr:expr) => (
{
#[inline(always)]
fn as_bytes<T: $crate::AsBytes>(b: &T) -> &[u8] {
b.as_bytes()
}
let expected = $arr;
let bytes = as_bytes(&expected);
match $input.iter().position(|c| {
for &i in bytes.iter() {
if *c == i { return false }
}
true
}) {
Some(0) => $crate::IResult::Error($crate::Err::Position($crate::ErrorCode::IsA as u32,$input)),
Some(n) => {
let res = $crate::IResult::Done(&$input[n..], &$input[..n]);
res
},
None => {
$crate::IResult::Done(&b""[..], $input)
}
}
}
);
);
#[macro_export]
macro_rules! filter(
($input:expr, $submac:ident!( $($args:tt)* )) => (
{
match $input.iter().position(|c| !$submac!(*c, $($args)*)) {
Some(n) => {
let res = $crate::IResult::Done(&$input[n..], &$input[..n]);
res
},
None => {
$crate::IResult::Done(&b""[..], $input)
}
}
}
);
($input:expr, $f:expr) => (
filter!($input, call!($f));
);
);
#[macro_export]
macro_rules! take_while (
($input:expr, $submac:ident!( $($args:tt)* )) => (
{
match $input.iter().position(|c| !$submac!(*c, $($args)*)) {
Some(n) => {
let res = $crate::IResult::Done(&$input[n..], &$input[..n]);
res
},
None => {
$crate::IResult::Done(&b""[..], $input)
}
}
}
);
($input:expr, $f:expr) => (
take_while!($input, call!($f));
);
);
#[macro_export]
macro_rules! take_while1 (
($input:expr, $submac:ident!( $($args:tt)* )) => (
{
match $input.iter().position(|c| !$submac!(*c, $($args)*)) {
Some(0) => $crate::IResult::Error($crate::Err::Position($crate::ErrorCode::TakeWhile1 as u32,$input)),
Some(n) => {
let res = $crate::IResult::Done(&$input[n..], &$input[..n]);
res
},
None => {
$crate::IResult::Done(&b""[..], $input)
}
}
}
);
($input:expr, $f:expr) => (
take_while1!($input, call!($f));
);
);
#[macro_export]
macro_rules! take_till (
($input:expr, $submac:ident!( $($args:tt)* )) => (
{
match $input.iter().position(|c| $submac!(c, $($args)*)) {
Some(n) => $crate::IResult::Done(&$input[n..], &$input[..n]),
None => $crate::IResult::Done(&b""[..], $input)
}
}
);
($input:expr, $f:expr) => (
take_till!($input, call!($f));
);
);
#[macro_export]
macro_rules! take(
($i:expr, $count:expr) => (
{
let cnt = $count as usize;
if $i.len() < cnt {
$crate::IResult::Incomplete($crate::Needed::Size(cnt))
} else {
$crate::IResult::Done(&$i[cnt..],&$i[0..cnt])
}
}
);
);
#[macro_export]
macro_rules! take_str (
( $i:expr, $size:expr ) => ( map_res!($i, take!($size), from_utf8) );
);
#[macro_export]
macro_rules! take_until_and_consume(
($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);
if bytes.len() > $i.len() {
$crate::IResult::Incomplete($crate::Needed::Size(bytes.len()))
} else {
let mut index = 0;
let mut parsed = false;
for idx in 0..$i.len() {
if idx + bytes.len() > $i.len() {
index = idx;
break;
}
if &$i[idx..idx + bytes.len()] == bytes {
parsed = true;
index = idx;
break;
}
}
if parsed {
$crate::IResult::Done(&$i[(index + bytes.len())..], &$i[0..index])
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorCode::TakeUntilAndConsume as u32,$i))
}
}
}
);
);
#[macro_export]
macro_rules! take_until(
($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);
if bytes.len() > $i.len() {
$crate::IResult::Incomplete($crate::Needed::Size(bytes.len()))
} else {
let mut index = 0;
let mut parsed = false;
for idx in 0..$i.len() {
if idx + bytes.len() > $i.len() {
index = idx;
break;
}
if &$i[idx..idx+bytes.len()] == bytes {
parsed = true;
index = idx;
break;
}
}
if parsed {
$crate::IResult::Done(&$i[index..], &$i[0..index])
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorCode::TakeUntil as u32,$i))
}
}
}
);
);
#[macro_export]
macro_rules! take_until_either_and_consume(
($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);
if 1 > $i.len() {
$crate::IResult::Incomplete($crate::Needed::Size(1))
} else {
let mut index = 0;
let mut parsed = false;
for idx in 0..$i.len() {
if idx + 1 > $i.len() {
index = idx;
break;
}
for &t in bytes.iter() {
if $i[idx] == t {
parsed = true;
index = idx;
break;
}
}
if parsed { break; }
}
if parsed {
$crate::IResult::Done(&$i[(index+1)..], &$i[0..index])
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorCode::TakeUntilEitherAndConsume as u32,$i))
}
}
}
);
);
#[macro_export]
macro_rules! take_until_either(
($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);
if 1 > $i.len() {
$crate::IResult::Incomplete($crate::Needed::Size(1))
} else {
let mut index = 0;
let mut parsed = false;
for idx in 0..$i.len() {
if idx + 1 > $i.len() {
index = idx;
break;
}
for &t in bytes.iter() {
if $i[idx] == t {
parsed = true;
index = idx;
break;
}
}
if parsed { break; }
}
if parsed {
$crate::IResult::Done(&$i[index..], &$i[0..index])
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorCode::TakeUntilEither as u32,$i))
}
}
}
);
);
#[cfg(test)]
mod tests {
use internal::Needed;
use internal::IResult::*;
use internal::Err::*;
use util::ErrorCode;
#[test]
fn is_a() {
named!(a_or_b, is_a!(&b"ab"[..]));
let a = &b"abcd"[..];
assert_eq!(a_or_b(a), Done(&b"cd"[..], &b"ab"[..]));
let b = &b"bcde"[..];
assert_eq!(a_or_b(b), Done(&b"cde"[..], &b"b"[..]));
let c = &b"cdef"[..];
assert_eq!(a_or_b(c), Error(Position(ErrorCode::IsA as u32,c)));
let d = &b"bacdef"[..];
assert_eq!(a_or_b(d), Done(&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), Done(&b"ab"[..], &b"cd"[..]));
let b = &b"cbde"[..];
assert_eq!(a_or_b(b), Done(&b"bde"[..], &b"c"[..]));
let c = &b"abab"[..];
assert_eq!(a_or_b(c), Error(Position(ErrorCode::IsNot as u32,c)));
let d = &b"cdefba"[..];
assert_eq!(a_or_b(d), Done(&b"ba"[..], &b"cdef"[..]));
let e = &b"e"[..];
assert_eq!(a_or_b(e), Done(&b""[..], &b"e"[..]));
let f = &b"fghi"[..];
assert_eq!(a_or_b(f), Done(&b""[..], &b"fghi"[..]));
}
#[test]
fn issue_84() {
let r0 = is_a!(&b"aaaaefgh"[..], "abcd");
assert_eq!(r0, Done(&b"efgh"[..], &b"aaaa"[..]));
let r1 = is_a!(&b"aaaa"[..], "abcd");
assert_eq!(r1, Done(&b""[..], &b"aaaa"[..]));
let r2 = is_a!(&b"1"[..], "123456789");
assert_eq!(r2, Done(&b""[..], &b"1"[..]));
}
use std::str::from_utf8;
#[test]
fn take_str_test() {
let a = b"omnomnom";
assert_eq!(take_str!(&a[..], 5), Done(&b"nom"[..], "omnom"));
assert_eq!(take_str!(&a[..], 9), Incomplete(Needed::Size(9)));
}
#[test]
fn take_until_test() {
named!(x, take_until_and_consume!("efgh"));
let r = x(&b"abcdabcdefghijkl"[..]);
assert_eq!(r, Done(&b"ijkl"[..], &b"abcdabcd"[..]));
println!("Done 1\n");
let r2 = x(&b"abcdabcdefgh"[..]);
assert_eq!(r2, Done(&b""[..], &b"abcdabcd"[..]));
println!("Done 2\n");
let r3 = x(&b"abcefg"[..]);
assert_eq!(r3, Error(Position(ErrorCode::TakeUntilAndConsume as u32, &b"abcefg"[..])));
assert_eq!(
x(&b"ab"[..]),
Incomplete(Needed::Size(4))
);
}
#[test]
fn take_until_either_incomplete() {
named!(x, take_until_either!("!."));
assert_eq!(
x(&b"123"[..]),
Error(Position(ErrorCode::TakeUntilEither as u32, &b"123"[..]))
);
}
#[test]
fn take_until_incomplete() {
named!(y, take_until!("end"));
assert_eq!(
y(&b"nd"[..]),
Incomplete(Needed::Size(3))
);
assert_eq!(
y(&b"123"[..]),
Error(Position(ErrorCode::TakeUntil as u32, &b"123"[..]))
);
}
#[cfg(feature = "nightly")]
use test::Bencher;
#[cfg(feature = "nightly")]
#[bench]
fn filter(b: &mut Bencher) {
use nom::is_alphabetic;
named!(f, filter!(is_alphabetic));
b.iter(|| {
f(&b"abcdefghijklABCDEejfrfrjgro12aa"[..])
});
}
}