split-digits 0.2.2

library to parse and interpret poetic source code
Documentation
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
use std::collections::VecDeque;

struct DigitAndPosition {
    digit: u8,
    position: u32,
}

fn get_most_significant_digit_and_position(d: usize) -> DigitAndPosition {
    let mut d = d;
    let mut position = 0;
    let mut digit: u8 = 0;

    while d > 0 {
        digit = (d % 10) as u8;
        d /= 10;
        position += 1;
    }

    DigitAndPosition { digit, position }
}

struct SplitDigitIterator {
    num: usize,
    trailing_zeroes: u32,
}

impl SplitDigitIterator {
    pub fn new(num: usize) -> Self {
        Self {
            num,
            trailing_zeroes: 0,
        }
    }
}

impl Iterator for SplitDigitIterator {
    type Item = u8;

    fn next(&mut self) -> Option<Self::Item> {
        if self.num != 0 {
            let dap = get_most_significant_digit_and_position(self.num);
            let digit = dap.digit;
            let sub = 10_usize.pow(dap.position) * dap.digit as usize;
            self.trailing_zeroes = dap.position;
            self.num -= sub;
            Some(digit)
        } else {
            if self.trailing_zeroes > 0 {
                self.trailing_zeroes -= 1;
                return Some(0);
            }

            None
        }
    }
}

impl DoubleEndedIterator for SplitDigitIterator {
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.num != 0 {
            let digit = (self.num % 10) as u8;
            self.num /= 10;
            Some(digit)
        } else {
            None
        }
    }
}

fn split_digits_vec_deque(d: usize) -> Vec<u8> {
    let mut digits = VecDeque::new();
    let mut n = d;
    while n > 0 {
        digits.push_front((n % 10) as u8);
        n /= 10;
    }

    digits.into()
}

fn split_digits_vec(d: usize) -> Vec<u8> {
    let mut digits = Vec::new();
    let mut n = d;
    while n > 0 {
        digits.insert(0, (n % 10) as u8);
        n /= 10;
    }

    digits
}

fn split_digits_vec_push_reverse(d: usize) -> Vec<u8> {
    let mut digits = Vec::new();
    let mut n = d;
    while n > 0 {
        digits.push((n % 10) as u8);
        n /= 10;
    }

    digits.reverse();

    digits
}

fn split_digits_iterator_reverse(d: usize) -> Vec<u8> {
    let mut digits: Vec<u8> = SplitDigitIterator::new(d).rev().collect();
    digits.reverse();

    digits
}

fn split_digits_iterator(d: usize) -> Vec<u8> {
    SplitDigitIterator::new(d).collect()
}

fn split_digits_string(d: usize) -> Vec<u8> {
    d.to_string()
        .chars()
        .map(|c| c.to_string().parse::<u8>().unwrap())
        .collect()
}

fn benchmark_split_digits(c: &mut Criterion) {
    let mut group = c.benchmark_group("split_digits");
    for (d, s) in [
        (1, 1),
        (12, 2),
        (123, 3),
        (1234, 4),
        (12345, 5),
        (123456, 6),
        (1234567, 7),
    ]
    .iter()
    {
        group.bench_with_input(BenchmarkId::new("split_digits_vec_deque", s), d, |b, d| {
            b.iter(|| split_digits_vec_deque(black_box(*d)))
        });
        group.bench_with_input(BenchmarkId::new("split_digits_vec", s), d, |b, d| {
            b.iter(|| split_digits_vec(black_box(*d)))
        });
        group.bench_with_input(
            BenchmarkId::new("split_digits_vec_push_reverse", s),
            d,
            |b, d| b.iter(|| split_digits_vec_push_reverse(black_box(*d))),
        );
        group.bench_with_input(
            BenchmarkId::new("split_digits_iterator_reverse", s),
            d,
            |b, d| b.iter(|| split_digits_iterator_reverse(black_box(*d))),
        );
        group.bench_with_input(BenchmarkId::new("split_digits_iterator", s), d, |b, d| {
            b.iter(|| split_digits_iterator(black_box(*d)))
        });
        group.bench_with_input(BenchmarkId::new("split_digits_string", s), d, |b, d| {
            b.iter(|| split_digits_string(black_box(*d)))
        });
    }

    group.finish()
}

criterion_group!(benches, benchmark_split_digits);
criterion_main!(benches);