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