num_runtime_fmt/numeric_trait/
impls.rs1use std::ops::{BitAnd, ShrAssign};
5
6macro_rules! impl_iter {
7 ($iter:ident) => {
8 impl<N> $iter<N> {
9 #[cfg(debug_assertions)]
14 pub fn new(n: N) -> Self
15 where
16 N: Default + PartialOrd,
17 {
18 assert!(n >= N::default(), "n must not be negative");
19 $iter(n)
20 }
21
22 #[cfg(not(debug_assertions))]
24 pub fn new(n: N) -> Self {
25 $iter(n)
26 }
27 }
28
29 impl<N> Iterator for $iter<N>
30 where
31 N: Clone + From<u8> + BitAnd<Output = N> + ShrAssign + PartialEq,
32 {
33 type Item = char;
34
35 fn next(&mut self) -> Option<Self::Item> {
36 if self.0 == 0.into() {
37 return None;
38 }
39 let digit = self.0.clone() & Self::MASK.into();
40 self.0 >>= Self::WIDTH.into();
41 for maybe_digit in 0..=Self::MASK {
46 if digit == maybe_digit.into() {
47 if maybe_digit < 10 {
48 return Some((maybe_digit + b'0') as char);
49 } else {
50 return Some((maybe_digit - 10 + b'a') as char);
51 }
52 }
53 }
54 panic!(
55 "no digit matched when computing {}",
56 std::any::type_name::<$iter<N>>()
57 );
58 }
59 }
60 };
61}
62
63pub struct BinIter<N>(N);
65
66impl<N> BinIter<N> {
67 const WIDTH: u8 = 1;
68 const MASK: u8 = 1;
69}
70
71impl_iter!(BinIter);
72
73pub struct OctIter<N>(N);
75
76impl<N> OctIter<N> {
77 const WIDTH: u8 = 3;
78 const MASK: u8 = 0b0111;
79}
80
81impl_iter!(OctIter);
82
83pub struct HexIter<N>(N);
85
86impl<N> HexIter<N> {
87 const WIDTH: u8 = 4;
88 const MASK: u8 = 0b1111;
89}
90
91impl_iter!(HexIter);
92
93pub struct DecIter(Vec<char>);
97
98impl DecIter {
99 pub fn new<N>(n: N) -> (DecIter, Option<DecIter>)
109 where
110 N: ToString,
111 {
112 let s = n.to_string();
113 debug_assert!(s.chars().all(|c| c == '.' || ('0'..='9').contains(&c)));
114 debug_assert!(s.chars().filter(|&c| c == '.').count() <= 1);
115 let mut found_decimal = false;
116 let (left, mut right): (Vec<_>, Vec<_>) = s.chars().partition(|&c| {
117 found_decimal |= c == '.';
118 !found_decimal
119 });
120
121 right.reverse();
123 right.pop();
125
126 let right = if right.is_empty() || right == ['0'] {
127 None
128 } else {
129 Some(DecIter(right))
130 };
131 (DecIter(left), right)
132 }
133}
134
135impl Iterator for DecIter {
136 type Item = char;
137
138 fn next(&mut self) -> Option<Self::Item> {
139 self.0.pop()
140 }
141}
142
143macro_rules! impl_for {
144 (unsigned_int $type:ident) => {
145 mod $type {
146 use super::{BinIter, DecIter, HexIter, OctIter};
147 use crate::Numeric;
148
149 impl Numeric for $type {
150 type BinIter = BinIter<$type>;
151 type OctIter = OctIter<$type>;
152 type DecLeftIter = DecIter;
153 type DecRightIter = DecIter;
154 type HexIter = HexIter<$type>;
155
156 fn binary(&self) -> Option<Self::BinIter> {
157 Some(BinIter::new(*self))
158 }
159
160 fn octal(&self) -> Option<Self::OctIter> {
161 Some(OctIter::new(*self))
162 }
163
164 fn hex(&self) -> Option<Self::HexIter> {
165 Some(HexIter::new(*self))
166 }
167
168 fn decimal(&self) -> (Self::DecLeftIter, Option<Self::DecRightIter>) {
169 DecIter::new(*self)
170 }
171
172 fn is_negative(&self) -> bool {
173 false
174 }
175 }
176 }
177 };
178 (signed_int $type:ident) => {
179 mod $type {
180 use super::{BinIter, DecIter, HexIter, OctIter};
181 use crate::Numeric;
182
183 impl Numeric for $type {
184 type BinIter = BinIter<$type>;
185 type OctIter = OctIter<$type>;
186 type DecLeftIter = DecIter;
187 type DecRightIter = DecIter;
188 type HexIter = HexIter<$type>;
189
190 fn binary(&self) -> Option<Self::BinIter> {
191 Some(BinIter::new(*self))
192 }
193
194 fn octal(&self) -> Option<Self::OctIter> {
195 Some(OctIter::new(*self))
196 }
197
198 fn hex(&self) -> Option<Self::HexIter> {
199 Some(HexIter::new(*self))
200 }
201
202 fn decimal(&self) -> (Self::DecLeftIter, Option<Self::DecRightIter>) {
203 DecIter::new(self.abs())
204 }
205
206 fn is_negative(&self) -> bool {
207 *self < 0
208 }
209 }
210 }
211 };
212 (float $type:ident) => {
213 mod $type {
214 use super::DecIter;
215 use crate::Numeric;
216 use std::iter::Empty;
217
218 impl Numeric for $type {
219 type BinIter = Empty<char>;
220 type OctIter = Empty<char>;
221 type DecLeftIter = DecIter;
222 type DecRightIter = DecIter;
223 type HexIter = Empty<char>;
224
225 fn binary(&self) -> Option<Self::BinIter> {
226 None
227 }
228
229 fn octal(&self) -> Option<Self::OctIter> {
230 None
231 }
232
233 fn hex(&self) -> Option<Self::HexIter> {
234 None
235 }
236
237 fn decimal(&self) -> (Self::DecLeftIter, Option<Self::DecRightIter>) {
238 DecIter::new(self.abs())
239 }
240
241 fn is_negative(&self) -> bool {
242 *self < 0.0
243 }
244 }
245 }
246 };
247}
248
249impl_for!(unsigned_int u8);
250impl_for!(unsigned_int u16);
251impl_for!(unsigned_int u32);
252impl_for!(unsigned_int u64);
253impl_for!(unsigned_int u128);
254impl_for!(unsigned_int usize);
255impl_for!(signed_int i16);
257impl_for!(signed_int i32);
258impl_for!(signed_int i64);
259impl_for!(signed_int i128);
260impl_for!(signed_int isize);
261impl_for!(float f32);
262impl_for!(float f64);
263
264#[cfg(test)]
265mod tests {
266 macro_rules! suite_for {
267 (dec: int $( $type_int:ident ),+ ; float $( $type_float:ident ),+ ) => {
268 #[allow(non_snake_case)]
269 mod DecIter {
270 use super::super::DecIter as Iter;
271 use std::convert::TryInto;
272
273 $(
274 #[test]
275 fn $type_int() {
276 for n in 1..=$type_int::MAX.min(1024.try_into().unwrap_or($type_int::MAX)) {
278 let expect = format!("{}", n);
279 let (left, right) = Iter::new(n);
280 assert!(right.is_none(), "ints should not have a fractional part");
281
282 let mut digits: Vec<_> = left.map(|d| d.to_string()).collect();
283 digits.reverse();
284 let actual = digits.join("");
285 dbg!(&actual, &expect);
286 assert_eq!(actual, expect);
287 }
288 }
289 )+
290
291 $(
292 #[test]
293 fn $type_float() {
294 for n in 1..=1024 {
296 let n = n as $type_float / 20.0;
297 let expect = format!("{}", n);
298 let (left, right) = Iter::new(n);
299
300 let mut actual: Vec<_> = left.map(|d| d.to_string()).collect();
301 actual.reverse();
302 if let Some(right) = right {
303 actual.push('.'.into());
304 actual.extend(right.map(|d| d.to_string()));
305 }
306
307 let actual = actual.join("");
308 dbg!(&actual, &expect);
309 assert_eq!(actual, expect);
310 }
311 }
312 )+
313 }
314 };
315 ($iter:ident, $fmt:literal, $( $test_type:ident ),+) => {
316 #[allow(non_snake_case)]
317 mod $iter {
318 use super::super::$iter as Iter;
319 use std::convert::TryInto;
320
321 $(
322 #[test]
323 fn $test_type() {
324 for n in 1..=$test_type::MAX.min(1024.try_into().unwrap_or($test_type::MAX)) {
326 let expect = format!($fmt, n);
327 let mut digits: Vec<_> = Iter::new(n).map(|d| d.to_string()).collect();
328 digits.reverse();
329 let actual = digits.join("");
330 dbg!(&actual, &expect);
331 assert_eq!(actual, expect);
332 }
333 }
334 )+
335 }
336 };
337 }
338
339 suite_for!(BinIter, "{:b}", u8, u16, u32, u64, u128, usize, i16, i32, i64, i128, isize);
343 suite_for!(OctIter, "{:o}", u8, u16, u32, u64, u128, usize, i16, i32, i64, i128, isize);
344 suite_for!(HexIter, "{:x}", u8, u16, u32, u64, u128, usize, i16, i32, i64, i128, isize);
345 suite_for!(dec: int u8, u16, u32, u64, u128, usize, i16, i32, i64, i128, isize; float f32, f64);
346}