utils/parser/tinystr.rs
1use crate::parser::{Leaf, LeafResult, ParseError};
2use crate::str::{TinyStr, TinyStrInt, TinyStrLen};
3use std::num::NonZero;
4
5#[derive(Copy, Clone)]
6pub struct TinyStringParser<T: TinyStrInt> {
7 _phantom: std::marker::PhantomData<T>,
8 f: fn(&u8) -> bool,
9}
10impl<'i, T: TinyStrInt> Leaf<'i> for TinyStringParser<T> {
11 type Output = TinyStr<T>;
12
13 #[inline]
14 fn parse(&self, input: &'i [u8]) -> LeafResult<'i, Self::Output> {
15 let mut accumulator = T::Raw::default();
16 let mut len = 0;
17 while len < T::LEN
18 && let Some(&b) = input.get(len)
19 && (self.f)(&b)
20 {
21 accumulator = T::set_raw(accumulator, b, len);
22 len += 1;
23 }
24
25 if len == 0 {
26 return Err((ParseError::ExpectedAtLeastMatches(1, self.f), input));
27 }
28
29 if len == T::LEN
30 && let Some(b) = input.get(T::LEN)
31 && (self.f)(b)
32 {
33 return Err((
34 ParseError::ExpectedAtMostMatches(T::LEN, self.f),
35 &input[T::LEN..],
36 ));
37 }
38
39 match T::from_raw(accumulator) {
40 None => Err((ParseError::ExpectedAtLeastMatches(1, self.f), input)),
41 Some(v) => Ok((TinyStr::from_raw(v), &input[len..])),
42 }
43 }
44}
45
46/// [`Leaf`] parser for [`TinyStr`] strings between 1 and 2 bytes matching the provided function.
47///
48/// Similar to [`Parser::repeat_arrayvec`](crate::parser::Parser::repeat_arrayvec) if more than 2
49/// bytes match, it will return an error.
50///
51/// # Examples
52/// ```
53/// # use utils::parser::{self, Leaf};
54/// # use utils::str::TinyStr2;
55/// let parser = parser::tinystr2(u8::is_ascii_lowercase);
56/// assert_eq!(
57/// parser.parse(b"ab: 123"),
58/// Ok((TinyStr2::from_const(b"ab"), &b": 123"[..]))
59/// );
60/// assert!(parser.parse(b"abc: 123").is_err());
61/// assert!(parser.parse(b"ABC").is_err());
62/// ```
63#[inline]
64#[must_use]
65pub fn tinystr2(f: fn(&u8) -> bool) -> TinyStringParser<NonZero<u16>> {
66 TinyStringParser {
67 _phantom: std::marker::PhantomData,
68 f,
69 }
70}
71
72/// [`Leaf`] parser for [`TinyStr`] strings between 1 and 4 bytes matching the provided function.
73///
74/// Similar to [`Parser::repeat_arrayvec`](crate::parser::Parser::repeat_arrayvec) if more than 4
75/// bytes match, it will return an error.
76///
77/// # Examples
78/// ```
79/// # use utils::parser::{self, Leaf};
80/// # use utils::str::TinyStr4;
81/// let parser = parser::tinystr4(u8::is_ascii_lowercase);
82/// assert_eq!(
83/// parser.parse(b"abc: 123"),
84/// Ok((TinyStr4::from_const(b"abc"), &b": 123"[..]))
85/// );
86/// assert_eq!(
87/// parser.parse(b"abcd: 123"),
88/// Ok((TinyStr4::from_const(b"abcd"), &b": 123"[..]))
89/// );
90/// assert!(parser.parse(b"abcde: 123").is_err());
91/// assert!(parser.parse(b"ABC").is_err());
92/// ```
93#[inline]
94#[must_use]
95pub fn tinystr4(f: fn(&u8) -> bool) -> TinyStringParser<NonZero<u32>> {
96 TinyStringParser {
97 _phantom: std::marker::PhantomData,
98 f,
99 }
100}
101
102/// [`Leaf`] parser for [`TinyStr`] strings between 1 and 8 bytes matching the provided function.
103///
104/// Similar to [`Parser::repeat_arrayvec`](crate::parser::Parser::repeat_arrayvec) if more than 8
105/// bytes match, it will return an error.
106///
107/// # Examples
108/// ```
109/// # use utils::parser::{self, Leaf};
110/// # use utils::str::TinyStr8;
111/// let parser = parser::tinystr8(u8::is_ascii_lowercase);
112/// assert_eq!(
113/// parser.parse(b"abcde: 123"),
114/// Ok((TinyStr8::from_const(b"abcde"), &b": 123"[..]))
115/// );
116/// assert_eq!(
117/// parser.parse(b"abcdefgh: 123"),
118/// Ok((TinyStr8::from_const(b"abcdefgh"), &b": 123"[..]))
119/// );
120/// assert!(parser.parse(b"abcdefghi: 123").is_err());
121/// assert!(parser.parse(b"ABC").is_err());
122/// ```
123#[inline]
124#[must_use]
125pub fn tinystr8(f: fn(&u8) -> bool) -> TinyStringParser<NonZero<u64>> {
126 TinyStringParser {
127 _phantom: std::marker::PhantomData,
128 f,
129 }
130}
131
132#[derive(Copy, Clone)]
133pub struct TinyStringExact<const N: usize> {
134 f: fn(&u8) -> bool,
135}
136impl<'i, const N: usize> Leaf<'i> for TinyStringExact<N>
137where
138 (): TinyStrLen<N>,
139{
140 type Output = TinyStr<<() as TinyStrLen<N>>::Int>;
141
142 #[inline]
143 fn parse(&self, input: &'i [u8]) -> LeafResult<'i, Self::Output> {
144 let mut accumulator = <<() as TinyStrLen<N>>::Int as TinyStrInt>::Raw::default();
145
146 for i in 0..N {
147 if let Some(&b) = input.get(i)
148 && (self.f)(&b)
149 {
150 accumulator =
151 <<() as TinyStrLen<N>>::Int as TinyStrInt>::set_raw(accumulator, b, i);
152 } else {
153 return Err((ParseError::ExpectedExactlyMatches(N, self.f), &input[i..]));
154 }
155 }
156
157 match <<() as TinyStrLen<N>>::Int as TinyStrInt>::from_raw(accumulator) {
158 None => Err((ParseError::ExpectedExactlyMatches(N, self.f), input)),
159 Some(v) => Ok((TinyStr::from_raw(v), &input[N..])),
160 }
161 }
162}
163
164/// [`Leaf`] parser for [`TinyStr`] strings exactly `N` long matching the provided function.
165///
166/// # Examples
167/// ```
168/// # use utils::parser::{self, Leaf};
169/// # use utils::str::TinyStr4;
170/// let parser = parser::tinystr::<3>(u8::is_ascii_lowercase);
171/// assert_eq!(
172/// parser.parse(b"abc: 123"),
173/// Ok((TinyStr4::from_const(b"abc"), &b": 123"[..]))
174/// );
175/// assert_eq!(
176/// parser.parse(b"abcd: 123"),
177/// Ok((TinyStr4::from_const(b"abc"), &b"d: 123"[..]))
178/// );
179/// assert!(parser.parse(b"ab: 123").is_err());
180/// assert!(parser.parse(b"ABC").is_err());
181/// ```
182#[inline]
183#[must_use]
184pub fn tinystr<const N: usize>(f: fn(&u8) -> bool) -> TinyStringExact<N>
185where
186 (): TinyStrLen<N>,
187{
188 TinyStringExact { f }
189}