nu_protocol/value/
filesize.rsuse crate::Config;
use byte_unit::UnitType;
use nu_utils::get_system_locale;
use num_format::ToFormattedString;
pub fn format_filesize_from_conf(num_bytes: i64, config: &Config) -> String {
format_filesize(
num_bytes,
&config.filesize.format,
Some(config.filesize.metric),
)
}
pub fn format_filesize(
num_bytes: i64,
format_value: &str,
filesize_metric: Option<bool>,
) -> String {
let filesize_unit = get_filesize_format(format_value, filesize_metric);
let byte = byte_unit::Byte::from_u64(num_bytes.unsigned_abs());
let adj_byte = if let Some(unit) = filesize_unit {
byte.get_adjusted_unit(unit)
} else {
byte.get_appropriate_unit(if filesize_metric.unwrap_or(false) {
UnitType::Decimal
} else {
UnitType::Binary
})
};
match adj_byte.get_unit() {
byte_unit::Unit::B => {
let locale = get_system_locale();
let locale_byte = adj_byte.get_value() as u64;
let locale_byte_string = locale_byte.to_formatted_string(&locale);
let locale_signed_byte_string = if num_bytes.is_negative() {
format!("-{locale_byte_string}")
} else {
locale_byte_string
};
if filesize_unit.is_none() {
format!("{locale_signed_byte_string} B")
} else {
locale_signed_byte_string
}
}
_ => {
if num_bytes.is_negative() {
format!("-{:.1}", adj_byte)
} else {
format!("{:.1}", adj_byte)
}
}
}
}
fn get_filesize_format(
format_value: &str,
filesize_metric: Option<bool>,
) -> Option<byte_unit::Unit> {
let metric = filesize_metric.unwrap_or(!format_value.ends_with("ib"));
if metric {
match format_value {
"b" => Some(byte_unit::Unit::B),
"kb" | "kib" => Some(byte_unit::Unit::KB),
"mb" | "mib" => Some(byte_unit::Unit::MB),
"gb" | "gib" => Some(byte_unit::Unit::GB),
"tb" | "tib" => Some(byte_unit::Unit::TB),
"pb" | "pib" => Some(byte_unit::Unit::TB),
"eb" | "eib" => Some(byte_unit::Unit::EB),
_ => None,
}
} else {
match format_value {
"b" => Some(byte_unit::Unit::B),
"kb" | "kib" => Some(byte_unit::Unit::KiB),
"mb" | "mib" => Some(byte_unit::Unit::MiB),
"gb" | "gib" => Some(byte_unit::Unit::GiB),
"tb" | "tib" => Some(byte_unit::Unit::TiB),
"pb" | "pib" => Some(byte_unit::Unit::TiB),
"eb" | "eib" => Some(byte_unit::Unit::EiB),
_ => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use rstest::rstest;
#[rstest]
#[case(1000, Some(true), "auto", "1.0 KB")]
#[case(1000, Some(false), "auto", "1,000 B")]
#[case(1000, Some(false), "kb", "1.0 KiB")]
#[case(3000, Some(false), "auto", "2.9 KiB")]
#[case(3_000_000, None, "auto", "2.9 MiB")]
#[case(3_000_000, None, "kib", "2929.7 KiB")]
fn test_filesize(
#[case] val: i64,
#[case] filesize_metric: Option<bool>,
#[case] filesize_format: String,
#[case] exp: &str,
) {
assert_eq!(exp, format_filesize(val, &filesize_format, filesize_metric));
}
}