1use crate::number::{Integer, SignedInteger, UnsignedInteger};
2use crate::parser::{Leaf, LeafResult, ParseError, Parseable};
3use std::marker::PhantomData;
4use std::ops::RangeInclusive;
5
6#[derive(Copy, Clone)]
7pub struct UnsignedParser<U: UnsignedInteger>(PhantomData<U>);
8impl<'i, U: UnsignedInteger> Leaf<'i> for UnsignedParser<U> {
9 type Output = U;
10
11 #[inline]
12 fn parse(&self, mut input: &'i [u8]) -> LeafResult<'i, Self::Output> {
13 let mut n = match input {
14 [d @ b'0'..=b'9', ..] => {
15 input = &input[1..];
16 U::from(d - b'0')
17 }
18 _ => return Err((ParseError::Expected("unsigned integer"), input)),
19 };
20
21 while let Some(d @ b'0'..=b'9') = input.first() {
22 n = n
23 .checked_mul(U::from(10))
24 .and_then(|n| n.checked_add(U::from(d - b'0')))
25 .ok_or((ParseError::too_large(U::MAX), input))?;
26 input = &input[1..];
27 }
28
29 Ok((n, input))
30 }
31}
32
33#[derive(Copy, Clone)]
34pub struct SignedParser<S: SignedInteger>(PhantomData<S>);
35impl<'i, S: SignedInteger> Leaf<'i> for SignedParser<S> {
36 type Output = S;
37
38 #[expect(clippy::cast_possible_wrap)]
39 #[inline]
40 fn parse(&self, mut input: &'i [u8]) -> LeafResult<'i, Self::Output> {
41 let (mut n, positive) = match input {
42 [d @ b'0'..=b'9', rem @ ..] | [b'+', d @ b'0'..=b'9', rem @ ..] => {
43 input = rem;
44 (S::from((d - b'0') as i8), true)
45 }
46 [b'-', d @ b'0'..=b'9', rem @ ..] => {
47 input = rem;
48 (S::from(-((d - b'0') as i8)), false)
49 }
50 _ => return Err((ParseError::Expected("signed integer"), input)),
51 };
52
53 if positive {
54 while let Some(d @ b'0'..=b'9') = input.first() {
55 n = n
56 .checked_mul(S::from(10))
57 .and_then(|n| n.checked_add(S::from((d - b'0') as i8)))
58 .ok_or((ParseError::too_large(S::MAX), input))?;
59 input = &input[1..];
60 }
61 } else {
62 while let Some(d @ b'0'..=b'9') = input.first() {
63 n = n
64 .checked_mul(S::from(10))
65 .and_then(|n| n.checked_sub(S::from((d - b'0') as i8)))
66 .ok_or((ParseError::too_small(S::MIN), input))?;
67 input = &input[1..];
68 }
69 }
70
71 Ok((n, input))
72 }
73}
74
75macro_rules! parser_for {
76 ($p:ident => $($n:ident),+) => {$(
77 impl Parseable for std::primitive::$n {
78 type Parser = $p<std::primitive::$n>;
79 const PARSER: Self::Parser = $p(PhantomData);
80 }
81
82 #[doc = concat!("[`Leaf`] parser for [`prim@", stringify!($n), "`] values.")]
83 #[inline]
84 #[must_use]
85 pub fn $n() -> $p<std::primitive::$n> {
86 $p(PhantomData)
87 }
88 )+};
89}
90parser_for! { UnsignedParser => u8, u16, u32, u64, u128 }
91parser_for! { SignedParser => i8, i16, i32, i64, i128 }
92
93impl Parseable for std::primitive::usize {
100 type Parser = UnsignedParser<std::primitive::usize>;
101 const PARSER: Self::Parser = UnsignedParser(PhantomData);
102}
103
104#[derive(Copy, Clone)]
105pub struct NumberRange<I> {
106 min: I,
107 max: I,
108}
109
110impl<'i, I: Integer + Parseable> Leaf<'i> for NumberRange<I> {
111 type Output = I;
112
113 #[inline]
114 fn parse(&self, input: &'i [u8]) -> LeafResult<'i, Self::Output> {
115 let (v, remaining) = I::PARSER.parse(input)?;
116 if v < self.min {
117 Err((ParseError::too_small(self.min), input))
118 } else if v > self.max {
119 Err((ParseError::too_large(self.max), input))
120 } else {
121 Ok((v, remaining))
122 }
123 }
124}
125
126#[inline]
141#[must_use]
142pub fn number_range<I: Integer + Parseable>(range: RangeInclusive<I>) -> NumberRange<I> {
143 let min = *range.start();
144 let max = *range.end();
145 assert!(min <= max);
146 NumberRange { min, max }
147}
148
149#[derive(Copy, Clone)]
150pub struct Digit {}
151
152impl<'i> Leaf<'i> for Digit {
153 type Output = u8;
154
155 #[inline]
156 fn parse(&self, input: &'i [u8]) -> LeafResult<'i, Self::Output> {
157 if let Some(d @ b'0'..=b'9') = input.first() {
158 Ok((d - b'0', &input[1..]))
159 } else {
160 Err((ParseError::Expected("digit"), input))
161 }
162 }
163}
164
165#[inline]
176#[must_use]
177pub fn digit() -> Digit {
178 Digit {}
179}