use std::str::FromStr; use crate::{PissError, PissAmount}; impl From for PissAmount where T: Into { fn from(num: T) -> Self { Self { 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" => 0x0010_0000, "gi" | "gib" => 0x4000_0000, "ti" | "tib" => 0x0100_0000_0000, "pi" | "pib" => 0x0004_0000_0000_0000, "ei" | "eib" => 0x1000_0000_0000_0000, "xi" | "xib" => 0x0040_0000_0000_0000_0000, "yi" | "yib" => 0x0001_0000_0000_0000_0000_0000, "ri" | "rib" => 0x0400_0000_0000_0000_0000_0000, "qi" | "qib" => 0x0010_0000_0000_0000_0000_0000_0000, "" | "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_ascii_digit() || 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) } }