Reputation: 139
I am making a chess game and I'm looking to return a mutable null character from an array of pieces when the index of the array (a Vec2
is out of bounds), the reason I need to do this is that my function for moving the piece needs a mutable reference to the Indexed piece, long story short I ended up needing to create a static NULL_PIECE
that I could reference within the function but this is potentially quite dangerous as you'll see from my code
impl Index<IVec2> for Board {
type Output = Piece;
fn index(&self, index : IVec2) -> &Self::Output{
if (index.abs() != index) || (index.max_element() > WIDTH-1) {
&Piece('\0') // this works
} else {
let i : usize = (index.x + WIDTH* index.y).try_into().unwrap();
&self.pieces[i]
}
}
}
impl IndexMut<IVec2> for Board {
fn index_mut(&mut self, index: IVec2) -> &mut Self::Output{
if (index.abs() != index) || (index.max_element() > WIDTH-1) {
// &mut Piece('\0') // this does not work
unsafe {&mut NULL_PIECE} // this works but I don't like it
} else {
let i : usize = (index.x + WIDTH * index.y).try_into().unwrap();
&mut self.pieces[i]
}
}
}
There is a lot of potential for this to cause an error in the event that this mutates to be a piece because of the recursion I've implemented on the piece movement.
You can find the GitHub link here: https://github.com/LyndonAlcock/chess_test/tree/main/src
Upvotes: 1
Views: 117
Reputation: 27548
Instead of implementing Index
you could write it as:
impl Board {
fn get(&self, index: IVec2) -> Option<&Piece> {
if (index.abs() != index) || (index.max_element() > WIDTH-1) {
None
} else {
let i = (index.x + WIDTH* index.y).try_into().ok()?;
Some(&self.pieces[i])
}
}
fn get_mut(&mut self, index: IVec2) -> Option<&mut Piece> {
if (index.abs() != index) || (index.max_element() > WIDTH-1) {
None
} else {
let i = (index.x + WIDTH * index.y).try_into().ok()?;
Some(&mut self.pieces[i])
}
}
}
Index
implementations should panic
when the index is out of bounds.
Upvotes: 5