pub const BLOCK_SIZE: usize = 2880;
pub const CARD_SIZE: usize = 80;
pub(crate) const SPACE_FILL: u8 = b' ';
pub(crate) const ZERO_FILL: u8 = 0;
fn blocks_for(len: u64) -> u64 {
len.div_ceil(BLOCK_SIZE as u64)
}
pub(crate) fn padded_len(len: u64) -> u64 {
blocks_for(len).saturating_mul(BLOCK_SIZE as u64)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn block_geometry_constants_are_consistent() {
assert_eq!(BLOCK_SIZE, 2880);
assert_eq!(CARD_SIZE, 80);
assert_eq!(BLOCK_SIZE / CARD_SIZE, 36);
assert_eq!(BLOCK_SIZE % CARD_SIZE, 0);
}
#[test]
fn blocks_for_rounds_up_at_the_boundary() {
let cases = [
(0u64, 0u64),
(1, 1),
(2879, 1),
(2880, 1),
(2881, 2),
(5760, 2),
(5761, 3),
];
for (len, blocks) in cases {
assert_eq!(blocks_for(len), blocks, "blocks_for({len})");
assert_eq!(
padded_len(len),
blocks * BLOCK_SIZE as u64,
"padded_len({len})"
);
}
}
#[test]
fn padded_len_is_idempotent_on_aligned_input() {
for blocks in [0u64, 1, 2, 199] {
let aligned = blocks * BLOCK_SIZE as u64;
assert_eq!(padded_len(aligned), aligned);
}
}
#[test]
fn padded_len_saturates_instead_of_wrapping() {
assert_eq!(padded_len(u64::MAX), u64::MAX);
let wrapped = blocks_for(u64::MAX).wrapping_mul(BLOCK_SIZE as u64);
assert!(
wrapped < u64::MAX,
"the unguarded multiply wraps below the input"
);
}
}