// Eryn Wells use std::str::FromStr; #[derive(Debug)] pub struct ParseSquareError; #[derive(Debug)] pub struct SquareIndexOutOfBoundsError; #[derive(Debug, Eq, PartialEq)] pub struct Square { pub rank: u8, pub file: u8, pub index: u8, } impl Square { pub fn from_index(index: u8) -> Result { if index >= 64 { return Err(SquareIndexOutOfBoundsError); } Ok(Square { rank: index / 8, file: index % 8, index: index, }) } pub fn from_algebraic_string(s: &str) -> Result { s.parse() } pub fn rank_index(&self) -> usize { self.rank.into() } pub fn file_index(&self) -> usize { self.file.into() } } impl FromStr for Square { type Err = ParseSquareError; fn from_str(s: &str) -> Result { if !s.is_ascii() || s.len() != 2 { return Err(ParseSquareError); } let chars: Vec = s.chars().collect(); let rank_char = chars[0].to_ascii_lowercase(); if !rank_char.is_ascii_lowercase() { return Err(ParseSquareError); } let rank = (rank_char as u8) - ('a' as u8); if rank >= 8 { return Err(ParseSquareError); } let converted_file_digit = chars[1] .to_digit(10) .and_then(|x| if x != 0 { Some(x) } else { None }) .ok_or(ParseSquareError)?; let file = u8::try_from(converted_file_digit).map_err(|_| ParseSquareError)? - 1; Ok(Square { rank: rank, file: file, index: rank * 8 + file, }) } } #[cfg(test)] mod tests { use super::*; #[test] fn indexes() { let sq1 = Square::from_algebraic_string("c5").expect("Failed to parse 'c5' square"); assert_eq!(sq1.rank_index(), 2, "Rank doesn't match"); assert_eq!(sq1.file_index(), 4, "File doesn't match"); let sq2 = Square::from_algebraic_string("b2").expect("Failed to parse 'b2' square"); assert_eq!(sq2.rank_index(), 1, "Rank doesn't match"); assert_eq!(sq2.file_index(), 1, "File doesn't match"); } #[test] fn good_algebraic_input() { let sq1 = Square::from_algebraic_string("a4").expect("Failed to parse 'a4' square"); assert_eq!(sq1.rank, 0); assert_eq!(sq1.file, 3); let sq2 = Square::from_algebraic_string("B8").expect("Failed to parse 'B8' square"); assert_eq!(sq2.rank, 1); assert_eq!(sq2.file, 7); } #[test] fn bad_algebraic_input() { Square::from_algebraic_string("a0").expect_err("Got valid Square for 'a0'"); Square::from_algebraic_string("j3").expect_err("Got valid Square for 'j3'"); Square::from_algebraic_string("a11").expect_err("Got valid Square for 'a11'"); Square::from_algebraic_string("b-1").expect_err("Got valid Square for 'b-1'"); Square::from_algebraic_string("a 1").expect_err("Got valid Square for 'a 1'"); Square::from_algebraic_string("").expect_err("Got valid Square for ''"); } #[test] fn from_index() { let sq1 = Square::from_index(4).expect("Unable to get Square from index"); assert_eq!(sq1.rank, 0); assert_eq!(sq1.file, 4); } }