Skip to content

Commit

Permalink
refactor: minimum-size & output-format
Browse files Browse the repository at this point in the history
share code for handling kb/kib/mb/mib logic
  • Loading branch information
bootandy committed Mar 14, 2024
1 parent 4df4eea commit a8bf76c
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 43 deletions.
46 changes: 16 additions & 30 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand Down Expand Up @@ -116,44 +116,30 @@ impl Config {
}

fn convert_min_size(input: &str) -> Option<usize> {
// let chars_as_vec: Vec<char> = 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::<usize>() {
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<usize> = 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
Expand Down
43 changes: 30 additions & 13 deletions src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit a8bf76c

Please sign in to comment.