diff --git a/src/callbacks.rs b/src/callbacks.rs index 46cf04c..638b321 100644 --- a/src/callbacks.rs +++ b/src/callbacks.rs @@ -93,6 +93,9 @@ async fn send_error_message( Some(&FuukaBotError::ShouldAvaliable) => RoomMessageEventContent::text_plain(format!( "⁉️ The bot fired an internal error: {err:#}" )), + Some(&FuukaBotError::MathOverflow) | Some(&FuukaBotError::DivByZero) => { + RoomMessageEventContent::text_plain(format!("⁉️ Math error happened: {err:#}")) + } None => { RoomMessageEventContent::text_plain(format!("⁉️ An unexpected error occoured: {err:#}")) } diff --git a/src/dicer.rs b/src/dicer.rs index 716d5cb..120321b 100644 --- a/src/dicer.rs +++ b/src/dicer.rs @@ -26,6 +26,8 @@ use nom::sequence::{delimited, pair, preceded, separated_pair, terminated}; use nom::{bytes::complete::tag_no_case, IResult}; use std::str::FromStr; +use crate::FuukaBotError; + /// A dice candicate. #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct DiceCandidate { @@ -87,21 +89,27 @@ pub enum Expr { impl Expr { /// Evaluate the expression. - pub fn eval(self) -> i32 { + pub fn eval(self) -> anyhow::Result { match self { Self::DiceOrInt(result) => match result { DiceOrInt::Dice(dice) => { let Dice { count, sides } = dice; - (fastrand::u32(1..=sides) * count) as i32 + Ok((fastrand::u32(1..=sides) * count) as i32) } - DiceOrInt::Int(num) => num, - }, - Self::BinOp { lhs, op, rhs } => match op { - Op::Add => lhs.eval() + rhs.eval(), - Op::Sub => lhs.eval() - rhs.eval(), - Op::Mul => lhs.eval() * rhs.eval(), - Op::Div => lhs.eval() / rhs.eval(), + DiceOrInt::Int(num) => Ok(num), }, + Self::BinOp { lhs, op, rhs } => { + match op { + Op::Add => Ok(i32::checked_add(lhs.eval()?, rhs.eval()?) + .ok_or(FuukaBotError::MathOverflow)?), + Op::Sub => Ok(i32::checked_sub(lhs.eval()?, rhs.eval()?) + .ok_or(FuukaBotError::MathOverflow)?), + Op::Mul => Ok(i32::checked_mul(lhs.eval()?, rhs.eval()?) + .ok_or(FuukaBotError::MathOverflow)?), + Op::Div => Ok(i32::checked_div(lhs.eval()?, rhs.eval()?) + .ok_or(FuukaBotError::DivByZero)?), + } + } } } } diff --git a/src/lib.rs b/src/lib.rs index 2888475..0431822 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -115,6 +115,12 @@ pub enum FuukaBotError { /// The specified user does not exist. #[error("The specified user does not exist.")] UserNotFound, + /// Math overflow happened. + #[error("Math overflow happened.")] + MathOverflow, + /// Divide by zero happened. + #[error("Divisioned by zero.")] + DivByZero, // Internal errors. /// The bot encountered an internal error that the user it checked should be avaliable but didn't. #[error("This user should be avaliable.")] diff --git a/src/message_responses.rs b/src/message_responses.rs index 4ed5bb4..96008c5 100644 --- a/src/message_responses.rs +++ b/src/message_responses.rs @@ -157,7 +157,7 @@ async fn _dispatch_dicer(body: &str) -> anyhow::Result { if result < (target as i32) {