utils/parser/simple.rs
1use crate::parser::{Leaf, LeafResult, ParseError};
2use std::ops::RangeInclusive;
3
4#[derive(Copy, Clone)]
5pub struct Byte();
6impl<'i> Leaf<'i> for Byte {
7    type Output = u8;
8
9    #[inline]
10    fn parse(&self, input: &'i [u8]) -> LeafResult<'i, Self::Output> {
11        if let [byte, remaining @ ..] = input {
12            Ok((*byte, remaining))
13        } else {
14            Err((ParseError::Expected("byte"), input))
15        }
16    }
17}
18
19/// [`Leaf`] parser that consumes a single byte.
20///
21/// Not to be confused with [`u8`](super::u8), which parses a number in the range 0-255.
22///
23/// # Examples
24/// ```
25/// # use utils::parser::{self, Leaf};
26/// assert_eq!(
27///     parser::byte().parse(b"abcdef"),
28///     Ok((b'a', &b"bcdef"[..]))
29/// );
30/// assert_eq!(
31///     parser::byte().parse(b"123"),
32///     Ok((b'1', &b"23"[..]))
33/// );
34/// ```
35#[inline]
36#[must_use]
37pub fn byte() -> Byte {
38    Byte()
39}
40
41#[derive(Copy, Clone)]
42pub struct ByteLut<'a, O> {
43    lut: &'a [Option<O>; 256],
44    error: ParseError,
45}
46impl<'i, O: Copy> Leaf<'i> for ByteLut<'_, O> {
47    type Output = O;
48
49    #[inline]
50    fn parse(&self, input: &'i [u8]) -> LeafResult<'i, Self::Output> {
51        if let [byte, remaining @ ..] = input
52            && let Some(output) = self.lut[*byte as usize]
53        {
54            Ok((output, remaining))
55        } else {
56            Err((self.error, input))
57        }
58    }
59}
60
61/// [`Leaf`] parser that consumes a single byte and maps it using a lookup table.
62///
63/// Equivalent to `parser::byte().map_res(|b| LOOKUP[b as usize].ok_or("expected ..."))`, which is
64/// usually faster than an equivalent match statement in the closure.
65///
66/// See also [`parser::byte_map!`](crate::parser::byte_map!) which wraps this function, allowing a
67/// match-like syntax to be used to define the lookup table.
68///
69/// # Examples
70/// ```
71/// # use utils::parser::{self, Leaf, ParseError};
72/// const LOOKUP: [Option<bool>; 256] = {
73///     let mut x = [None; 256];
74///     x['#' as usize] = Some(true);
75///     x['.' as usize] = Some(false);
76///     x
77/// };
78///
79/// let parser = parser::byte_lut(&LOOKUP, ParseError::Custom("expected '#' or '.'"));
80/// assert_eq!(parser.parse(b"#..##"), Ok((true, &b"..##"[..])));
81/// assert_eq!(parser.parse(b"..##"), Ok((false, &b".##"[..])));
82/// assert_eq!(parser.parse(b"abc"), Err((ParseError::Custom("expected '#' or '.'"), &b"abc"[..])));
83/// ```
84#[inline]
85#[must_use]
86pub fn byte_lut<T: Copy>(lut: &'_ [Option<T>; 256], error: ParseError) -> ByteLut<'_, T> {
87    ByteLut { lut, error }
88}
89
90#[derive(Copy, Clone)]
91pub struct ByteRange {
92    min: u8,
93    max: u8,
94}
95impl<'i> Leaf<'i> for ByteRange {
96    type Output = u8;
97
98    #[inline]
99    fn parse(&self, input: &'i [u8]) -> LeafResult<'i, Self::Output> {
100        if let [byte, remaining @ ..] = input {
101            if *byte >= self.min && *byte <= self.max {
102                Ok((*byte, remaining))
103            } else {
104                Err((ParseError::ExpectedByteRange(self.min, self.max), input))
105            }
106        } else {
107            Err((ParseError::Expected("byte"), input))
108        }
109    }
110}
111
112/// [`Leaf`] parser that consumes a single byte in the supplied range.
113///
114/// See also [`number_range`](super::number_range) and [`byte`].
115///
116/// # Examples
117/// ```
118/// # use utils::parser::{self, Leaf};
119/// assert_eq!(
120///     parser::byte_range(b'a'..=b'z').parse(b"hello world"),
121///     Ok((b'h', &b"ello world"[..]))
122/// );
123/// ```
124#[inline]
125#[must_use]
126pub fn byte_range(range: RangeInclusive<u8>) -> ByteRange {
127    let min = *range.start();
128    let max = *range.end();
129    assert!(min <= max);
130    ByteRange { min, max }
131}
132
133#[derive(Copy, Clone)]
134pub struct Constant<V: Copy>(pub(super) V);
135impl<'i, V: Copy> Leaf<'i> for Constant<V> {
136    type Output = V;
137
138    #[inline]
139    fn parse(&self, input: &'i [u8]) -> LeafResult<'i, Self::Output> {
140        Ok((self.0, input))
141    }
142}
143
144/// [`Leaf`] parser that consumes no input and always succeeds, returning the provided value.
145///
146/// # Examples
147/// ```
148/// # use utils::parser::{self, Leaf};
149/// assert_eq!(
150///     parser::constant(1).parse(b"abc"),
151///     Ok((1, &b"abc"[..]))
152/// );
153/// ```
154#[inline]
155#[must_use]
156pub fn constant<T: Copy>(v: T) -> Constant<T> {
157    Constant(v)
158}
159
160/// [`Leaf`] parser that consumes no input and always succeeds, returning [`()`](unit).
161///
162/// # Examples
163/// ```
164/// # use utils::parser::{self, Leaf};
165/// assert_eq!(
166///     parser::noop().parse(b"abc"),
167///     Ok(((), &b"abc"[..]))
168/// );
169/// ```
170#[inline]
171#[must_use]
172pub fn noop() -> Constant<()> {
173    const {
174        assert!(size_of::<Constant<()>>() == 0);
175    }
176    Constant(())
177}
178
179#[derive(Copy, Clone)]
180pub struct Eof();
181impl<'i> Leaf<'i> for Eof {
182    type Output = ();
183
184    #[inline]
185    fn parse(&self, input: &'i [u8]) -> LeafResult<'i, Self::Output> {
186        match input {
187            [] => Ok(((), input)),
188            _ => Err((ParseError::ExpectedEof(), input)),
189        }
190    }
191}
192
193/// [`Leaf`] parser which matches the end of the input.
194///
195/// Useful when parsing a list and each item is separated by a separator, unless it is at the end of
196/// the input.
197///
198/// # Examples
199/// ```
200/// # use utils::parser::{self, Leaf, Parser};
201/// assert_eq!(
202///     parser::eof().parse(b""),
203///     Ok(((), &b""[..]))
204/// );
205/// assert_eq!(
206///     parser::u32()
207///         .with_suffix(b','.or(parser::eof()))
208///         .parse_all("12,34,56")
209///         .unwrap(),
210///     vec![12, 34, 56],
211/// );
212/// ```
213#[inline]
214#[must_use]
215pub fn eof() -> Eof {
216    Eof()
217}
218
219#[derive(Copy, Clone)]
220pub struct Eol();
221impl<'i> Leaf<'i> for Eol {
222    type Output = ();
223
224    #[inline]
225    fn parse(&self, input: &'i [u8]) -> LeafResult<'i, Self::Output> {
226        match input {
227            [b'\n', remaining @ ..] | [b'\r', b'\n', remaining @ ..] => Ok(((), remaining)),
228            [] => Ok(((), input)),
229            _ => Err((ParseError::Expected("newline or end of input"), input)),
230        }
231    }
232}
233
234/// [`Leaf`] parser which matches newlines or the end of the input.
235///
236/// Matches both LF and CRLF line endings.
237///
238/// # Examples
239/// ```
240/// # use utils::parser::{self, Leaf};
241/// assert_eq!(
242///     parser::eol().parse(b"\nabc"),
243///     Ok(((), &b"abc"[..]))
244/// );
245/// assert_eq!(
246///     parser::eol().parse(b"\r\nabc"),
247///     Ok(((), &b"abc"[..]))
248/// );
249/// assert_eq!(
250///     parser::eol().parse(b""),
251///     Ok(((), &b""[..]))
252/// );
253/// ```
254#[inline]
255#[must_use]
256pub fn eol() -> Eol {
257    Eol()
258}
259
260#[derive(Copy, Clone)]
261pub struct TakeWhile<const N: usize>(fn(&u8) -> bool);
262impl<'i, const N: usize> Leaf<'i> for TakeWhile<N> {
263    type Output = &'i [u8];
264
265    #[inline]
266    fn parse(&self, input: &'i [u8]) -> LeafResult<'i, Self::Output> {
267        let mut end = 0;
268        while end < input.len() && self.0(&input[end]) {
269            end += 1;
270        }
271        if end >= N {
272            Ok(input.split_at(end))
273        } else {
274            Err((ParseError::ExpectedMatches(N), &input[end..]))
275        }
276    }
277}
278
279/// [`Leaf`] parser for substrings matching the provided function.
280///
281/// # Examples
282/// ```
283/// # use utils::parser::{self, Leaf};
284/// let parser = parser::take_while(u8::is_ascii_lowercase);
285/// assert_eq!(
286///     parser.parse(b"abc def"),
287///     Ok((&b"abc"[..], &b" def"[..]))
288/// );
289/// assert_eq!(
290///     parser.parse(b"ABC"),
291///     Ok((&b""[..], &b"ABC"[..]))
292/// );
293/// ```
294#[inline]
295#[must_use]
296pub fn take_while(f: fn(&u8) -> bool) -> TakeWhile<0> {
297    TakeWhile(f)
298}
299
300/// [`Leaf`] parser for non-empty substrings matching the provided function.
301///
302/// # Examples
303/// ```
304/// # use utils::parser::{self, Leaf};
305/// let parser = parser::take_while1(u8::is_ascii_lowercase);
306/// assert_eq!(
307///     parser.parse(b"abc def"),
308///     Ok((&b"abc"[..], &b" def"[..]))
309/// );
310/// assert!(parser.parse(b"ABC").is_err());
311/// ```
312#[inline]
313#[must_use]
314pub fn take_while1(f: fn(&u8) -> bool) -> TakeWhile<1> {
315    TakeWhile(f)
316}