chessfriend/board/src/square.rs

104 lines
2.5 KiB
Rust
Raw Normal View History

// Eryn Wells <eryn@erynwells.me>
use std::str::FromStr;
#[derive(Debug)]
struct ParseSquareError;
#[derive(Debug)]
struct SquareIndexOutOfBoundsError;
#[derive(Debug, Eq, PartialEq)]
struct Square {
rank: u8,
file: u8,
}
impl Square {
fn from_index(index: u8) -> Result<Square, SquareIndexOutOfBoundsError> {
if index >= 64 {
return Err(SquareIndexOutOfBoundsError);
}
Ok(Square {
rank: index / 8,
file: index % 8,
})
}
fn from_algebraic_string(s: &str) -> Result<Square, ParseSquareError> {
s.parse()
}
fn rank_index(&self) -> usize {
self.rank.into()
}
fn file_index(&self) -> usize {
self.file.into()
}
}
impl FromStr for Square {
type Err = ParseSquareError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if !s.is_ascii() || s.len() != 2 {
return Err(ParseSquareError);
}
let chars: Vec<char> = 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) + 1;
if rank < 1 || rank > 8 {
return Err(ParseSquareError);
}
let file = u8::try_from(chars[1].to_digit(10).ok_or(ParseSquareError)?)
.map_err(|_| ParseSquareError)?;
Ok(Square {
rank: rank - 1,
file: file - 1,
})
}
}
#[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 parse_good_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 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);
}
}