Upload files to 'src'

main
elfein 2022-03-14 09:29:39 +00:00
parent a92244c1ac
commit 675817e1e8
1 changed files with 252 additions and 0 deletions

252
src/main.rs Normal file
View File

@ -0,0 +1,252 @@
#[derive(Copy, Clone)]
enum HowUnits {
SeparateUnits,
BiggestUnit,
Both,
}
#[derive(Copy, Clone)]
enum HowNumberBase {
Decimal,
Hex,
Both,
}
fn hex_float(h: f64) -> String {
let neg = h.is_sign_negative();
let mut h = h.abs();
let mut e = 0;
while h.fract() != 0.0 {
h *= 16.0;
e += 1;
}
let mut h = h as usize;
let mut output = String::new();
let mut num_divides = 0;
while h > 0 {
output.push(match h % 16 {
0 => '0',
1 => '1',
2 => '2',
3 => '3',
4 => '4',
5 => '5',
6 => '6',
7 => '7',
8 => '8',
9 => '9',
10 => 'A',
11 => 'B',
12 => 'C',
13 => 'D',
14 => 'E',
15 => 'F',
_ => unreachable![],
});
h /= 16;
num_divides += 1;
if num_divides == e {
output.push('.');
}
}
if neg {
output.push('-');
}
output.chars().rev().collect()
}
#[test]
fn test_hex_float() {
assert_eq!["1.8", hex_float(1.5)];
}
fn separate_units(n: usize, how_base: HowNumberBase) -> String {
let peta = n / 1024usize.pow(5);
let n = n - peta * 1024usize.pow(5);
let tera = n / 1024usize.pow(4);
let n = n - tera * 1024usize.pow(4);
let giga = n / 1024usize.pow(3);
let n = n - giga * 1024usize.pow(3);
let mega = n / 1024usize.pow(2);
let n = n - mega * 1024usize.pow(2);
let kilo = n / 1024usize.pow(1);
let bytes = n - kilo * 1024usize.pow(1);
match how_base {
HowNumberBase::Decimal => format![
"{peta} petabytes\n{tera} terabytes\n{giga} gigabytes\n{mega} megabytes\n{kilo} kilobytes\n{bytes} bytes"
],
HowNumberBase::Hex => format![
"0x{peta:X} petabytes\n0x{tera:X} terabytes\n0x{giga:X} gigabytes\n0x{mega:X} megabytes\n0x{kilo:X} kilobytes\n0x{bytes:X} bytes"
],
HowNumberBase::Both => format![
"0x{peta:X} ({peta}) petabytes\n0x{tera:X} ({tera}) terabytes\n0x{giga:X} ({giga}) gigabytes\n0x{mega:X} ({mega}) megabytes\n0x{kilo:X} ({kilo}) kilobytes\n0x{bytes:X} ({bytes}) bytes"
],
}
}
fn biggest_unit(n: usize, how_base: HowNumberBase) -> String {
let mut biggest = 0;
let mut unit_val = 0;
for e in (0..6).rev() {
unit_val = n / 1024usize.pow(e);
if unit_val > 0 {
biggest = e;
break;
}
}
let unit = format![
"{}{}",
match biggest {
0 => "byte",
1 => "kilobyte",
2 => "megabyte",
3 => "gigabyte",
4 => "terabyte",
5 => "petabyte",
_ => unreachable!(),
},
if unit_val != 1 { "s" } else { "" }
];
match how_base {
HowNumberBase::Decimal => format!["{} {}", n as f64 / 1024.0f64.powf(biggest as f64), unit],
HowNumberBase::Hex => format![
"0x{} {}",
hex_float(n as f64 / 1024.0f64.powf(biggest as f64)),
unit
],
HowNumberBase::Both => format![
"0x{} ({}) {}",
hex_float(n as f64 / 1024.0f64.powf(biggest as f64)),
n as f64 / 1024.0f64.powf(biggest as f64),
unit
],
}
}
fn to_readable_units(n: usize, how_units: HowUnits, how_base: HowNumberBase) -> String {
match how_units {
HowUnits::SeparateUnits => separate_units(n, how_base),
HowUnits::BiggestUnit => biggest_unit(n, how_base),
HowUnits::Both => format![
"{}\n{}",
biggest_unit(n, how_base),
separate_units(n, how_base)
],
}
}
const USAGE: &str = "Usage: cntin [options]
options:
Note: If both of a complementary set of options are specified, both are used.
-d, --decimal Sets the output number base to decimal.
-h, --hex Sets the output number base to hexadecimal.
-s, --separate Displays all byte units.
-b, --biggest Displays the biggest unit.";
fn main() -> Result<(), std::io::Error> {
let args = std::env::args();
let mut how_units = HowUnits::BiggestUnit;
let mut how_base = HowNumberBase::Decimal;
let mut set_d = false;
let mut set_h = false;
let mut set_s = false;
let mut set_b = false;
for arg in args.skip(1) {
let arg = arg.trim();
if atty::is(atty::Stream::Stdin) {
return Ok(());
}
if arg.starts_with('-') && !arg.starts_with("--") {
// It's a single dash option
for ch in arg.chars().skip(1) {
match ch {
'd' => {
set_d = true;
if set_h {
how_base = HowNumberBase::Both;
} else {
how_base = HowNumberBase::Decimal;
}
}
'h' => {
set_h = true;
if set_d {
how_base = HowNumberBase::Both;
} else {
how_base = HowNumberBase::Hex;
}
}
's' => {
set_s = true;
if set_b {
how_units = HowUnits::Both;
} else {
how_units = HowUnits::SeparateUnits;
}
}
'b' => {
set_b = true;
if set_s {
how_units = HowUnits::Both;
} else {
how_units = HowUnits::BiggestUnit;
}
}
_ => {
eprintln!["unknown option '{}'", ch];
eprint!["{}", USAGE];
return Ok(());
}
}
}
} else if arg == "--biggest" {
set_b = true;
if set_s {
how_units = HowUnits::Both;
} else {
how_units = HowUnits::BiggestUnit;
}
} else if arg == "--separate" {
set_s = true;
if set_b {
how_units = HowUnits::Both;
} else {
how_units = HowUnits::BiggestUnit;
}
} else if arg == "--decimal" {
set_d = true;
if set_h {
how_base = HowNumberBase::Both;
} else {
how_base = HowNumberBase::Decimal;
}
} else if arg == "--hex" {
set_h = true;
if set_d {
how_base = HowNumberBase::Both;
} else {
how_base = HowNumberBase::Decimal;
}
} else if arg == "--help" {
eprintln!["{}", USAGE];
return Ok(());
} else {
eprintln!["unknown argument: {}", arg];
eprint!["{}", USAGE];
return Ok(());
}
}
let std_out = std::io::stdout();
let mut n = 0usize;
while let Some(Ok(byte)) = std::io::Read::bytes(std::io::stdin()).next() {
n += 1;
std::io::Write::write(&mut std_out.lock(), &[byte])?;
}
eprintln!["{}", to_readable_units(n, how_units, how_base)];
Ok(())
}