Update unit conversions (#597)

* Refactor Dir

* Update unit conversions
This commit is contained in:
Vincent Ollivier 2024-03-16 11:00:45 +01:00 committed by GitHub
parent 5ca0894241
commit 4d0c956a0e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 43 additions and 35 deletions

View File

@ -9,39 +9,53 @@ pub enum SizeUnit {
} }
impl SizeUnit { impl SizeUnit {
pub fn format(&self, size: usize) -> String { pub fn format(&self, bytes: usize) -> String {
match self { match self {
SizeUnit::None => format!("{}", size), SizeUnit::None => format!("{}", bytes),
SizeUnit::Binary => binary_size(size), SizeUnit::Binary => readable_size(bytes, 1024),
SizeUnit::Decimal => decimal_size(size), SizeUnit::Decimal => readable_size(bytes, 1000),
} }
} }
} }
const PREFIXES: [&str; 5] = ["", "K", "M", "G", "T"]; fn readable_size(bytes: usize, divisor: usize) -> String {
let units = ["", "K", "M", "G", "T"];
fn binary_size(size: usize) -> String { let d = divisor as f64;
let n = PREFIXES.len(); let mut s = bytes as f64;
for i in 0..n { let mut i = 0;
let prefix = PREFIXES[i]; while s >= d && i < units.len() - 1 {
if size < (1 << ((i + 1) * 10)) || i == n - 1 { s /= d;
let s = ((size * 10) >> (i * 10)) as f64 / 10.0; i += 1;
let s = if s >= 10.0 { libm::round(s) } else { s };
return format!("{}{}", s, prefix);
}
} }
unreachable!(); let p = if i > 0 && s < 10.0 { 1 } else { 0 };
format!("{:.2$}{}", s, units[i], p)
} }
fn decimal_size(size: usize) -> String { #[test_case]
let n = PREFIXES.len(); fn test_binary_size() {
for i in 0..n { let unit = SizeUnit::Binary;
let prefix = PREFIXES[i]; assert_eq!(unit.format(1), "1");
if size < usize::pow(10, 3 * (i + 1) as u32) || i == n - 1 { assert_eq!(unit.format(10), "10");
let s = (size as f64) / libm::pow(10.0, 3.0 * (i as f64)); assert_eq!(unit.format(100), "100");
let precision = if s >= 10.0 { 0 } else { 1 }; assert_eq!(unit.format(1000), "1000");
return format!("{:.2$}{}", s, prefix, precision); assert_eq!(unit.format(1024), "1.0K");
} assert_eq!(unit.format(1120), "1.1K");
} assert_eq!(unit.format(1160), "1.1K");
unreachable!(); assert_eq!(unit.format(15000), "15K");
assert_eq!(unit.format(1000000), "977K");
}
#[test_case]
fn test_decimal_size() {
let unit = SizeUnit::Decimal;
assert_eq!(unit.format(1), "1");
assert_eq!(unit.format(10), "10");
assert_eq!(unit.format(100), "100");
assert_eq!(unit.format(1000), "1.0K");
assert_eq!(unit.format(1024), "1.0K");
assert_eq!(unit.format(1120), "1.1K");
assert_eq!(unit.format(1160), "1.2K");
assert_eq!(unit.format(1500), "1.5K");
assert_eq!(unit.format(15000), "15K");
assert_eq!(unit.format(1000000), "1.0M");
} }

View File

@ -77,14 +77,8 @@ impl Dir {
for name in pathname.trim_start_matches('/').split('/') { for name in pathname.trim_start_matches('/').split('/') {
match dir.find(name) { match dir.find(name) {
Some(dir_entry) => { Some(entry) if entry.is_dir() => dir = entry.into(),
if dir_entry.is_dir() { _ => return None,
dir = dir_entry.into()
} else {
return None;
}
}
None => return None,
} }
} }
Some(dir) Some(dir)