leak_memory 0.1.1

The enterprise way to leak memory
Documentation
use std::str::FromStr;
use crate::{LeakError, LeakAmount};

macro_rules! from_num {
    ($t:ty) => {
        impl From<$t> for LeakAmount {
            fn from(num: $t) -> Self {
                Self {
                    to_leak: num as u128
                }
            }
        }

        impl From<Vec<$t>> for LeakAmount {
            fn from(vec: Vec<$t>) -> Self {
                let mut amount = 0;
                for i in vec {
                    amount += i as u128;
                }
                Self {
                    to_leak: amount
                }
            }
        }
    };
}

from_num!(u128);
from_num!(u64);
from_num!(u32);
from_num!(u16);
from_num!(u8);
from_num!(i128);
from_num!(i64);
from_num!(i32);
from_num!(i16);
from_num!(i8);
from_num!(f32);
from_num!(f64);
from_num!(bool);

fn parse_suffix(s: &str) -> Result<u128, LeakError> {
    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(LeakError::InvalidSuffix(s.into())) // such nepal
    })
}

fn parse_file_size(s: &str) -> Result<LeakAmount, LeakError> {
    let mut end = 0;
    for (i, c) in s.char_indices() {
        end = i;
        if !c.is_ascii_digit() && c != '.' { break; }
    }

    if end == 0 {
        if let Some(c) = s.chars().nth(0) {
            return Err(LeakError::Unexpected(c))
        }
    }

    let num_text = &s[..end];
    let suffix_text = &s[end..];
    
    let Ok(num) = num_text.parse::<f64>() else {
        return Err(LeakError::InvalidNumber(num_text.into()))
    };

    let multiplier = parse_suffix(suffix_text)?;
    
    Ok(LeakAmount {
        to_leak: (num * multiplier as f64) as u128
    })
}

impl FromStr for LeakAmount {
    type Err = LeakError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        parse_file_size(s.to_lowercase().as_str())
    }
}