1use std::iter::from_fn;
17
18use crate::util::integer::*;
19
20const MINUS: u8 = b'-'.wrapping_sub(b'0');
21
22pub trait ParseByte {
23 fn to_decimal<T: Integer>(self) -> T;
24}
25
26impl ParseByte for u8 {
27 #[inline]
28 fn to_decimal<T: Integer>(self) -> T {
29 T::from(self.wrapping_sub(b'0'))
30 }
31}
32
33pub trait ParseOps {
34 fn unsigned<T: Unsigned>(&self) -> T;
35 fn signed<T: Signed>(&self) -> T;
36 fn iter_unsigned<T: Unsigned>(&self) -> impl Iterator<Item = T>;
37 fn iter_signed<T: Signed>(&self) -> impl Iterator<Item = T>;
38}
39
40impl<S: AsRef<str> + ?Sized> ParseOps for S {
41 #[inline]
42 fn unsigned<T: Unsigned>(&self) -> T {
43 let mut bytes = self.as_ref().bytes();
44 try_unsigned(&mut bytes).unwrap()
45 }
46
47 #[inline]
48 fn signed<T: Signed>(&self) -> T {
49 let mut bytes = self.as_ref().bytes();
50 try_signed(&mut bytes).unwrap()
51 }
52
53 #[inline]
54 fn iter_unsigned<T: Unsigned>(&self) -> impl Iterator<Item = T> {
55 let mut bytes = self.as_ref().bytes();
56 from_fn(move || try_unsigned(&mut bytes))
57 }
58
59 #[inline]
60 fn iter_signed<T: Signed>(&self) -> impl Iterator<Item = T> {
61 let mut bytes = self.as_ref().bytes();
62 from_fn(move || try_signed(&mut bytes))
63 }
64}
65
66fn try_unsigned<T: Unsigned>(bytes: &mut impl Iterator<Item = u8>) -> Option<T> {
67 let mut n = loop {
68 let digit = bytes.next()?.to_decimal();
69 if digit < 10 {
70 break T::from(digit);
71 }
72 };
73
74 for byte in bytes {
75 let digit = byte.to_decimal();
76 if digit >= 10 {
77 break;
78 }
79 n = T::TEN * n + T::from(digit);
80 }
81
82 Some(n)
83}
84
85fn try_signed<T: Signed>(bytes: &mut impl Iterator<Item = u8>) -> Option<T> {
86 let (mut n, negative) = loop {
87 let digit = bytes.next()?.to_decimal();
88 if digit == MINUS {
89 break (T::ZERO, true);
90 }
91 if digit < 10 {
92 break (T::from(digit), false);
93 }
94 };
95
96 for byte in bytes {
97 let digit = byte.to_decimal();
98 if digit >= 10 {
99 break;
100 }
101 n = T::TEN * n + T::from(digit);
102 }
103
104 Some(if negative { -n } else { n })
105}