1use super::*;
2
3#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4#[repr(u8)]
5#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Hash)]
6pub enum Rank {
7 First = 0,
8 Second = 1,
9 Third = 2,
10 Fourth = 3,
11 Fifth = 4,
12 Sixth = 5,
13 Seventh = 6,
14 Eighth = 7,
15}
16
17impl Rank {
18 #[inline]
19 pub const unsafe fn from_int(i: u8) -> Self {
20 std::mem::transmute(i)
21 }
22
23 #[inline]
24 pub const unsafe fn from_index(i: usize) -> Self {
25 Self::from_int(i as u8)
26 }
27
28 #[inline]
29 pub fn up(self) -> Option<Self> {
30 (self != Self::Eighth).then(|| unsafe { Self::from_int(self.to_int() + 1) })
31 }
32
33 #[inline]
34 pub fn down(self) -> Option<Self> {
35 (self != Self::First).then(|| unsafe { Self::from_int(self.to_int() - 1) })
36 }
37
38 #[inline]
39 pub fn wrapping_up(self) -> Self {
40 self.up().unwrap_or(Self::First)
41 }
42
43 #[inline]
44 pub fn wrapping_down(self) -> Self {
45 self.down().unwrap_or(Self::Eighth)
46 }
47
48 #[inline]
49 pub const fn to_int(self) -> u8 {
50 self as u8
51 }
52
53 #[inline]
54 pub const fn to_index(self) -> usize {
55 self as usize
56 }
57
58 #[inline]
59 pub const fn to_bitboard(self) -> BitBoard {
60 BitBoard::new(0xff << (self.to_int() << 3))
61 }
62
63 #[inline]
64 pub fn get_upper_board_mask(self, color: Color) -> BitBoard {
65 *get_item_unchecked!(UPPER_BOARD_MASK, color.to_index(), self.to_index())
66 }
67
68 #[inline]
69 pub fn get_lower_board_mask(self, color: Color) -> BitBoard {
70 self.get_upper_board_mask(!color)
71 }
72}
73
74impl fmt::Display for Rank {
75 #[inline]
76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77 write!(f, "{}", self.to_int() + 1)
78 }
79}
80
81impl TryFrom<char> for Rank {
82 type Error = TimecatError;
83
84 #[inline]
85 fn try_from(c: char) -> Result<Self> {
86 match c {
87 '1' => Ok(Self::First),
88 '2' => Ok(Self::Second),
89 '3' => Ok(Self::Third),
90 '4' => Ok(Self::Fourth),
91 '5' => Ok(Self::Fifth),
92 '6' => Ok(Self::Sixth),
93 '7' => Ok(Self::Seventh),
94 '8' => Ok(Self::Eighth),
95 _ => Err(TimecatError::InvalidRankString {
96 s: c.to_string().into(),
97 }),
98 }
99 }
100}
101
102impl FromStr for Rank {
103 type Err = TimecatError;
104
105 #[inline]
106 fn from_str(s: &str) -> Result<Self> {
107 match s.trim() {
108 "1" => Ok(Self::First),
109 "2" => Ok(Self::Second),
110 "3" => Ok(Self::Third),
111 "4" => Ok(Self::Fourth),
112 "5" => Ok(Self::Fifth),
113 "6" => Ok(Self::Sixth),
114 "7" => Ok(Self::Seventh),
115 "8" => Ok(Self::Eighth),
116 _ => Err(TimecatError::InvalidRankString {
117 s: s.to_string().into(),
118 }),
119 }
120 }
121}