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
75#[derive(Copy, Clone)]
76pub struct NonZeroParser<I: Integer + Parseable>(PhantomData<I>);
77impl<'i, I: Integer + Parseable> Leaf<'i> for NonZeroParser<I> {
78 type Output = I::NonZero;
79
80 #[inline]
81 fn parse(&self, input: &'i [u8]) -> LeafResult<'i, Self::Output> {
82 let (value, remaining) = I::PARSER.parse(input)?;
83 match I::NonZero::try_from(value) {
84 Ok(value) => Ok((value, remaining)),
85 Err(_) => Err((ParseError::Expected("non-zero integer"), input)),
86 }
87 }
88}
89
90macro_rules! parser_for {
91 ($p:ident => $($n:ident: $nonzero:ident),+ $(,)?) => {$(
92 impl Parseable for std::primitive::$n {
93 type Parser = $p<std::primitive::$n>;
94 const PARSER: Self::Parser = $p(PhantomData);
95 }
96
97 #[doc = concat!("[`Leaf`] parser for [`prim@", stringify!($n), "`] values.")]
98 #[inline]
99 #[must_use]
100 pub fn $n() -> $p<std::primitive::$n> {
101 $p(PhantomData)
102 }
103
104 impl Parseable for std::num::NonZero<$n> {
105 type Parser = NonZeroParser<$n>;
106 const PARSER: Self::Parser = NonZeroParser(PhantomData);
107 }
108
109 #[doc = concat!(
110 "[`Leaf`] parser for [`NonZero<", stringify!($n), ">`](std::num::NonZero) values.",
111 "\n\n# Examples\n```\n",
112 "# use utils::parser::{self, Parser};\n",
113 "assert!(parser::", stringify!($nonzero), "().parse_complete(\"0\").is_err());\n",
114 "assert!(parser::", stringify!($nonzero), "().parse_complete(\"1\").is_ok_and(|n| n.get() == 1));\n",
115 "```"
116 )]
117 #[inline]
118 #[must_use]
119 pub fn $nonzero() -> NonZeroParser<std::primitive::$n> {
120 NonZeroParser(PhantomData)
121 }
122 )+};
123}
124parser_for! {
125 UnsignedParser =>
126 u8: nonzero_u8,
127 u16: nonzero_u16,
128 u32: nonzero_u32,
129 u64: nonzero_u64,
130 u128: nonzero_u128,
131}
132parser_for! {
133 SignedParser =>
134 i8: nonzero_i8,
135 i16: nonzero_i16,
136 i32: nonzero_i32,
137 i64: nonzero_i64,
138 i128: nonzero_i128,
139}
140
141impl Parseable for std::primitive::usize {
148 type Parser = UnsignedParser<std::primitive::usize>;
149 const PARSER: Self::Parser = UnsignedParser(PhantomData);
150}
151
152#[derive(Copy, Clone)]
153pub struct NumberRange<I> {
154 min: I,
155 max: I,
156}
157
158impl<'i, I: Integer + Parseable> Leaf<'i> for NumberRange<I> {
159 type Output = I;
160
161 #[inline]
162 fn parse(&self, input: &'i [u8]) -> LeafResult<'i, Self::Output> {
163 let (v, remaining) = I::PARSER.parse(input)?;
164 if v < self.min {
165 Err((ParseError::too_small(self.min), input))
166 } else if v > self.max {
167 Err((ParseError::too_large(self.max), input))
168 } else {
169 Ok((v, remaining))
170 }
171 }
172}
173
174#[inline]
189#[must_use]
190pub fn number_range<I: Integer + Parseable>(range: RangeInclusive<I>) -> NumberRange<I> {
191 let min = *range.start();
192 let max = *range.end();
193 assert!(min <= max);
194 NumberRange { min, max }
195}
196
197#[derive(Copy, Clone)]
198pub struct Digit {}
199
200impl<'i> Leaf<'i> for Digit {
201 type Output = u8;
202
203 #[inline]
204 fn parse(&self, input: &'i [u8]) -> LeafResult<'i, Self::Output> {
205 if let Some(d @ b'0'..=b'9') = input.first() {
206 Ok((d - b'0', &input[1..]))
207 } else {
208 Err((ParseError::Expected("digit"), input))
209 }
210 }
211}
212
213#[inline]
224#[must_use]
225pub fn digit() -> Digit {
226 Digit {}
227}