Need a library for parsing byte units like bytesize, but with no floating point errors

Tried: byte_unit, bytesize and ubyte.
All of them, when given a string "4.1 MB" return 4099999 bytes. Not good.

Is there anything there that works properly on decimals and not floats?

/// Takes a decimal number.
/// The `unit` argument should be how many digits after the period to accept:
/// for kB => 3, MB => 6, GB => 9
///
/// Returns None on parse failure.
fn parse_decimal(s: &str, unit: usize) -> Option<u128> {
    if s == "." || s.is_empty() { return None; }
    let (to_dot, from_dot) = s.as_bytes().iter().position(|i| *i == b'.')
        .map(|i| (i, i+1))
        .unwrap_or((s.len(), s.len()));

    let mut res = if to_dot == 0 { 0 } else { s[..to_dot].parse::<u128>().ok()? };
    for _ in 0..unit {
        res = res.checked_mul(10)?;
    }
    
    let after_dot = &s[from_dot..];
    if !after_dot.is_empty() {
        let mut len = after_dot.len();
        while after_dot[..len].as_bytes().last().copied() == Some(b'0') {
            len -= 1;
        }

        if len > unit {
            // Not an integer number of bytes.
            return None;
        }

        let mut after_dot = after_dot[..len].parse::<u128>().ok()?;
        for _ in 0..unit - len {
            after_dot = after_dot.checked_mul(10)?;
        }
        res += after_dot;
    }
    Some(res)
}

fn main() {
    println!("{:?}", parse_decimal("4.1", 6));
}
Some(4100000)

Thank you, @alice, I haven't expected you code it by yourself :upside_down_face:
Wow, this forum is awesome!

Anyway, I guess the fact you coded it instead of pointing me to a library means there is probably no crate that does it correctly out-of-the-box.

Ah, nope, I was wrong, there is one that seems to work correctly:
https://crates.io/crates/parse-size

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.