Upload files to 'src'
parent
a92244c1ac
commit
675817e1e8
|
@ -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(())
|
||||
}
|
Loading…
Reference in New Issue