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