easychess_lib/
pieces.rs

1use std::fmt::Debug;
2
3/// Error for when [Piece::try_from] gets an invalid [char].
4pub struct TryFromError(char, u32, &'static str);
5
6impl Debug for TryFromError {
7    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8        write!(
9            f,
10            "invalid char '{}' at line {} in file {}",
11            self.0, self.1, self.2
12        )
13    }
14}
15
16#[derive(Clone, Copy)]
17pub enum PieceType {
18    King,
19    Queen,
20    Rook,
21    Bishop,
22    Knight,
23    Pawn,
24}
25
26#[derive(Clone, Copy)]
27pub enum PieceTeam {
28    White(PieceType),
29    Black(PieceType),
30    None,
31}
32
33/// Is placed on [crate::board::Board]
34#[derive(Clone, Copy)]
35pub struct Piece(PieceTeam);
36impl Piece {
37    /// Piece struct with [PieceTeam::None]
38    pub const NONE: Self = Self(PieceTeam::None);
39}
40
41impl TryFrom<char> for Piece {
42    type Error = TryFromError;
43    /// Matches a [char] that represents a chess piece to a [Piece].
44    /// Valid chars are:
45    /// ```no_run
46    /// '.' => return PieceTeam::None
47    /// 'k' => PieceType::King,
48    /// 'q' => PieceType::Queen,
49    /// 'r' => PieceType::Rook,
50    /// 'b' => PieceType::Bishop,
51    /// 'n' => PieceType::Knight,
52    /// 'p' => PieceType::Pawn,
53    /// ```
54    /// Matches uppercase and lowercase to [PieceTeam]:
55    /// ```no_run
56    /// true => PieceTeam::White(ptype),
57    /// false => PieceTeam::Black(ptype),
58    /// ```
59    ///
60    /// # Errors
61    /// Invalid chars return:
62    /// ```
63    /// Err(TryFromError(c, line!(), module_path!()))
64    /// ```
65    fn try_from(value: char) -> Result<Self, Self::Error> {
66        let ptype = match value.to_ascii_lowercase() {
67            '.' => return Ok(Self(PieceTeam::None)),
68            'k' => PieceType::King,
69            'q' => PieceType::Queen,
70            'r' => PieceType::Rook,
71            'b' => PieceType::Bishop,
72            'n' => PieceType::Knight,
73            'p' => PieceType::Pawn,
74            //' ' | '.' => PieceType::None,
75            c => return Err(TryFromError(c, line!(), module_path!())),
76        };
77        let pteam = match value.is_ascii_uppercase() {
78            true => PieceTeam::White(ptype),
79            false => PieceTeam::Black(ptype),
80        };
81        Ok(Self(pteam))
82    }
83}
84impl Into<char> for Piece {
85    /// Matches a [PieceType] variant to a [char] that represents a chess piece:
86    /**
87    ```
88    PieceType::None => return '.',
89    PieceType::King => 'k',
90    PieceType::Queen => 'q',
91    PieceType::Rook => 'r',
92    PieceType::Bishop => 'b',
93    PieceType::Knight => 'n',
94    PieceType::Pawn => 'p',
95    ```
96    */
97    ///
98    fn into(self) -> char {
99        // let matched_char = match self.piece_type {
100        // PieceType::King => 'k',
101        // PieceType::Queen => 'q',
102        // PieceType::Rook => 'r',
103        // PieceType::Bishop => 'b',
104        // PieceType::Knight => 'n',
105        // PieceType::Pawn => 'p',
106        // PieceType::None => '.',
107        // };
108        // match self.piece_team {
109        //     PieceTeam::White => matched_char.to_ascii_uppercase(),
110        //     _ => matched_char,
111        // }
112        let matched_char = match self.0 {
113            PieceTeam::None => return '.',
114            PieceTeam::White(ptype) | PieceTeam::Black(ptype) => match ptype {
115                PieceType::King => 'k',
116                PieceType::Queen => 'q',
117                PieceType::Rook => 'r',
118                PieceType::Bishop => 'b',
119                PieceType::Knight => 'n',
120                PieceType::Pawn => 'p',
121            },
122        };
123        match self.0 {
124            PieceTeam::White(_) => matched_char.to_ascii_uppercase(),
125            _ => matched_char,
126        }
127    }
128}
129//TODO: impl display sometime