pounce 2.0.2

A mediocre (but trying its best) uci chess engine
Documentation
use std::ops::{Index, IndexMut};
use std::str::FromStr;

use thiserror::Error;

use crate::chess::Rank;

#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
#[repr(u8)]
pub enum Color {
    #[default]
    White = 0,
    Black,
}

impl Color {
    pub const fn new(color: u8) -> Color {
        assert!(color < 2);
        unsafe { std::mem::transmute(color) }
    }

    #[inline]
    pub fn home_rank(&self) -> Rank {
        match self {
            Color::White => Rank::R2,
            Color::Black => Rank::R7,
        }
    }

    #[inline]
    pub fn back_rank(&self) -> Rank {
        match self {
            Color::White => Rank::R1,
            Color::Black => Rank::R8,
        }
    }

    #[inline]
    pub fn double_pawn_rank(&self) -> Rank {
        match self {
            Color::White => Rank::R4,
            Color::Black => Rank::R5,
        }
    }

    #[inline]
    pub fn opponent(&self) -> Color {
        match self {
            Color::White => Color::Black,
            Color::Black => Color::White,
        }
    }

    pub const ALL: [Color; 2] = [Color::White, Color::Black];
    pub const NUM: usize = 2;
}

#[derive(Error, Debug)]
#[error("invalid color: {0}")]
pub struct ParseColorError(String);

impl FromStr for Color {
    type Err = ParseColorError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "w" => Ok(Color::White),
            "b" => Ok(Color::Black),
            _ => Err(ParseColorError(s.to_string())),
        }
    }
}

impl<T> Index<Color> for [T; Color::NUM] {
    type Output = T;
    fn index(&self, index: Color) -> &Self::Output {
        unsafe { self.get_unchecked(index as usize) }
    }
}

impl<T> IndexMut<Color> for [T; Color::NUM] {
    fn index_mut(&mut self, index: Color) -> &mut Self::Output {
        unsafe { self.get_unchecked_mut(index as usize) }
    }
}

impl std::ops::Not for Color {
    type Output = Color;
    fn not(self) -> Self::Output {
        self.opponent()
    }
}