initial
This commit is contained in:
commit
2dad06cae3
6 changed files with 172 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/target
|
16
Cargo.lock
generated
Normal file
16
Cargo.lock
generated
Normal file
|
@ -0,0 +1,16 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.146"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
|
||||
|
||||
[[package]]
|
||||
name = "urine"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "urine"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2.146"
|
17
src/error.rs
Normal file
17
src/error.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
use std::fmt::{Result, Display, Formatter};
|
||||
|
||||
pub enum PissError {
|
||||
InvalidSuffix(String),
|
||||
InvalidNumber(String),
|
||||
NumberNotPositive
|
||||
}
|
||||
|
||||
impl Display for PissError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||
match self {
|
||||
Self::InvalidSuffix(s) => write!(f, "I cannot piss the suffix {s:?}"),
|
||||
Self::InvalidNumber(s) => write!(f, "I cannot piss the invalid number {s:?}"),
|
||||
Self::NumberNotPositive => write!(f, "I cannot piss nonexistent memory")
|
||||
}
|
||||
}
|
||||
}
|
58
src/lib.rs
Normal file
58
src/lib.rs
Normal file
|
@ -0,0 +1,58 @@
|
|||
use std::cell::RefCell;
|
||||
use libc::malloc;
|
||||
|
||||
pub mod error;
|
||||
pub mod parse;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub struct PissAmount {
|
||||
to_piss: u128
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Toliet {
|
||||
Rust,
|
||||
Lazy,
|
||||
Unsafe
|
||||
}
|
||||
|
||||
fn leak_rust(amount: usize) {
|
||||
Vec::<u8>::with_capacity(amount).leak();
|
||||
}
|
||||
|
||||
thread_local!(static TOLIET: RefCell<Vec<Vec<u8>>> = RefCell::new(Vec::new()));
|
||||
|
||||
fn leak_lazy(amount: usize) {
|
||||
TOLIET.with(|t| {
|
||||
t.borrow_mut().push(Vec::<u8>::with_capacity(amount));
|
||||
})
|
||||
}
|
||||
|
||||
fn leak_unsafe(amount: usize) {
|
||||
unsafe {
|
||||
malloc(amount);
|
||||
}
|
||||
}
|
||||
|
||||
fn leak_match(amount: usize, method: Toliet) {
|
||||
match method {
|
||||
Toliet::Rust => leak_rust(amount),
|
||||
Toliet::Lazy => leak_lazy(amount),
|
||||
Toliet::Unsafe => leak_unsafe(amount),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn leak<T: Into<PissAmount>>(amount: T, method: Toliet) {
|
||||
let num: u128 = amount.into().to_piss;
|
||||
let count = num / usize::MAX as u128;
|
||||
|
||||
for _ in 0..count {
|
||||
leak_match(usize::MAX, method);
|
||||
}
|
||||
|
||||
leak_match((num % usize::MAX as u128) as usize, method);
|
||||
}
|
||||
|
||||
pub async fn leak_async<T: Into<PissAmount>>(amount: T, method: Toliet) {
|
||||
leak(amount, method);
|
||||
}
|
71
src/parse.rs
Normal file
71
src/parse.rs
Normal file
|
@ -0,0 +1,71 @@
|
|||
use std::str::FromStr;
|
||||
use crate::{error::PissError, PissAmount};
|
||||
|
||||
impl<T> From<T> for PissAmount
|
||||
where T: Into<u128> {
|
||||
fn from(num: T) -> PissAmount {
|
||||
PissAmount {
|
||||
to_piss: num.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_suffix(s: &str) -> Result<u128, PissError> {
|
||||
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<PissAmount, PissError> {
|
||||
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::<f64>() 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<Self, Self::Err> {
|
||||
parse_file_size(s)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue