//! Basic types to build the parsers use self::Needed::*; use crate::error::ErrorKind; /// Holds the result of parsing functions /// /// It depends on I, the input type, O, the output type, and E, the error type (by default u32) /// /// The `Ok` side is a pair containing the remainder of the input (the part of the data that /// was not parsed) and the produced value. The `Err` side contains an instance of `nom::Err`. /// pub type IResult = Result<(I, O), Err>; /// Contains information on needed data if a parser returned `Incomplete` #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum Needed { /// needs more data, but we do not know how much Unknown, /// contains the required data size Size(usize), } impl Needed { /// indicates if we know how many bytes we need pub fn is_known(&self) -> bool { *self != Unknown } /// Maps a `Needed` to `Needed` by applying a function to a contained `Size` value. #[inline] pub fn map usize>(self, f: F) -> Needed { match self { Unknown => Unknown, Size(n) => Size(f(n)), } } } /// The `Err` enum indicates the parser was not successful /// /// It has three cases: /// /// * `Incomplete` indicates that more data is needed to decide. The `Needed` enum /// can contain how many additional bytes are necessary. If you are sure your parser /// is working on full data, you can wrap your parser with the `complete` combinator /// to transform that case in `Error` /// * `Error` means some parser did not succeed, but another one might (as an example, /// when testing different branches of an `alt` combinator) /// * `Failure` indicates an unrecoverable error. As an example, if you recognize a prefix /// to decide on the next parser to apply, and that parser fails, you know there's no need /// to try other parsers, you were already in the right branch, so the data is invalid /// #[derive(Debug, Clone, PartialEq)] pub enum Err { /// There was not enough data Incomplete(Needed), /// The parser had an error (recoverable) Error(E), /// The parser had an unrecoverable error: we got to the right /// branch and we know other branches won't work, so backtrack /// as fast as possible Failure(E), } impl Err { /// tests if the result is Incomplete pub fn is_incomplete(&self) -> bool { if let Err::Incomplete(_) = self { true } else { false } } /// Applies the given function to the inner error pub fn map(self, f: F) -> Err 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)), } } /// automatically converts between errors if the underlying type supports it pub fn convert(e: Err) -> Self where E: From { e.map(Into::into) } } impl Err<(T, ErrorKind)> { /// maps `Err<(T, ErrorKind)>` to `Err<(U, ErrorKind)>` with the given F: T -> U pub fn map_input(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)> { /// Obtaining ownership pub fn to_owned(self) -> Err<(Vec, ErrorKind)> { self.map_input(ToOwned::to_owned) } } #[cfg(feature = "std")] impl Err<(&str, ErrorKind)> { /// automatically converts between errors if the underlying type supports it pub fn to_owned(self) -> Err<(String, ErrorKind)> { self.map_input(ToOwned::to_owned) } } impl Eq for Err {} #[cfg(feature = "std")] use std::fmt; #[cfg(feature = "std")] impl fmt::Display for Err 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 Error for Err where E: fmt::Debug, { fn source(&self) -> Option<&(dyn Error + 'static)> { None // no underlying error } } #[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, 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)); } }