1pub struct DigitIterator<T>(pub T, bool); pub trait IntoDigits<T> {
21 fn digits(self) -> DigitIterator<T>;
22}
23
24macro_rules! impl_digit_positive {
25 ($T:ty) => {
26 impl IntoDigits<$T> for $T {
27 fn digits(self) -> DigitIterator<$T> {
28 DigitIterator(self, self == 0)
29 }
30 }
31
32 impl Iterator for DigitIterator<$T> {
33 type Item = u8;
34
35 fn next(&mut self) -> Option<Self::Item> {
36 if self.1 {
37 self.1 = false;
38 Some(0)
39 } else if self.0 != 0 {
40 let remainder = (self.0 % (10 as $T)) as Self::Item;
41 self.0 /= (10 as $T);
42 Some(remainder)
43 } else {
44 None
45 }
46 }
47 }
48 };
49}
50
51macro_rules! impl_digit_negative {
52 ($T:ty) => {
53 impl IntoDigits<$T> for $T {
54 fn digits(self) -> DigitIterator<$T> {
55 DigitIterator(-self, self == 0)
56 }
57 }
58
59 impl Iterator for DigitIterator<$T> {
60 type Item = u8;
61
62 fn next(&mut self) -> Option<Self::Item> {
63 if self.1 {
64 self.1 = false;
65 Some(0)
66 } else if self.0 != 0 {
67 let remainder = (self.0 % (10 as $T)) as Self::Item;
68 self.0 /= (10 as $T);
69 Some(remainder)
70 } else {
71 None
72 }
73 }
74 }
75 };
76}
77
78impl_digit_positive!(u8);
79impl_digit_positive!(u16);
80impl_digit_positive!(u32);
81impl_digit_positive!(u64);
82impl_digit_positive!(u128);
83
84impl_digit_negative!(i8);
85impl_digit_negative!(i16);
86impl_digit_negative!(i32);
87impl_digit_negative!(i64);
88impl_digit_negative!(i128);
89
90#[test]
91fn test_all_numbers() {
92 for x in u128::MIN..10000u128 {
93 let length = x
94 .digits()
95 .enumerate()
96 .map(|(idx, _)| idx + 1)
97 .last()
98 .unwrap();
99 assert_eq!(length, x.to_string().len());
100 }
101
102 for x in 0..-10000i128 {
103 let length = x
104 .digits()
105 .enumerate()
106 .map(|(idx, _)| idx + 1)
107 .last()
108 .unwrap();
109 assert_eq!(length, x.to_string().len());
110 }
111}