use self::Needed::*;
use crate::error::ErrorKind;
pub type IResult<I, O, E=(I,ErrorKind)> = Result<(I, O), Err<E>>;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Needed {
Unknown,
Size(usize),
}
impl Needed {
pub fn is_known(&self) -> bool {
*self != Unknown
}
#[inline]
pub fn map<F: Fn(usize) -> usize>(self, f: F) -> Needed {
match self {
Unknown => Unknown,
Size(n) => Size(f(n)),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Err<E> {
Incomplete(Needed),
Error(E),
Failure(E),
}
impl<E> Err<E> {
pub fn is_incomplete(&self) -> bool {
if let Err::Incomplete(_) = self {
true
} else {
false
}
}
pub fn map<E2, F>(self, f: F) -> Err<E2>
where F: FnOnce(E) -> E2
{
match self {
Err::Incomplete(n) => Err::Incomplete(n),
Err::Failure(t) => Err::Failure(f(t)),
Err::Error(t) => Err::Error(f(t)),
}
}
pub fn convert<F>(e: Err<F>) -> Self
where E: From<F>
{
e.map(Into::into)
}
}
impl<T> Err<(T, ErrorKind)> {
pub fn map_input<U, F>(self, f: F) -> Err<(U, ErrorKind)>
where F: FnOnce(T) -> U {
match self {
Err::Incomplete(n) => Err::Incomplete(n),
Err::Failure((input, k)) => Err::Failure((f(input), k)),
Err::Error((input, k)) => Err::Error((f(input), k)),
}
}
}
#[cfg(feature = "std")]
impl Err<(&[u8], ErrorKind)> {
pub fn to_owned(self) -> Err<(Vec<u8>, ErrorKind)> {
self.map_input(ToOwned::to_owned)
}
}
#[cfg(feature = "std")]
impl Err<(&str, ErrorKind)> {
pub fn to_owned(self) -> Err<(String, ErrorKind)> {
self.map_input(ToOwned::to_owned)
}
}
impl<E: Eq> Eq for Err<E> {}
#[cfg(feature = "std")]
use std::fmt;
#[cfg(feature = "std")]
impl<E> fmt::Display for Err<E>
where
E: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Err::Incomplete(Needed::Size(u)) => write!(f, "Parsing requires {} bytes/chars", u),
Err::Incomplete(Needed::Unknown) => write!(f, "Parsing requires more data"),
Err::Failure(c) => write!(f, "Parsing Failure: {:?}", c),
Err::Error(c) => write!(f, "Parsing Error: {:?}", c),
}
}
}
#[cfg(feature = "std")]
use std::error::Error;
#[cfg(feature = "std")]
impl<E> Error for Err<E>
where
E: fmt::Debug,
{
fn source(&self) -> Option<&(dyn Error + 'static)> {
None }
}
#[cfg(test)]
mod tests {
use super::*;
use crate::error::ErrorKind;
#[doc(hidden)]
#[macro_export]
macro_rules! assert_size (
($t:ty, $sz:expr) => (
assert_eq!(crate::lib::std::mem::size_of::<$t>(), $sz);
);
);
#[test]
#[cfg(target_pointer_width = "64")]
fn size_test() {
assert_size!(IResult<&[u8], &[u8], (&[u8], u32)>, 40);
assert_size!(IResult<&str, &str, u32>, 40);
assert_size!(Needed, 16);
assert_size!(Err<u32>, 24);
assert_size!(ErrorKind, 1);
}
#[test]
fn err_map_test() {
let e = Err::Error(1);
assert_eq!(e.map(|v| v + 1), Err::Error(2));
}
}