1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
use core::ops::RangeFrom;
use nom::error::ParseError;
use nom::IResult;
use nom::{AsChar, InputIter, InputTake, Slice};

pub fn satisfy_one<F, I, Error: ParseError<I>>(cond: F) -> impl Fn(I) -> IResult<I, I, Error>
where
    I: Slice<RangeFrom<usize>> + InputIter + InputTake,
    <I as InputIter>::Item: AsChar,
    F: Fn(char) -> bool,
{
    move |input: I| {
        if input.iter_elements().next().is_none() {
            return Err(nom::Err::Error(Error::from_error_kind(
                input,
                nom::error::ErrorKind::Eof,
            )));
        }
        match input.take(1usize).iter_elements().nth(0).map(|a| {
            if cond(a.as_char()) {
                (input.take(1), true)
            } else {
                (input.take(1), false)
            }
        }) {
            Some((slice, matched)) => {
                if matched {
                    Ok((input.slice(1usize..), slice))
                } else {
                    Err(nom::Err::Error(Error::from_error_kind(
                        input,
                        nom::error::ErrorKind::Satisfy,
                    )))
                }
            }
            _ => Err(nom::Err::Error(Error::from_error_kind(
                input,
                nom::error::ErrorKind::Eof,
            ))),
        }
    }
}

#[cfg(test)]
mod test {
    use crate::public_parsers::satisfy_one;

    #[test]
    fn satisfy_one_test() {
        let input = "";
        match satisfy_one::<_, _, (&str, nom::error::ErrorKind)>(|_| true)(input) {
            Ok(_) => panic!("Wrong behavior, should return error with ErrorKind EOF"),
            Err(nom::Err::Error((_, code))) => match code {
                nom::error::ErrorKind::Eof => (),
                _ => panic!("Wrong behavior, should return error with ErrorKind EOF"),
            },
            Err(_) => panic!("?? What are these error types"),
        }
    }
}