From d5cdf273c86abfcf27e49623cf702b79284416f8 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 3 May 2025 16:03:18 -0700 Subject: [PATCH] [bitboard] Fix some random clippy issues --- bitboard/src/bitboard.rs | 88 ++++++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 31 deletions(-) diff --git a/bitboard/src/bitboard.rs b/bitboard/src/bitboard.rs index 1ef26e9..ce1852d 100644 --- a/bitboard/src/bitboard.rs +++ b/bitboard/src/bitboard.rs @@ -8,6 +8,9 @@ use forward_ref::{forward_ref_binop, forward_ref_op_assign, forward_ref_unop}; use std::fmt; use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not}; +#[allow(clippy::cast_possible_truncation)] +const SQUARES_NUM: u8 = Square::NUM as u8; + /// A bitfield representation of a chess board that uses the bits of a 64-bit /// unsigned integer to represent whether a square on the board is occupied. /// Squares are laid out as follows, starting at the bottom left, going row-wise, @@ -103,21 +106,21 @@ impl BitBoard { } impl BitBoard { - /// Converts this [BitBoard] to an unsigned 64-bit integer. + /// Converts this [`BitBoard`] to an unsigned 64-bit integer. #[must_use] pub const fn as_bits(&self) -> u64 { self.0 } - /// Returns `true` if this [BitBoard] has no bits set. This is the opposite + /// Returns `true` if this [`BitBoard`] has no bits set. This is the opposite /// of [`BitBoard::is_populated`]. /// /// ## Examples /// /// ``` /// use chessfriend_bitboard::BitBoard; - /// assert!(BitBoard::EMPTY.is_empty()); - /// assert!(!BitBoard::FULL.is_empty()); + /// assert!(BitBoard::empty().is_empty()); + /// assert!(!BitBoard::full().is_empty()); /// assert!(!BitBoard::new(0b1000).is_empty()); /// ``` #[must_use] @@ -125,17 +128,18 @@ impl BitBoard { self.0 == 0 } - /// Returns `true` if the [BitBoard] has at least one bit set. This is the + /// Returns `true` if the [`BitBoard`] has at least one bit set. This is the /// opposite of [`BitBoard::is_empty`]. /// /// ## Examples /// /// ``` /// use chessfriend_bitboard::BitBoard; - /// assert!(!BitBoard::EMPTY.is_populated()); - /// assert!(BitBoard::FULL.is_populated()); + /// assert!(!BitBoard::empty().is_populated()); + /// assert!(BitBoard::full().is_populated()); /// assert!(BitBoard::new(0b1).is_populated()); /// ``` + #[must_use] pub const fn is_populated(&self) -> bool { self.0 != 0 } @@ -154,21 +158,23 @@ impl BitBoard { /// assert!(bitboard.contains(Square::C1)); /// assert!(!bitboard.contains(Square::B1)); /// ``` + #[must_use] pub fn contains(self, square: Square) -> bool { let square_bitboard: BitBoard = square.into(); !(self & square_bitboard).is_empty() } - /// Counts the number of set squares (1 bits) in this [BitBoard]. + /// Counts the number of set squares (1 bits) in this [`BitBoard`]. /// /// ## Examples /// /// ``` /// use chessfriend_bitboard::BitBoard; - /// assert_eq!(BitBoard::EMPTY.population_count(), 0); + /// assert_eq!(BitBoard::empty().population_count(), 0); /// assert_eq!(BitBoard::new(0b01011110010).population_count(), 6); - /// assert_eq!(BitBoard::FULL.population_count(), 64); + /// assert_eq!(BitBoard::full().population_count(), 64); /// ``` + #[must_use] pub const fn population_count(&self) -> u32 { self.0.count_ones() } @@ -188,10 +194,10 @@ impl BitBoard { /// ``` pub fn set(&mut self, square: Square) { let square_bitboard: BitBoard = square.into(); - self.0 |= square_bitboard.0 + self.0 |= square_bitboard.0; } - /// Clear a square (set it to 0) in this [BitBoard]. This always succeeds + /// Clear a square (set it to 0) in this [`BitBoard`]. This always succeeds /// even if the bit is not set. /// /// ## Examples @@ -206,20 +212,21 @@ impl BitBoard { /// ``` pub fn clear(&mut self, square: Square) { let square_bitboard: BitBoard = square.into(); - self.0 &= !square_bitboard.0 + self.0 &= !square_bitboard.0; } - /// Returns `true` if this BitBoard represents a single square. + /// Returns `true` if this [`BitBoard`] represents a single square. /// /// ## Examples /// /// ``` /// use chessfriend_bitboard::BitBoard; - /// assert!(!BitBoard::EMPTY.is_single_square(), "Empty bitboards represent no squares"); - /// assert!(!BitBoard::FULL.is_single_square(), "Full bitboards represent all the squares"); + /// assert!(!BitBoard::empty().is_single_square(), "Empty bitboards represent no squares"); + /// assert!(!BitBoard::full().is_single_square(), "Full bitboards represent all the squares"); /// assert!(!BitBoard::new(0b010011110101101100).is_single_square(), "This bitboard represents a bunch of squares"); /// assert!(BitBoard::new(0b10000000000000).is_single_square()); /// ``` + #[must_use] pub fn is_single_square(&self) -> bool { self.0.is_power_of_two() } @@ -228,8 +235,9 @@ impl BitBoard { #[must_use] pub fn occupied_squares( &self, - direction: IterationDirection, + direction: &IterationDirection, ) -> Box> { + #[allow(clippy::cast_possible_truncation)] fn index_to_square(index: usize) -> Square { unsafe { Square::from_index_unchecked(index as u8) } } @@ -245,7 +253,7 @@ impl BitBoard { } #[must_use] - pub fn first_occupied_square(&self, direction: IterationDirection) -> Option { + pub fn first_occupied_square(&self, direction: &IterationDirection) -> Option { match direction { IterationDirection::Leading => self.first_occupied_square_leading(), IterationDirection::Trailing => self.first_occupied_square_trailing(), @@ -256,12 +264,12 @@ impl BitBoard { /// board, starting at the leading (most-significant) end of the board. If /// the board is empty, returns `None`. #[must_use] - fn first_occupied_square_leading(&self) -> Option { - let leading_zeros = self.0.leading_zeros() as u8; - if leading_zeros < Square::NUM as u8 { + fn first_occupied_square_leading(self) -> Option { + let leading_zeros = self._leading_zeros(); + if leading_zeros < SQUARES_NUM { unsafe { Some(Square::from_index_unchecked( - Square::NUM as u8 - leading_zeros - 1, + SQUARES_NUM - leading_zeros - 1, )) } } else { @@ -273,9 +281,10 @@ impl BitBoard { /// board, starting at the trailing (least-significant) end of the board. /// If the board is empty, returns `None`. #[must_use] - fn first_occupied_square_trailing(&self) -> Option { - let trailing_zeros = self.0.trailing_zeros() as u8; - if trailing_zeros < Square::NUM as u8 { + fn first_occupied_square_trailing(self) -> Option { + let trailing_zeros = self._trailing_zeros(); + + if trailing_zeros < SQUARES_NUM { unsafe { Some(Square::from_index_unchecked(trailing_zeros)) } } else { None @@ -283,6 +292,20 @@ impl BitBoard { } } +impl BitBoard { + #[must_use] + #[allow(clippy::cast_possible_truncation)] + fn _leading_zeros(self) -> u8 { + self.0.leading_zeros() as u8 + } + + #[must_use] + #[allow(clippy::cast_possible_truncation)] + fn _trailing_zeros(self) -> u8 { + self.0.trailing_zeros() as u8 + } +} + impl Default for BitBoard { fn default() -> Self { BitBoard::EMPTY @@ -341,7 +364,7 @@ impl TryFrom for Square { return Err(TryFromBitBoardError::NotSingleSquare); } - unsafe { Ok(Square::from_index_unchecked(value.0.trailing_zeros() as u8)) } + unsafe { Ok(Square::from_index_unchecked(value._trailing_zeros())) } } } @@ -376,8 +399,7 @@ impl fmt::Display for BitBoard { let mut ranks_written = 0; for rank in binary_ranks.chunks(8).rev() { - let joined_rank = rank.join(" "); - write!(f, "{}", joined_rank)?; + write!(f, "{}", rank.join(" "))?; ranks_written += 1; if ranks_written < 8 { @@ -456,6 +478,7 @@ mod tests { } #[test] + #[allow(clippy::unreadable_literal)] fn rank() { assert_eq!(BitBoard::rank(&0).0, 0xFF, "Rank 1"); assert_eq!(BitBoard::rank(&1).0, 0xFF00, "Rank 2"); @@ -469,11 +492,13 @@ mod tests { #[test] fn single_rank_occupancy() { + #[allow(clippy::unreadable_literal)] let bb = BitBoard(0b01010100); + let expected_squares = [Square::G1, Square::E1, Square::C1]; for (a, b) in bb - .occupied_squares(IterationDirection::Leading) - .zip(expected_squares.iter().cloned()) + .occupied_squares(&IterationDirection::Leading) + .zip(expected_squares.iter().copied()) { assert_eq!(a, b); } @@ -481,13 +506,14 @@ mod tests { #[test] fn occupancy_spot_check() { + #[allow(clippy::unreadable_literal)] let bb = BitBoard(0b10000000_00000000_00100000_00000100_00000000_00000000_00010000_00001000); let expected_squares = [Square::H8, Square::F6, Square::C5, Square::E2, Square::D1]; for (a, b) in bb - .occupied_squares(IterationDirection::Leading) + .occupied_squares(&IterationDirection::Leading) .zip(expected_squares.iter().cloned()) { assert_eq!(a, b);