tree_builder/
public_parsers.rs1use core::ops::RangeFrom;
2use nom::error::ParseError;
3use nom::IResult;
4use nom::{AsChar, InputIter, InputTake, Slice};
5
6pub fn satisfy_one<F, I, Error: ParseError<I>>(cond: F) -> impl Fn(I) -> IResult<I, I, Error>
9where
10 I: Slice<RangeFrom<usize>> + InputIter + InputTake,
11 <I as InputIter>::Item: AsChar,
12 F: Fn(char) -> bool,
13{
14 move |input: I| {
15 if input.iter_elements().next().is_none() {
16 return Err(nom::Err::Error(Error::from_error_kind(
17 input,
18 nom::error::ErrorKind::Eof,
19 )));
20 }
21 match input.take(1usize).iter_elements().nth(0).map(|a| {
22 if cond(a.as_char()) {
23 (input.take(1), true)
24 } else {
25 (input.take(1), false)
26 }
27 }) {
28 Some((slice, matched)) => {
29 if matched {
30 Ok((input.slice(1usize..), slice))
31 } else {
32 Err(nom::Err::Error(Error::from_error_kind(
33 input,
34 nom::error::ErrorKind::Satisfy,
35 )))
36 }
37 }
38 _ => Err(nom::Err::Error(Error::from_error_kind(
39 input,
40 nom::error::ErrorKind::Eof,
41 ))),
42 }
43 }
44}
45
46#[cfg(test)]
47mod test {
48 use crate::public_parsers::satisfy_one;
49
50 #[test]
51 fn satisfy_one_test() {
52 let input = "";
53 match satisfy_one::<_, _, (&str, nom::error::ErrorKind)>(|_| true)(input) {
54 Ok(_) => panic!("Wrong behavior, should return error with ErrorKind EOF"),
55 Err(nom::Err::Error((_, code))) => match code {
56 nom::error::ErrorKind::Eof => (),
57 _ => panic!("Wrong behavior, should return error with ErrorKind EOF"),
58 },
59 Err(_) => panic!("?? What are these error types"),
60 }
61 }
62}