From fa9335973fe8d258cda6abf111ed08487bf3a897 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Thu, 24 Jun 2021 13:21:28 +0200 Subject: [PATCH 1/2] Remove unsafe from public method CasteRights::from_index. Add unsafe CastleRights::new_unchecked and use it internally. --- src/castle_rights.rs | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/castle_rights.rs b/src/castle_rights.rs index 14674ea8..c0912ca7 100644 --- a/src/castle_rights.rs +++ b/src/castle_rights.rs @@ -9,6 +9,7 @@ use crate::magic::{KINGSIDE_CASTLE_SQUARES, QUEENSIDE_CASTLE_SQUARES}; /// What castle rights does a particular player have? #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Debug, Hash)] +#[repr(u8)] pub enum CastleRights { NoRights, KingSide, @@ -51,6 +52,12 @@ const CASTLES_PER_SQUARE: [[u8; 64]; 2] = [ ]; impl CastleRights { + /// SAFETY: value must be smaller NUM_CASTLE_RIGHTS + unsafe fn new_unchecked(value: usize) -> CastleRights { + debug_assert!(value < NUM_CASTLE_RIGHTS); + std::mem::transmute(value as u8) + } + /// Can I castle kingside? pub fn has_kingside(&self) -> bool { self.to_index() & 1 == 1 @@ -62,11 +69,13 @@ impl CastleRights { } pub fn square_to_castle_rights(color: Color, sq: Square) -> CastleRights { - CastleRights::from_index(unsafe { - *CASTLES_PER_SQUARE - .get_unchecked(color.to_index()) - .get_unchecked(sq.to_index()) - } as usize) + unsafe { + CastleRights::new_unchecked( + *CASTLES_PER_SQUARE + .get_unchecked(color.to_index()) + .get_unchecked(sq.to_index()) as usize + ) + } } /// What squares need to be empty to castle kingside? @@ -81,12 +90,16 @@ impl CastleRights { /// Remove castle rights, and return a new `CastleRights`. pub fn remove(&self, remove: CastleRights) -> CastleRights { - CastleRights::from_index(self.to_index() & !remove.to_index()) + unsafe { + CastleRights::new_unchecked(self.to_index() & !remove.to_index()) + } } /// Add some castle rights, and return a new `CastleRights`. pub fn add(&self, add: CastleRights) -> CastleRights { - CastleRights::from_index(self.to_index() | add.to_index()) + unsafe { + CastleRights::new_unchecked(self.to_index() | add.to_index()) + } } /// Convert `CastleRights` to `usize` for table lookups @@ -101,7 +114,7 @@ impl CastleRights { 1 => CastleRights::KingSide, 2 => CastleRights::QueenSide, 3 => CastleRights::Both, - _ => unsafe { unreachable_unchecked() }, + _ => unreachable!() } } @@ -149,7 +162,7 @@ impl CastleRights { match square.get_file() { File::A => CastleRights::QueenSide, File::H => CastleRights::KingSide, - _ => unsafe { unreachable_unchecked() }, + _ => unreachable!(), } } } From 02f52e75c57ee342da61122cdd173be8df18daf7 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Thu, 24 Jun 2021 19:45:33 +0200 Subject: [PATCH 2/2] Add safety comments --- src/castle_rights.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/castle_rights.rs b/src/castle_rights.rs index c0912ca7..436f73bb 100644 --- a/src/castle_rights.rs +++ b/src/castle_rights.rs @@ -70,6 +70,7 @@ impl CastleRights { pub fn square_to_castle_rights(color: Color, sq: Square) -> CastleRights { unsafe { + // SAFETY: All values in constant are < 4 CastleRights::new_unchecked( *CASTLES_PER_SQUARE .get_unchecked(color.to_index()) @@ -91,6 +92,7 @@ impl CastleRights { /// Remove castle rights, and return a new `CastleRights`. pub fn remove(&self, remove: CastleRights) -> CastleRights { unsafe { + // SAFETY: x < 4 => (x & y) < 4 CastleRights::new_unchecked(self.to_index() & !remove.to_index()) } } @@ -98,6 +100,7 @@ impl CastleRights { /// Add some castle rights, and return a new `CastleRights`. pub fn add(&self, add: CastleRights) -> CastleRights { unsafe { + // SAFETY: x < 4 && y < 4 => (x | y) < 4 CastleRights::new_unchecked(self.to_index() | add.to_index()) } }