#[macro_export(local_inner_macros)]
macro_rules! tuple (
($i:expr, $($rest:tt)*) => (
{
tuple_parser!($i, (), $($rest)*)
}
);
);
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! tuple_parser (
($i:expr, ($($parsed:tt),*), $e:path, $($rest:tt)*) => (
tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*);
);
($i:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => (
{
let i_ = $i.clone();
( $submac!(i_, $($args)*) ).and_then(|(i,o)| {
let i_ = i.clone();
tuple_parser!(i_, (o), $($rest)*)
})
}
);
($i:expr, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => (
{
let i_ = $i.clone();
( $submac!(i_, $($args)*) ).and_then(|(i,o)| {
let i_ = i.clone();
tuple_parser!(i_, ($($parsed)* , o), $($rest)*)
})
}
);
($i:expr, ($($parsed:tt),*), $e:path) => (
tuple_parser!($i, ($($parsed),*), call!($e));
);
($i:expr, (), $submac:ident!( $($args:tt)* )) => (
{
let i_ = $i.clone();
( $submac!(i_, $($args)*) ).map(|(i,o)| (i, (o)))
}
);
($i:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => (
{
let i_ = $i.clone();
( $submac!(i_, $($args)*) ).map(|(i,o)| (i, ($($parsed),* , o)))
}
);
($i:expr, ($($parsed:expr),*)) => (
{
$crate::lib::std::result::Result::Ok(($i, ($($parsed),*)))
}
);
);
#[macro_export(local_inner_macros)]
macro_rules! pair(
($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
pair!($i, |i| $submac!(i, $($args)*), |i| $submac2!(i, $($args2)*))
);
($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => (
pair!($i, |i| $submac!(i, $($args)*), $g);
);
($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => (
pair!($i, $f, |i| $submac!(i, $($args)*));
);
($i:expr, $f:expr, $g:expr) => (
$crate::sequence::pairc($i, $f, $g)
);
);
#[macro_export(local_inner_macros)]
macro_rules! separated_pair(
($i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)*) => (
separated_pair!($i, |i| $submac!(i, $($args)*), $($rest)*)
);
($i:expr, $f:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)*) => (
separated_pair!($i, $f, |i| $submac!(i, $($args)*), $($rest)*)
);
($i:expr, $f:expr, $g:expr, $submac:ident!( $($args:tt)* )) => (
separated_pair!($i, $f, $g, |i| $submac!(i, $($args)*))
);
($i:expr, $f:expr, $g:expr, $h:expr) => (
$crate::sequence::separated_pairc($i, $f, $g, $h)
);
);
#[macro_export(local_inner_macros)]
macro_rules! preceded(
($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
preceded!($i, |i| $submac!(i, $($args)*), |i| $submac2!(i, $($args2)*))
);
($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => (
preceded!($i, |i| $submac!(i, $($args)*), $g);
);
($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => (
preceded!($i, $f, |i| $submac!(i, $($args)*));
);
($i:expr, $f:expr, $g:expr) => (
$crate::sequence::precededc($i, $f, $g)
);
);
#[macro_export(local_inner_macros)]
macro_rules! terminated(
($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
terminated!($i, |i| $submac!(i, $($args)*), |i| $submac2!(i, $($args2)*))
);
($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => (
terminated!($i, |i| $submac!(i, $($args)*), $g);
);
($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => (
terminated!($i, $f, |i| $submac!(i, $($args)*));
);
($i:expr, $f:expr, $g:expr) => (
$crate::sequence::terminatedc($i, $f, $g)
);
);
#[macro_export(local_inner_macros)]
macro_rules! delimited(
($i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)*) => (
delimited!($i, |i| $submac!(i, $($args)*), $($rest)*)
);
($i:expr, $f:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)*) => (
delimited!($i, $f, |i| $submac!(i, $($args)*), $($rest)*)
);
($i:expr, $f:expr, $g:expr, $submac:ident!( $($args:tt)* )) => (
delimited!($i, $f, $g, |i| $submac!(i, $($args)*))
);
($i:expr, $f:expr, $g:expr, $h:expr) => (
$crate::sequence::delimitedc($i, $f, $g, $h)
);
);
#[macro_export(local_inner_macros)]
macro_rules! do_parse (
(__impl $i:expr, ( $($rest:expr),* )) => (
$crate::lib::std::result::Result::Ok(($i, ( $($rest),* )))
);
(__impl $i:expr, $field:ident : $submac:ident!( $($args:tt)* ) ) => (
do_parse!(__impl $i, $submac!( $($args)* ))
);
(__impl $i:expr, $submac:ident!( $($args:tt)* ) ) => (
nom_compile_error!("do_parse is missing the return value. A do_parse call must end
with a return value between parenthesis, as follows:
do_parse!(
a: tag!(\"abcd\") >>
b: tag!(\"efgh\") >>
( Value { a: a, b: b } )
");
);
(__impl $i:expr, $field:ident : $submac:ident!( $($args:tt)* ) ~ $($rest:tt)* ) => (
nom_compile_error!("do_parse uses >> as separator, not ~");
);
(__impl $i:expr, $submac:ident!( $($args:tt)* ) ~ $($rest:tt)* ) => (
nom_compile_error!("do_parse uses >> as separator, not ~");
);
(__impl $i:expr, $field:ident : $e:ident ~ $($rest:tt)*) => (
do_parse!(__impl $i, $field: call!($e) ~ $($rest)*);
);
(__impl $i:expr, $e:ident ~ $($rest:tt)*) => (
do_parse!(__impl $i, call!($e) ~ $($rest)*);
);
(__impl $i:expr, $e:ident >> $($rest:tt)*) => (
do_parse!(__impl $i, call!($e) >> $($rest)*);
);
(__impl $i:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => (
{
use $crate::lib::std::result::Result::*;
let i_ = $i.clone();
match $submac!(i_, $($args)*) {
Err(e) => Err(e),
Ok((i,_)) => {
let i_ = i.clone();
do_parse!(__impl i_, $($rest)*)
},
}
}
);
(__impl $i:expr, $field:ident : $e:ident >> $($rest:tt)*) => (
do_parse!(__impl $i, $field: call!($e) >> $($rest)*);
);
(__impl $i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => (
{
use $crate::lib::std::result::Result::*;
let i_ = $i.clone();
match $submac!(i_, $($args)*) {
Err(e) => Err(e),
Ok((i,o)) => {
let $field = o;
let i_ = i.clone();
do_parse!(__impl i_, $($rest)*)
},
}
}
);
(__impl $i:expr, $e:ident >> ( $($rest:tt)* )) => (
do_parse!(__impl $i, call!($e) >> ( $($rest)* ));
);
(__impl $i:expr, $submac:ident!( $($args:tt)* ) >> ( $($rest:tt)* )) => ({
use $crate::lib::std::result::Result::*;
match $submac!($i, $($args)*) {
Err(e) => Err(e),
Ok((i,_)) => {
do_parse!(__finalize i, $($rest)*)
},
}
});
(__impl $i:expr, $field:ident : $e:ident >> ( $($rest:tt)* )) => (
do_parse!(__impl $i, $field: call!($e) >> ( $($rest)* ) );
);
(__impl $i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> ( $($rest:tt)* )) => ({
use $crate::lib::std::result::Result::*;
match $submac!($i, $($args)*) {
Err(e) => Err(e),
Ok((i,o)) => {
let $field = o;
do_parse!(__finalize i, $($rest)*)
},
}
});
(__finalize $i:expr, ( $o: expr )) => ({
use $crate::lib::std::result::Result::Ok;
Ok(($i, $o))
});
(__finalize $i:expr, ( $($rest:tt)* )) => ({
use $crate::lib::std::result::Result::Ok;
Ok(($i, ( $($rest)* )))
});
($i:expr, $($rest:tt)*) => (
{
do_parse!(__impl $i, $($rest)*)
}
);
($submac:ident!( $($args:tt)* ) >> $($rest:tt)* ) => (
nom_compile_error!("if you are using do_parse outside of a named! macro, you must
pass the input data as first argument, like this:
let res = do_parse!(input,
a: tag!(\"abcd\") >>
b: tag!(\"efgh\") >>
( Value { a: a, b: b } )
);");
);
($e:ident! >> $($rest:tt)* ) => (
do_parse!( call!($e) >> $($rest)*);
);
);
#[doc(hidden)]
#[macro_export]
macro_rules! nom_compile_error (
(( $($args:tt)* )) => ( compile_error!($($args)*) );
);
#[cfg(test)]
mod tests {
use crate::internal::{Err, IResult, Needed};
use crate::number::streaming::be_u16;
use crate::error::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::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<_,_,_> = if reduced != b {
Err($crate::Err::Error(error_position!($i, $crate::error::ErrorKind::Tag)))
} else if m < blen {
Err($crate::Err::Incomplete(Needed::Size(blen)))
} else {
Ok((&$i[blen..], reduced))
};
res
}
);
);
macro_rules! take (
($i:expr, $count:expr) => (
{
let cnt = $count as usize;
let res:IResult<&[u8],&[u8],_> = if $i.len() < cnt {
Err($crate::Err::Incomplete(Needed::Size(cnt)))
} else {
Ok((&$i[cnt..],&$i[0..cnt]))
};
res
}
);
);
#[derive(PartialEq, Eq, Debug)]
struct B {
a: u8,
b: u8,
}
#[derive(PartialEq, Eq, Debug)]
struct C {
a: u8,
b: Option<u8>,
}
#[cfg_attr(rustfmt, rustfmt_skip)]
#[allow(unused_variables)]
#[test]
fn add_err() {
named!(err_test,
preceded!(
tag!("efgh"),
add_return_error!(
ErrorKind::Char,
do_parse!(
tag!("ijkl") >>
res: add_return_error!(ErrorKind::Eof, tag!("mnop")) >>
(res)
)
)
)
);
let a = &b"efghblah"[..];
let b = &b"efghijklblah"[..];
let c = &b"efghijklmnop"[..];
let blah = &b"blah"[..];
let res_a = err_test(a);
let res_b = err_test(b);
let res_c = err_test(c);
assert_eq!(res_a,
Err(Err::Error(error_node_position!(blah,
ErrorKind::Eof,
error_position!(blah, ErrorKind::Tag)))));
assert_eq!(res_b, Err(Err::Error(error_node_position!(&b"ijklblah"[..], ErrorKind::Eof,
error_node_position!(blah, ErrorKind::Eof, error_position!(blah, ErrorKind::Tag))))));
assert_eq!(res_c, Ok((&b""[..], &b"mnop"[..])));
}
#[cfg_attr(rustfmt, rustfmt_skip)]
#[test]
fn complete() {
named!(err_test,
do_parse!(
tag!("ijkl") >>
res: complete!(tag!("mnop")) >>
(res)
)
);
let a = &b"ijklmn"[..];
let res_a = err_test(a);
assert_eq!(res_a,
Err(Err::Error(error_position!(&b"mn"[..], ErrorKind::Complete))));
}
#[test]
fn pair() {
named!(tag_abc, tag!("abc"));
named!(tag_def, tag!("def"));
named!( pair_abc_def<&[u8],(&[u8], &[u8])>, pair!(tag_abc, tag_def) );
assert_eq!(pair_abc_def(&b"abcdefghijkl"[..]), Ok((&b"ghijkl"[..], (&b"abc"[..], &b"def"[..]))));
assert_eq!(pair_abc_def(&b"ab"[..]), Err(Err::Incomplete(Needed::Size(3))));
assert_eq!(pair_abc_def(&b"abcd"[..]), Err(Err::Incomplete(Needed::Size(3))));
assert_eq!(
pair_abc_def(&b"xxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
assert_eq!(
pair_abc_def(&b"xxxdef"[..]),
Err(Err::Error(error_position!(&b"xxxdef"[..], ErrorKind::Tag)))
);
assert_eq!(
pair_abc_def(&b"abcxxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
}
#[test]
fn separated_pair() {
named!(tag_abc, tag!("abc"));
named!(tag_def, tag!("def"));
named!(tag_separator, tag!(","));
named!( sep_pair_abc_def<&[u8],(&[u8], &[u8])>, separated_pair!(tag_abc, tag_separator, tag_def) );
assert_eq!(
sep_pair_abc_def(&b"abc,defghijkl"[..]),
Ok((&b"ghijkl"[..], (&b"abc"[..], &b"def"[..])))
);
assert_eq!(sep_pair_abc_def(&b"ab"[..]), Err(Err::Incomplete(Needed::Size(3))));
assert_eq!(sep_pair_abc_def(&b"abc,d"[..]), Err(Err::Incomplete(Needed::Size(3))));
assert_eq!(
sep_pair_abc_def(&b"xxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
assert_eq!(
sep_pair_abc_def(&b"xxx,def"[..]),
Err(Err::Error(error_position!(&b"xxx,def"[..], ErrorKind::Tag)))
);
assert_eq!(
sep_pair_abc_def(&b"abc,xxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
}
#[test]
fn preceded() {
named!(tag_abcd, tag!("abcd"));
named!(tag_efgh, tag!("efgh"));
named!( preceded_abcd_efgh<&[u8], &[u8]>, preceded!(tag_abcd, tag_efgh) );
assert_eq!(preceded_abcd_efgh(&b"abcdefghijkl"[..]), Ok((&b"ijkl"[..], &b"efgh"[..])));
assert_eq!(preceded_abcd_efgh(&b"ab"[..]), Err(Err::Incomplete(Needed::Size(4))));
assert_eq!(preceded_abcd_efgh(&b"abcde"[..]), Err(Err::Incomplete(Needed::Size(4))));
assert_eq!(
preceded_abcd_efgh(&b"xxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
assert_eq!(
preceded_abcd_efgh(&b"xxxxdef"[..]),
Err(Err::Error(error_position!(&b"xxxxdef"[..], ErrorKind::Tag)))
);
assert_eq!(
preceded_abcd_efgh(&b"abcdxxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
}
#[test]
fn terminated() {
named!(tag_abcd, tag!("abcd"));
named!(tag_efgh, tag!("efgh"));
named!( terminated_abcd_efgh<&[u8], &[u8]>, terminated!(tag_abcd, tag_efgh) );
assert_eq!(terminated_abcd_efgh(&b"abcdefghijkl"[..]), Ok((&b"ijkl"[..], &b"abcd"[..])));
assert_eq!(terminated_abcd_efgh(&b"ab"[..]), Err(Err::Incomplete(Needed::Size(4))));
assert_eq!(terminated_abcd_efgh(&b"abcde"[..]), Err(Err::Incomplete(Needed::Size(4))));
assert_eq!(
terminated_abcd_efgh(&b"xxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
assert_eq!(
terminated_abcd_efgh(&b"xxxxdef"[..]),
Err(Err::Error(error_position!(&b"xxxxdef"[..], ErrorKind::Tag)))
);
assert_eq!(
terminated_abcd_efgh(&b"abcdxxxx"[..]),
Err(Err::Error(error_position!(&b"xxxx"[..], ErrorKind::Tag)))
);
}
#[test]
fn delimited() {
named!(tag_abc, tag!("abc"));
named!(tag_def, tag!("def"));
named!(tag_ghi, tag!("ghi"));
named!( delimited_abc_def_ghi<&[u8], &[u8]>, delimited!(tag_abc, tag_def, tag_ghi) );
assert_eq!(delimited_abc_def_ghi(&b"abcdefghijkl"[..]), Ok((&b"jkl"[..], &b"def"[..])));
assert_eq!(delimited_abc_def_ghi(&b"ab"[..]), Err(Err::Incomplete(Needed::Size(3))));
assert_eq!(delimited_abc_def_ghi(&b"abcde"[..]), Err(Err::Incomplete(Needed::Size(3))));
assert_eq!(delimited_abc_def_ghi(&b"abcdefgh"[..]), Err(Err::Incomplete(Needed::Size(3))));
assert_eq!(
delimited_abc_def_ghi(&b"xxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
assert_eq!(
delimited_abc_def_ghi(&b"xxxdefghi"[..]),
Err(Err::Error(error_position!(&b"xxxdefghi"[..], ErrorKind::Tag),))
);
assert_eq!(
delimited_abc_def_ghi(&b"abcxxxghi"[..]),
Err(Err::Error(error_position!(&b"xxxghi"[..], ErrorKind::Tag)))
);
assert_eq!(
delimited_abc_def_ghi(&b"abcdefxxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
}
#[test]
fn tuple_test() {
named!(tuple_3<&[u8], (u16, &[u8], &[u8]) >,
tuple!( be_u16 , take!(3), tag!("fg") ) );
assert_eq!(tuple_3(&b"abcdefgh"[..]), Ok((&b"h"[..], (0x6162u16, &b"cde"[..], &b"fg"[..]))));
assert_eq!(tuple_3(&b"abcd"[..]), Err(Err::Incomplete(Needed::Size(3))));
assert_eq!(tuple_3(&b"abcde"[..]), Err(Err::Incomplete(Needed::Size(2))));
assert_eq!(
tuple_3(&b"abcdejk"[..]),
Err(Err::Error(error_position!(&b"jk"[..], ErrorKind::Tag)))
);
}
#[test]
fn do_parse() {
fn ret_int1(i: &[u8]) -> IResult<&[u8], u8> {
Ok((i, 1))
};
fn ret_int2(i: &[u8]) -> IResult<&[u8], u8> {
Ok((i, 2))
};
named!(do_parser<&[u8], (u8, u8)>,
do_parse!(
tag!("abcd") >>
opt!(tag!("abcd")) >>
aa: ret_int1 >>
tag!("efgh") >>
bb: ret_int2 >>
tag!("efgh") >>
(aa, bb)
)
);
assert_eq!(do_parser(&b"abcdabcdefghefghX"[..]), Ok((&b"X"[..], (1, 2))));
assert_eq!(do_parser(&b"abcdefghefghX"[..]), Ok((&b"X"[..], (1, 2))));
assert_eq!(do_parser(&b"abcdab"[..]), Err(Err::Incomplete(Needed::Size(4))));
assert_eq!(do_parser(&b"abcdefghef"[..]), Err(Err::Incomplete(Needed::Size(4))));
}
#[cfg_attr(rustfmt, rustfmt_skip)]
#[test]
fn do_parse_dependency() {
use crate::number::streaming::be_u8;
named!(length_value,
do_parse!(
length: be_u8 >>
bytes: take!(length) >>
(bytes)
)
);
let a = [2u8, 3, 4, 5];
let res_a = [3u8, 4];
assert_eq!(length_value(&a[..]), Ok((&a[3..], &res_a[..])));
let b = [5u8, 3, 4, 5];
assert_eq!(length_value(&b[..]), Err(Err::Incomplete(Needed::Size(5))));
}
}