use std::iter;
pub(crate) struct NumberPadder {
width: usize,
}
impl NumberPadder {
pub(crate) fn new(upper_bound: usize) -> Self {
let width = upper_bound.checked_ilog10().map(|log| log as usize + 1).unwrap_or_default();
Self { width }
}
pub(crate) fn pad_right(&self, number: usize) -> String {
let line_number_width = number.ilog10() as usize + 1;
let number_padding = self.width - line_number_width;
let mut output = String::with_capacity(self.width);
output.extend(iter::repeat_n(' ', number_padding));
output.push_str(&number.to_string());
output
}
}
#[cfg(test)]
mod test {
use super::*;
use rstest::rstest;
#[rstest]
#[case(&[1, 2], &["1", "2"])]
#[case(&[1, 9], &["1", "9"])]
#[case(&[1, 10], &[" 1", "10"])]
#[case(&[1, 10, 100], &[" 1", " 10", "100"])]
fn right_padding(#[case] numbers: &[usize], #[case] expected: &[&str]) {
let max = numbers.iter().max().expect("no numbers");
let padder = NumberPadder::new(*max);
let rendered: Vec<_> = numbers.iter().map(|n| padder.pad_right(*n)).collect();
assert_eq!(rendered, expected);
}
#[test]
fn zero_count() {
NumberPadder::new(0);
}
}