1use core::marker::PhantomData;
6
7use crate::error::ErrorKind;
8use crate::FindToken;
9use crate::IsStreaming;
10use crate::Mode;
11use crate::{error::ParseError, AsChar, Err, IResult, Input, Needed, Parser};
12
13#[cfg(test)]
14mod tests;
15
16pub mod complete;
17pub mod streaming;
18
19#[inline]
20#[doc(hidden)]
21#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_alpha`")]
22pub fn is_alphabetic(chr: u8) -> bool {
23 matches!(chr, 0x41..=0x5A | 0x61..=0x7A)
24}
25
26#[inline]
27#[doc(hidden)]
28#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_dec_digit`")]
29pub fn is_digit(chr: u8) -> bool {
30 matches!(chr, 0x30..=0x39)
31}
32
33#[inline]
34#[doc(hidden)]
35#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_hex_digit`")]
36pub fn is_hex_digit(chr: u8) -> bool {
37 matches!(chr, 0x30..=0x39 | 0x41..=0x46 | 0x61..=0x66)
38}
39
40#[inline]
41#[doc(hidden)]
42#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_oct_digit`")]
43pub fn is_oct_digit(chr: u8) -> bool {
44 matches!(chr, 0x30..=0x37)
45}
46
47#[inline]
59pub fn is_bin_digit(chr: u8) -> bool {
60 matches!(chr, 0x30..=0x31)
61}
62
63#[inline]
64#[doc(hidden)]
65#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_alphanum`")]
66pub fn is_alphanumeric(chr: u8) -> bool {
67 AsChar::is_alphanum(chr)
68}
69
70#[inline]
71#[doc(hidden)]
72#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_space`")]
73pub fn is_space(chr: u8) -> bool {
74 chr == b' ' || chr == b'\t'
75}
76
77#[inline]
78#[doc(hidden)]
79#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_newline`")]
80pub fn is_newline(chr: u8) -> bool {
81 chr == b'\n'
82}
83
84pub fn char<I, Error: ParseError<I>>(c: char) -> impl Parser<I, Output = char, Error = Error>
99where
100 I: Input,
101 <I as Input>::Item: AsChar,
102{
103 Char { c, e: PhantomData }
104}
105
106pub struct Char<E> {
108 c: char,
109 e: PhantomData<E>,
110}
111
112impl<I, Error: ParseError<I>> Parser<I> for Char<Error>
113where
114 I: Input,
115 <I as Input>::Item: AsChar,
116{
117 type Output = char;
118 type Error = Error;
119 #[inline(always)]
120 fn process<OM: crate::OutputMode>(
121 &mut self,
122 i: I,
123 ) -> crate::PResult<OM, I, Self::Output, Self::Error> {
124 match (i).iter_elements().next().map(|t| {
125 let b = t.as_char() == self.c;
126 (&self.c, b)
127 }) {
128 None => {
129 if OM::Incomplete::is_streaming() {
130 Err(Err::Incomplete(Needed::new(self.c.len() - i.input_len())))
131 } else {
132 Err(Err::Error(OM::Error::bind(|| Error::from_char(i, self.c))))
133 }
134 }
135 Some((_, false)) => Err(Err::Error(OM::Error::bind(|| Error::from_char(i, self.c)))),
136 Some((c, true)) => Ok((i.take_from(c.len()), OM::Output::bind(|| c.as_char()))),
137 }
138 }
139}
140
141pub fn satisfy<F, I, Error: ParseError<I>>(
156 predicate: F,
157) -> impl Parser<I, Output = char, Error = Error>
158where
159 I: Input,
160 <I as Input>::Item: AsChar,
161 F: Fn(char) -> bool,
162{
163 Satisfy {
164 predicate,
165 make_error: |i: I| Error::from_error_kind(i, ErrorKind::Satisfy),
166 }
167}
168
169pub struct Satisfy<F, MakeError> {
171 predicate: F,
172 make_error: MakeError,
173}
174
175impl<I, Error: ParseError<I>, F, MakeError> Parser<I> for Satisfy<F, MakeError>
176where
177 I: Input,
178 <I as Input>::Item: AsChar,
179 F: Fn(char) -> bool,
180 MakeError: Fn(I) -> Error,
181{
182 type Output = char;
183 type Error = Error;
184
185 #[inline(always)]
186 fn process<OM: crate::OutputMode>(
187 &mut self,
188 i: I,
189 ) -> crate::PResult<OM, I, Self::Output, Self::Error> {
190 match (i).iter_elements().next().map(|t| {
191 let c = t.as_char();
192 let b = (self.predicate)(c);
193 (c, b)
194 }) {
195 None => {
196 if OM::Incomplete::is_streaming() {
197 Err(Err::Incomplete(Needed::Unknown))
198 } else {
199 Err(Err::Error(OM::Error::bind(|| (self.make_error)(i))))
200 }
201 }
202 Some((_, false)) => Err(Err::Error(OM::Error::bind(|| (self.make_error)(i)))),
203 Some((c, true)) => Ok((i.take_from(c.len()), OM::Output::bind(|| c.as_char()))),
204 }
205 }
206}
207
208pub fn one_of<I, T, Error: ParseError<I>>(list: T) -> impl Parser<I, Output = char, Error = Error>
220where
221 I: Input,
222 <I as Input>::Item: AsChar,
223 T: FindToken<char>,
224{
225 Satisfy {
226 predicate: move |c: char| list.find_token(c),
227 make_error: move |i| Error::from_error_kind(i, ErrorKind::OneOf),
228 }
229}
230
231pub fn none_of<I, T, Error: ParseError<I>>(list: T) -> impl Parser<I, Output = char, Error = Error>
243where
244 I: Input,
245 <I as Input>::Item: AsChar,
246 T: FindToken<char>,
247{
248 Satisfy {
249 predicate: move |c: char| !list.find_token(c),
250 make_error: move |i| Error::from_error_kind(i, ErrorKind::NoneOf),
251 }
252}
253
254pub fn anychar<T, E: ParseError<T>>(input: T) -> IResult<T, char, E>
269where
270 T: Input,
271 <T as Input>::Item: AsChar,
272{
273 let mut it = input.iter_elements();
274 match it.next() {
275 None => Err(Err::Error(E::from_error_kind(input, ErrorKind::Eof))),
276 Some(c) => Ok((input.take_from(c.len()), c.as_char())),
277 }
278}
279
280pub struct AnyChar<E> {
282 e: PhantomData<E>,
283}
284
285impl<I, Error: ParseError<I>> Parser<I> for AnyChar<Error>
286where
287 I: Input,
288 <I as Input>::Item: AsChar,
289{
290 type Output = char;
291 type Error = Error;
292
293 fn process<OM: crate::OutputMode>(
294 &mut self,
295 i: I,
296 ) -> crate::PResult<OM, I, Self::Output, Self::Error> {
297 match (i).iter_elements().next() {
298 None => {
299 if OM::Incomplete::is_streaming() {
300 Err(Err::Incomplete(Needed::new(1)))
301 } else {
302 Err(Err::Error(OM::Error::bind(|| {
303 Error::from_error_kind(i, ErrorKind::Eof)
304 })))
305 }
306 }
307 Some(c) => Ok((i.take_from(c.len()), OM::Output::bind(|| c.as_char()))),
308 }
309 }
310}
311
312pub fn digit1<T, E: ParseError<T>>() -> impl Parser<T, Output = T, Error = E>
326where
327 T: Input,
328 <T as Input>::Item: AsChar,
329{
330 Digit1 { e: PhantomData }
331}
332
333pub struct Digit1<E> {
335 e: PhantomData<E>,
336}
337
338impl<I: Input, E: ParseError<I>> Parser<I> for Digit1<E>
339where
340 <I as Input>::Item: AsChar,
341{
342 type Output = I;
343
344 type Error = E;
345
346 #[inline]
347 fn process<OM: crate::OutputMode>(
348 &mut self,
349 input: I,
350 ) -> crate::PResult<OM, I, Self::Output, Self::Error> {
351 input.split_at_position_mode1::<OM, _, _>(|item| !item.is_dec_digit(), ErrorKind::Digit)
352 }
353}
354
355pub fn multispace0<T, E: ParseError<T>>() -> impl Parser<T, Output = T, Error = E>
369where
370 T: Input,
371 <T as Input>::Item: AsChar,
372{
373 MultiSpace0 { e: PhantomData }
374 }
379
380pub struct MultiSpace0<E> {
382 e: PhantomData<E>,
383}
384
385impl<I, Error: ParseError<I>> Parser<I> for MultiSpace0<Error>
386where
387 I: Input,
388 <I as Input>::Item: AsChar,
389{
390 type Output = I;
391 type Error = Error;
392
393 fn process<OM: crate::OutputMode>(
394 &mut self,
395 i: I,
396 ) -> crate::PResult<OM, I, Self::Output, Self::Error> {
397 i.split_at_position_mode::<OM, _, _>(|item| {
398 let c = item.as_char();
399 !(c == ' ' || c == '\t' || c == '\r' || c == '\n')
400 })
401 }
402}