From d58ee5a28a5ffbf7da142a233104d75fe48d96ff Mon Sep 17 00:00:00 2001 From: Jed Denlea Date: Mon, 24 Apr 2023 23:41:59 -0700 Subject: [PATCH] wc: skip String to measure number length Sadly ilog10 isn't available until we use 1.67, but we can get close in the meantime. --- src/uu/wc/src/wc.rs | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/uu/wc/src/wc.rs b/src/uu/wc/src/wc.rs index 00f898868..2ed43e16a 100644 --- a/src/uu/wc/src/wc.rs +++ b/src/uu/wc/src/wc.rs @@ -5,7 +5,7 @@ // * For the full copyright and license information, please view the LICENSE // * file that was distributed with this source code. -// cSpell:ignore wc wc's +// cSpell:ignore ilog wc wc's mod count_fast; mod countable; @@ -632,7 +632,14 @@ fn compute_number_width(inputs: &[Input], settings: &Settings) -> usize { } } - max(minimum_width, total.to_string().len()) + if total == 0 { + minimum_width + } else { + let total_width = (1 + ilog10_u64(total)) + .try_into() + .expect("ilog of a u64 should fit into a usize"); + max(total_width, minimum_width) + } } fn wc(inputs: &[Input], settings: &Settings) -> UResult<()> { @@ -712,3 +719,29 @@ fn print_stats( writeln!(stdout) } } + +// TODO: remove and just use usize::ilog10 once the MSRV is >= 1.67. +fn ilog10_u64(mut u: u64) -> u32 { + if u == 0 { + panic!("cannot compute log of 0") + } + let mut log = 0; + if u >= 10_000_000_000 { + log += 10; + u /= 10_000_000_000; + } + if u >= 100_000 { + log += 5; + u /= 100_000; + } + // Rust's standard library in versions >= 1.67 does something even more clever than this, but + // this should work just fine for the time being. + log + match u { + 1..=9 => 0, + 10..=99 => 1, + 100..=999 => 2, + 1000..=9999 => 3, + 10000..=99999 => 4, + _ => unreachable!(), + } +}