1use std::marker::PhantomData;
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 bytes = self.as_ref().bytes();
56 ParseUnsigned { bytes, phantom: PhantomData }
57 }
58
59 #[inline]
60 fn iter_signed<T: Signed>(&self) -> impl Iterator<Item = T> {
61 let bytes = self.as_ref().bytes();
62 ParseSigned { bytes, phantom: PhantomData }
63 }
64}
65
66struct ParseUnsigned<I, T> {
67 bytes: I,
68 phantom: PhantomData<T>,
69}
70
71impl<I: Iterator<Item = u8>, T: Unsigned> Iterator for ParseUnsigned<I, T> {
72 type Item = T;
73
74 #[inline]
75 fn size_hint(&self) -> (usize, Option<usize>) {
76 let (lower, upper) = self.bytes.size_hint();
77 (lower / 3, upper.map(|u| u / 3))
78 }
79
80 #[inline]
81 fn next(&mut self) -> Option<Self::Item> {
82 try_unsigned(&mut self.bytes)
83 }
84}
85
86struct ParseSigned<I, T> {
87 bytes: I,
88 phantom: PhantomData<T>,
89}
90
91impl<I: Iterator<Item = u8>, T: Signed> Iterator for ParseSigned<I, T> {
92 type Item = T;
93
94 #[inline]
95 fn size_hint(&self) -> (usize, Option<usize>) {
96 let (lower, upper) = self.bytes.size_hint();
97 (lower / 3, upper.map(|u| u / 3))
98 }
99
100 #[inline]
101 fn next(&mut self) -> Option<Self::Item> {
102 try_signed(&mut self.bytes)
103 }
104}
105
106fn try_unsigned<T: Unsigned>(bytes: &mut impl Iterator<Item = u8>) -> Option<T> {
107 let mut n = loop {
108 let digit = bytes.next()?.to_decimal();
109 if digit < 10 {
110 break T::from(digit);
111 }
112 };
113
114 for byte in bytes {
115 let digit = byte.to_decimal();
116 if digit >= 10 {
117 break;
118 }
119 n = T::TEN * n + T::from(digit);
120 }
121
122 Some(n)
123}
124
125fn try_signed<T: Signed>(bytes: &mut impl Iterator<Item = u8>) -> Option<T> {
126 let (mut n, negative) = loop {
127 let digit = bytes.next()?.to_decimal();
128 if digit == MINUS {
129 break (T::ZERO, true);
130 }
131 if digit < 10 {
132 break (T::from(digit), false);
133 }
134 };
135
136 for byte in bytes {
137 let digit = byte.to_decimal();
138 if digit >= 10 {
139 break;
140 }
141 n = T::TEN * n + T::from(digit);
142 }
143
144 Some(if negative { -n } else { n })
145}