1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
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())
}
}
|