1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

ls: Add extend_pad_left/right functions that operate on Vec<u8>

Saves another ~7% performance.
This commit is contained in:
Nicolas Boichat 2025-04-19 20:47:47 +02:00
parent 8b9960f093
commit 4212385f76

View file

@ -5,6 +5,7 @@
// spell-checker:ignore (ToDO) somegroup nlink tabsize dired subdired dtype colorterm stringly
use std::iter;
#[cfg(windows)]
use std::os::windows::fs::MetadataExt;
use std::{cell::OnceCell, num::IntErrorKind};
@ -2420,12 +2421,33 @@ fn display_dir_entry_size(
}
}
fn pad_left(string: &str, count: usize) -> String {
format!("{string:>count$}")
// A simple, performant, ExtendPad trait to add a string to a Vec<u8>, padding with spaces
// on the left or right, without making additional copies, or using formatting functions.
trait ExtendPad {
fn extend_pad_left(&mut self, string: &str, count: usize);
fn extend_pad_right(&mut self, string: &str, count: usize);
}
fn pad_right(string: &str, count: usize) -> String {
format!("{string:<count$}")
impl ExtendPad for Vec<u8> {
fn extend_pad_left(&mut self, string: &str, count: usize) {
if string.len() < count {
self.extend(iter::repeat_n(b' ', count - string.len()));
}
self.extend(string.as_bytes());
}
fn extend_pad_right(&mut self, string: &str, count: usize) {
self.extend(string.as_bytes());
if string.len() < count {
self.extend(iter::repeat_n(b' ', count - string.len()));
}
}
}
// TODO: Consider converting callers to use ExtendPad instead, as it avoids
// additional copies.
fn pad_left(string: &str, count: usize) -> String {
format!("{string:>count$}")
}
fn return_total(
@ -2784,61 +2806,55 @@ fn display_item_long(
output_display.extend(b"+");
}
output_display.extend(b" ");
output_display.extend(pad_left(&display_symlink_count(md), padding.link_count).as_bytes());
output_display.extend_pad_left(&display_symlink_count(md), padding.link_count);
if config.long.owner {
output_display.extend(b" ");
output_display.extend(pad_right(&display_uname(md, config), padding.uname).as_bytes());
output_display.extend_pad_right(&display_uname(md, config), padding.uname);
}
if config.long.group {
output_display.extend(b" ");
output_display.extend(pad_right(&display_group(md, config), padding.group).as_bytes());
output_display.extend_pad_right(&display_group(md, config), padding.group);
}
if config.context {
output_display.extend(b" ");
output_display.extend(pad_right(&item.security_context, padding.context).as_bytes());
output_display.extend_pad_right(&item.security_context, padding.context);
}
// Author is only different from owner on GNU/Hurd, so we reuse
// the owner, since GNU/Hurd is not currently supported by Rust.
if config.long.author {
output_display.extend(b" ");
output_display.extend(pad_right(&display_uname(md, config), padding.uname).as_bytes());
output_display.extend_pad_right(&display_uname(md, config), padding.uname);
}
match display_len_or_rdev(md, config) {
SizeOrDeviceId::Size(size) => {
output_display.extend(b" ");
output_display.extend(pad_left(&size, padding.size).as_bytes());
output_display.extend_pad_left(&size, padding.size);
}
SizeOrDeviceId::Device(major, minor) => {
output_display.extend(b" ");
output_display.extend(
pad_left(
&major,
#[cfg(not(unix))]
0usize,
#[cfg(unix)]
padding.major.max(
padding
.size
.saturating_sub(padding.minor.saturating_add(2usize)),
),
)
.as_bytes(),
output_display.extend_pad_left(
&major,
#[cfg(not(unix))]
0usize,
#[cfg(unix)]
padding.major.max(
padding
.size
.saturating_sub(padding.minor.saturating_add(2usize)),
),
);
output_display.extend(b", ");
output_display.extend(
pad_left(
&minor,
#[cfg(not(unix))]
0usize,
#[cfg(unix)]
padding.minor,
)
.as_bytes(),
output_display.extend_pad_left(
&minor,
#[cfg(not(unix))]
0usize,
#[cfg(unix)]
padding.minor,
);
}
};
@ -2917,28 +2933,28 @@ fn display_item_long(
output_display.extend(b".");
}
output_display.extend(b" ");
output_display.extend(pad_left("?", padding.link_count).as_bytes());
output_display.extend_pad_left("?", padding.link_count);
if config.long.owner {
output_display.extend(b" ");
output_display.extend(pad_right("?", padding.uname).as_bytes());
output_display.extend_pad_right("?", padding.uname);
}
if config.long.group {
output_display.extend(b" ");
output_display.extend(pad_right("?", padding.group).as_bytes());
output_display.extend_pad_right("?", padding.group);
}
if config.context {
output_display.extend(b" ");
output_display.extend(pad_right(&item.security_context, padding.context).as_bytes());
output_display.extend_pad_right(&item.security_context, padding.context);
}
// Author is only different from owner on GNU/Hurd, so we reuse
// the owner, since GNU/Hurd is not currently supported by Rust.
if config.long.author {
output_display.extend(b" ");
output_display.extend(pad_right("?", padding.uname).as_bytes());
output_display.extend_pad_right("?", padding.uname);
}
let displayed_item = display_item_name(
@ -2953,9 +2969,9 @@ fn display_item_long(
let date_len = 12;
output_display.extend(b" ");
output_display.extend(pad_left("?", padding.size).as_bytes());
output_display.extend_pad_left("?", padding.size);
output_display.extend(b" ");
output_display.extend(pad_left("?", date_len).as_bytes());
output_display.extend_pad_left("?", date_len);
output_display.extend(b" ");
if config.dired {