use fastrand::Rng;
use crate::traits::{Polyhedral, Roll, RollMut, Rotate, RotateMut};
#[derive(Clone, Default)]
pub struct NopRoller;
impl NopRoller {
pub const fn new() -> Self {
Self
}
}
impl Roll for NopRoller {
fn roll<T>(&self, rotate: &T) -> T
where
T: Rotate,
{
rotate.to_owned()
}
}
impl RollMut for NopRoller {
fn roll_mut<T>(&self, _rotate: &mut T)
where
T: RotateMut,
{
}
}
#[cfg(feature = "fastrand")]
#[derive(Clone, Default)]
pub struct RngRoller(Rng);
impl RngRoller {
pub fn new() -> Self {
Self(Rng::new())
}
}
impl From<Rng> for RngRoller {
fn from(rng: Rng) -> Self {
Self(rng)
}
}
impl Roll for RngRoller {
fn roll<T>(&self, rotate: &T) -> T
where
T: Polyhedral + Rotate,
{
let sides = T::sides();
let range = 0..sides;
let amount = self.0.usize(range);
rotate.rotate(amount as i8)
}
}
impl RollMut for RngRoller {
fn roll_mut<T>(&self, rotate: &mut T)
where
T: Polyhedral + RotateMut,
{
let sides = T::sides();
let range = 0..sides;
let amount = self.0.usize(range);
rotate.rotate_mut(amount as i8);
}
}
#[cfg(test)]
mod tests {
use crate::traits::{Step, StepMut};
use super::*;
#[derive(Clone)]
struct PanicDie;
impl Step for PanicDie {
fn next(&self) -> Self {
unreachable!()
}
fn back(&self) -> Self {
unreachable!()
}
}
impl StepMut for PanicDie {
fn next_mut(&mut self) {
unreachable!()
}
fn back_mut(&mut self) {
unreachable!()
}
}
impl Rotate for PanicDie {}
impl RotateMut for PanicDie {}
impl Polyhedral for PanicDie {
fn sides() -> usize {
unreachable!()
}
}
#[test]
#[allow(clippy::redundant_clone)]
fn nop_roller_new_and_clone() {
let _ = NopRoller::new().clone();
}
#[test]
fn nop_roller_default() {
let _: NopRoller = Default::default();
}
#[test]
fn nop_roller_no_changes() {
let panic = PanicDie {};
let roller = NopRoller::new();
for _ in 0..10 {
let _ = roller.roll(&panic);
}
}
#[test]
fn nop_roller_mut_no_changes() {
let mut panic = PanicDie {};
let roller = NopRoller::new();
for _ in 0..10 {
roller.roll_mut(&mut panic);
}
}
#[test]
#[allow(clippy::redundant_clone)]
fn rng_roller_new_and_clone() {
let _ = RngRoller::new().clone();
}
#[test]
fn rng_roller_default() {
let _: RngRoller = Default::default();
}
}