use strum_macros::EnumIter;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumIter)]
pub enum Color {
Red,
Green,
}
impl std::fmt::Display for Color {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{self:?}")
}
}
impl std::ops::Not for Color {
type Output = Color;
fn not(self) -> Self::Output {
use Color::*;
match self {
Red => Green,
Green => Red,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumIter)]
pub enum Dove {
B,
A,
Y,
M,
T,
H,
}
#[inline]
pub(crate) fn color_to_index(color: Color) -> usize {
use Color::*;
match color {
Red => 0,
Green => 1,
}
}
#[inline]
pub(crate) fn try_index_to_color(index: usize) -> Option<Color> {
use Color::*;
let color = match index {
0 => Red,
1 => Green,
_ => return None,
};
Some(color)
}
#[inline]
pub(crate) fn dove_to_index(dove: Dove) -> usize {
use Dove::*;
match dove {
B => 0,
A => 1,
Y => 2,
M => 3,
T => 4,
H => 5,
}
}
#[inline]
pub(crate) fn try_index_to_dove(index: usize) -> Option<Dove> {
use Dove::*;
let dove = match index {
0 => B,
1 => A,
2 => Y,
3 => M,
4 => T,
5 => H,
_ => return None,
};
Some(dove)
}
#[inline]
pub fn color_dove_to_char(color: Color, dove: Dove) -> char {
use Color::*;
use Dove::*;
match (color, dove) {
(Red, B) => 'B',
(Green, B) => 'b',
(Red, A) => 'A',
(Green, A) => 'a',
(Red, Y) => 'Y',
(Green, Y) => 'y',
(Red, M) => 'M',
(Green, M) => 'm',
(Red, T) => 'T',
(Green, T) => 't',
(Red, H) => 'H',
(Green, H) => 'h',
}
}
#[inline]
pub fn try_char_to_color_dove(c: char) -> Option<(Color, Dove)> {
use Color::*;
use Dove::*;
let color_dove = match c {
'B' => (Red, B),
'b' => (Green, B),
'A' => (Red, A),
'a' => (Green, A),
'Y' => (Red, Y),
'y' => (Green, Y),
'M' => (Red, M),
'm' => (Green, M),
'T' => (Red, T),
't' => (Green, T),
'H' => (Red, H),
'h' => (Green, H),
_ => return None,
};
Some(color_dove)
}
#[cfg(test)]
mod tests {
use crate::strum::IntoEnumIterator;
use crate::*;
#[test]
fn test_color_dove_char() {
for color in Color::iter() {
for dove in Dove::iter() {
let ch = color_dove_to_char(color, dove);
assert_eq!(Some((color, dove)), try_char_to_color_dove(ch));
}
}
}
#[test]
fn test_color_dove_char_irregular() {
for ch in 'a'..='Z' {
let Some((color, dove)) = try_char_to_color_dove(ch) else {
continue;
};
assert_eq!(ch, color_dove_to_char(color, dove));
}
}
#[test]
fn test_color_index() {
for color in Color::iter() {
let idx = color_to_index(color);
assert_eq!(Some(color), try_index_to_color(idx));
}
}
#[test]
fn test_color_index_irregular() {
for idx in 0..1_000_000 {
let Some(color) = try_index_to_color(idx) else {
continue;
};
assert_eq!(idx, color_to_index(color));
}
}
#[test]
fn test_dove_index() {
for dove in Dove::iter() {
let idx = dove_to_index(dove);
assert_eq!(Some(dove), try_index_to_dove(idx));
}
}
#[test]
fn test_dove_index_irregular() {
for idx in 0..1_000_000 {
let Some(dove) = try_index_to_dove(idx) else {
continue;
};
assert_eq!(idx, dove_to_index(dove));
}
}
}