Skip to main content

nekolib/math/
digits.rs

1pub trait Digits: Sized {
2    fn digits(self, base: Self) -> DigitsIter<Self>;
3}
4
5pub struct DigitsIter<I> {
6    x: I,
7    base: I,
8}
9
10impl<I> DigitsIter<I> {
11    pub fn new(x: I, base: I) -> Self { Self { x, base } }
12}
13
14macro_rules! impl_uint {
15    ( $($ty:ty)* ) => { $(
16        impl Digits for $ty {
17            fn digits(self, base: Self) -> DigitsIter<Self> {
18                DigitsIter::new(self, base)
19            }
20        }
21        impl Iterator for DigitsIter<$ty> {
22            type Item = $ty;
23            fn next(&mut self) -> Option<$ty> {
24                if self.x == 0 {
25                    return None;
26                }
27
28                let res = self.x % self.base;
29                self.x /= self.base;
30                Some(res)
31            }
32        }
33    )* }
34}
35
36impl_uint! { u8 u16 u32 u64 u128 usize }
37
38#[test]
39fn sanity_check() {
40    let a: Vec<_> = 1234_u32.digits(10).collect();
41    assert_eq!(a, [4, 3, 2, 1]);
42
43    let a: Vec<_> = 0_u32.digits(10).collect();
44    assert!(a.is_empty());
45
46    let a: Vec<_> = 13_u32.digits(2).collect();
47    assert_eq!(a, [1, 0, 1, 1]);
48}