use crate::prelude::*;
use std::ops::{BitOr, Not};
enumeration! {
#[derive_const(Ord, PartialOrd)]
pub Rank, [
_1, _2, _3, _4, _5, _6, _7, _8,
]
}
impl Rank {
#[inline]
#[must_use]
pub const fn from_fen(byte: u8) -> Option<Self> {
match byte {
b'1'..=b'8' => Self::from_u8(byte - b'1'),
_ => None,
}
}
#[inline]
#[must_use]
pub const fn distance(self, other: Self) -> u8 {
self.as_u8().abs_diff(other.as_u8())
}
}
impl IntoIterator for Rank {
type Item = Square;
type IntoIter = std::array::IntoIter<Square, 8>;
#[inline]
#[must_use]
fn into_iter(self) -> Self::IntoIter {
use Square as S;
match self {
Self::_1 => [S::A1, S::B1, S::C1, S::D1, S::E1, S::F1, S::G1, S::H1],
Self::_2 => [S::A2, S::B2, S::C2, S::D2, S::E2, S::F2, S::G2, S::H2],
Self::_3 => [S::A3, S::B3, S::C3, S::D3, S::E3, S::F3, S::G3, S::H3],
Self::_4 => [S::A4, S::B4, S::C4, S::D4, S::E4, S::F4, S::G4, S::H4],
Self::_5 => [S::A5, S::B5, S::C5, S::D5, S::E5, S::F5, S::G5, S::H5],
Self::_6 => [S::A6, S::B6, S::C6, S::D6, S::E6, S::F6, S::G6, S::H6],
Self::_7 => [S::A7, S::B7, S::C7, S::D7, S::E7, S::F7, S::G7, S::H7],
Self::_8 => [S::A8, S::B8, S::C8, S::D8, S::E8, S::F8, S::G8, S::H8],
}.into_iter()
}
}
impl const From<Rank> for char {
#[inline]
fn from(value: Rank) -> Self {
(value.as_u8() + b'1') as _
}
}
impl const From<Square> for Rank {
#[inline]
fn from(s: Square) -> Self {
unsafe_optimization!(
Self::from_u8(s.rank_index()).unwrap(),
Self::from_u8_unchecked(s.rank_index()),
)
}
}
impl const BitOr<Self> for Rank {
type Output = Bitboard;
fn bitor(self, rhs: Self) -> Self::Output {
Bitboard::from(self) | rhs
}
}
impl const BitOr<File> for Rank {
type Output = Square;
fn bitor(self, rhs: File) -> Self::Output {
Square::new(rhs, self)
}
}
impl const Not for Rank {
type Output = Bitboard;
fn not(self) -> Self::Output {
! Bitboard::from(self)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn rank_distance() {
assert_eq!(Rank::_1.distance(Rank::_1), 0);
assert_eq!(Rank::_1.distance(Rank::_2), 1);
assert_eq!(Rank::_1.distance(Rank::_3), 2);
assert_eq!(Rank::_1.distance(Rank::_4), 3);
assert_eq!(Rank::_1.distance(Rank::_5), 4);
assert_eq!(Rank::_1.distance(Rank::_6), 5);
assert_eq!(Rank::_1.distance(Rank::_7), 6);
assert_eq!(Rank::_1.distance(Rank::_8), 7);
assert_eq!(Rank::_2.distance(Rank::_1), 1);
assert_eq!(Rank::_2.distance(Rank::_7), 5);
assert_eq!(Rank::_2.distance(Rank::_8), 6);
assert_eq!(Rank::_3.distance(Rank::_3), 0);
assert_eq!(Rank::_7.distance(Rank::_1), 6);
assert_eq!(Rank::_7.distance(Rank::_8), 1);
assert_eq!(Rank::_8.distance(Rank::_8), 0);
}
#[test]
fn rank_bitor_file() {
for square in Square::iter() {
assert_eq!(square.rank() | square.file(), square);
}
}
#[test]
fn rank_into_iter() {
for rank in Rank::iter() {
assert_eq!(8, rank.into_iter().count());
assert!(rank.into_iter().is_sorted_by_key(Square::rank));
}
}
}