udled_tokenizers/
numeric.rs1use alloc::string::ToString;
2use udled::{
3 tokenizers::{opt, Digit, Peek},
4 AsBytes, AsChar, AsSlice, AsStr, Buffer, Error, Item, Reader, Span, Tokenizer, TokenizerExt,
5};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
8pub struct Integer;
9
10impl<'input, B> Tokenizer<'input, B> for Integer
11where
12 B: Buffer<'input>,
13 B::Item: AsChar,
14{
15 type Token = Item<i128>;
16
17 fn to_token<'a>(&self, reader: &mut Reader<'_, 'input, B>) -> Result<Self::Token, Error> {
18 let start = reader.position();
19 let mut val: i128 = 0;
20 let base = 10;
21
22 let sign = if reader.eat('-').is_ok() { -1 } else { 1 };
23
24 loop {
25 let ch = reader.parse(Digit(base))?;
26
27 val = (base as i128) * val + (ch.value as i128);
28
29 if !reader.is(Digit(base)) {
30 break;
31 }
32 }
33
34 return Ok(Item::new(Span::new(start, reader.position()), val * sign));
35 }
36
37 fn peek(&self, reader: &mut Reader<'_, 'input, B>) -> bool {
38 reader.is(Peek((opt('-'), Digit(10))))
39 }
40}
41
42#[derive(Debug, Clone, Copy, Default)]
43pub struct Float;
44
45impl<'input, B> Tokenizer<'input, B> for Float
46where
47 B: Buffer<'input>,
48 B::Item: AsChar,
49 B::Source: AsBytes<'input>,
50{
51 type Token = Item<f64>;
52
53 fn to_token<'a>(&self, reader: &mut Reader<'_, 'input, B>) -> Result<Self::Token, Error> {
54 let span = reader.parse(
55 (
56 Integer,
57 '.',
58 Digit(10).many(),
59 ('e'.or('E'), opt('-'), Digit(10).many()).optional(),
60 )
61 .spanned(),
62 )?;
63
64 let string = reader.buffer().source().as_bytes();
65 let string = unsafe { core::str::from_utf8_unchecked(string) };
66 let string = span.slice(string).unwrap();
67
68 let float: f64 = string
69 .parse()
70 .map_err(|err: core::num::ParseFloatError| reader.error(err.to_string()))?;
71
72 Ok(Item::new(span, float))
73 }
74
75 fn peek(&self, reader: &mut Reader<'_, 'input, B>) -> bool {
76 reader.is(Peek((Integer, '.')))
77 }
78}
79
80#[cfg(test)]
81mod test {
82 use udled::Input;
83
84 use super::{Float, Integer};
85
86 #[test]
87 fn integer() {
88 let mut input = Input::new("10203 0 42");
89
90 let (a, _, b, _, c) = input.parse((Integer, ' ', Integer, ' ', Integer)).unwrap();
91
92 assert_eq!(a.value, 10203);
93 assert_eq!(b.value, 0);
94 assert_eq!(c.value, 42);
95 }
96
97 #[test]
109 fn float() {
110 let mut input = Input::new("1.0000033 2003.303 12.03e-20");
111
112 let (a, _, b, _, c) = input.parse((Float, ' ', Float, ' ', Float)).unwrap();
113
114 assert_eq!(a.value, 1.0000033);
115 assert_eq!(b.value, 2003.303);
116 assert_eq!(c.value, 12.03e-20);
117 }
118}