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
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
use crate::parsers::branch::alternative;
use crate::parsers::characters::{decimal_digit1, read_any_of, read_char};
use crate::parsers::combinator::optional;
use crate::parsers::helpers::{consumed, ensure, ignore_result};
use crate::parsers::sequence::tuple;
use crate::parsers::verifiers::text_verifier;
use crate::{ParserResult, Reader};

/// Reads an integer number.
pub fn read_integer<'a, C, Err>(reader: &mut Reader<'a, Err, C>) -> ParserResult<&'a str, Err> {
    consumed(tuple((
        optional(read_any_of(text_verifier("+-"))),
        decimal_digit1,
    )))(reader)
}

/// Reads a float number.
pub fn read_float<'a, C, Err: From<&'static str>>(
    reader: &mut Reader<'a, Err, C>,
) -> ParserResult<&'a str, Err> {
    consumed(tuple((
        optional(read_any_of(text_verifier("+-"))),
        alternative((
            ignore_result(tuple((
                decimal_digit1,
                optional(tuple((read_char('.'), optional(decimal_digit1)))),
            ))),
            ignore_result(tuple((read_char('.'), decimal_digit1))),
        )),
        optional(tuple((
            read_any_of(text_verifier("eE")),
            optional(read_any_of(text_verifier("+-"))),
            ensure(decimal_digit1, |_| {
                "A number is required after the exponent".into()
            }),
        ))),
    )))(reader)
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------

#[cfg(test)]
mod test {
    use crate::result::ParserResultError;

    use super::*;

    #[test]
    fn test_read_integer() {
        let mut reader = Reader::new("0123456789");
        let result = read_integer(&mut reader);
        assert_eq!(result, Ok("0123456789"));

        let mut reader = Reader::new("+0123456789");
        let result = read_integer(&mut reader);
        assert_eq!(result, Ok("+0123456789"));

        let mut reader = Reader::new("-0123456789");
        let result = read_integer(&mut reader);
        assert_eq!(result, Ok("-0123456789"));

        let mut reader = Reader::new("a23");
        let result = read_integer(&mut reader);
        assert_eq!(result, Err(ParserResultError::NotFound));
    }

    #[test]
    fn test_read_float() {
        let mut reader = Reader::new_with_error::<&str>("0123456789");
        let result = read_float(&mut reader);
        assert_eq!(result, Ok("0123456789"));

        let mut reader = Reader::new_with_error::<&str>("+0123456789.0123456789");
        let result = read_float(&mut reader);
        assert_eq!(result, Ok("+0123456789.0123456789"));

        let mut reader = Reader::new_with_error::<&str>("-.0123456789");
        let result = read_float(&mut reader);
        assert_eq!(result, Ok("-.0123456789"));

        let mut reader = Reader::new_with_error::<&str>("-0123456789.");
        let result = read_float(&mut reader);
        assert_eq!(result, Ok("-0123456789."));

        let mut reader = Reader::new_with_error::<&str>("0123456789e0123456789");
        let result = read_float(&mut reader);
        assert_eq!(result, Ok("0123456789e0123456789"));

        let mut reader = Reader::new_with_error::<&str>("0123456789E+0123456789");
        let result = read_float(&mut reader);
        assert_eq!(result, Ok("0123456789E+0123456789"));

        let mut reader = Reader::new_with_error::<&str>("0123456789E-0123456789");
        let result = read_float(&mut reader);
        assert_eq!(result, Ok("0123456789E-0123456789"));

        let mut reader = Reader::new_with_error::<&str>("a23");
        let result = read_float(&mut reader);
        assert_eq!(result, Err(ParserResultError::NotFound));
    }
}