bitbottle 0.10.0

a modern archive file format
Documentation
// atto femto pico nano micro milli, kilo mega giga tera peta exa
const SI_LABELS: &str = "afpnum KMGTPE";
const SI_SPACE: usize = 6;
const TEN: f64 = 10.0;

pub fn round_to_precision(n: f64, digits: usize) -> f64 {
    if n == 0.0 {
        return n;
    }
    let scale = digits as f64 - n.log10().floor() - 1.0;
    (n * TEN.powf(scale)).round() * TEN.powf(-scale)
}

pub fn to_si(mut n: f64, base: f64) -> String {
    let mut index = SI_SPACE;
    while n >= base && index < SI_LABELS.len() - 1 {
        n /= base;
        index += 1;
    }
    while n < 1.0 && n != 0.0 && index > 0 {
        n *= base;
        index -= 1;
    }

    if index == SI_SPACE {
        return format!("{n}");
    }

    let rounded_n = n.round();
    let s = if rounded_n < 10.0 {
        format!("{:.2}", round_to_precision(n, 3))
    } else if rounded_n < 100.0 {
        format!("{:.1}", round_to_precision(n, 3))
    } else {
        format!("{rounded_n}")
    };
    s + &SI_LABELS[index .. index + 1]
}

pub fn to_binary_si(n: f64) -> String {
    to_si(n, 1024.0)
}


#[cfg(test)]
mod test {
    use super::to_binary_si;

    #[test]
    fn test_to_si() {
        assert_eq!(to_binary_si(0.0), "0");
        assert_eq!(to_binary_si(1245.0), "1.22K");
        assert_eq!(to_binary_si(12456.0), "12.2K");
    }
}