use self::Needed::*;
use crate::error::{self, ErrorKind};
use crate::lib::std::fmt;
use core::num::NonZeroUsize;
pub type IResult<I, O, E = error::Error<I>> = Result<(I, O), Err<E>>;
pub trait Finish<I, O, E> {
fn finish(self) -> Result<(I, O), E>;
}
impl<I, O, E> Finish<I, O, E> for IResult<I, O, E> {
fn finish(self) -> Result<(I, O), E> {
match self {
Ok(res) => Ok(res),
Err(Err::Error(e)) | Err(Err::Failure(e)) => Err(e),
Err(Err::Incomplete(_)) => {
panic!("Cannot call `finish()` on `Err(Err::Incomplete(_))`: this result means that the parser does not have enough data to decide, you should gather more data and try to reapply the parser instead")
}
}
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
pub enum Needed {
Unknown,
Size(NonZeroUsize),
}
impl Needed {
pub fn new(s: usize) -> Self {
match NonZeroUsize::new(s) {
Some(sz) => Needed::Size(sz),
None => Needed::Unknown,
}
}
pub fn is_known(&self) -> bool {
*self != Unknown
}
#[inline]
pub fn map<F: Fn(NonZeroUsize) -> usize>(self, f: F) -> Needed {
match self {
Unknown => Unknown,
Size(n) => Needed::new(f(n)),
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
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(crate::lib::std::convert::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)),
}
}
}
impl<T> Err<error::Error<T>> {
pub fn map_input<U, F>(self, f: F) -> Err<error::Error<U>>
where
F: FnOnce(T) -> U,
{
match self {
Err::Incomplete(n) => Err::Incomplete(n),
Err::Failure(error::Error { input, code }) => Err::Failure(error::Error {
input: f(input),
code,
}),
Err::Error(error::Error { input, code }) => Err::Error(error::Error {
input: f(input),
code,
}),
}
}
}
#[cfg(feature = "alloc")]
use crate::lib::std::{borrow::ToOwned, string::String, vec::Vec};
#[cfg(feature = "alloc")]
impl Err<(&[u8], ErrorKind)> {
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
pub fn to_owned(self) -> Err<(Vec<u8>, ErrorKind)> {
self.map_input(ToOwned::to_owned)
}
}
#[cfg(feature = "alloc")]
impl Err<(&str, ErrorKind)> {
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
pub fn to_owned(self) -> Err<(String, ErrorKind)> {
self.map_input(ToOwned::to_owned)
}
}
#[cfg(feature = "alloc")]
impl Err<error::Error<&[u8]>> {
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
pub fn to_owned(self) -> Err<error::Error<Vec<u8>>> {
self.map_input(ToOwned::to_owned)
}
}
#[cfg(feature = "alloc")]
impl Err<error::Error<&str>> {
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
pub fn to_owned(self) -> Err<error::Error<String>> {
self.map_input(ToOwned::to_owned)
}
}
impl<E: Eq> Eq for Err<E> {}
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 }
}
pub trait Parser<I, O, E> {
fn parse(&mut self, input: I) -> IResult<I, O, E>;
fn map<G, O2>(self, g: G) -> Map<Self, G, O>
where
G: Fn(O) -> O2,
Self: core::marker::Sized,
{
Map {
f: self,
g,
phantom: core::marker::PhantomData,
}
}
fn flat_map<G, H, O2>(self, g: G) -> FlatMap<Self, G, O>
where
G: FnMut(O) -> H,
H: Parser<I, O2, E>,
Self: core::marker::Sized,
{
FlatMap {
f: self,
g,
phantom: core::marker::PhantomData,
}
}
fn and_then<G, O2>(self, g: G) -> AndThen<Self, G, O>
where
G: Parser<O, O2, E>,
Self: core::marker::Sized,
{
AndThen {
f: self,
g,
phantom: core::marker::PhantomData,
}
}
fn and<G, O2>(self, g: G) -> And<Self, G>
where
G: Parser<I, O2, E>,
Self: core::marker::Sized,
{
And { f: self, g }
}
fn or<G>(self, g: G) -> Or<Self, G>
where
G: Parser<I, O, E>,
Self: core::marker::Sized,
{
Or { f: self, g }
}
fn into<O2: From<O>, E2: From<E>>(self) -> Into<Self, O, O2, E, E2>
where
Self: core::marker::Sized,
{
Into {
f: self,
phantom_out1: core::marker::PhantomData,
phantom_err1: core::marker::PhantomData,
phantom_out2: core::marker::PhantomData,
phantom_err2: core::marker::PhantomData,
}
}
}
impl<'a, I, O, E, F> Parser<I, O, E> for F
where
F: FnMut(I) -> IResult<I, O, E> + 'a,
{
fn parse(&mut self, i: I) -> IResult<I, O, E> {
self(i)
}
}
#[cfg(feature = "alloc")]
use alloc::boxed::Box;
#[cfg(feature = "alloc")]
impl<'a, I, O, E> Parser<I, O, E> for Box<dyn Parser<I, O, E> + 'a> {
fn parse(&mut self, input: I) -> IResult<I, O, E> {
(**self).parse(input)
}
}
#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
pub struct Map<F, G, O1> {
f: F,
g: G,
phantom: core::marker::PhantomData<O1>,
}
impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Fn(O1) -> O2> Parser<I, O2, E> for Map<F, G, O1> {
fn parse(&mut self, i: I) -> IResult<I, O2, E> {
match self.f.parse(i) {
Err(e) => Err(e),
Ok((i, o)) => Ok((i, (self.g)(o))),
}
}
}
#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
pub struct FlatMap<F, G, O1> {
f: F,
g: G,
phantom: core::marker::PhantomData<O1>,
}
impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Fn(O1) -> H, H: Parser<I, O2, E>> Parser<I, O2, E>
for FlatMap<F, G, O1>
{
fn parse(&mut self, i: I) -> IResult<I, O2, E> {
let (i, o1) = self.f.parse(i)?;
(self.g)(o1).parse(i)
}
}
#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
pub struct AndThen<F, G, O1> {
f: F,
g: G,
phantom: core::marker::PhantomData<O1>,
}
impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Parser<O1, O2, E>> Parser<I, O2, E>
for AndThen<F, G, O1>
{
fn parse(&mut self, i: I) -> IResult<I, O2, E> {
let (i, o1) = self.f.parse(i)?;
let (_, o2) = self.g.parse(o1)?;
Ok((i, o2))
}
}
#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
pub struct And<F, G> {
f: F,
g: G,
}
impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Parser<I, O2, E>> Parser<I, (O1, O2), E>
for And<F, G>
{
fn parse(&mut self, i: I) -> IResult<I, (O1, O2), E> {
let (i, o1) = self.f.parse(i)?;
let (i, o2) = self.g.parse(i)?;
Ok((i, (o1, o2)))
}
}
#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
pub struct Or<F, G> {
f: F,
g: G,
}
impl<'a, I: Clone, O, E: crate::error::ParseError<I>, F: Parser<I, O, E>, G: Parser<I, O, E>>
Parser<I, O, E> for Or<F, G>
{
fn parse(&mut self, i: I) -> IResult<I, O, E> {
match self.f.parse(i.clone()) {
Err(Err::Error(e1)) => match self.g.parse(i) {
Err(Err::Error(e2)) => Err(Err::Error(e1.or(e2))),
res => res,
},
res => res,
}
}
}
#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
pub struct Into<F, O1, O2: From<O1>, E1, E2: From<E1>> {
f: F,
phantom_out1: core::marker::PhantomData<O1>,
phantom_err1: core::marker::PhantomData<E1>,
phantom_out2: core::marker::PhantomData<O2>,
phantom_err2: core::marker::PhantomData<E2>,
}
impl<
'a,
I: Clone,
O1,
O2: From<O1>,
E1,
E2: crate::error::ParseError<I> + From<E1>,
F: Parser<I, O1, E1>,
> Parser<I, O2, E2> for Into<F, O1, O2, E1, E2>
{
fn parse(&mut self, i: I) -> IResult<I, O2, E2> {
match self.f.parse(i) {
Ok((i, o)) => Ok((i, o.into())),
Err(Err::Error(e)) => Err(Err::Error(e.into())),
Err(Err::Failure(e)) => Err(Err::Failure(e.into())),
Err(Err::Incomplete(e)) => Err(Err::Incomplete(e)),
}
}
}
#[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!(Needed, 8);
assert_size!(Err<u32>, 16);
assert_size!(ErrorKind, 1);
}
#[test]
fn err_map_test() {
let e = Err::Error(1);
assert_eq!(e.map(|v| v + 1), Err::Error(2));
}
}