use util::{ErrorKind,Convert};
use std::convert::From;
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum Context<I,E=u32>{
Code(I, ErrorKind<E>),
List(Vec<(I, ErrorKind<E>)>),
}
impl<I,E: From<u32>> Convert<Context<I,u32>> for Context<I,E> {
fn convert(c: Context<I,u32>) -> Self {
match c {
Context::Code(i, e) => Context::Code(i, ErrorKind::convert(e)),
Context::List(mut v) => Context::List(v.drain(..).map(|(i, e)| (i, ErrorKind::convert(e))).collect())
}
}
impl<I,E> Context<I,E> {
pub fn into_error_kind(self) -> ErrorKind<E> {
match self {
Err::Code(kind) => kind,
Err(List(v)) => {
let (_, kind) = v.get(0);
kind
},
}
}
}
#[macro_export]
macro_rules! fix_error (
($i:expr, $t:ty, $submac:ident!( $($args:tt)* )) => (
{
use ::std::result::Result::*;
use $crate::{Err,Convert,ErrorKind,Context};
match $submac!($i, $($args)*) {
Err(e) => {
let e2 = match e {
Err::Error(err) => {
let err2 = match err {
Context::Code(i, code) => {
let code2: ErrorKind<$t> = ErrorKind::convert(code);
Context::Code(i, code2)
},
Context::List(mut v) => {
Context::List(v.drain(..).map(|(i, code)| {
let code2: ErrorKind<$t> = ErrorKind::convert(code);
(i, code2)
}).collect())
}
};
Err::Error(err2)
},
Err::Failure(err) => {
let err2 = match err {
Context::Code(i, code) => {
let code2: ErrorKind<$t> = ErrorKind::convert(code);
Context::Code(i, code2)
},
Context::List(mut v) => {
Context::List(v.drain(..).map(|(i, code)| {
let code2: ErrorKind<$t> = ErrorKind::convert(code);
(i, code2)
}).collect())
}
};
Err::Failure(err2)
},
Err::Incomplete(i) => Err::Incomplete(i),
};
Err(e2)
},
Ok((i, o)) => Ok((i, o)),
}
}
);
($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)* )) => (
{
use ::std::result::Result::*;
use $crate::{Err,Convert};
match $submac!($i, $($args)*) {
Err(e) => Err(Err::convert(e)),
Ok((i, o)) => match $submac2!(o, $($args2)*) {
Err(e) => Err(Err::convert(e)),
Ok((_,o2)) => Ok((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)*));
);
);