use std::str::FromStr; use crate::{error::PissError, PissAmount}; impl From for PissAmount where T: Into { fn from(num: T) -> PissAmount { PissAmount { to_piss: num.into() } } } fn parse_suffix(s: &str) -> Result { Ok(match s { // nepal "k" | "kb" => 1_000, "m" | "mb" => 1_000_000, "g" | "gb" => 1_000_000_000, "t" | "tb" => 1_000_000_000_000, "p" | "pb" => 1_000_000_000_000_000, "e" | "eb" => 1_000_000_000_000_000_000, "x" | "xb" => 1_000_000_000_000_000_000_000, "y" | "yb" => 1_000_000_000_000_000_000_000_000, "r" | "rb" => 1_000_000_000_000_000_000_000_000_000, "q" | "qb" => 1_000_000_000_000_000_000_000_000_000_000, "ki" | "kib" => 0x400, "mi" | "mib" => 0x100000, "gi" | "gib" => 0x40000000, "ti" | "tib" => 0x10000000000, "pi" | "pib" => 0x4000000000000, "ei" | "eib" => 0x1000000000000000, "xi" | "xib" => 0x400000000000000000, "yi" | "yib" => 0x100000000000000000000, "ri" | "rib" => 0x40000000000000000000000, "qi" | "qib" => 0x10000000000000000000000000, "" | "b" => 1, // uwu _ => return Err(PissError::InvalidSuffix(s.into())) // such nepal }) } fn parse_file_size(s: &str) -> Result { let mut end = 0; for (i, c) in s.char_indices() { if c.is_digit(10) || c == '.' { continue; } end = i; break; } let num_text = &s[..end]; let suffix_text = &s[end..]; let Ok(num) = num_text.parse::() else { return Err(PissError::InvalidNumber(num_text.into())) }; if num <= 0f64 { return Err(PissError::NumberNotPositive) } let multiplier = parse_suffix(suffix_text)?; Ok(PissAmount { to_piss: (num * multiplier as f64) as u128 }) } impl FromStr for PissAmount { type Err = PissError; fn from_str(s: &str) -> Result { parse_file_size(s) } }