diff --git a/src/config.rs b/src/config.rs index fda83930..1346fffd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -6,7 +6,7 @@ use std::io::IsTerminal; use std::path::Path; use std::path::PathBuf; -use crate::display::UNITS; +use crate::display::get_number_format; #[derive(Deserialize, Default)] #[serde(rename_all = "kebab-case")] @@ -116,44 +116,30 @@ impl Config { } fn convert_min_size(input: &str) -> Option { - // let chars_as_vec: Vec = input.chars().collect(); let re = Regex::new(r"([0-9]+)(\w*)").unwrap(); if let Some(cap) = re.captures(input) { let (_, [digits, letters]) = cap.extract(); - let letters = letters.to_uppercase(); - let first = letters.chars().next(); - - // If we did specify a letter and it doesnt begin with 'b' - if first.is_some() && first != Some('b') { - // Are we using KB, MB, GB etc ? - for (i, u) in UNITS.iter().rev().enumerate() { - if Some(*u) == first { - return match digits.parse::() { - Ok(pure) => { - let is_si = letters.contains('I'); // KiB, MiB, etc - let num: usize = if is_si { 1000 } else { 1024 }; - - let marker = pure * (num.pow((i + 1) as u32)); - Some(marker) - } - Err(_) => { + + // Failure to parse should be impossible due to regex match + let digits_as_usize: Option = digits.parse().ok(); + + match digits_as_usize { + Some(parsed_digits) => { + let number_format = get_number_format(&letters.to_lowercase()); + match number_format { + Some((multiple, _)) => Some(parsed_digits * (multiple as usize)), + None => { + if letters.eq("") { + Some(parsed_digits) + } else { eprintln!("Ignoring invalid min-size: {input}"); None } - }; + } } } - eprintln!("Ignoring invalid min-size: {input}"); - None - // Else we are working with bytes - } else { - digits - .parse() - .map_err(|_| { - eprintln!("Ignoring invalid min-size: {input}"); - }) - .ok() + None => None, } } else { None diff --git a/src/display.rs b/src/display.rs index 9f96741d..de828c69 100644 --- a/src/display.rs +++ b/src/display.rs @@ -409,31 +409,48 @@ fn get_pretty_name( } } -pub fn human_readable_number(size: u64, output_str: &str) -> String { +// If we are working with SI units or not +pub fn get_type_of_thousand(output_str: &str) -> u64 { let is_si = output_str.contains('i'); // si, KiB, MiB, etc - let num: u64 = if is_si { 1000 } else { 1024 }; + if is_si { + 1000 + } else { + 1024 + } +} +pub fn get_number_format(output_str: &str) -> Option<(u64, char)> { if output_str.starts_with('b') { - return format!("{}B", size); + return Some((1, 'B')); } for (i, u) in UNITS.iter().enumerate() { if output_str.starts_with((*u).to_ascii_lowercase()) { - let marker = num.pow((UNITS.len() - i) as u32); - return format!("{}{}", (size / marker), u); + let marker = get_type_of_thousand(output_str).pow((UNITS.len() - i) as u32); + return Some((marker, *u)); } } + None +} - for (i, u) in UNITS.iter().enumerate() { - let marker = num.pow((UNITS.len() - i) as u32); - if size >= marker { - if size / marker < 10 { - return format!("{:.1}{}", (size as f32 / marker as f32), u); - } else { - return format!("{}{}", (size / marker), u); +pub fn human_readable_number(size: u64, output_str: &str) -> String { + match get_number_format(output_str) { + Some((x, u)) => { + format!("{}{}", (size / x), u) + } + None => { + for (i, u) in UNITS.iter().enumerate() { + let marker = get_type_of_thousand(output_str).pow((UNITS.len() - i) as u32); + if size >= marker { + if size / marker < 10 { + return format!("{:.1}{}", (size as f32 / marker as f32), u); + } else { + return format!("{}{}", (size / marker), u); + } + } } + format!("{size}B") } } - format!("{size}B") } mod tests {