use std::time::Duration;
pub fn duration_string(d: Duration) -> String {
let mut u = d.as_nanos() as i128;
let neg = u < 0;
if neg {
u = -u;
}
let mut s = String::new();
if u < 1_000_000_000 {
if u == 0 {
return "0s".to_string();
}
let prec: usize;
let unit: &str;
if u < 1_000 {
prec = 0;
unit = "n";
} else if u < 1_000_000 {
prec = 3;
unit = "µ";
} else {
prec = 6;
unit = "m";
}
let mut digits: Vec<char> = Vec::new();
fmt_frac(&mut digits, &mut u, prec);
fmt_int(&mut digits, u);
for c in digits.iter().rev() {
s.push(*c);
}
s.push_str(unit);
s.push('s');
} else {
let mut digits: Vec<char> = Vec::new();
digits.push('s');
fmt_frac(&mut digits, &mut u, 9);
fmt_int(&mut digits, u % 60);
u /= 60;
if u > 0 {
digits.push('m');
fmt_int(&mut digits, u % 60);
u /= 60;
if u > 0 {
digits.push('h');
fmt_int(&mut digits, u);
}
}
for c in digits.iter().rev() {
s.push(*c);
}
}
if neg {
s.insert(0, '-');
}
s
}
fn fmt_frac(digits: &mut Vec<char>, v: &mut i128, prec: usize) {
let mut print = false;
for _ in 0..prec {
let digit = *v % 10;
print = print || digit != 0;
if print {
digits.push((digit as u8 + b'0') as char);
}
*v /= 10;
}
if print {
digits.push('.');
}
}
fn fmt_int(digits: &mut Vec<char>, v: i128) {
if v == 0 {
digits.push('0');
} else {
let mut v = v;
while v > 0 {
digits.push(((v % 10) as u8 + b'0') as char);
v /= 10;
}
}
}