Skip to main content

oni_comb_parser/text/
integer.rs

1use crate::error::ParseError;
2use crate::fail::{Fail, PResult};
3use crate::input::Input;
4use crate::parser::Parser;
5use crate::str_input::StrInput;
6
7pub struct Integer;
8
9pub fn integer() -> Integer {
10  Integer
11}
12
13impl<'a> Parser<StrInput<'a>> for Integer {
14  type Error = ParseError;
15  type Output = i64;
16
17  #[inline]
18  fn parse_next(&mut self, input: &mut StrInput<'a>) -> PResult<i64, ParseError> {
19    let pos = input.offset();
20    let remaining = input.as_str();
21    let mut consumed = 0;
22
23    // optional leading '-'
24    if remaining.starts_with('-') {
25      consumed += 1;
26    }
27
28    // at least one digit required
29    let digit_start = consumed;
30    for c in remaining[consumed..].chars() {
31      if c.is_ascii_digit() {
32        consumed += c.len_utf8();
33      } else {
34        break;
35      }
36    }
37
38    if consumed == digit_start {
39      return Err(Fail::Backtrack(ParseError::expected_description(pos, "integer")));
40    }
41
42    let s = &remaining[..consumed];
43    let value = s
44      .parse::<i64>()
45      .map_err(|_| Fail::Backtrack(ParseError::expected_description(pos, "integer")))?;
46    input.advance(consumed);
47    Ok(value)
48  }
49}