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<U: UnsignedInteger> Parser for UnsignedParser<U> {
10 type Output<'i> = U;
11 type Then<T: Parser> = Then2<Self, T>;
12
13 #[inline]
14 fn parse<'i>(&self, mut input: &'i [u8]) -> ParseResult<'i, Self::Output<'i>> {
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<S: SignedInteger> Parser for SignedParser<S> {
38 type Output<'i> = S;
39 type Then<T: Parser> = Then2<Self, T>;
40
41 #[expect(clippy::cast_possible_wrap)]
42 #[inline]
43 fn parse<'i>(&self, mut input: &'i [u8]) -> ParseResult<'i, Self::Output<'i>> {
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 #[must_use]
87 pub fn $n() -> $p<std::primitive::$n> {
88 $p(PhantomData)
89 }
90 )+};
91}
92parser_for! { UnsignedParser => u8, u16, u32, u64, u128 }
93parser_for! { SignedParser => i8, i16, i32, i64, i128 }
94
95impl Parseable for std::primitive::usize {
102 type Parser = UnsignedParser<std::primitive::usize>;
103 const PARSER: Self::Parser = UnsignedParser(PhantomData);
104}
105
106#[derive(Copy, Clone)]
107pub struct NumberRange<I> {
108 min: I,
109 max: I,
110}
111
112impl<I: Integer + Parseable> Parser for NumberRange<I> {
113 type Output<'i> = I;
114 type Then<T: Parser> = Then2<Self, T>;
115
116 fn parse<'i>(&self, input: &'i [u8]) -> ParseResult<'i, Self::Output<'i>> {
117 let (v, remaining) = I::PARSER.parse(input)?;
118 if v < self.min {
119 Err((ParseError::too_small(self.min), input))
120 } else if v > self.max {
121 Err((ParseError::too_large(self.max), input))
122 } else {
123 Ok((v, remaining))
124 }
125 }
126}
127
128#[inline]
143#[must_use]
144pub fn number_range<I: Integer + Parseable>(range: RangeInclusive<I>) -> NumberRange<I> {
145 let min = *range.start();
146 let max = *range.end();
147 assert!(min <= max);
148 NumberRange { min, max }
149}