1use crate::parser::then::Then2;
2use crate::parser::{ParseError, ParseState, Parser, ParserResult};
3
4pub type LeafResult<'i, T> = Result<(T, &'i [u8]), (ParseError, &'i [u8])>;
8
9#[must_use]
13pub trait Leaf<'i>: Sized {
14    type Output;
16
17    fn parse(&self, input: &'i [u8]) -> LeafResult<'i, Self::Output>;
22}
23
24impl<'i, L: Leaf<'i>> Parser<'i> for L {
25    type Output = L::Output;
26    type Then<T: Parser<'i>> = Then2<Self, T>;
27
28    fn parse_ctx(
29        &self,
30        input: &'i [u8],
31        state: &mut ParseState<'i>,
32        _: &mut bool,
33        _: bool,
34    ) -> ParserResult<'i, Self::Output> {
35        match self.parse(input) {
36            Ok(v) => Ok(v),
37            Err((err, remaining)) => Err(state.error(err, remaining)),
38        }
39    }
40}
41
42impl<'i> Leaf<'i> for &'static str {
46    type Output = ();
47
48    #[inline]
49    fn parse(&self, input: &'i [u8]) -> LeafResult<'i, Self::Output> {
50        if input.len() >= self.len() && self.bytes().zip(input).all(|(a, &b)| a == b) {
53            Ok(((), &input[self.len()..]))
54        } else {
55            Err((ParseError::ExpectedLiteral(self), input))
56        }
57    }
58}
59
60impl<'i> Leaf<'i> for u8 {
64    type Output = ();
65
66    #[inline]
67    fn parse(&self, input: &'i [u8]) -> LeafResult<'i, Self::Output> {
68        if input.first() == Some(self) {
69            Ok(((), &input[1..]))
70        } else {
71            Err((ParseError::ExpectedByte(*self), input))
72        }
73    }
74}
75
76impl<'i, F: Fn(&'i [u8]) -> LeafResult<'i, O>, O> Leaf<'i> for F {
78    type Output = O;
79
80    #[inline]
81    fn parse(&self, input: &'i [u8]) -> LeafResult<'i, Self::Output> {
82        self(input)
83    }
84}
85
86#[inline]
90#[must_use]
91pub const fn from_leaf_fn<'i, F, O>(f: F) -> F
92where
93    F: Fn(&'i [u8]) -> LeafResult<'i, O>,
94    F: Leaf<'i, Output = O>,
95{
96    f
97}
98
99pub trait Parseable {
101    type Parser: for<'i> Leaf<'i, Output = Self>;
102    const PARSER: Self::Parser;
103}