1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use std::str::FromStr;
use crate::error::Error;
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Hash)]
pub enum Rank {
First = 0,
Second = 1,
Third = 2,
Fourth = 3,
Fifth = 4,
Sixth = 5,
Seventh = 6,
Eighth = 7,
}
impl FromStr for Rank {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.len() != 1 {
return Err(Error::InvalidRank);
}
match unsafe { s.chars().next().unwrap_unchecked() } {
'1' => Ok(Rank::First),
'2' => Ok(Rank::Second),
'3' => Ok(Rank::Third),
'4' => Ok(Rank::Fourth),
'5' => Ok(Rank::Fifth),
'6' => Ok(Rank::Sixth),
'7' => Ok(Rank::Seventh),
'8' => Ok(Rank::Eighth),
_ => Err(Error::InvalidRank),
}
}
}
impl Rank {
/// Convert a `usize` to a `Rank`. If the index is > 7 wrap around.
///
/// # Example
/// ```
/// use chessframe::rank::Rank;
///
/// assert_eq!(Rank::from_index(0), Rank::First);
/// assert_eq!(Rank::from_index(7), Rank::Eighth);
/// ```
#[inline]
pub fn from_index(index: usize) -> Rank {
match index % 8 {
0 => Rank::First,
1 => Rank::Second,
2 => Rank::Third,
3 => Rank::Fourth,
4 => Rank::Fifth,
5 => Rank::Sixth,
6 => Rank::Seventh,
7 => Rank::Eighth,
_ => unreachable!(),
}
}
/// Get the rank below this one. If the rank is `First` wrap around.
///
/// # Example
/// ```
/// use chessframe::rank::Rank;
///
/// assert_eq!(Rank::First, Rank::Second.down());
/// assert_eq!(Rank::Eighth, Rank::First.down());
/// ```
#[inline]
pub fn down(&self) -> Rank {
Rank::from_index(self.to_index().wrapping_sub(1))
}
/// Get the rank above this one. If the rank is `Eighth` wrap around.
///
/// # Example
/// ```
/// use chessframe::rank::Rank;
///
/// assert_eq!(Rank::Second, Rank::First.up());
/// assert_eq!(Rank::First, Rank::Eighth.up());
/// ```
#[inline]
pub fn up(&self) -> Rank {
Rank::from_index(unsafe { self.to_index().unchecked_add(1) })
}
/// Convert this `Rank` into a `usize` between 0 and 7.
///
/// # Example
/// ```
/// use chessframe::rank::Rank;
///
/// assert_eq!(0, Rank::First.to_index());
/// assert_eq!(7, Rank::Eighth.to_index());
/// ```
#[inline]
pub fn to_index(self) -> usize {
self as usize
}
}