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