use util::ErrorKind;
use internal::{IResult, IError};
use internal::IResult::*;
use std::boxed::Box;
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum Err<P,E=u32>{
Code(ErrorKind<E>),
Node(ErrorKind<E>, Box<Err<P,E>>),
Position(ErrorKind<E>, P),
NodePosition(ErrorKind<E>, P, Box<Err<P,E>>)
}
impl<I,O,E> IResult<I,O,E> {
#[inline]
pub fn map_err<N, F>(self, f: F) -> IResult<I, O, N>
where F: FnOnce(Err<I, E>) -> Err<I, N> {
match self {
Error(e) => Error(f(e)),
Incomplete(n) => Incomplete(n),
Done(i, o) => Done(i, o),
}
}
pub fn unwrap_err(self) -> Err<I, E> {
match self {
Error(e) => e,
Done(_, _) => panic!("unwrap_err() called on an IResult that is Done"),
Incomplete(_) => panic!("unwrap_err() called on an IResult that is Incomplete"),
}
}
pub fn to_full_result(self) -> Result<O, IError<I,E>> {
match self {
Done(_, o) => Ok(o),
Incomplete(n) => Err(IError::Incomplete(n)),
Error(e) => Err(IError::Error(e))
}
}
pub fn to_result(self) -> Result<O, Err<I,E>> {
match self {
Done(_, o) => Ok(o),
Error(e) => Err(e),
Incomplete(_) => panic!("to_result() called on an IResult that is Incomplete")
}
}
}
#[cfg(not(feature = "core"))]
use std::any::Any;
#[cfg(not(feature = "core"))]
use std::{error,fmt};
#[cfg(not(feature = "core"))]
use std::fmt::Debug;
#[cfg(not(feature = "core"))]
impl<P:Debug+Any,E:Debug+Any> error::Error for Err<P,E> {
fn description(&self) -> &str {
let kind = match *self {
Err::Code(ref e) | Err::Node(ref e, _) | Err::Position(ref e, _) | Err::NodePosition(ref e, _, _) => e
};
kind.description()
}
}
#[cfg(not(feature = "core"))]
impl<P:fmt::Debug,E:fmt::Debug> fmt::Display for Err<P,E> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Err::Code(ref e) | Err::Node(ref e, _) => {
write!(f, "{:?}", e)
},
Err::Position(ref e, ref p) | Err::NodePosition(ref e, ref p, _) => {
write!(f, "{:?}:{:?}", p, e)
}
}
}
}
#[macro_export]
macro_rules! fix_error (
($i:expr, $t:ty, $submac:ident!( $($args:tt)* )) => (
{
match $submac!($i, $($args)*) {
$crate::IResult::Incomplete(x) => $crate::IResult::Incomplete(x),
$crate::IResult::Done(i, o) => $crate::IResult::Done(i, o),
$crate::IResult::Error(e) => {
let err = match e {
$crate::Err::Code($crate::ErrorKind::Custom(_)) |
$crate::Err::Node($crate::ErrorKind::Custom(_), _) => {
let e: $crate::ErrorKind<$t> = $crate::ErrorKind::Fix;
$crate::Err::Code(e)
},
$crate::Err::Position($crate::ErrorKind::Custom(_), p) |
$crate::Err::NodePosition($crate::ErrorKind::Custom(_), p, _) => {
let e: $crate::ErrorKind<$t> = $crate::ErrorKind::Fix;
$crate::Err::Position(e, p)
},
$crate::Err::Code(_) |
$crate::Err::Node(_, _) => {
let e: $crate::ErrorKind<$t> = $crate::ErrorKind::Fix;
$crate::Err::Code(e)
},
$crate::Err::Position(_, p) |
$crate::Err::NodePosition(_, p, _) => {
let e: $crate::ErrorKind<$t> = $crate::ErrorKind::Fix;
$crate::Err::Position(e, p)
},
};
$crate::IResult::Error(err)
}
}
}
);
($i:expr, $t:ty, $f:expr) => (
fix_error!($i, $t, call!($f));
);
);
#[macro_export]
macro_rules! flat_map(
($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2: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)) => $crate::IResult::Incomplete($crate::Needed::Size(i)),
$crate::IResult::Done(i, o) => match $submac2!(o, $($args2)*) {
$crate::IResult::Error(e) => {
let err = match e {
$crate::Err::Code(k) | $crate::Err::Node(k, _) | $crate::Err::Position(k, _) | $crate::Err::NodePosition(k, _, _) => {
$crate::Err::Position(k, $i)
}
};
$crate::IResult::Error(err)
},
$crate::IResult::Incomplete($crate::Needed::Unknown) => $crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::IResult::Incomplete($crate::Needed::Size(ref i2)) => $crate::IResult::Incomplete($crate::Needed::Size(*i2)),
$crate::IResult::Done(_, o2) => $crate::IResult::Done(i, o2)
}
}
}
);
($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => (
flat_map!($i, $submac!($($args)*), call!($g));
);
($i:expr, $f:expr, $g:expr) => (
flat_map!($i, call!($f), call!($g));
);
($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => (
flat_map!($i, call!($f), $submac!($($args)*));
);
);