From 3fccf27d0749ff3bd6a51534ea417c5278ed04e8 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Sun, 30 Jan 2022 15:48:28 -0500 Subject: [PATCH 1/9] Wandom awowithm optimization --- src/lib.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a277068..a543efc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ use indicatif::{ProgressBar, ProgressStyle}; use linkify::{LinkFinder, LinkKind}; use rand::{Rng, RngCore, SeedableRng}; -use rand_xoshiro::{Xoshiro256Plus, Xoshiro256PlusPlus}; +use rand_xoshiro::Xoshiro256Plus; use std::fs::File; use std::io::{BufWriter, Error, Write}; use std::path::Path; @@ -34,8 +34,7 @@ pub struct UwUify<'a> { faces: f64, actions: f64, stutters: f64, - floating_rng: Xoshiro256Plus, - int_rng: Xoshiro256PlusPlus, + rng: Xoshiro256Plus, linkify: LinkFinder, } @@ -49,8 +48,7 @@ impl<'a> Default for UwUify<'a> { faces: 0.05, actions: 0.125, stutters: 0.225, - floating_rng: Xoshiro256Plus::seed_from_u64(69), - int_rng: Xoshiro256PlusPlus::seed_from_u64(420), + rng: Xoshiro256Plus::seed_from_u64(69), linkify: LinkFinder::new(), } } @@ -81,8 +79,7 @@ impl<'a> UwUify<'a> { }; if random { - uwuify.floating_rng = Xoshiro256Plus::seed_from_u64(rand::rngs::OsRng.next_u64()); - uwuify.int_rng = Xoshiro256PlusPlus::seed_from_u64(rand::rngs::OsRng.next_u64()); + uwuify.rng = Xoshiro256Plus::seed_from_u64(rand::rngs::OsRng.next_u64()); } if let Some(words) = words { @@ -162,16 +159,16 @@ impl<'a> UwUify<'a> { line.split_whitespace() .map(|f| f.as_bytes()) .try_for_each(|word| { - let random_value = self.floating_rng.gen_range(0.0..1.0); + let random_value = self.rng.gen_range(0.0..1.0); if random_value <= self.faces { - out.write_all(FACES[self.int_rng.gen_range(0..FACES_SIZE)])?; + out.write_all(FACES[self.rng.gen_range(0..FACES_SIZE)])?; out.write_all(b" ")?; } else if random_value <= self.actions { - out.write_all(ACTIONS[self.int_rng.gen_range(0..ACTIONS_SIZE)])?; + out.write_all(ACTIONS[self.rng.gen_range(0..ACTIONS_SIZE)])?; out.write_all(b" ")?; } else if random_value <= self.stutters { - (0..self.int_rng.gen_range(1..2)) + (0..self.rng.gen_range(1..2)) .into_iter() .try_for_each(|_| { match word[0] { From 27a95fdcc7d85006dcf8e85b77842f523fbde2d1 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 1 Feb 2022 18:12:45 -0500 Subject: [PATCH 2/9] So many faces --- Cargo.toml | 22 +++-- infile.txt | 1 + outfile.txt | 1 + src/constants.rs | 217 +++++++++++++++++++++++++++++++++++++++++++---- src/lib.rs | 104 +++++++++++++++++------ src/main.rs | 2 +- src/seeder.rs | 34 -------- src/test.txt | 14 +++ 8 files changed, 309 insertions(+), 86 deletions(-) create mode 100644 infile.txt create mode 100644 outfile.txt delete mode 100644 src/seeder.rs create mode 100644 src/test.txt diff --git a/Cargo.toml b/Cargo.toml index 0b316b2..6e228fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,12 +10,12 @@ repository = "https://github.com/sgoudham/uwuifyy" keywords = ["cli", "uwu", "owo", "uwuify", "anime"] categories = ["command-line-utilities"] exclude = [ - "examples/the-complete-works-of-william-shakespeare.txt", - "examples/tiktok_app_reviews.csv", - "examples/tokyo-2020-olympics-tweets.csv", - "examples/uwu/**", - ".github/**", - "scripts/**" + "examples/the-complete-works-of-william-shakespeare.txt", + "examples/tiktok_app_reviews.csv", + "examples/tokyo-2020-olympics-tweets.csv", + "examples/uwu/**", + ".github/**", + "scripts/**", ] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -31,11 +31,19 @@ linkify = "0.8.0" rand_xoshiro = "0.6.0" ahash = "0.7.6" memmap = "0.7.0" +kaomoji-ru = "1.0.0" [profile.release] lto = "fat" codegen-units = 1 panic = "abort" +[profile.dev] +overflow-checks = false + +[profile.bench] +lto = "fat" +codegen-units = 1 + [features] -bench = [] \ No newline at end of file +bench = [] diff --git a/infile.txt b/infile.txt new file mode 100644 index 0000000..e80fa1c --- /dev/null +++ b/infile.txt @@ -0,0 +1 @@ +According to all known laws of aviation, there is no way a bee should be able to fly. diff --git a/outfile.txt b/outfile.txt new file mode 100644 index 0000000..0cb44dd --- /dev/null +++ b/outfile.txt @@ -0,0 +1 @@ +Accowding to aww uWu knyown waws of aviation, thewe i-is nyo way *moans* a bee shouwd be abwe to fwy. diff --git a/src/constants.rs b/src/constants.rs index 4a9cc51..4102fa9 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -1,19 +1,204 @@ -pub const FACES_SIZE: usize = 14; +pub const FACES_SIZE: usize = 106; + pub const FACES: [&[u8]; FACES_SIZE] = [ - b"OwO ", - b"UwU ", - b">w< ", - b"^w^ ", - b"^-^ ", - b":3 ", - b"x3 ", - b"xDD ", - b";;w;; ", - b">_< ", - b">_> ", - b"^.^ ", - b":33 ", - b"uWu ", + b"OwO", + b"UwU", + b">w<", + b"^w^", + b"^-^", + b":3", + b"x3", + b"xDD", + b";;w;;", + b">_<", + b">_>", + b"^.^", + b":33", + b"uWu", + // (* ^ ω ^) + kaomoji_ru::positive_emotions::JOY[0], + // (´ ∀ ` *) + kaomoji_ru::positive_emotions::JOY[1], + // (o^▽^o) + kaomoji_ru::positive_emotions::JOY[4], + // (⌒▽⌒)☆ + kaomoji_ru::positive_emotions::JOY[5], + // <( ̄︶ ̄)> + kaomoji_ru::positive_emotions::JOY[6], + // ヽ(・∀・)ノ + kaomoji_ru::positive_emotions::JOY[8], + // (´。• ω •。`) + kaomoji_ru::positive_emotions::JOY[9], + // ( ̄ω ̄) + kaomoji_ru::positive_emotions::JOY[10], + // (o・ω・o) + kaomoji_ru::positive_emotions::JOY[12], + // ヽ(*・ω・)ノ + kaomoji_ru::positive_emotions::JOY[14], + // (^人^) + kaomoji_ru::positive_emotions::JOY[16], + // (*´▽`*) + kaomoji_ru::positive_emotions::JOY[18], + // ( ´ ω ` ) + kaomoji_ru::positive_emotions::JOY[20], + // (≧◡≦) + kaomoji_ru::positive_emotions::JOY[22], + // (o´∀`o) + kaomoji_ru::positive_emotions::JOY[23], + // (´• ω •`) + kaomoji_ru::positive_emotions::JOY[24], + // (^▽^) + kaomoji_ru::positive_emotions::JOY[25], + // (⌒ω⌒) + kaomoji_ru::positive_emotions::JOY[26], + // ╰(▔∀▔)╯ + kaomoji_ru::positive_emotions::JOY[28], + // (*^‿^*) + kaomoji_ru::positive_emotions::JOY[30], + // (✯◡✯) + kaomoji_ru::positive_emotions::JOY[32], + // (*≧ω≦*) + kaomoji_ru::positive_emotions::JOY[34], + // (☆▽☆) + kaomoji_ru::positive_emotions::JOY[35], + // \(≧▽≦)/ + kaomoji_ru::positive_emotions::JOY[37], + // ヽ(o^▽^o)ノ + kaomoji_ru::positive_emotions::JOY[38], + // (*°▽°*) + kaomoji_ru::positive_emotions::JOY[40], + // (✧ω✧) + kaomoji_ru::positive_emotions::JOY[42], + // ヽ(*⌒▽⌒*)ノ + kaomoji_ru::positive_emotions::JOY[43], + // ヽ(>∀<☆)ノ + kaomoji_ru::positive_emotions::JOY[48], + // o(≧▽≦)o + kaomoji_ru::positive_emotions::JOY[49], + // (☆ω☆) + kaomoji_ru::positive_emotions::JOY[50], + // (っ˘ω˘ς ) + kaomoji_ru::positive_emotions::JOY[51], + // \(★ω★)/ + kaomoji_ru::positive_emotions::JOY[57], + // (╯✧▽✧)╯ + kaomoji_ru::positive_emotions::JOY[60], + // o(>ω<)o + kaomoji_ru::positive_emotions::JOY[61], + // (´・ᴗ・ ` ) + kaomoji_ru::positive_emotions::JOY[72], + // (¬‿¬ ) + kaomoji_ru::positive_emotions::JOY[77], + // („• ᴗ •„) + kaomoji_ru::positive_emotions::JOY[84], + // (´ ω `♡) + kaomoji_ru::positive_emotions::LOVE[12], + // (♡°▽°♡) + kaomoji_ru::positive_emotions::LOVE[17], + // ♡(。- ω -) + kaomoji_ru::positive_emotions::LOVE[18], + // (´。• ω •。`) ♡ + kaomoji_ru::positive_emotions::LOVE[22], + // (❤ω❤) + kaomoji_ru::positive_emotions::LOVE[39], + // (´,,•ω•,,)♡ + kaomoji_ru::positive_emotions::LOVE[45], + // (*ノωノ) + kaomoji_ru::positive_emotions::EMBARRESMENT[5], + // (⁄ ⁄•⁄ω⁄•⁄ ⁄) + kaomoji_ru::positive_emotions::EMBARRESMENT[17], + // (# ̄ω ̄) + kaomoji_ru::negative_emotions::DISSATISFACTION[7], + // (>m<) + kaomoji_ru::negative_emotions::DISSATISFACTION[9], + // (」°ロ°)」 + kaomoji_ru::negative_emotions::DISSATISFACTION[10], + // (ᗒᗣᗕ)՞ + kaomoji_ru::negative_emotions::DISSATISFACTION[24], + // (#`Д´) + kaomoji_ru::negative_emotions::ANGER[0], + // (・`ω´・) + kaomoji_ru::negative_emotions::ANGER[4], + // (°ㅂ°╬) + kaomoji_ru::negative_emotions::ANGER[17], + // (╬ Ò﹏Ó) + kaomoji_ru::negative_emotions::ANGER[25], + // (´-ω-`) + kaomoji_ru::negative_emotions::SADNESS[2], + // (-ω-、) + kaomoji_ru::negative_emotions::SADNESS[6], + // ( ; ω ; ) + kaomoji_ru::negative_emotions::SADNESS[9], + // ( ╥ω╥ ) + kaomoji_ru::negative_emotions::SADNESS[16], + // (ノωヽ) + kaomoji_ru::negative_emotions::FEAR[0], + // (・_・ヾ + kaomoji_ru::neutral_emotions::CONFUSSION[5], + // ╮( ̄ω ̄;)╭ + kaomoji_ru::neutral_emotions::CONFUSSION[10], + // (*・ω・)ノ + kaomoji_ru::various_actions::GREETING[0], + // (✧∀✧)/ + kaomoji_ru::various_actions::GREETING[25], + // (つ≧▽≦)つ + kaomoji_ru::various_actions::HUGGING[1], + // (つ✧ω✧)つ + kaomoji_ru::various_actions::HUGGING[2], + // ⊂(´• ω •`⊂) + kaomoji_ru::various_actions::HUGGING[8], + // ⊂(・ω・*⊂) + kaomoji_ru::various_actions::HUGGING[9], + // (^ω~) + kaomoji_ru::various_actions::WINKING[3], + // |・ω・) + kaomoji_ru::various_actions::HIDING[0], + // ☆ミ(o*・ω・)ノ + kaomoji_ru::various_actions::RUNNING[0], + // C= C= C= C= C=┌(;・ω・)┘ + kaomoji_ru::various_actions::RUNNING[1], + // ε===(っ≧ω≦)っ + kaomoji_ru::various_actions::RUNNING[6], + // (-ω-) zzZ + kaomoji_ru::various_actions::SLEEPING[3], + // (=^・ω・^=) + kaomoji_ru::animals::CAT[0], + // (=^・ェ・^=) + kaomoji_ru::animals::CAT[1], + // (=①ω①=) + kaomoji_ru::animals::CAT[2], + // ( =ω=)..nyaa + kaomoji_ru::animals::CAT[3], + // (= ; ェ ; =) + kaomoji_ru::animals::CAT[4], + // (=`ω´=) + kaomoji_ru::animals::CAT[5], + // (=^‥^=) + kaomoji_ru::animals::CAT[6], + // ( =ノωヽ=) + kaomoji_ru::animals::CAT[9], + // (=^ ◡ ^=) + kaomoji_ru::animals::CAT[11], + // (=^-ω-^=) + kaomoji_ru::animals::CAT[12], + // ヾ(=`ω´=)ノ” + kaomoji_ru::animals::CAT[13], + // (^• ω •^) + kaomoji_ru::animals::CAT[14], + // (/ =ω=)/ + kaomoji_ru::animals::CAT[15], + // ฅ(•ㅅ•❀)ฅ + kaomoji_ru::animals::CAT[16], + // ଲ(ⓛ ω ⓛ)ଲ + kaomoji_ru::animals::CAT[18], + // (^=◕ᴥ◕=^) + kaomoji_ru::animals::CAT[19], + // ( =ω= ) + kaomoji_ru::animals::CAT[20], + // (^◔ᴥ◔^) + kaomoji_ru::animals::CAT[25], + // ( ・ω・)☞ + kaomoji_ru::special::POINTING, ]; pub const ACTIONS_SIZE: usize = 17; @@ -35,4 +220,4 @@ pub const ACTIONS: [&[u8]; ACTIONS_SIZE] = [ b"*pokes you* ", b"*teleports behind you* ", b"*shuffles closer* ", -]; \ No newline at end of file +]; diff --git a/src/lib.rs b/src/lib.rs index 60a9338..6fe2fa1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,11 @@ +#![cfg_attr(all(feature = "bench", test), feature(test))] + use std::fs::File; -use std::io::{stdout, BufWriter, Error, ErrorKind, Write}; +use std::io::{BufWriter, Error, ErrorKind, Write}; use std::path::Path; use std::str::from_utf8_unchecked; -use indicatif::{ProgressBar, ProgressStyle}; +use ahash::RandomState; use linkify::{LinkFinder, LinkKind}; use memmap::Mmap; @@ -11,25 +13,43 @@ use constants::ACTIONS; use constants::ACTIONS_SIZE; use constants::FACES; use constants::FACES_SIZE; -use seeder::UwUSeeder; mod constants; -mod seeder; macro_rules! progress_bar { - ($bytes:expr) => {{ - let progress_bar = ProgressBar::new($bytes); - progress_bar.set_style( - ProgressStyle::default_spinner() - .template("{spinner:.magenta} [{elapsed_precise:.bold}] {msg:.green.bold}"), - ); - progress_bar.set_message("UwU'ifying In Progress..."); + () => {{ + let progress_bar = indicatif::ProgressBar::new_spinner() + .with_style( + indicatif::ProgressStyle::default_spinner() + .template("{spinner:.magenta} [{elapsed_precise:.bold}] {msg:.green.bold}"), + ) + .with_message("UwU'ifying In Progress..."); progress_bar.enable_steady_tick(30); progress_bar }}; } +macro_rules! new_seeder { + ($word:expr, $random:expr) => { + ::seed_from_u64( + <[u8] as ahash::CallHasher>::get_hash($word, $random), + ) + }; +} + +macro_rules! random_float { + ($seeder:expr) => { + rand::Rng::gen_range($seeder, 0.0..1.0) + }; +} + +macro_rules! random_int { + ($seeder:expr, $range:expr) => { + rand::Rng::gen_range($seeder, $range) + }; +} + #[derive(Debug)] pub struct UwUify<'a> { text: &'a str, @@ -39,7 +59,7 @@ pub struct UwUify<'a> { faces: f64, actions: f64, stutters: f64, - random: bool, + random: RandomState, is_runtime: bool, linkify: LinkFinder, } @@ -54,7 +74,7 @@ impl<'a> Default for UwUify<'a> { faces: 0.05, actions: 0.125, stutters: 0.225, - random: false, + random: RandomState::with_seeds(69, 420, 28, 95), is_runtime: false, linkify: LinkFinder::new(), } @@ -81,12 +101,15 @@ impl<'a> UwUify<'a> { text: text.unwrap_or_default(), input: infile.unwrap_or_default(), output: outfile.unwrap_or_default(), - random, is_runtime, linkify, ..Default::default() }; + if random { + uwuify.random = RandomState::new(); + } + if let Some(words) = words { uwuify.words = words.parse::().unwrap(); } @@ -103,7 +126,7 @@ impl<'a> UwUify<'a> { uwuify } - pub fn uwuify(&mut self) -> Result<(), Error> { + pub fn uwuify(&self) -> Result<(), Error> { // Handle Text if !self.text.is_empty() { // Handle Text Output @@ -115,11 +138,14 @@ impl<'a> UwUify<'a> { )); } - let uwu_progress_bar = progress_bar!(self.text.len() as u64); + let uwu_progress_bar = progress_bar!(); self.uwuify_sentence(self.text, &mut BufWriter::new(File::create(&self.output)?))?; uwu_progress_bar.finish_with_message("UwU'ifying Complete!"); } else { - self.uwuify_sentence(self.text, &mut BufWriter::new(stdout().lock()))?; + #[cfg(not(test))] + self.uwuify_sentence(self.text, &mut BufWriter::new(std::io::stdout().lock()))?; + #[cfg(test)] + self.uwuify_sentence(self.text, &mut std::io::sink())?; } } else { // Handle File I/O @@ -130,10 +156,9 @@ impl<'a> UwUify<'a> { )); } - let infile = File::open(&self.input)?; - let uwu_progress_bar = progress_bar!(infile.metadata()?.len()); + let uwu_progress_bar = progress_bar!(); self.uwuify_sentence( - unsafe { from_utf8_unchecked(Mmap::map(&infile)?.as_ref()) }, + unsafe { from_utf8_unchecked(Mmap::map(&File::open(&self.input)?)?.as_ref()) }, &mut BufWriter::new(File::create(&self.output)?), )?; uwu_progress_bar.finish_with_message("UwU'ifying Complete!"); @@ -142,19 +167,20 @@ impl<'a> UwUify<'a> { Ok(()) } - pub fn uwuify_sentence(&mut self, text: &str, out: &mut T) -> Result<(), Error> { + pub fn uwuify_sentence(&self, text: &str, out: &mut T) -> Result<(), Error> { text.lines().try_for_each(|line| { line.split_whitespace() .map(|word_str| word_str.as_bytes()) .try_for_each(|word| { - let mut seeder = UwUSeeder::new(word, self.random); - let random_value = seeder.random_float(); + let mut seeder = new_seeder!(word, &self.random); + let random_value = random_float!(&mut seeder); if !self.is_runtime { if random_value <= self.faces { - out.write_all(FACES[seeder.random_int(0..FACES_SIZE)])?; + out.write_all(FACES[random_int!(&mut seeder, 0..FACES_SIZE)])?; + out.write_all(b" ")?; } else if random_value <= self.actions { - out.write_all(ACTIONS[seeder.random_int(0..ACTIONS_SIZE)])?; + out.write_all(ACTIONS[random_int!(&mut seeder, 0..ACTIONS_SIZE)])?; } else if random_value <= self.stutters { match word[0] { b'L' | b'R' => out.write_all(b"W"), @@ -165,10 +191,10 @@ impl<'a> UwUify<'a> { } } else { if random_value <= self.faces { - out.write_all(FACES[seeder.random_int(0..FACES_SIZE)])?; + out.write_all(FACES[random_int!(&mut seeder, 0..FACES_SIZE)])?; } if random_value <= self.actions { - out.write_all(ACTIONS[seeder.random_int(0..ACTIONS_SIZE)])?; + out.write_all(ACTIONS[random_int!(&mut seeder, 0..ACTIONS_SIZE)])?; } if random_value <= self.stutters { match word[0] { @@ -206,4 +232,26 @@ impl<'a> UwUify<'a> { out.write_all(b"\n") }) } -} \ No newline at end of file +} +#[cfg(test)] +mod tests { + #[cfg(feature = "bench")] + extern crate test; + + #[cfg(feature = "bench")] + #[bench] + fn uwu_bench(b: &mut test::Bencher) { + let uwuify = super::UwUify::new( + Some(include_str!("test.txt")), + None, + None, + None, + None, + None, + None, + false, + false, + ); + b.iter(|| uwuify.uwuify()); + } +} diff --git a/src/main.rs b/src/main.rs index e41ce0c..29bd31c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -142,4 +142,4 @@ fn is_between_zero_and_one(input: &str) -> Result<(), &'static str> { return Ok(()); } Err("The value must be between 0.0 and 1.0") -} \ No newline at end of file +} diff --git a/src/seeder.rs b/src/seeder.rs deleted file mode 100644 index 722cd12..0000000 --- a/src/seeder.rs +++ /dev/null @@ -1,34 +0,0 @@ -use std::hash::Hasher; - -use ahash::AHasher; -use rand::distributions::uniform::{SampleRange, SampleUniform}; -use rand::{Rng, RngCore, SeedableRng}; -use rand_xoshiro::Xoshiro256Plus; - -pub struct UwUSeeder { - rng: Xoshiro256Plus, -} - -impl UwUSeeder { - pub fn new(word: &[u8], random: bool) -> UwUSeeder { - let rand_u64 = if !random { - let mut hasher = AHasher::new_with_keys(0, 0); - hasher.write(word); - hasher.finish() - } else { - rand::rngs::OsRng::default().next_u64() - }; - - UwUSeeder { - rng: Xoshiro256Plus::seed_from_u64(rand_u64), - } - } - - pub fn random_float(&mut self) -> f64 { - self.rng.gen_range(0.0..1.0) - } - - pub fn random_int>(&mut self, range: R) -> T { - self.rng.gen_range(range) - } -} \ No newline at end of file diff --git a/src/test.txt b/src/test.txt new file mode 100644 index 0000000..d5cf3c3 --- /dev/null +++ b/src/test.txt @@ -0,0 +1,14 @@ +From fairest creatures we desire increase, +That thereby beauty's rose might never die, +But as the riper should by time decease, +His tender heir might bear his memory: +But thou contracted to thine own bright eyes, +Feed'st thy light's flame with self-substantial fuel, +Making a famine where abundance lies, +Thy self thy foe, to thy sweet self too cruel: +Thou that art now the world's fresh ornament, +And only herald to the gaudy spring, +Within thine own bud buriest thy content, +And tender churl mak'st waste in niggarding: +Pity the world, or else this glutton be, +To eat the world's due, by the grave and thee. From 0057f08273988b55e8e31edbbca75358f44c8c2e Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 1 Feb 2022 18:13:15 -0500 Subject: [PATCH 3/9] Wemove U-Unused fiwe --- infile.txt | 1 - outfile.txt | 1 - 2 files changed, 2 deletions(-) delete mode 100644 infile.txt delete mode 100644 outfile.txt diff --git a/infile.txt b/infile.txt deleted file mode 100644 index e80fa1c..0000000 --- a/infile.txt +++ /dev/null @@ -1 +0,0 @@ -According to all known laws of aviation, there is no way a bee should be able to fly. diff --git a/outfile.txt b/outfile.txt deleted file mode 100644 index 0cb44dd..0000000 --- a/outfile.txt +++ /dev/null @@ -1 +0,0 @@ -Accowding to aww uWu knyown waws of aviation, thewe i-is nyo way *moans* a bee shouwd be abwe to fwy. From 5b8c40ada1ac274379e55c601a34b8da1d489ad5 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 1 Feb 2022 18:23:39 -0500 Subject: [PATCH 4/9] Fwix Buwgs --- src/lib.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ea803cd..1f73cf0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,5 @@ #![cfg_attr(all(feature = "bench", test), feature(test))] -use indicatif::{ProgressBar, ProgressStyle}; -use linkify::{LinkFinder, LinkKind}; -use rand::{Rng, RngCore, SeedableRng}; -use rand_xoshiro::Xoshiro256Plus; use std::fs::File; use std::io::{BufWriter, Error, ErrorKind, Write}; use std::path::Path; From b6dcad187805c66add285785738d07d20067bab6 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 1 Feb 2022 19:10:20 -0500 Subject: [PATCH 5/9] Add ascii only option --- src/constants.rs | 50 +++++++++++++++++++++++++++++++++++++++++++++++- src/lib.rs | 44 +++++++++++++++++++++--------------------- src/main.rs | 26 ++++++++++++++++--------- 3 files changed, 88 insertions(+), 32 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 4102fa9..afa81fc 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -1,5 +1,4 @@ pub const FACES_SIZE: usize = 106; - pub const FACES: [&[u8]; FACES_SIZE] = [ b"OwO", b"UwU", @@ -201,6 +200,55 @@ pub const FACES: [&[u8]; FACES_SIZE] = [ kaomoji_ru::special::POINTING, ]; +pub const ASCII_SIZE: usize = ascii_len(&FACES); +pub const ASCII: [&[u8]; ASCII_SIZE] = ascii_array(&FACES); + +pub const fn ascii_len(array: &[&[u8]]) -> usize { + let mut result = 0; + let len = array.len(); + let mut head = 0; + while head != len { + let mut ascii_head = 0; + let ascii_len = array[head].len(); + let mut ascii_res = 0; + while ascii_head != ascii_len { + if array[head][ascii_head].is_ascii() { + ascii_res += 1; + } + ascii_head += 1; + } + if ascii_res == array[head].len() { + result += 1; + } + head += 1; + } + result +} + +pub const fn ascii_array(array: &'static [&'static [u8]]) -> [&'static [u8]; ASCII_SIZE] { + let mut ascii_array: [&'static [u8]; ASCII_SIZE] = [&[]; ASCII_SIZE]; + let mut result_head = 0; + let len = array.len(); + let mut head = 0; + while head != len { + let mut ascii_head = 0; + let ascii_len = array[head].len(); + let mut ascii_res = 0; + while ascii_head != ascii_len { + if array[head][ascii_head].is_ascii() { + ascii_res += 1; + } + ascii_head += 1; + } + if ascii_res == array[head].len() { + ascii_array[result_head] = array[head]; + result_head += 1; + } + head += 1; + } + ascii_array +} + pub const ACTIONS_SIZE: usize = 17; pub const ACTIONS: [&[u8]; ACTIONS_SIZE] = [ b"*notices bulge* ", diff --git a/src/lib.rs b/src/lib.rs index 1f73cf0..722b609 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,14 +5,15 @@ use std::io::{BufWriter, Error, ErrorKind, Write}; use std::path::Path; use std::str::from_utf8_unchecked; -use ahash::RandomState; use linkify::{LinkFinder, LinkKind}; use memmap::Mmap; -use constants::ACTIONS; use constants::ACTIONS_SIZE; use constants::FACES; use constants::FACES_SIZE; +use constants::{ACTIONS, ASCII, ASCII_SIZE}; +use rand::SeedableRng; +use rand_xoshiro::Xoshiro256Plus; mod constants; @@ -30,14 +31,6 @@ macro_rules! progress_bar { }}; } -macro_rules! new_seeder { - ($word:expr, $random:expr) => { - ::seed_from_u64( - <[u8] as ahash::CallHasher>::get_hash($word, $random), - ) - }; -} - macro_rules! random_float { ($seeder:expr) => { rand::Rng::gen_range($seeder, 0.0..1.0) @@ -59,7 +52,8 @@ pub struct UwUify<'a> { faces: f64, actions: f64, stutters: f64, - random: RandomState, + random: Xoshiro256Plus, + ascii: bool, is_runtime: bool, linkify: LinkFinder, } @@ -74,8 +68,9 @@ impl<'a> Default for UwUify<'a> { faces: 0.05, actions: 0.125, stutters: 0.225, - random: RandomState::with_seeds(69, 420, 28, 95), + random: Xoshiro256Plus::seed_from_u64(69420), is_runtime: false, + ascii: false, linkify: LinkFinder::new(), } } @@ -90,6 +85,7 @@ impl<'a> UwUify<'a> { faces: Option<&'a str>, actions: Option<&'a str>, stutters: Option<&'a str>, + ascii: bool, random: bool, is_runtime: bool, ) -> UwUify<'a> { @@ -101,13 +97,14 @@ impl<'a> UwUify<'a> { text: text.unwrap_or_default(), input: infile.unwrap_or_default(), output: outfile.unwrap_or_default(), + ascii, is_runtime, linkify, ..Default::default() }; if random { - uwuify.random = RandomState::new(); + uwuify.random = Xoshiro256Plus::from_entropy(); } if let Some(words) = words { @@ -126,7 +123,7 @@ impl<'a> UwUify<'a> { uwuify } - pub fn uwuify(&self) -> Result<(), Error> { + pub fn uwuify(&mut self) -> Result<(), Error> { // Handle Text if !self.text.is_empty() { // Handle Text Output @@ -167,20 +164,19 @@ impl<'a> UwUify<'a> { Ok(()) } - pub fn uwuify_sentence(&self, text: &str, out: &mut T) -> Result<(), Error> { + pub fn uwuify_sentence(&mut self, text: &str, out: &mut T) -> Result<(), Error> { text.lines().try_for_each(|line| { line.split_whitespace() .map(|word_str| word_str.as_bytes()) .try_for_each(|word| { - let mut seeder = new_seeder!(word, &self.random); - let random_value = random_float!(&mut seeder); + let random_value = random_float!(&mut self.random); if !self.is_runtime { if random_value <= self.faces { - out.write_all(FACES[random_int!(&mut seeder, 0..FACES_SIZE)])?; + out.write_all(FACES[random_int!(&mut self.random, 0..FACES_SIZE)])?; out.write_all(b" ")?; } else if random_value <= self.actions { - out.write_all(ACTIONS[random_int!(&mut seeder, 0..ACTIONS_SIZE)])?; + out.write_all(ACTIONS[random_int!(&mut self.random, 0..ACTIONS_SIZE)])?; } else if random_value <= self.stutters { match word[0] { b'L' | b'R' => out.write_all(b"W"), @@ -191,11 +187,15 @@ impl<'a> UwUify<'a> { } } else { if random_value <= self.faces { - out.write_all(FACES[random_int!(&mut seeder, 0..FACES_SIZE)])?; + if self.ascii { + out.write_all(ASCII[random_int!(&mut self.random, 0..ASCII_SIZE)])?; + } else { + out.write_all(FACES[random_int!(&mut self.random, 0..FACES_SIZE)])?; + } out.write_all(b" ")?; } if random_value <= self.actions { - out.write_all(ACTIONS[random_int!(&mut seeder, 0..ACTIONS_SIZE)])?; + out.write_all(ACTIONS[random_int!(&mut self.random, 0..ACTIONS_SIZE)])?; } if random_value <= self.stutters { match word[0] { @@ -242,7 +242,7 @@ mod tests { #[cfg(feature = "bench")] #[bench] fn uwu_bench(b: &mut test::Bencher) { - let uwuify = super::UwUify::new( + let mut uwuify = super::UwUify::new( Some(include_str!("test.txt")), None, None, diff --git a/src/main.rs b/src/main.rs index 29bd31c..0e1296b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,6 +25,12 @@ macro_rules! app { .required_unless_present_all(["infile", "outfile"]) .display_order(1), ) + .arg( + Arg::new("ascii-only") + .help("The output file will not use UTF-8 charecters") + .long("ascii-only") + .display_order(2), + ) .arg( Arg::new("infile") .help("The file to uwu'ify") @@ -34,7 +40,7 @@ macro_rules! app { .requires("outfile") .value_name("FILE") .value_hint(clap::ValueHint::FilePath) - .display_order(2), + .display_order(3), ) .arg( Arg::new("outfile") @@ -43,7 +49,7 @@ macro_rules! app { .long("outfile") .value_name("FILE") .value_hint(clap::ValueHint::FilePath) - .display_order(3), + .display_order(4), ) .arg( Arg::new("words") @@ -53,7 +59,7 @@ macro_rules! app { .value_name("VALUE") .default_value("1") .validator(is_between_zero_and_one) - .display_order(4), + .display_order(5), ) .arg( Arg::new("faces") @@ -63,7 +69,7 @@ macro_rules! app { .value_name("VALUE") .default_value("0.05") .validator(is_between_zero_and_one) - .display_order(5), + .display_order(6), ) .arg( Arg::new("actions") @@ -73,7 +79,7 @@ macro_rules! app { .value_name("VALUE") .default_value("0.125") .validator(is_between_zero_and_one) - .display_order(6), + .display_order(7), ) .arg( Arg::new("stutters") @@ -83,14 +89,14 @@ macro_rules! app { .value_name("VALUE") .default_value("0.225") .validator(is_between_zero_and_one) - .display_order(7), + .display_order(8), ) .arg( Arg::new("random") .help("Flag to enable/disable random uwu'ifying") .short('r') .long("random") - .display_order(8), + .display_order(9), ) }; } @@ -102,8 +108,8 @@ macro_rules! clap_panic { } macro_rules! is_runtime { - ($faces:expr, $actions:expr, $stutters:expr) => { - $faces > 0 || $actions > 0 || $stutters > 0 + ($faces:expr, $actions:expr, $ascii:expr, $stutters:expr) => { + $faces > 0 || $actions > 0 || $ascii > 0 || $stutters > 0 }; } @@ -119,10 +125,12 @@ fn main() { matches.value_of("faces"), matches.value_of("actions"), matches.value_of("stutters"), + matches.is_present("ascii-only"), matches.is_present("random"), is_runtime!( matches.occurrences_of("faces"), matches.occurrences_of("actions"), + matches.occurrences_of("ascii-only"), matches.occurrences_of("stutters") ), ) From 389cb0052d717bf056f040fe14a77ac3a997036d Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 1 Feb 2022 19:18:38 -0500 Subject: [PATCH 6/9] Add bwack wowd based wandomness --- src/lib.rs | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 722b609..84cffe0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,7 @@ use std::io::{BufWriter, Error, ErrorKind, Write}; use std::path::Path; use std::str::from_utf8_unchecked; +use ahash::RandomState; use linkify::{LinkFinder, LinkKind}; use memmap::Mmap; @@ -12,8 +13,6 @@ use constants::ACTIONS_SIZE; use constants::FACES; use constants::FACES_SIZE; use constants::{ACTIONS, ASCII, ASCII_SIZE}; -use rand::SeedableRng; -use rand_xoshiro::Xoshiro256Plus; mod constants; @@ -31,6 +30,14 @@ macro_rules! progress_bar { }}; } +macro_rules! new_seeder { + ($word:expr,$seeder:expr) => { + ::seed_from_u64( + <[u8] as ahash::CallHasher>::get_hash($word, $seeder), + ) + }; +} + macro_rules! random_float { ($seeder:expr) => { rand::Rng::gen_range($seeder, 0.0..1.0) @@ -52,7 +59,7 @@ pub struct UwUify<'a> { faces: f64, actions: f64, stutters: f64, - random: Xoshiro256Plus, + random: RandomState, ascii: bool, is_runtime: bool, linkify: LinkFinder, @@ -68,7 +75,7 @@ impl<'a> Default for UwUify<'a> { faces: 0.05, actions: 0.125, stutters: 0.225, - random: Xoshiro256Plus::seed_from_u64(69420), + random: RandomState::with_seeds(69, 420, 96, 84), is_runtime: false, ascii: false, linkify: LinkFinder::new(), @@ -104,7 +111,7 @@ impl<'a> UwUify<'a> { }; if random { - uwuify.random = Xoshiro256Plus::from_entropy(); + uwuify.random = RandomState::new(); } if let Some(words) = words { @@ -123,7 +130,7 @@ impl<'a> UwUify<'a> { uwuify } - pub fn uwuify(&mut self) -> Result<(), Error> { + pub fn uwuify(&self) -> Result<(), Error> { // Handle Text if !self.text.is_empty() { // Handle Text Output @@ -164,19 +171,20 @@ impl<'a> UwUify<'a> { Ok(()) } - pub fn uwuify_sentence(&mut self, text: &str, out: &mut T) -> Result<(), Error> { + pub fn uwuify_sentence(&self, text: &str, out: &mut T) -> Result<(), Error> { text.lines().try_for_each(|line| { line.split_whitespace() .map(|word_str| word_str.as_bytes()) .try_for_each(|word| { - let random_value = random_float!(&mut self.random); + let mut seeder = new_seeder!(word, &self.random); + let random_value = random_float!(&mut seeder); if !self.is_runtime { if random_value <= self.faces { - out.write_all(FACES[random_int!(&mut self.random, 0..FACES_SIZE)])?; + out.write_all(FACES[random_int!(&mut seeder, 0..FACES_SIZE)])?; out.write_all(b" ")?; } else if random_value <= self.actions { - out.write_all(ACTIONS[random_int!(&mut self.random, 0..ACTIONS_SIZE)])?; + out.write_all(ACTIONS[random_int!(&mut seeder, 0..ACTIONS_SIZE)])?; } else if random_value <= self.stutters { match word[0] { b'L' | b'R' => out.write_all(b"W"), @@ -188,14 +196,14 @@ impl<'a> UwUify<'a> { } else { if random_value <= self.faces { if self.ascii { - out.write_all(ASCII[random_int!(&mut self.random, 0..ASCII_SIZE)])?; + out.write_all(ASCII[random_int!(&mut seeder, 0..ASCII_SIZE)])?; } else { - out.write_all(FACES[random_int!(&mut self.random, 0..FACES_SIZE)])?; + out.write_all(FACES[random_int!(&mut seeder, 0..FACES_SIZE)])?; } out.write_all(b" ")?; } if random_value <= self.actions { - out.write_all(ACTIONS[random_int!(&mut self.random, 0..ACTIONS_SIZE)])?; + out.write_all(ACTIONS[random_int!(&mut seeder, 0..ACTIONS_SIZE)])?; } if random_value <= self.stutters { match word[0] { @@ -242,7 +250,7 @@ mod tests { #[cfg(feature = "bench")] #[bench] fn uwu_bench(b: &mut test::Bencher) { - let mut uwuify = super::UwUify::new( + let uwuify = super::UwUify::new( Some(include_str!("test.txt")), None, None, From a9d3d3fe0cdf62023c349802270292613f2bae55 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 1 Feb 2022 19:20:40 -0500 Subject: [PATCH 7/9] Fwix benchmawk --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.rs b/src/lib.rs index 84cffe0..e1c68b5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -260,6 +260,7 @@ mod tests { None, false, false, + false, ); b.iter(|| uwuify.uwuify()); } From 73f81bc82132fc991263df15fbfc953b09ea6c4b Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 1 Feb 2022 19:32:51 -0500 Subject: [PATCH 8/9] Updwate dependencwy --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 6e228fc..8a5ed80 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ linkify = "0.8.0" rand_xoshiro = "0.6.0" ahash = "0.7.6" memmap = "0.7.0" -kaomoji-ru = "1.0.0" +kaomoji-ru = "1.0.1" [profile.release] lto = "fat" From c8c3c96df625b8c71f62fcbae2092ef116ac1d98 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 1 Feb 2022 20:04:09 -0500 Subject: [PATCH 9/9] Uncoupwe --ascii-only and is_runtime --- src/lib.rs | 6 +++++- src/main.rs | 5 ++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e1c68b5..377a431 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -181,7 +181,11 @@ impl<'a> UwUify<'a> { if !self.is_runtime { if random_value <= self.faces { - out.write_all(FACES[random_int!(&mut seeder, 0..FACES_SIZE)])?; + if self.ascii { + out.write_all(ASCII[random_int!(&mut seeder, 0..ASCII_SIZE)])?; + } else { + out.write_all(FACES[random_int!(&mut seeder, 0..FACES_SIZE)])?; + } out.write_all(b" ")?; } else if random_value <= self.actions { out.write_all(ACTIONS[random_int!(&mut seeder, 0..ACTIONS_SIZE)])?; diff --git a/src/main.rs b/src/main.rs index 0e1296b..04e95dc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -108,8 +108,8 @@ macro_rules! clap_panic { } macro_rules! is_runtime { - ($faces:expr, $actions:expr, $ascii:expr, $stutters:expr) => { - $faces > 0 || $actions > 0 || $ascii > 0 || $stutters > 0 + ($faces:expr, $actions:expr, $stutters:expr) => { + $faces > 0 || $actions > 0 || $stutters > 0 }; } @@ -130,7 +130,6 @@ fn main() { is_runtime!( matches.occurrences_of("faces"), matches.occurrences_of("actions"), - matches.occurrences_of("ascii-only"), matches.occurrences_of("stutters") ), )