summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock16
-rw-r--r--Cargo.toml9
-rw-r--r--src/error.rs17
-rw-r--r--src/lib.rs58
-rw-r--r--src/parse.rs71
6 files changed, 172 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..6ce4a59
--- /dev/null
+++ b/Cargo.lock
@@ -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",
+]
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..f2be850
--- /dev/null
+++ b/Cargo.toml
@@ -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"
diff --git a/src/error.rs b/src/error.rs
new file mode 100644
index 0000000..399eb33
--- /dev/null
+++ b/src/error.rs
@@ -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")
+ }
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..ebf3274
--- /dev/null
+++ b/src/lib.rs
@@ -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);
+}
diff --git a/src/parse.rs b/src/parse.rs
new file mode 100644
index 0000000..edfd9c5
--- /dev/null
+++ b/src/parse.rs
@@ -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)
+ }
+}