Skip to main content

chess_lab/common/errors/
position.rs

1use thiserror::Error;
2
3use crate::core::Position;
4
5/// Error indicating that a specific [Position] is already occupied
6///
7#[derive(Debug, Error)]
8#[error("Position {position} is already occupied")]
9pub struct PositionOccupiedError {
10    /// The [Position] that is already occupied
11    pub position: Position,
12}
13
14impl PositionOccupiedError {
15    /// Creates a new [PositionOccupiedError] with the given [Position]
16    ///
17    /// # Arguments
18    /// * `position` - The [Position] that is occupied
19    ///
20    /// # Example
21    /// ```
22    /// # use chess_lab::errors::PositionOccupiedError;
23    /// use chess_lab::core::Position;
24    ///
25    /// let position = Position::from_string("a1").unwrap();
26    /// let error = PositionOccupiedError::new(position);
27    /// ```
28    ///
29    pub fn new(position: Position) -> Self {
30        PositionOccupiedError { position }
31    }
32}
33
34/// Error indicating that a specific [Position] is empty
35///
36#[derive(Debug, Error)]
37#[error("Position {position} is empty")]
38pub struct PositionEmptyError {
39    /// The [Position] that is empty
40    pub position: Position,
41}
42
43impl PositionEmptyError {
44    /// Creates a new [PositionEmptyError] with the given [Position]
45    ///
46    /// # Arguments
47    /// * `position` - The [Position] that is empty
48    ///
49    /// # Example
50    /// ```
51    /// # use chess_lab::errors::PositionEmptyError;
52    /// use chess_lab::core::Position;
53    ///
54    /// let position = Position::from_string("a1").unwrap();
55    /// let error = PositionEmptyError::new(position);
56    /// ```
57    ///
58    pub fn new(position: Position) -> Self {
59        PositionEmptyError { position }
60    }
61}
62
63/// Error indicating that a [Position] is out of the allowed range
64///
65#[derive(Debug, PartialEq, Error)]
66#[error("Position ({col}, {row}) is out of range")]
67pub struct PositionOutOfRangeError {
68    /// The column index that is out of range
69    pub col: u8,
70    /// The row index that is out of range
71    pub row: u8,
72}
73
74impl PositionOutOfRangeError {
75    /// Creates a new [PositionOutOfRangeError] with the given column and row
76    ///
77    /// # Arguments
78    /// * `col` - The column index that is out of range
79    /// * `row` - The row index that is out of range
80    ///
81    /// # Example
82    /// ```
83    /// # use chess_lab::errors::PositionOutOfRangeError;
84    /// let col = 8;
85    /// let row = 8;
86    /// let error = PositionOutOfRangeError::new(col, row);
87    /// ```
88    ///
89    pub fn new(col: u8, row: u8) -> Self {
90        PositionOutOfRangeError { col, row }
91    }
92}
93
94/// Error indicating that a [Position] is invalid
95///
96#[derive(Debug, PartialEq, Error)]
97#[error("Invalid position: {position_str}")]
98pub struct PositionInvalidError {
99    /// The string representation of the [Position] that is invali
100    pub position_str: String,
101}
102
103impl PositionInvalidError {
104    /// Creates a new [PositionInvalidError] with the given message
105    ///
106    /// # Arguments
107    /// * `message` - The message that describes the error
108    ///
109    /// # Example
110    /// ```
111    /// # use chess_lab::errors::PositionInvalidError;
112    /// let error = PositionInvalidError::new("Invalid position".to_string());
113    /// ```
114    ///
115    pub fn new(position_str: String) -> Self {
116        PositionInvalidError { position_str }
117    }
118}
119
120/// Error indicating that two [Positions](Position) are not aligned
121///
122#[derive(Debug, PartialEq, Error)]
123#[error("Positions {position1} and {position2} are not aligned")]
124pub struct UnalignedPositionsError {
125    /// The first [Position] that is not aligned
126    pub position1: Position,
127    /// The second [Position] that is not aligned
128    pub position2: Position,
129}
130
131impl UnalignedPositionsError {
132    /// Creates a new [UnalignedPositionsError] with the given positions
133    ///
134    /// # Arguments
135    /// * `position1` - The first [Position] that is not aligned
136    /// * `position2` - The second [Position] that is not aligned
137    ///
138    /// # Example
139    /// ```
140    /// # use chess_lab::errors::UnalignedPositionsError;
141    /// use chess_lab::core::Position;
142    ///
143    /// let position1 = Position::from_string("a1").unwrap();
144    /// let position2 = Position::from_string("b3").unwrap();
145    ///
146    /// let error = UnalignedPositionsError::new(position1, position2);
147    /// ```
148    ///
149    pub fn new(position1: Position, position2: Position) -> Self {
150        UnalignedPositionsError {
151            position1,
152            position2,
153        }
154    }
155}
156
157/// Error types for [Position] between operations
158///
159#[non_exhaustive]
160#[derive(Debug, PartialEq, Error)]
161pub enum PositionBetweenError {
162    /// Indicates that two [Positions](Position) are not aligned and they should be
163    #[error(transparent)]
164    Unaligned(#[from] UnalignedPositionsError),
165}
166
167#[cfg(test)]
168mod tests {
169    use super::*;
170
171    #[test]
172    fn test_position_occupied_error() {
173        let position = Position::from_string("a1").unwrap();
174        let error = PositionOccupiedError::new(position);
175
176        assert_eq!(error.position, position);
177        assert_eq!(format!("{}", error), "Position a1 is already occupied");
178    }
179
180    #[test]
181    fn test_position_empty_error() {
182        let position = Position::from_string("a1").unwrap();
183        let error = PositionEmptyError::new(position);
184
185        assert_eq!(error.position, position);
186        assert_eq!(format!("{}", error), "Position a1 is empty");
187    }
188
189    #[test]
190    fn test_position_out_of_range_error() {
191        let col = 8;
192        let row = 8;
193        let error = PositionOutOfRangeError::new(col, row);
194
195        assert_eq!(error.col, col);
196        assert_eq!(error.row, row);
197        assert_eq!(format!("{}", error), "Position (8, 8) is out of range");
198    }
199
200    #[test]
201    fn test_position_invalid_error() {
202        let position_str = "abc".to_string();
203        let error = PositionInvalidError::new(position_str.clone());
204
205        assert_eq!(error.position_str, position_str);
206        assert_eq!(format!("{}", error), "Invalid position: abc");
207    }
208
209    #[test]
210    fn test_unaligned_positions_error() {
211        let position1 = Position::from_string("a1").unwrap();
212        let position2 = Position::from_string("b3").unwrap();
213        let error = UnalignedPositionsError {
214            position1,
215            position2,
216        };
217
218        assert_eq!(error.position1, position1);
219        assert_eq!(error.position2, position2);
220        assert_eq!(format!("{}", error), "Positions a1 and b3 are not aligned");
221    }
222}