digits_iterator 0.1.0

Iterate over the digits of numbers in an arbitrary radix
Documentation
#[cfg(test)]
mod tests;

use int::Int;

pub struct Digits<T>
where
    T: Int,
{
    n: T::Unsigned,
    div: T::Unsigned,
    base: T::Unsigned,
}

impl<T> Digits<T>
where
    T: Int,
{
    pub fn new(n: T) -> Digits<T> {
        Self::with_base(n, 10)
    }

    pub fn with_base(n: T, base: u32) -> Digits<T> {
        fn is_ok_as_base(base: u32) -> bool {
            base >= 2 && base <= 36
        }
        assert!(is_ok_as_base(base));

        let base = T::from_base(base);

        let mut div = T::one();
        loop {
            div = match div.checked_mul(base) {
                None => break,
                Some(i) if n < i => break,
                Some(i) => i,
            };
        }

        Digits {
            n: n.as_unsigned(),
            div: div.as_unsigned(),
            base: base.as_unsigned(),
        }
    }
}

macro_rules! impl_iterators {
    { $from: ty, $u: ty } => {
        impl Iterator for Digits<$from> {
            type Item = u8;

            fn next(&mut self) -> Option<Self::Item> {
                if self.div == 0 {
                    None
                } else {
                    let result = self.n / self.div;
                    self.n %= self.div;
                    self.div /= self.base;

                    Some(result as u8)
                }
            }
        }

        impl DoubleEndedIterator for Digits<$from> {
            fn next_back(&mut self) -> Option<Self::Item> {
                if self.div == 0 {
                    None
                } else {
                    let result = self.n % self.base;
                    self.n /= self.base;
                    self.div /= self.base;

                    Some(result as u8)
                }
            }
        }
    }
}

impl_iterators!(isize, usize);
impl_iterators!(usize, usize);

impl_iterators!(i128, u128);
impl_iterators!(u128, u128);

impl_iterators!(i64, u64);
impl_iterators!(u64, u64);

impl_iterators!(i32, u32);
impl_iterators!(u32, u32);

impl_iterators!(i16, u16);
impl_iterators!(u16, u16);

impl_iterators!(i8, u8);
impl_iterators!(u8, u8);