use std::fmt::Display;
use crate::algorithm::r#move::r#move::Move;
pub trait MoveDisplay {
#[must_use]
fn new(mv: Move) -> Self;
}
macro_rules! define_display {
($($(#[$annot:meta])* $name:ident),* $(,)?) => {
$(
$(#[$annot])*
#[derive(Clone, Debug)]
pub struct $name(Move);
impl MoveDisplay for $name {
fn new(mv: Move) -> Self {
Self(mv)
}
}
)*
};
}
define_display!(
DisplayLongSpaced,
DisplayLongUnspaced,
DisplayShort
);
impl Display for DisplayLongSpaced {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut s = self.0.direction.to_string();
s.push(' ');
s = s.repeat(self.0.amount as usize);
s.pop();
f.write_str(&s)
}
}
impl Display for DisplayLongUnspaced {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0.direction.to_string().repeat(self.0.amount as usize))
}
}
impl Display for DisplayShort {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.0.amount == 1 {
write!(f, "{}", self.0.direction)
} else {
write!(f, "{}{}", self.0.direction, self.0.amount)
}
}
}
#[cfg(test)]
mod tests {
use crate::algorithm::{
direction::Direction,
display::r#move::{DisplayLongSpaced, DisplayLongUnspaced, DisplayShort},
r#move::r#move::Move,
};
#[test]
fn test_display() {
let m = Move {
direction: Direction::Up,
amount: 1,
};
assert_eq!(DisplayLongSpaced(m).to_string(), "U");
assert_eq!(DisplayLongUnspaced(m).to_string(), "U");
assert_eq!(DisplayShort(m).to_string(), "U");
}
#[test]
fn test_display_2() {
let m = Move {
direction: Direction::Up,
amount: 3,
};
assert_eq!(DisplayLongSpaced(m).to_string(), "U U U");
assert_eq!(DisplayLongUnspaced(m).to_string(), "UUU");
assert_eq!(DisplayShort(m).to_string(), "U3");
}
}