#![forbid(unsafe_code)]
#[macro_use]
extern crate lazy_static;
use num_traits;
use rand;
use num_traits::int::PrimInt;
use rand::distributions::range::SampleRange;
use std::fmt::Debug;
use std::str::FromStr;
mod parsing;
mod rolling;
#[derive(Debug)]
pub struct DiceData<T>
where
T: PrimInt,
{
num_dice: T,
num_faces: T,
modifier: bool,
modifier_val: T,
}
#[cfg(test)]
impl<T> PartialEq for DiceData<T>
where
T: PrimInt,
{
fn eq(&self, other: &DiceData<T>) -> bool {
self.num_dice == other.num_dice
&& self.num_faces == other.num_faces
&& self.modifier == other.modifier
&& self.modifier_val == other.modifier_val
}
}
pub fn roll_dice<T>(notation: &str) -> Result<T, &str>
where
T: PrimInt + FromStr + SampleRange,
<T as FromStr>::Err: Debug,
{
let dice_data = parsing::parse(notation);
let dice_data = match dice_data {
Ok(d) => d,
Err(e) => return Err(e),
};
let result = rolling::roll(dice_data);
Ok(result)
}
pub fn roll_dice_with_fn<T,F>(notation: &str, random: F) -> Result<T, &str>
where
T: PrimInt + FromStr + SampleRange,
<T as FromStr>::Err: Debug,
F: Fn(T,T) -> T,
{
let dice_data = parsing::parse(notation);
let dice_data = match dice_data {
Ok(d) => d,
Err(e) => return Err(e),
};
let result = rolling::roll_with_fn(dice_data, &random);
Ok(result)
}
#[cfg(test)]
mod test {
#[test]
fn it_rolls_two_dices_of_three_faces_with_modifier_plus_two_correctly() {
let result = super::roll_dice::<i32>("2d3+2").unwrap();
assert!(result >= 4);
assert!(result <= 8);
}
}