From 7cce361c7361977b2cea2b95e660b4ac8b249687 Mon Sep 17 00:00:00 2001 From: Lilith Schier Date: Fri, 21 Aug 2026 13:20:52 +0200 Subject: [PATCH 1/2] minor code cleanup --- Cargo.lock | 2 +- src/dice.rs | 43 +++++++++++++++++++------------------------ src/main.rs | 20 +++++++++++--------- 3 files changed, 31 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9716d17..e5487b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1420,7 +1420,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/src/dice.rs b/src/dice.rs index 169ea03..fc33011 100644 --- a/src/dice.rs +++ b/src/dice.rs @@ -1,4 +1,6 @@ -use crate::limits::{MAX_DICE_COUNT_PER_ROLL, MAX_DISPLAYED_DICE_PER_MESSAGE, RESULT_CULL_CHARACTER_THRESHOLD}; +use crate::limits::{ + MAX_DICE_COUNT_PER_ROLL, MAX_DISPLAYED_DICE_PER_MESSAGE, RESULT_CULL_CHARACTER_THRESHOLD, +}; use anyhow::bail; use rand::{Rng, RngExt}; use std::convert::Infallible; @@ -116,10 +118,10 @@ impl Expression { // Exploding dice are early, they add rolls if let Some(fragments) = x { write!(w, "x")?; - let mut comparers = Vec::with_capacity(fragments.len()); - for fragment in fragments { - comparers.push(fragment.comparer(rng, w)?); - } + let comparers = fragments + .iter() + .map(|fragment| fragment.comparer(rng, w)) + .collect::, _>>()?; let mut i = 0; while i < rolls.len() { if i > MAX_DICE_COUNT_PER_ROLL { @@ -131,12 +133,8 @@ impl Expression { rolls.push(rng.random_range(1..=size)); } } else { - // Explode based on comparers provided - for comparer in comparers.iter() { - if comparer(rolls[i] as f64) { - rolls.push(rng.random_range(1..=size)); - break; - } + if comparers.iter().any(|comparer| comparer(rolls[i] as f64)) { + rolls.push(rng.random_range(1..=size)); } } i += 1; @@ -454,12 +452,15 @@ pub(crate) enum DiscordMdWitnessError { } impl DiscordMd { - pub(crate) fn create_witness(md: &Arc>) -> DiscordMdWitness { - let mut parent = md.write().unwrap(); - parent.buffers.push(String::new()); + pub(crate) fn create_witness(md: Arc>) -> DiscordMdWitness { + let buffer_idx = { + let mut md = md.write().unwrap(); + md.buffers.push(String::new()); + md.buffers.len() - 1 + }; DiscordMdWitness { - parent: md.clone(), - buffer_idx: parent.buffers.len() - 1, + parent: md, + buffer_idx, result: None, } } @@ -469,7 +470,6 @@ impl DiscordMd { } } - impl DiscordMdWitness { pub(crate) fn end(self) { let mut parent = self.parent.write().unwrap(); @@ -479,8 +479,7 @@ impl DiscordMdWitness { .map(|result| format!("**{result} = …**")) .unwrap_or_else(|| String::new()); } else if let Some(result) = self.result { - parent.buffers[self.buffer_idx] - .insert_str(0, &format!("**{result}** = ")); + parent.buffers[self.buffer_idx].insert_str(0, &format!("**{result}** = ")); } } } @@ -510,7 +509,6 @@ impl Witness for DiscordMdWitness { } } - impl<'a> WitnessSet for DiscordMdWitnessSet<'a> { type Ok = (); type Error = DiscordMdWitnessError; @@ -519,10 +517,7 @@ impl<'a> WitnessSet for DiscordMdWitnessSet<'a> { let mut parent = self.witness.parent.write().unwrap(); if parent.dice_written >= MAX_DISPLAYED_DICE_PER_MESSAGE { if !self.dice_elided { - write!( - parent.buffers[self.witness.buffer_idx], - "…" - )?; + write!(parent.buffers[self.witness.buffer_idx], "…")?; self.dice_elided = true; } return Ok(()); diff --git a/src/main.rs b/src/main.rs index 742b301..78308c0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -137,8 +137,7 @@ pub async fn roll(ctx: &Context, command: &CommandInteraction) -> anyhow::Result } }) .unwrap_or(1) - .min(MAX_ROLL_REPEATS as i64) - .max(1) as usize; + .clamp(1, MAX_ROLL_REPEATS as i64) as usize; let private = options .iter() .find(|option| option.name == "private") @@ -170,7 +169,8 @@ pub async fn roll(ctx: &Context, command: &CommandInteraction) -> anyhow::Result None } }) - .and_then(|s| s.parse::().ok()); + .map(|s| s.parse::().context("Seed could not be parsed. Make sure it is a 64 bit integer between 0 and 2^64-1.")) + .transpose()?; let expression = parsing::parse(&formula).context("Dice formula could not be parsed.")?; @@ -193,13 +193,13 @@ pub async fn roll(ctx: &Context, command: &CommandInteraction) -> anyhow::Result let surrounding_par_count = pre_paragraphs.len() + post_paragraphs.len(); - let paragraphs = if repeat <= 40 - surrounding_par_count { + let roll_paragraphs = if repeat <= 40 - surrounding_par_count { let discord_md = Arc::new(std::sync::RwLock::new(DiscordMd { buffers: Vec::with_capacity(repeat), dice_written: 0, })); for _ in 0..repeat { - let mut witness = DiscordMd::create_witness(&discord_md); + let mut witness = DiscordMd::create_witness(discord_md.clone()); let result = expression.evaluate(&mut rng, &mut witness, i64::MAX)?; witness.witness_total_result(result)?; witness.end(); @@ -208,7 +208,7 @@ pub async fn roll(ctx: &Context, command: &CommandInteraction) -> anyhow::Result discord_md.buffers } else { - let mut par = String::new(); + let mut par = String::with_capacity(8 * repeat); for i in 0..repeat { if i > 0 { write!(par, ", ")?; @@ -222,9 +222,11 @@ pub async fn roll(ctx: &Context, command: &CommandInteraction) -> anyhow::Result vec![par] }; - pre_paragraphs.extend(paragraphs); - pre_paragraphs.extend(post_paragraphs); - let paragraphs = pre_paragraphs; + let paragraphs = { + pre_paragraphs.extend(roll_paragraphs); + pre_paragraphs.extend(post_paragraphs); + pre_paragraphs + }; if paragraphs.iter().map(|s| s.chars().count()).sum::() > 4000 || paragraphs.len() > 40 From e2649ce6ed10ffa352407d3bacb1e142ed473ef2 Mon Sep 17 00:00:00 2001 From: Lilith Schier Date: Fri, 21 Aug 2026 13:33:58 +0200 Subject: [PATCH 2/2] clippy fixes --- Cargo.lock | 2 +- Cargo.toml | 5 ++++- src/dice.rs | 46 +++++++++++++++++++++++----------------------- src/main.rs | 46 ++++++++++++++++++++++++---------------------- src/parsing.rs | 2 +- 5 files changed, 53 insertions(+), 48 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e5487b7..a244f97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1570,7 +1570,7 @@ dependencies = [ [[package]] name = "serenity" version = "0.12.5" -source = "git+https://github.com/serenity-rs/serenity.git?rev=refs%2Fheads%2Fnext#37b9f433ada8b9ccc5f93f04826403b175855f86" +source = "git+https://github.com/serenity-rs/serenity.git?branch=next#37b9f433ada8b9ccc5f93f04826403b175855f86" dependencies = [ "aformat", "arrayvec", diff --git a/Cargo.toml b/Cargo.toml index 5d24596..4fe1f28 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] dotenv = "0.15.0" -serenity = { git = "https://github.com/serenity-rs/serenity.git", rev = "refs/heads/next" , features = ["collector"] } +serenity = { version = "0.12.5" } tokio = { version = "1.53.1", features = ["rt-multi-thread"] } tracing = "0.1.44" tracing-subscriber = "0.3.23" @@ -15,3 +15,6 @@ thiserror = "2.0.20" nom-language = "0.1.0" rand_xoshiro = "0.8.1" rand = "0.10.2" + +[patch.crates-io] +serenity = { git = "https://github.com/serenity-rs/serenity.git", branch = "next" } diff --git a/src/dice.rs b/src/dice.rs index fc33011..49cdac4 100644 --- a/src/dice.rs +++ b/src/dice.rs @@ -127,7 +127,7 @@ impl Expression { if i > MAX_DICE_COUNT_PER_ROLL { bail!("Explosion added too many dice.") } - if comparers.len() == 0 { + if comparers.is_empty() { // Explode on max size dice if rolls[i] == size { rolls.push(rng.random_range(1..=size)); @@ -185,25 +185,25 @@ impl Expression { let mut skip = false; let roll = rolls[idx]; let rank = ranks[idx]; - if let Some(kh) = kh { - if rolls.len() - 1 - rank >= kh { - skip = true; - } + if let Some(kh) = kh + && rolls.len() - 1 - rank >= kh + { + skip = true; } - if let Some(dh) = dh { - if rolls.len() - 1 - rank < dh { - skip = true; - } + if let Some(dh) = dh + && rolls.len() - 1 - rank < dh + { + skip = true; } - if let Some(kl) = kl { - if rank >= kl { - skip = true; - } + if let Some(kl) = kl + && rank >= kl + { + skip = true; } - if let Some(dl) = dl { - if rank < dl { - skip = true; - } + if let Some(dl) = dl + && rank < dl + { + skip = true; } if !skip { result_set.push(roll as f64); @@ -298,19 +298,19 @@ impl Expression { bail!("Invalid die size.") } - if let Some(_) = x { + if x.is_some() { bail!("Not implemented yet"); } - if let Some(_) = kh { + if kh.is_some() { bail!("Not implemented yet"); }; - if let Some(_) = kl { + if kl.is_some() { bail!("Not implemented yet"); }; - if let Some(_) = dh { + if dh.is_some() { bail!("Not implemented yet"); }; - if let Some(_) = dl { + if dl.is_some() { bail!("Not implemented yet"); }; @@ -477,7 +477,7 @@ impl DiscordMdWitness { parent.buffers[self.buffer_idx] = self .result .map(|result| format!("**{result} = …**")) - .unwrap_or_else(|| String::new()); + .unwrap_or_default(); } else if let Some(result) = self.result { parent.buffers[self.buffer_idx].insert_str(0, &format!("**{result}** = ")); } diff --git a/src/main.rs b/src/main.rs index 78308c0..c82fcab 100644 --- a/src/main.rs +++ b/src/main.rs @@ -172,7 +172,7 @@ pub async fn roll(ctx: &Context, command: &CommandInteraction) -> anyhow::Result .map(|s| s.parse::().context("Seed could not be parsed. Make sure it is a 64 bit integer between 0 and 2^64-1.")) .transpose()?; - let expression = parsing::parse(&formula).context("Dice formula could not be parsed.")?; + let expression = parsing::parse(formula).context("Dice formula could not be parsed.")?; let seed = fixed_seed.unwrap_or_else(|| rand::rng().next_u64()); let mut rng = rand_xoshiro::Xoshiro256PlusPlus::seed_from_u64(seed); @@ -255,27 +255,29 @@ pub async fn roll(ctx: &Context, command: &CommandInteraction) -> anyhow::Result Ok(()) } - if let Ok(_) = inner(ctx, command).await { - } else if let Err(err) = inner(ctx, command).await { - warn!("Error encountered: {err:?}"); - command - .create_response( - &ctx.http, - CreateInteractionResponse::Message( - CreateInteractionResponseMessage::new() - .components(vec![CreateComponent::Container(CreateContainer::new( - vec![CreateContainerComponent::TextDisplay( - CreateTextDisplay::new(err.to_string()), - )], - ))]) - // flags needs to be called before ephemeral for correct ordering - .flags( - MessageFlags::IS_COMPONENTS_V2 | MessageFlags::SUPPRESS_NOTIFICATIONS, - ) - .ephemeral(true), - ), - ) - .await? + match inner(ctx, command).await { + Ok(_) => {} + Err(err) => { + warn!("Error encountered: {err:?}"); + command + .create_response( + &ctx.http, + CreateInteractionResponse::Message( + CreateInteractionResponseMessage::new() + .components(vec![CreateComponent::Container(CreateContainer::new( + vec![CreateContainerComponent::TextDisplay( + CreateTextDisplay::new(err.to_string()), + )], + ))]) + // flags needs to be called before ephemeral for correct ordering + .flags( + MessageFlags::IS_COMPONENTS_V2 | MessageFlags::SUPPRESS_NOTIFICATIONS, + ) + .ephemeral(true), + ), + ) + .await? + } }; Ok(()) } diff --git a/src/parsing.rs b/src/parsing.rs index 81dc420..92c2f25 100644 --- a/src/parsing.rs +++ b/src/parsing.rs @@ -80,7 +80,7 @@ fn expr<'c, 'i>( ) .map(|(count, size, (kh, kl, dh, dl, x))| { Dice(DiceFormula { - count: count.map(|n| Box::new(n)), + count: count.map(Box::new), size: Box::new(size), kh: kh.map(|n| Box::new(n.unwrap_or(Const(1f64)))), kl: kl.map(|n| Box::new(n.unwrap_or(Const(1f64)))),