#[macro_export]
#[deprecated(since="2.0.0", note="please use [`do_parse!`](macro.do_parse.html) instead")]
macro_rules! chain (
($i:expr, $($rest:tt)*) => (
{
chaining_parser!($i, 0usize, $($rest)*)
}
);
);
#[doc(hidden)]
#[macro_export]
macro_rules! chaining_parser (
($i:expr, $consumed:expr, $e:ident ~ $($rest:tt)*) => (
chaining_parser!($i, $consumed, call!($e) ~ $($rest)*);
);
($i:expr, $consumed:expr, $submac:ident!( $($args:tt)* ) ~ $($rest:tt)*) => (
{
match $submac!($i, $($args)*) {
$crate::IResult::Error(e) => $crate::IResult::Error(e),
$crate::IResult::Incomplete($crate::Needed::Unknown) =>
$crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::IResult::Incomplete($crate::Needed::Size(i)) => {
let (needed,overflowed) = $consumed.overflowing_add(i);
match overflowed {
true => $crate::IResult::Incomplete($crate::Needed::Unknown),
false => $crate::IResult::Incomplete($crate::Needed::Size(needed)),
}
},
$crate::IResult::Done(i,_) => {
chaining_parser!(i,
$consumed + ($crate::InputLength::input_len(&($i)) -
$crate::InputLength::input_len(&i)), $($rest)*)
}
}
}
);
($i:expr, $consumed:expr, $e:ident ? ~ $($rest:tt)*) => (
chaining_parser!($i, $consumed, call!($e) ? ~ $($rest)*);
);
($i:expr, $consumed:expr, $submac:ident!( $($args:tt)* ) ? ~ $($rest:tt)*) => (
{
let res = $submac!($i, $($args)*);
if let $crate::IResult::Incomplete(inc) = res {
match inc {
$crate::Needed::Unknown =>
$crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::Needed::Size(i) => {
let (needed,overflowed) = $consumed.overflowing_add(i);
match overflowed {
true => $crate::IResult::Incomplete($crate::Needed::Unknown),
false => $crate::IResult::Incomplete($crate::Needed::Size(needed)),
}
},
}
} else {
let input = if let $crate::IResult::Done(i,_) = res {
i
} else {
$i
};
chaining_parser!(input,
$consumed + ($crate::InputLength::input_len(&($i)) -
$crate::InputLength::input_len(&input)), $($rest)*)
}
}
);
($i:expr, $consumed:expr, $field:ident : $e:ident ~ $($rest:tt)*) => (
chaining_parser!($i, $consumed, $field: call!($e) ~ $($rest)*);
);
($i:expr, $consumed:expr, $field:ident : $submac:ident!( $($args:tt)* ) ~ $($rest:tt)*) => (
{
match $submac!($i, $($args)*) {
$crate::IResult::Error(e) => $crate::IResult::Error(e),
$crate::IResult::Incomplete($crate::Needed::Unknown) =>
$crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::IResult::Incomplete($crate::Needed::Size(i)) => {
let (needed,overflowed) = $consumed.overflowing_add(i);
match overflowed {
true => $crate::IResult::Incomplete($crate::Needed::Unknown),
false => $crate::IResult::Incomplete($crate::Needed::Size(needed)),
}
},
$crate::IResult::Done(i,o) => {
let $field = o;
chaining_parser!(i,
$consumed + ($crate::InputLength::input_len(&($i)) -
$crate::InputLength::input_len(&i)), $($rest)*)
}
}
}
);
($i:expr, $consumed:expr, mut $field:ident : $e:ident ~ $($rest:tt)*) => (
chaining_parser!($i, $consumed, mut $field: call!($e) ~ $($rest)*);
);
($i:expr, $consumed:expr, mut $field:ident : $submac:ident!( $($args:tt)* ) ~ $($rest:tt)*) => (
{
match $submac!($i, $($args)*) {
$crate::IResult::Error(e) => $crate::IResult::Error(e),
$crate::IResult::Incomplete($crate::Needed::Unknown) =>
$crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::IResult::Incomplete($crate::Needed::Size(i)) => {
let (needed,overflowed) = $consumed.overflowing_add(i);
match overflowed {
true => $crate::IResult::Incomplete($crate::Needed::Unknown),
false => $crate::IResult::Incomplete($crate::Needed::Size(needed)),
}
},
$crate::IResult::Done(i,o) => {
let mut $field = o;
chaining_parser!(i,
$consumed + $crate::InputLength::input_len(&($i)) -
$crate::InputLength::input_len(&i), $($rest)*)
}
}
}
);
($i:expr, $consumed:expr, $field:ident : $e:ident ? ~ $($rest:tt)*) => (
chaining_parser!($i, $consumed, $field : call!($e) ? ~ $($rest)*);
);
($i:expr, $consumed:expr, $field:ident : $submac:ident!( $($args:tt)* ) ? ~ $($rest:tt)*) => (
{
let res = $submac!($i, $($args)*);
if let $crate::IResult::Incomplete(inc) = res {
match inc {
$crate::Needed::Unknown =>
$crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::Needed::Size(i) => {
let (needed,overflowed) = $consumed.overflowing_add(i);
match overflowed {
true => $crate::IResult::Incomplete($crate::Needed::Unknown),
false => $crate::IResult::Incomplete($crate::Needed::Size(needed)),
}
},
}
} else {
let ($field,input) = if let $crate::IResult::Done(i,o) = res {
(::std::option::Option::Some(o),i)
} else {
(::std::option::Option::None,$i)
};
chaining_parser!(input,
$consumed + $crate::InputLength::input_len(&($i)) -
$crate::InputLength::input_len(&input), $($rest)*)
}
}
);
($i:expr, $consumed:expr, mut $field:ident : $e:ident ? ~ $($rest:tt)*) => (
chaining_parser!($i, $consumed, mut $field : call!($e) ? ~ $($rest)*);
);
($i:expr, $consumed:expr, mut $field:ident : $submac:ident!( $($args:tt)* ) ? ~ $($rest:tt)*) => (
{
let res = $submac!($i, $($args)*);
if let $crate::IResult::Incomplete(inc) = res {
match inc {
$crate::Needed::Unknown =>
$crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::Needed::Size(i) => {
let (needed,overflowed) = $consumed.overflowing_add(i);
match overflowed {
true => $crate::IResult::Incomplete($crate::Needed::Unknown),
false => $crate::IResult::Incomplete($crate::Needed::Size(needed)),
}
},
}
} else {
let (mut $field,input) = if let $crate::IResult::Done(i,o) = res {
(::std::option::Option::Some(o),i)
} else {
(::std::option::Option::None,$i)
};
chaining_parser!(input,
$consumed + $crate::InputLength::input_len(&($i)) -
$crate::InputLength::input_len(&input), $($rest)*)
}
}
);
($i:expr, $consumed:expr, $e:ident, $assemble:expr) => (
chaining_parser!($i, $consumed, call!($e), $assemble);
);
($i:expr, $consumed:expr, $submac:ident!( $($args:tt)* ), $assemble:expr) => (
match $submac!($i, $($args)*) {
$crate::IResult::Error(e) => $crate::IResult::Error(e),
$crate::IResult::Incomplete($crate::Needed::Unknown) =>
$crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::IResult::Incomplete($crate::Needed::Size(i)) => {
let (needed,overflowed) = $consumed.overflowing_add(i);
match overflowed {
true => $crate::IResult::Incomplete($crate::Needed::Unknown),
false => $crate::IResult::Incomplete($crate::Needed::Size(needed)),
}
},
$crate::IResult::Done(i,_) => {
$crate::IResult::Done(i, $assemble())
}
}
);
($i:expr, $consumed:expr, $e:ident ?, $assemble:expr) => (
chaining_parser!($i, $consumed, call!($e) ?, $assemble);
);
($i:expr, $consumed:expr, $submac:ident!( $($args:tt)* ) ?, $assemble:expr) => ({
let res = $submac!($i, $($args)*);
if let $crate::IResult::Incomplete(inc) = res {
match inc {
$crate::Needed::Unknown =>
$crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::Needed::Size(i) => {
let (needed,overflowed) = $consumed.overflowing_add(i);
match overflowed {
true => $crate::IResult::Incomplete($crate::Needed::Unknown),
false => $crate::IResult::Incomplete($crate::Needed::Size(needed)),
}
},
}
} else {
let input = if let $crate::IResult::Done(i,_) = res {
i
} else {
$i
};
$crate::IResult::Done(input, $assemble())
}
});
($i:expr, $consumed:expr, $field:ident : $e:ident, $assemble:expr) => (
chaining_parser!($i, $consumed, $field: call!($e), $assemble);
);
($i:expr, $consumed:expr, $field:ident : $submac:ident!( $($args:tt)* ), $assemble:expr) => (
match $submac!($i, $($args)*) {
$crate::IResult::Error(e) => $crate::IResult::Error(e),
$crate::IResult::Incomplete($crate::Needed::Unknown) =>
$crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::IResult::Incomplete($crate::Needed::Size(i)) => {
let (needed,overflowed) = $consumed.overflowing_add(i);
match overflowed {
true => $crate::IResult::Incomplete($crate::Needed::Unknown),
false => $crate::IResult::Incomplete($crate::Needed::Size(needed)),
}
},
$crate::IResult::Done(i,o) => {
let $field = o;
$crate::IResult::Done(i, $assemble())
}
}
);
($i:expr, $consumed:expr, mut $field:ident : $e:ident, $assemble:expr) => (
chaining_parser!($i, $consumed, mut $field: call!($e), $assemble);
);
($i:expr, $consumed:expr, mut $field:ident : $submac:ident!( $($args:tt)* ), $assemble:expr) => (
match $submac!($i, $($args)*) {
$crate::IResult::Error(e) => $crate::IResult::Error(e),
$crate::IResult::Incomplete($crate::Needed::Unknown) =>
$crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::IResult::Incomplete($crate::Needed::Size(i)) => {
let (needed,overflowed) = $consumed.overflowing_add(i);
match overflowed {
true => $crate::IResult::Incomplete($crate::Needed::Unknown),
false => $crate::IResult::Incomplete($crate::Needed::Size(needed)),
}
},
$crate::IResult::Done(i,o) => {
let mut $field = o;
$crate::IResult::Done(i, $assemble())
}
}
);
($i:expr, $consumed:expr, $field:ident : $e:ident ? , $assemble:expr) => (
chaining_parser!($i, $consumed, $field : call!($e) ? , $assemble);
);
($i:expr, $consumed:expr, $field:ident : $submac:ident!( $($args:tt)* ) ? , $assemble:expr) => ({
let res = $submac!($i, $($args)*);
if let $crate::IResult::Incomplete(inc) = res {
match inc {
$crate::Needed::Unknown =>
$crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::Needed::Size(i) => {
let (needed,overflowed) = $consumed.overflowing_add(i);
match overflowed {
true => $crate::IResult::Incomplete($crate::Needed::Unknown),
false => $crate::IResult::Incomplete($crate::Needed::Size(needed)),
}
},
}
} else {
let ($field,input) = if let $crate::IResult::Done(i,o) = res {
(::std::option::Option::Some(o), i)
} else {
(::std::option::Option::None, $i)
};
$crate::IResult::Done(input, $assemble())
}
});
($i:expr, $consumed:expr, mut $field:ident : $e:ident ? , $assemble:expr) => (
chaining_parser!($i, $consumed, $field : call!($e) ? , $assemble);
);
($i:expr, $consumed:expr, mut $field:ident : $submac:ident!( $($args:tt)* ) ? , $assemble:expr) => ({
let res = $submac!($i, $($args)*);
if let $crate::IResult::Incomplete(inc) = res {
match inc {
$crate::Needed::Unknown =>
$crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::Needed::Size(i) => {
let (needed,overflowed) = $consumed.overflowing_add(i);
match overflowed {
true => $crate::IResult::Incomplete($crate::Needed::Unknown),
false => $crate::IResult::Incomplete($crate::Needed::Size(needed)),
}
},
}
} else {
let (mut $field,input) = if let $crate::IResult::Done(i,o) = res {
(::std::option::Option::Some(o), i)
} else {
(::std::option::Option::None, $i)
};
$crate::IResult::Done(input, $assemble())
}
});
($i:expr, $consumed:expr, $assemble:expr) => (
$crate::IResult::Done($i, $assemble())
)
);
#[macro_export]
macro_rules! tuple (
($i:expr, $($rest:tt)*) => (
{
tuple_parser!($i, 0usize, (), $($rest)*)
}
);
);
#[doc(hidden)]
#[macro_export]
macro_rules! tuple_parser (
($i:expr, $consumed:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => (
tuple_parser!($i, $consumed, ($($parsed),*), call!($e), $($rest)*);
);
($i:expr, $consumed:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => (
{
match $submac!($i, $($args)*) {
$crate::IResult::Error(e) =>
$crate::IResult::Error(e),
$crate::IResult::Incomplete($crate::Needed::Unknown) =>
$crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::IResult::Incomplete($crate::Needed::Size(i)) => {
let (needed,overflowed) = $consumed.overflowing_add(i);
match overflowed {
true => $crate::IResult::Incomplete($crate::Needed::Unknown),
false => $crate::IResult::Incomplete($crate::Needed::Size(needed)),
}
},
$crate::IResult::Done(i,o) => {
tuple_parser!(i,
$consumed + ($crate::InputLength::input_len(&($i)) -
$crate::InputLength::input_len(&i)), (o), $($rest)*)
}
}
}
);
($i:expr, $consumed:expr, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => (
{
match $submac!($i, $($args)*) {
$crate::IResult::Error(e) =>
$crate::IResult::Error(e),
$crate::IResult::Incomplete($crate::Needed::Unknown) =>
$crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::IResult::Incomplete($crate::Needed::Size(i)) => {
let (needed,overflowed) = $consumed.overflowing_add(i);
match overflowed {
true => $crate::IResult::Incomplete($crate::Needed::Unknown),
false => $crate::IResult::Incomplete($crate::Needed::Size(needed)),
}
},
$crate::IResult::Done(i,o) => {
tuple_parser!(i,
$consumed + ($crate::InputLength::input_len(&($i)) -
$crate::InputLength::input_len(&i)), ($($parsed)* , o), $($rest)*)
}
}
}
);
($i:expr, $consumed:expr, ($($parsed:tt),*), $e:ident) => (
tuple_parser!($i, $consumed, ($($parsed),*), call!($e));
);
($i:expr, $consumed:expr, (), $submac:ident!( $($args:tt)* )) => (
{
match $submac!($i, $($args)*) {
$crate::IResult::Error(e) =>
$crate::IResult::Error(e),
$crate::IResult::Incomplete($crate::Needed::Unknown) =>
$crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::IResult::Incomplete($crate::Needed::Size(i)) => {
let (needed,overflowed) = $consumed.overflowing_add(i);
match overflowed {
true => $crate::IResult::Incomplete($crate::Needed::Unknown),
false => $crate::IResult::Incomplete($crate::Needed::Size(needed)),
}
},
$crate::IResult::Done(i,o) => {
$crate::IResult::Done(i, (o))
}
}
}
);
($i:expr, $consumed:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => (
{
match $submac!($i, $($args)*) {
$crate::IResult::Error(e) =>
$crate::IResult::Error(e),
$crate::IResult::Incomplete($crate::Needed::Unknown) =>
$crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::IResult::Incomplete($crate::Needed::Size(i)) => {
let (needed,overflowed) = $consumed.overflowing_add(i);
match overflowed {
true => $crate::IResult::Incomplete($crate::Needed::Unknown),
false => $crate::IResult::Incomplete($crate::Needed::Size(needed)),
}
},
$crate::IResult::Done(i,o) => {
$crate::IResult::Done(i, ($($parsed),* , o))
}
}
}
);
($i:expr, $consumed:expr, ($($parsed:expr),*)) => (
{
$crate::IResult::Done($i, ($($parsed),*))
}
);
);
#[macro_export]
macro_rules! pair(
($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
{
tuple!($i, $submac!($($args)*), $submac2!($($args2)*))
}
);
($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => (
pair!($i, $submac!($($args)*), call!($g));
);
($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => (
pair!($i, call!($f), $submac!($($args)*));
);
($i:expr, $f:expr, $g:expr) => (
pair!($i, call!($f), call!($g));
);
);
#[macro_export]
macro_rules! separated_pair(
($i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)+) => (
{
match tuple_parser!($i, 0usize, (), $submac!($($args)*), $($rest)*) {
$crate::IResult::Error(a) => $crate::IResult::Error(a),
$crate::IResult::Incomplete(i) => $crate::IResult::Incomplete(i),
$crate::IResult::Done(i1, (o1, _, o2)) => {
$crate::IResult::Done(i1, (o1, o2))
}
}
}
);
($i:expr, $f:expr, $($rest:tt)+) => (
separated_pair!($i, call!($f), $($rest)*);
);
);
#[macro_export]
macro_rules! preceded(
($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
{
match tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) {
$crate::IResult::Error(a) => $crate::IResult::Error(a),
$crate::IResult::Incomplete(i) => $crate::IResult::Incomplete(i),
$crate::IResult::Done(remaining, (_,o)) => {
$crate::IResult::Done(remaining, o)
}
}
}
);
($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => (
preceded!($i, $submac!($($args)*), call!($g));
);
($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => (
preceded!($i, call!($f), $submac!($($args)*));
);
($i:expr, $f:expr, $g:expr) => (
preceded!($i, call!($f), call!($g));
);
);
#[macro_export]
macro_rules! terminated(
($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
{
match tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) {
$crate::IResult::Error(a) => $crate::IResult::Error(a),
$crate::IResult::Incomplete(i) => $crate::IResult::Incomplete(i),
$crate::IResult::Done(remaining, (o,_)) => {
$crate::IResult::Done(remaining, o)
}
}
}
);
($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => (
terminated!($i, $submac!($($args)*), call!($g));
);
($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => (
terminated!($i, call!($f), $submac!($($args)*));
);
($i:expr, $f:expr, $g:expr) => (
terminated!($i, call!($f), call!($g));
);
);
#[macro_export]
macro_rules! delimited(
($i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)+) => (
{
match tuple_parser!($i, 0usize, (), $submac!($($args)*), $($rest)*) {
$crate::IResult::Error(a) => $crate::IResult::Error(a),
$crate::IResult::Incomplete(i) => $crate::IResult::Incomplete(i),
$crate::IResult::Done(i1, (_, o, _)) => {
$crate::IResult::Done(i1, o)
}
}
}
);
($i:expr, $f:expr, $($rest:tt)+) => (
delimited!($i, call!($f), $($rest)*);
);
);
#[macro_export]
macro_rules! do_parse (
(__impl $i:expr, $consumed:expr, ( $($rest:expr),* )) => (
$crate::IResult::Done($i, ( $($rest),* ))
);
(__impl $i:expr, $consumed:expr, $e:ident >> $($rest:tt)*) => (
do_parse!(__impl $i, $consumed, call!($e) >> $($rest)*);
);
(__impl $i:expr, $consumed:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => (
{
match $submac!($i, $($args)*) {
$crate::IResult::Error(e) => $crate::IResult::Error(e),
$crate::IResult::Incomplete($crate::Needed::Unknown) =>
$crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::IResult::Incomplete($crate::Needed::Size(i)) => {
let (needed,overflowed) = $consumed.overflowing_add(i);
match overflowed {
true => $crate::IResult::Incomplete($crate::Needed::Unknown),
false => $crate::IResult::Incomplete($crate::Needed::Size(needed)),
}
},
$crate::IResult::Done(i,_) => {
do_parse!(__impl i,
$consumed + ($crate::InputLength::input_len(&($i)) -
$crate::InputLength::input_len(&i)), $($rest)*)
},
}
}
);
(__impl $i:expr, $consumed:expr, $field:ident : $e:ident >> $($rest:tt)*) => (
do_parse!(__impl $i, $consumed, $field: call!($e) >> $($rest)*);
);
(__impl $i:expr, $consumed:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => (
{
match $submac!($i, $($args)*) {
$crate::IResult::Error(e) => $crate::IResult::Error(e),
$crate::IResult::Incomplete($crate::Needed::Unknown) =>
$crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::IResult::Incomplete($crate::Needed::Size(i)) => {
let (needed,overflowed) = $consumed.overflowing_add(i);
match overflowed {
true => $crate::IResult::Incomplete($crate::Needed::Unknown),
false => $crate::IResult::Incomplete($crate::Needed::Size(needed)),
}
},
$crate::IResult::Done(i,o) => {
let $field = o;
do_parse!(__impl i,
$consumed + ($crate::InputLength::input_len(&($i)) -
$crate::InputLength::input_len(&i)), $($rest)*)
},
}
}
);
(__impl $i:expr, $consumed:expr, $e:ident >> ( $($rest:tt)* )) => (
do_parse!(__impl $i, $consumed, call!($e) >> ( $($rest)* ));
);
(__impl $i:expr, $consumed:expr, $submac:ident!( $($args:tt)* ) >> ( $($rest:tt)* )) => (
match $submac!($i, $($args)*) {
$crate::IResult::Error(e) => $crate::IResult::Error(e),
$crate::IResult::Incomplete($crate::Needed::Unknown) =>
$crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::IResult::Incomplete($crate::Needed::Size(i)) => {
let (needed,overflowed) = $consumed.overflowing_add(i);
match overflowed {
true => $crate::IResult::Incomplete($crate::Needed::Unknown),
false => $crate::IResult::Incomplete($crate::Needed::Size(needed)),
}
},
$crate::IResult::Done(i,_) => {
$crate::IResult::Done(i, ( $($rest)* ))
},
}
);
(__impl $i:expr, $consumed:expr, $field:ident : $e:ident >> ( $($rest:tt)* )) => (
do_parse!(__impl $i, $consumed, $field: call!($e) >> ( $($rest)* ) );
);
(__impl $i:expr, $consumed:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> ( $($rest:tt)* )) => (
match $submac!($i, $($args)*) {
$crate::IResult::Error(e) => $crate::IResult::Error(e),
$crate::IResult::Incomplete($crate::Needed::Unknown) =>
$crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::IResult::Incomplete($crate::Needed::Size(i)) => {
let (needed,overflowed) = $consumed.overflowing_add(i);
match overflowed {
true => $crate::IResult::Incomplete($crate::Needed::Unknown),
false => $crate::IResult::Incomplete($crate::Needed::Size(needed)),
}
},
$crate::IResult::Done(i,o) => {
let $field = o;
$crate::IResult::Done(i, ( $($rest)* ))
},
}
);
($i:expr, $($rest:tt)*) => (
{
do_parse!(__impl $i, 0usize, $($rest)*)
}
);
);
#[cfg(test)]
mod tests {
use internal::{Needed,IResult};
use internal::IResult::*;
use util::ErrorKind;
use nom::be_u16;
#[cfg(feature = "verbose-errors")]
use verbose_errors::Err;
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 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: $crate::IResult<_,_> = if reduced != b {
$crate::IResult::Error(error_position!($crate::ErrorKind::Tag, $i))
} else if m < blen {
$crate::IResult::Incomplete($crate::Needed::Size(blen))
} else {
$crate::IResult::Done(&$i[blen..], reduced)
};
res
}
);
);
macro_rules! take (
($i:expr, $count:expr) => (
{
let cnt = $count as usize;
let res:$crate::IResult<&[u8],&[u8]> = if $i.len() < cnt {
$crate::IResult::Incomplete($crate::Needed::Size(cnt))
} else {
$crate::IResult::Done(&$i[cnt..],&$i[0..cnt])
};
res
}
);
);
#[derive(PartialEq,Eq,Debug)]
struct B {
a: u8,
b: u8
}
#[test]
fn chain2() {
fn ret_int1(i:&[u8]) -> IResult<&[u8], u8> { Done(i,1) };
fn ret_int2(i:&[u8]) -> IResult<&[u8], u8> { Done(i,2) };
named!(chain_parser<&[u8],B>,
chain!(
tag!("abcd") ~
tag!("abcd")? ~
aa: ret_int1 ~
tag!("efgh") ~
bb: ret_int2 ~
tag!("efgh") ,
||{B{a: aa, b: bb}}
)
);
assert_eq!(chain_parser(&b"abcdabcdefghefghX"[..]), Done(&b"X"[..], B{a: 1, b: 2}));
assert_eq!(chain_parser(&b"abcdefghefghX"[..]), Done(&b"X"[..], B{a: 1, b: 2}));
assert_eq!(chain_parser(&b"abcdab"[..]), Incomplete(Needed::Size(8)));
assert_eq!(chain_parser(&b"abcdefghef"[..]), Incomplete(Needed::Size(12)));
}
#[test]
fn nested_chain() {
fn ret_int1(i:&[u8]) -> IResult<&[u8], u8> { Done(i,1) };
fn ret_int2(i:&[u8]) -> IResult<&[u8], u8> { Done(i,2) };
named!(chain_parser<&[u8],B>,
chain!(
chain!(
tag!("abcd") ~
tag!("abcd")? ,
|| {}
) ~
aa: ret_int1 ~
tag!("efgh") ~
bb: ret_int2 ~
tag!("efgh") ,
||{B{a: aa, b: bb}}
)
);
assert_eq!(chain_parser(&b"abcdabcdefghefghX"[..]), Done(&b"X"[..], B{a: 1, b: 2}));
assert_eq!(chain_parser(&b"abcdefghefghX"[..]), Done(&b"X"[..], B{a: 1, b: 2}));
assert_eq!(chain_parser(&b"abcdab"[..]), Incomplete(Needed::Size(8)));
assert_eq!(chain_parser(&b"abcdefghef"[..]), Incomplete(Needed::Size(12)));
}
#[derive(PartialEq,Eq,Debug)]
struct C {
a: u8,
b: Option<u8>
}
#[test]
fn chain_mut() {
fn ret_b1_2(i:&[u8]) -> IResult<&[u8], B> { Done(i,B{a:1,b:2}) };
named!(f<&[u8],B>,
chain!(
tag!("abcd") ~
tag!("abcd")? ~
tag!("efgh") ~
mut bb: ret_b1_2 ~
tag!("efgh") ,
||{
bb.b = 3;
bb
}
)
);
let r = f(&b"abcdabcdefghefghX"[..]);
assert_eq!(r, Done(&b"X"[..], B{a: 1, b: 3}));
}
#[test]
fn chain_opt() {
named!(y, tag!("efgh"));
fn ret_int1(i:&[u8]) -> IResult<&[u8], u8> { Done(i,1) };
named!(ret_y<&[u8], u8>, map!(y, |_| 2));
named!(chain_parser<&[u8],C>,
chain!(
tag!("abcd") ~
aa: ret_int1 ~
bb: ret_y? ,
||{C{a: aa, b: bb}}
)
);
assert_eq!(chain_parser(&b"abcdefghX"[..]), Done(&b"X"[..], C{a: 1, b: Some(2)}));
assert_eq!(chain_parser(&b"abcdWXYZ"[..]), Done(&b"WXYZ"[..], C{a: 1, b: None}));
assert_eq!(chain_parser(&b"abcdX"[..]), Done(&b"X"[..], C{ a: 1, b: None }));
assert_eq!(chain_parser(&b"abcdef"[..]), Incomplete(Needed::Size(8)));
}
#[cfg(feature = "verbose-errors")]
use util::{error_to_list, add_error_pattern, print_error};
#[cfg(feature = "verbose-errors")]
fn error_to_string<P>(e: &Err<P>) -> &'static str {
let v:Vec<ErrorKind> = error_to_list(e);
if &v[..] == [ErrorKind::Custom(42),ErrorKind::Tag] {
"missing `ijkl` tag"
} else if &v[..] == [ErrorKind::Custom(42), ErrorKind::Custom(128), ErrorKind::Tag] {
"missing `mnop` tag after `ijkl`"
} else {
"unrecognized error"
}
}
#[cfg(feature = "verbose-errors")]
use std::collections;
#[cfg(feature = "verbose-errors")]
#[test]
fn err() {
named!(err_test, alt!(
tag!("abcd") |
preceded!(tag!("efgh"), return_error!(ErrorKind::Custom(42),
do_parse!(
tag!("ijkl") >>
res: return_error!(ErrorKind::Custom(128), 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, Error(error_node_position!(ErrorKind::Custom(42), blah, error_position!(ErrorKind::Tag, blah))));
assert_eq!(res_b, Error(error_node_position!(ErrorKind::Custom(42), &b"ijklblah"[..], error_node_position!(ErrorKind::Custom(128), blah, error_position!(ErrorKind::Tag, blah)))));
assert_eq!(res_c, Done(&b""[..], &b"mnop"[..]));
let mut err_map = collections::HashMap::new();
assert!(add_error_pattern(&mut err_map, err_test(&b"efghpouet"[..]), "missing `ijkl` tag"));
assert!(add_error_pattern(&mut err_map, err_test(&b"efghijklpouet"[..]), "missing `mnop` tag after `ijkl`"));
let res_a2 = res_a.clone();
match res_a {
Error(e) => {
assert_eq!(error_to_list(&e), [ErrorKind::Custom(42), ErrorKind::Tag]);
assert_eq!(error_to_string(&e), "missing `ijkl` tag");
assert_eq!(err_map.get(&error_to_list(&e)), Some(&"missing `ijkl` tag"));
},
_ => panic!()
};
let res_b2 = res_b.clone();
match res_b {
Error(e) => {
assert_eq!(error_to_list(&e), [ErrorKind::Custom(42), ErrorKind::Custom(128), ErrorKind::Tag]);
assert_eq!(error_to_string(&e), "missing `mnop` tag after `ijkl`");
assert_eq!(err_map.get(&error_to_list(&e)), Some(&"missing `mnop` tag after `ijkl`"));
},
_ => panic!()
};
print_error(a, res_a2);
print_error(b, res_b2);
}
#[allow(unused_variables)]
#[test]
fn add_err() {
named!(err_test,
preceded!(tag!("efgh"), add_return_error!(ErrorKind::Custom(42),
do_parse!(
tag!("ijkl") >>
res: add_return_error!(ErrorKind::Custom(128), 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, Error(error_node_position!(ErrorKind::Custom(42), blah, error_position!(ErrorKind::Tag, blah))));
assert_eq!(res_b, Error(error_node_position!(ErrorKind::Custom(42), &b"ijklblah"[..], error_node_position!(ErrorKind::Custom(128), blah, error_position!(ErrorKind::Tag, blah)))));
assert_eq!(res_c, Done(&b""[..], &b"mnop"[..]));
}
#[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, Error(error_position!(ErrorKind::Complete, &b"mn"[..])));
}
#[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"[..]), Done(&b"ghijkl"[..], (&b"abc"[..], &b"def"[..])));
assert_eq!(pair_abc_def(&b"ab"[..]), Incomplete(Needed::Size(3)));
assert_eq!(pair_abc_def(&b"abcd"[..]), Incomplete(Needed::Size(6)));
assert_eq!(pair_abc_def(&b"xxx"[..]), Error(error_position!(ErrorKind::Tag, &b"xxx"[..])));
assert_eq!(pair_abc_def(&b"xxxdef"[..]), Error(error_position!(ErrorKind::Tag, &b"xxxdef"[..])));
assert_eq!(pair_abc_def(&b"abcxxx"[..]), Error(error_position!(ErrorKind::Tag, &b"xxx"[..])));
}
#[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"[..]), Done(&b"ghijkl"[..], (&b"abc"[..], &b"def"[..])));
assert_eq!(sep_pair_abc_def(&b"ab"[..]), Incomplete(Needed::Size(3)));
assert_eq!(sep_pair_abc_def(&b"abc,d"[..]), Incomplete(Needed::Size(7)));
assert_eq!(sep_pair_abc_def(&b"xxx"[..]), Error(error_position!(ErrorKind::Tag, &b"xxx"[..])));
assert_eq!(sep_pair_abc_def(&b"xxx,def"[..]), Error(error_position!(ErrorKind::Tag, &b"xxx,def"[..])));
assert_eq!(sep_pair_abc_def(&b"abc,xxx"[..]), Error(error_position!(ErrorKind::Tag, &b"xxx"[..])));
}
#[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"[..]), Done(&b"ijkl"[..], &b"efgh"[..]));
assert_eq!(preceded_abcd_efgh(&b"ab"[..]), Incomplete(Needed::Size(4)));
assert_eq!(preceded_abcd_efgh(&b"abcde"[..]), Incomplete(Needed::Size(8)));
assert_eq!(preceded_abcd_efgh(&b"xxx"[..]), Error(error_position!(ErrorKind::Tag, &b"xxx"[..])));
assert_eq!(preceded_abcd_efgh(&b"xxxxdef"[..]), Error(error_position!(ErrorKind::Tag, &b"xxxxdef"[..])));
assert_eq!(preceded_abcd_efgh(&b"abcdxxx"[..]), Error(error_position!(ErrorKind::Tag, &b"xxx"[..])));
}
#[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"[..]), Done(&b"ijkl"[..], &b"abcd"[..]));
assert_eq!(terminated_abcd_efgh(&b"ab"[..]), Incomplete(Needed::Size(4)));
assert_eq!(terminated_abcd_efgh(&b"abcde"[..]), Incomplete(Needed::Size(8)));
assert_eq!(terminated_abcd_efgh(&b"xxx"[..]), Error(error_position!(ErrorKind::Tag, &b"xxx"[..])));
assert_eq!(terminated_abcd_efgh(&b"xxxxdef"[..]), Error(error_position!(ErrorKind::Tag, &b"xxxxdef"[..])));
assert_eq!(terminated_abcd_efgh(&b"abcdxxxx"[..]), Error(error_position!(ErrorKind::Tag, &b"xxxx"[..])));
}
#[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"[..]), Done(&b"jkl"[..], &b"def"[..]));
assert_eq!(delimited_abc_def_ghi(&b"ab"[..]), Incomplete(Needed::Size(3)));
assert_eq!(delimited_abc_def_ghi(&b"abcde"[..]), Incomplete(Needed::Size(6)));
assert_eq!(delimited_abc_def_ghi(&b"abcdefgh"[..]), Incomplete(Needed::Size(9)));
assert_eq!(delimited_abc_def_ghi(&b"xxx"[..]), Error(error_position!(ErrorKind::Tag, &b"xxx"[..])));
assert_eq!(delimited_abc_def_ghi(&b"xxxdefghi"[..]), Error(error_position!(ErrorKind::Tag, &b"xxxdefghi"[..])));
assert_eq!(delimited_abc_def_ghi(&b"abcxxxghi"[..]), Error(error_position!(ErrorKind::Tag, &b"xxxghi"[..])));
assert_eq!(delimited_abc_def_ghi(&b"abcdefxxx"[..]), Error(error_position!(ErrorKind::Tag, &b"xxx"[..])));
}
#[test]
fn chain_incomplete() {
let res = chain!(&b"abcdefgh"[..],
a: take!(4) ~
b: take!(8),
||{(a,b )}
);
assert_eq!(res, IResult::Incomplete(Needed::Size(12)));
}
#[test]
fn tuple_test() {
named!(tuple_3<&[u8], (u16, &[u8], &[u8]) >,
tuple!( be_u16 , take!(3), tag!("fg") ) );
assert_eq!(tuple_3(&b"abcdefgh"[..]), Done(&b"h"[..], (0x6162u16, &b"cde"[..], &b"fg"[..])));
assert_eq!(tuple_3(&b"abcd"[..]), Incomplete(Needed::Size(5)));
assert_eq!(tuple_3(&b"abcde"[..]), Incomplete(Needed::Size(7)));
assert_eq!(tuple_3(&b"abcdejk"[..]), Error(error_position!(ErrorKind::Tag, &b"jk"[..])));
}
#[test]
fn do_parse() {
fn ret_int1(i:&[u8]) -> IResult<&[u8], u8> { Done(i,1) };
fn ret_int2(i:&[u8]) -> IResult<&[u8], u8> { Done(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"[..]), Done(&b"X"[..], (1, 2)));
assert_eq!(do_parser(&b"abcdefghefghX"[..]), Done(&b"X"[..], (1, 2)));
assert_eq!(do_parser(&b"abcdab"[..]), Incomplete(Needed::Size(8)));
assert_eq!(do_parser(&b"abcdefghef"[..]), Incomplete(Needed::Size(12)));
}
#[test]
fn do_parse_dependency() {
use nom::be_u8;
named!(length_value,
do_parse!(
length: be_u8 >>
bytes: take!(length) >>
(bytes)
)
);
let a: Vec<u8> = vec!(2, 3, 4, 5);
let res_a: Vec<u8> = vec!(3, 4);
assert_eq!(length_value(&a[..]), Done(&a[3..], &res_a[..]));
let b: Vec<u8> = vec!(5, 3, 4, 5);
assert_eq!(length_value(&b[..]), Incomplete(Needed::Size(6)));
}
}