I'm developing a chess engine in Rust. I have a Move
struct with from
and to
fields, which are Square
. Square
is a struct containing a usize
, so that I can use it directly when accessing board elements of the position. Since in Rust indexing must be done with usize
, I'm wondering what's the fastest way to handle this situation (note that move generation should be as fast as possible). I understand it's more memory friendly to store u8
and cast them every time I need to use them as an index, but is it faster? What would be the idiomatic way to approach this?
I have:
struct Square {index: usize}
fn position.at(square: Square) -> Option<Piece> {
position.board[square.index]
}
I've tried migrating to u8 and casting every time with mixed results:
struct Square(u8)
fn position.at(square: Square) -> Option<Piece> {
position.board[square.0 as usize]
}
Pro u8
casting:
Con u8
:
Idiomatic way to avoid the as usize
: implement a wrapper
impl Square {
#[inline]
pub fn index(&self) -> usize {
self.0 as usize
}
}
Or, when you want to make it really typesafe, implement std::ops::Index
:
struct Piece;
struct Board([Piece; 64]);
struct Square(u8);
impl std::ops::Index<Square> for Board {
type Output = Piece;
fn index(&self, index: Square) -> &Self::Output {
&self.0[index.0 as usize]
}
}