use std::ops::BitAnd; pub trait Sortable { type Item; fn sort_by_key_b(&mut self, func: Func) where Func: FnMut(&Self::Item) -> Key, Key: Ord; } impl Sortable for [Item] { type Item = Item; fn sort_by_key_b(&mut self, func: Func) where Func: FnMut(&Self::Item) -> Key, Key: Ord, { self.sort_by_key(func); } } impl Sortable for [Item; LENGTH] { type Item = Item; fn sort_by_key_b(&mut self, func: Func) where Func: FnMut(&Self::Item) -> Key, Key: Ord, { self.sort_by_key(func); } } impl Sortable for Vec { type Item = Item; fn sort_by_key_b(&mut self, func: Func) where Func: FnMut(&Self::Item) -> Key, Key: Ord, { self.sort_by_key(func); } } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct BitMask { mask: Value, } impl BitMask { #[must_use] pub const fn new(mask: u64) -> Self { Self { mask } } pub const fn value(self) -> u64 { self.mask } /// Prepares a bitfield value in the range of bits specified by this `BitMask`. #[must_use] pub const fn field_prep(self, field_value: u64) -> u64 { ((field_value) << self.mask.trailing_zeros()) & (self.mask) } } impl BitAnd for BitMask { type Output = u64; fn bitand(self, rhs: u64) -> Self::Output { self.mask & rhs } } pub trait NumberExt: Sized { /// Returns a range of bits (field) specified by the provided [`BitMask`]. fn field_get(self, field_mask: BitMask) -> Self; } impl NumberExt for u64 { fn field_get(self, field_mask: BitMask) -> Self { (field_mask & self) >> field_mask.value().trailing_zeros() } } macro_rules! gen_mask_64 { ($low: literal..=$high: literal) => { const { if $high <= $low { panic!("High bit index cannot be less than or equal to low bit index"); } (((!0u64) - (1u64 << ($low)) + 1) & (!0u64 >> (u64::BITS as u64 - 1 - ($high)))) } }; } pub(crate) use gen_mask_64; #[cfg(test)] mod tests { use super::BitMask; use crate::util::NumberExt; #[test] fn field_get_works() { assert_eq!(0b11011u64.field_get(BitMask::new(0b11100)), 0b00110); } #[test] fn bitmask_field_prep_works() { assert_eq!(BitMask::new(0b11000).field_prep(3), 0b11000); } }