Skip to main content

chess/
file.rs

1use crate::error::Error;
2use std::str::FromStr;
3
4/// Describe a file (column) on a chess board
5#[repr(u8)]
6#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Debug, Hash)]
7pub enum File {
8	A = 0,
9	B = 1,
10	C = 2,
11	D = 3,
12	E = 4,
13	F = 5,
14	G = 6,
15	H = 7,
16}
17
18/// How many files are there?
19pub const NUM_FILES: usize = 8;
20
21/// Enumerate all files
22pub const ALL_FILES: [File; NUM_FILES] = [File::A, File::B, File::C, File::D, File::E, File::F, File::G, File::H];
23
24impl File {
25	/// Convert a `usize` into a `File` (the inverse of to_index).  If i > 7, wrap around.
26	#[inline]
27	pub fn from_index(i: usize) -> File {
28		// match is optimized to no-op with opt-level=1 with rustc 1.53.0
29		match i & 7 {
30			0 => File::A,
31			1 => File::B,
32			2 => File::C,
33			3 => File::D,
34			4 => File::E,
35			5 => File::F,
36			6 => File::G,
37			7 => File::H,
38			_ => unreachable!(),
39		}
40	}
41
42	/// Go one file to the left.  If impossible, wrap around.
43	#[inline]
44	pub fn left(&self) -> File {
45		File::from_index(self.to_index().wrapping_sub(1))
46	}
47
48	/// Go one file to the right.  If impossible, wrap around.
49	#[inline]
50	pub fn right(&self) -> File {
51		File::from_index(self.to_index() + 1)
52	}
53
54	/// Convert this `File` into a `usize` from 0 to 7 inclusive.
55	#[inline]
56	pub fn to_index(self) -> usize {
57		self as usize
58	}
59}
60
61impl FromStr for File {
62	type Err = Error;
63
64	fn from_str(s: &str) -> Result<Self, Self::Err> {
65		if s.is_empty() {
66			return Err(Error::InvalidFile);
67		}
68		match s.chars().next().unwrap() {
69			'a' => Ok(File::A),
70			'b' => Ok(File::B),
71			'c' => Ok(File::C),
72			'd' => Ok(File::D),
73			'e' => Ok(File::E),
74			'f' => Ok(File::F),
75			'g' => Ok(File::G),
76			'h' => Ok(File::H),
77			_ => Err(Error::InvalidFile),
78		}
79	}
80}