1
0
Fork 0
coreutils/src/hru.rs

108 lines
2.5 KiB
Rust
Raw Normal View History

2024-02-08 03:58:57 +00:00
/*
2024-02-08 04:42:43 +00:00
* Copyright (c) 20232024 Emma Tebibyte <emma@tebibyte.media>
2024-02-08 03:58:57 +00:00
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
use std::{
cmp::Ordering,
env::args,
2024-02-24 04:58:23 +00:00
io::{ stdin, stdout, Write },
process::{ ExitCode, exit },
2024-02-08 03:58:57 +00:00
};
extern crate sysexits;
2024-02-24 04:58:23 +00:00
use sysexits::{ EX_DATAERR, EX_IOERR, EX_SOFTWARE };
2024-02-08 03:58:57 +00:00
2024-02-14 07:07:06 +00:00
const LIST: [(u32, &str); 10] = [
2024-02-18 21:49:09 +00:00
(3, "k"),
2024-02-14 07:07:06 +00:00
(6, "M"),
(9, "G"),
(12, "T"),
(15, "P"),
(18, "E"),
(21, "Z"),
(24, "Y"),
(27, "R"),
(30, "Q")
];
2024-02-08 03:58:57 +00:00
2024-02-14 07:07:06 +00:00
fn convert(input: u128) -> Result<(f64, (u32, &'static str)), String> {
2024-02-14 00:32:31 +00:00
2024-02-14 07:07:06 +00:00
let mut out = (input as f64, (0_u32, ""));
if input < 1000 { return Ok(out); }
for (n, p) in LIST {
2024-02-14 06:56:01 +00:00
let c = match 10_u128.checked_pow(n) {
Some(c) => c,
None => {
return Err(format!("10^{}: Integer overflow.", n.to_string()));
},
};
2024-02-14 00:32:31 +00:00
match c.cmp(&input) {
2024-02-08 03:58:57 +00:00
Ordering::Less => {
2024-02-14 07:07:06 +00:00
out = (input as f64 / c as f64, (n, p));
2024-02-08 03:58:57 +00:00
},
2024-02-14 00:32:31 +00:00
Ordering::Equal => {
2024-02-14 07:07:06 +00:00
return Ok((input as f64 / c as f64, (n, p)));
2024-02-08 03:58:57 +00:00
},
2024-02-14 00:32:31 +00:00
Ordering::Greater => {},
2024-02-08 03:58:57 +00:00
};
}
2024-02-14 06:56:01 +00:00
Ok(out)
2024-02-08 03:58:57 +00:00
}
2024-02-14 00:32:31 +00:00
fn main() -> ExitCode {
2024-02-08 03:58:57 +00:00
let argv = args().collect::<Vec<String>>();
let mut buf = String::new();
2024-02-14 00:48:25 +00:00
while let Ok(_) = stdin().read_line(&mut buf) {
if buf.is_empty() { return ExitCode::SUCCESS; }
2024-02-08 03:58:57 +00:00
2024-02-14 06:56:01 +00:00
let n: u128 = match buf.trim().parse() {
2024-02-14 00:48:25 +00:00
Ok(f) => {
buf.clear();
f
},
Err(err) => {
2024-02-24 04:58:23 +00:00
eprintln!("{}: {}.", argv[0], err);
2024-02-14 00:48:25 +00:00
return ExitCode::from(EX_DATAERR as u8);
},
};
2024-02-08 03:58:57 +00:00
2024-02-14 06:56:01 +00:00
let (number, prefix) = match convert(n) {
Ok(x) => x,
Err(err) => {
2024-02-24 04:58:23 +00:00
eprintln!("{}: {}.", argv[0], err);
2024-02-14 06:56:01 +00:00
return ExitCode::from(EX_SOFTWARE as u8);
},
};
2024-02-08 03:58:57 +00:00
2024-02-14 07:07:06 +00:00
let si_prefix = format!("{}B", prefix.1);
2024-02-08 03:58:57 +00:00
2024-02-14 00:48:25 +00:00
let out = ((number * 10.0).round() / 10.0).to_string();
2024-02-14 00:32:31 +00:00
2024-02-24 05:11:23 +00:00
stdout().write_all(format!("{} {}\n", out, si_prefix).as_bytes())
2024-02-24 04:58:23 +00:00
.unwrap_or_else(|e| {
eprintln!("{}: {}.", argv[0], e);
exit(EX_IOERR);
});
2024-02-14 00:48:25 +00:00
}
2024-02-14 00:32:31 +00:00
ExitCode::SUCCESS
2024-02-08 03:58:57 +00:00
}