1use crate::util::integer::*;
17use std::marker::PhantomData;
18use std::str::Bytes;
19
20const MINUS: u8 = b'-'.wrapping_sub(b'0');
21
22pub trait ParseByte {
23 fn to_decimal(self) -> u8;
24}
25
26impl ParseByte for u8 {
27 #[inline]
28 fn to_decimal(self) -> u8 {
29 self.wrapping_sub(b'0')
30 }
31}
32
33pub struct ParseUnsigned<'a, T> {
34 bytes: Bytes<'a>,
35 phantom: PhantomData<T>,
36}
37
38pub struct ParseSigned<'a, T> {
39 bytes: Bytes<'a>,
40 phantom: PhantomData<T>,
41}
42
43pub trait ParseOps {
44 fn unsigned<T: Unsigned<T>>(&self) -> T;
45 fn signed<T: Signed<T>>(&self) -> T;
46 fn iter_unsigned<T: Unsigned<T>>(&self) -> ParseUnsigned<'_, T>;
47 fn iter_signed<T: Signed<T>>(&self) -> ParseSigned<'_, T>;
48}
49
50impl<S: AsRef<str>> ParseOps for S {
51 fn unsigned<T: Unsigned<T>>(&self) -> T {
52 let str = self.as_ref();
53 try_unsigned(&mut str.bytes()).unwrap_or_else(|| panic!("Unable to parse \"{str}\""))
54 }
55
56 fn signed<T: Signed<T>>(&self) -> T {
57 let str = self.as_ref();
58 try_signed(&mut str.bytes()).unwrap_or_else(|| panic!("Unable to parse \"{str}\""))
59 }
60
61 fn iter_unsigned<T: Unsigned<T>>(&self) -> ParseUnsigned<'_, T> {
62 ParseUnsigned { bytes: self.as_ref().bytes(), phantom: PhantomData }
63 }
64
65 fn iter_signed<T: Signed<T>>(&self) -> ParseSigned<'_, T> {
66 ParseSigned { bytes: self.as_ref().bytes(), phantom: PhantomData }
67 }
68}
69
70impl<T: Unsigned<T>> Iterator for ParseUnsigned<'_, T> {
71 type Item = T;
72
73 #[inline]
74 fn size_hint(&self) -> (usize, Option<usize>) {
75 let (lower, upper) = self.bytes.size_hint();
76 (lower / 3, upper.map(|u| u / 3))
77 }
78
79 #[inline]
80 fn next(&mut self) -> Option<Self::Item> {
81 try_unsigned(&mut self.bytes)
82 }
83}
84
85impl<T: Signed<T>> Iterator for ParseSigned<'_, T> {
86 type Item = T;
87
88 #[inline]
89 fn size_hint(&self) -> (usize, Option<usize>) {
90 let (lower, upper) = self.bytes.size_hint();
91 (lower / 3, upper.map(|u| u / 3))
92 }
93
94 #[inline]
95 fn next(&mut self) -> Option<Self::Item> {
96 try_signed(&mut self.bytes)
97 }
98}
99
100fn try_unsigned<T: Unsigned<T>>(bytes: &mut Bytes<'_>) -> Option<T> {
101 let mut n = loop {
102 let digit = bytes.next()?.to_decimal();
103 if digit < 10 {
104 break T::from(digit);
105 }
106 };
107
108 for byte in bytes {
109 let digit = byte.to_decimal();
110 if digit >= 10 {
111 break;
112 }
113 n = T::TEN * n + T::from(digit);
114 }
115
116 Some(n)
117}
118
119fn try_signed<T: Signed<T>>(bytes: &mut Bytes<'_>) -> Option<T> {
120 let (mut n, negative) = loop {
121 let digit = bytes.next()?.to_decimal();
122 if digit == MINUS {
123 break (T::ZERO, true);
124 }
125 if digit < 10 {
126 break (T::from(digit), false);
127 }
128 };
129
130 for byte in bytes {
131 let digit = byte.to_decimal();
132 if digit >= 10 {
133 break;
134 }
135 n = T::TEN * n + T::from(digit);
136 }
137
138 Some(if negative { -n } else { n })
139}