blob: 77e3bafa2c9dbb452e596c4cdb05c591b7fa3af1 [file] [log] [blame]
//! 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 an enum 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<I, O, E=(I,ErrorKind)> = Result<(I, O), Err<E>>;
/// 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 appling a function to a contained `Size` value.
#[inline]
pub fn map<F: Fn(usize) -> 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<E> {
/// 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<E> Err<E> {
/// tests if the result is Incomplete
pub fn is_incomplete(&self) -> bool {
if let Err::Incomplete(_) = self {
true
} else {
false
}
}
/// automatically converts between errors if the underlying type supports it
pub fn convert<F>(e: Err<F>) -> Self
where E: From<F> {
match e {
Err::Incomplete(n) => Err::Incomplete(n),
Err::Failure(c) => Err::Failure(c.into()),
Err::Error(c) => Err::Error(c.into()),
}
}
}
/*
#[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 {
write!(f, "{:?}", self)
}
}
#[cfg(feature = "std")]
use std::error::Error;
#[cfg(feature = "std")]
impl<E> Error for Err<E>
where
I: fmt::Debug,
E: fmt::Debug,
{
fn description(&self) -> &str {
match self {
&Err::Incomplete(..) => "there was not enough data",
&Err::Error(Context::Code(_, ref error_kind)) | &Err::Failure(Context::Code(_, ref error_kind)) => error_kind.description(),
}
}
fn cause(&self) -> Option<&Error> {
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);
}
}