1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
#![feature(assert_matches)]
#![feature(associated_type_defaults)]
#![feature(str_internals)]
use repeatable::Repeatable;
mod byte_stream;
mod extract_byte;
mod extract_utf8;
mod iterable;
mod repeatable;
mod tuple;
#[cfg(test)]
mod tests;
pub use self::byte_stream::ByteStream;
pub use self::extract_byte::byte;
pub use self::iterable::{Collectable, Mappable};
pub use self::tuple::ExtractTuple;
pub enum ParseResult<State, Output> {
NoMatch,
Partial(State),
Match(Output, ByteStream),
}
impl<State, Output> std::fmt::Debug for ParseResult<State, Output> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::NoMatch => write!(f, "NoMatch"),
Self::Partial(_arg0) => write!(f, "Partial"),
Self::Match(_arg0, _arg1) => write!(f, "Match"),
}
}
}
/// A trait to extract a type from a `ByteStream`. The `extract` method is initially called with a
/// state of `None`. If the type is extracted fully, the method returns `ParseResult::Match` with
/// the extracted type and the remaining `ByteStream`. If the type cannot be extracted because it
/// does not match, the `ParseResult::NoMatch` is returned. If the extraction reads to the end of
/// the `ByteStream` but needs more data to extract the type it returns `ParseResult::Partial` with
/// a state. The next call to `extract` with a new `ByteStream` must pass in the returned state to
/// continue parsing the type. If the end of the stream is reached while the state is `Partial` call
/// `stop` with the state as some extractors can return `ParseResult::Match` in this case. e.g.
/// `'a'.repeated(2..5)` will return Partial for "aaa" since it may be part of a longer pattern, but
/// on end of stream, will return the 3 characters as a match.
pub trait Extract {
type State;
type Output = ByteStream;
fn extract(
&self,
input: ByteStream,
state: Option<Self::State>,
last: bool,
) -> ParseResult<Self::State, Self::Output>;
}
impl<T> Extract for &T
where
T: Extract,
{
type State = T::State;
type Output = T::Output;
fn extract(
&self,
input: ByteStream,
state: Option<Self::State>,
last: bool,
) -> ParseResult<Self::State, Self::Output> {
(*self).extract(input, state, last)
}
}
pub trait ParseAny {
type Parser: Extract;
fn any() -> Self::Parser;
}
pub trait ParseWhen<T, F>
where
F: Fn(T) -> bool,
{
type Parser: Extract;
fn when(f: F) -> Self::Parser;
}