use crate::result::BitError;
use alloc::fmt::Debug;
use core::{convert::{TryFrom, TryInto}, hash::{Hash, Hasher}, mem, ops::*};
macro_rules! bit_count_one {
( $bit:expr) => {
if $bit.count_ones() != 1 {
return Err(BitError::CountNotEqualToOne);
}
};
}
macro_rules! bit_found {
( $self:expr, $bit:expr) => {
bit_count_one!($bit);
if $self & $bit == 0 {
return Err(BitError::NotFound);
}
};
}
macro_rules! bit_not_found {
( $self:expr, $bit:expr) => {
bit_count_one!($bit);
if $self & $bit == 1 {
return Err(BitError::Found);
}
};
}
macro_rules! bit_in_range {
( $type:ty, $index:expr) => {
if $index >= <$type>::max_ones() {
return Err(BitError::Range);
}
};
}
pub trait AsUsize {
#[must_use]
fn as_usize(&self) -> usize;
}
impl AsUsize for u8 { fn as_usize(&self) -> usize {*self as usize} }
impl AsUsize for u16 { fn as_usize(&self) -> usize {*self as usize} }
impl AsUsize for u32 { fn as_usize(&self) -> usize {*self as usize} }
impl AsUsize for u64 { fn as_usize(&self) -> usize {*self as usize} }
impl AsUsize for u128 { fn as_usize(&self) -> usize {*self as usize} }
impl AsUsize for usize { fn as_usize(&self) -> usize {*self} }
pub trait BitContains {
fn bit_contains(&self, bit: Self) -> Result<bool, BitError>;
}
impl BitContains for u8 { fn bit_contains(&self, bit: Self) -> Result<bool, BitError> {bit_count_one!(bit); Ok((self & bit) != 0)} }
impl BitContains for u16 { fn bit_contains(&self, bit: Self) -> Result<bool, BitError> {bit_count_one!(bit); Ok((self & bit) != 0)} }
impl BitContains for u32 { fn bit_contains(&self, bit: Self) -> Result<bool, BitError> {bit_count_one!(bit); Ok((self & bit) != 0)} }
impl BitContains for u64 { fn bit_contains(&self, bit: Self) -> Result<bool, BitError> {bit_count_one!(bit); Ok((self & bit) != 0)} }
impl BitContains for u128 { fn bit_contains(&self, bit: Self) -> Result<bool, BitError> {bit_count_one!(bit); Ok((self & bit) != 0)} }
impl BitContains for usize { fn bit_contains(&self, bit: Self) -> Result<bool, BitError> {bit_count_one!(bit); Ok((self & bit) != 0)} }
pub trait BitIndex {
fn bit_index(&self, bit: Self) -> Result<usize, BitError>;
}
impl BitIndex for u8 { fn bit_index(&self, bit: Self) -> Result<usize, BitError> {bit_found!(self, bit); Ok((self & (bit - 1)).count_ones() as usize)} }
impl BitIndex for u16 { fn bit_index(&self, bit: Self) -> Result<usize, BitError> {bit_found!(self, bit); Ok((self & (bit - 1)).count_ones() as usize)} }
impl BitIndex for u32 { fn bit_index(&self, bit: Self) -> Result<usize, BitError> {bit_found!(self, bit); Ok((self & (bit - 1)).count_ones() as usize)} }
impl BitIndex for u64 { fn bit_index(&self, bit: Self) -> Result<usize, BitError> {bit_found!(self, bit); Ok((self & (bit - 1)).count_ones() as usize)} }
impl BitIndex for u128 { fn bit_index(&self, bit: Self) -> Result<usize, BitError> {bit_found!(self, bit); Ok((self & (bit - 1)).count_ones() as usize)} }
impl BitIndex for usize { fn bit_index(&self, bit: Self) -> Result<usize, BitError> {bit_found!(self, bit); Ok((self & (bit - 1)).count_ones() as usize)} }
pub trait BitInsert {
fn bit_insert(&self, bit: Self) -> Result<Self, BitError> where Self: Sized;
}
impl BitInsert for u8 { fn bit_insert(&self, bit: Self) -> Result<Self, BitError> {bit_not_found!(self, bit); Ok(self | bit)} }
impl BitInsert for u16 { fn bit_insert(&self, bit: Self) -> Result<Self, BitError> {bit_not_found!(self, bit); Ok(self | bit)} }
impl BitInsert for u32 { fn bit_insert(&self, bit: Self) -> Result<Self, BitError> {bit_not_found!(self, bit); Ok(self | bit)} }
impl BitInsert for u64 { fn bit_insert(&self, bit: Self) -> Result<Self, BitError> {bit_not_found!(self, bit); Ok(self | bit)} }
impl BitInsert for u128 { fn bit_insert(&self, bit: Self) -> Result<Self, BitError> {bit_not_found!(self, bit); Ok(self | bit)} }
impl BitInsert for usize { fn bit_insert(&self, bit: Self) -> Result<Self, BitError> {bit_not_found!(self, bit); Ok(self | bit)} }
pub trait BitRemove {
fn bit_remove(&self, bit: Self) -> Result<Self, BitError> where Self: Sized;
}
impl BitRemove for u8 { fn bit_remove(&self, bit: Self) -> Result<Self, BitError> {bit_found!(self, bit); Ok(self ^ bit)} }
impl BitRemove for u16 { fn bit_remove(&self, bit: Self) -> Result<Self, BitError> {bit_found!(self, bit); Ok(self ^ bit)} }
impl BitRemove for u32 { fn bit_remove(&self, bit: Self) -> Result<Self, BitError> {bit_found!(self, bit); Ok(self ^ bit)} }
impl BitRemove for u64 { fn bit_remove(&self, bit: Self) -> Result<Self, BitError> {bit_found!(self, bit); Ok(self ^ bit)} }
impl BitRemove for u128 { fn bit_remove(&self, bit: Self) -> Result<Self, BitError> {bit_found!(self, bit); Ok(self ^ bit)} }
impl BitRemove for usize { fn bit_remove(&self, bit: Self) -> Result<Self, BitError> {bit_found!(self, bit); Ok(self ^ bit)} }
pub trait CountOnes {
#[must_use]
fn count_ones_t(&self) -> usize;
}
impl CountOnes for u8 { fn count_ones_t(&self) -> usize {self.count_ones() as usize} }
impl CountOnes for u16 { fn count_ones_t(&self) -> usize {self.count_ones() as usize} }
impl CountOnes for u32 { fn count_ones_t(&self) -> usize {self.count_ones() as usize} }
impl CountOnes for u64 { fn count_ones_t(&self) -> usize {self.count_ones() as usize} }
impl CountOnes for u128 { fn count_ones_t(&self) -> usize {self.count_ones() as usize} }
impl CountOnes for usize { fn count_ones_t(&self) -> usize {self.count_ones() as usize} }
pub trait LogB {
#[must_use]
fn log_b() -> usize;
}
impl LogB for u8 { fn log_b() -> usize {3} }
impl LogB for u16 { fn log_b() -> usize {4} }
impl LogB for u32 { fn log_b() -> usize {5} }
impl LogB for u64 { fn log_b() -> usize {6} }
impl LogB for u128 { fn log_b() -> usize {7} }
impl LogB for usize {
fn log_b() -> usize {
match mem::size_of::<usize>() {
1 => 3,
2 => 4,
4 => 5,
8 => 6,
16 => 7,
_ => panic!()
}
}
}
pub trait MaskLogB<T> {
#[must_use]
fn mask_log_b() -> T;
}
impl <T: From<u8>> MaskLogB<T> for u8 { fn mask_log_b() -> T {0b111.into()} }
impl <T: From<u8>> MaskLogB<T> for u16 { fn mask_log_b() -> T {0b1111.into()} }
impl <T: From<u16>> MaskLogB<T> for u32 { fn mask_log_b() -> T {0b11111.into()} }
impl <T: From<u16>> MaskLogB<T> for u64 { fn mask_log_b() -> T {0b111111.into()} }
impl <T: From<u16>> MaskLogB<T> for u128 { fn mask_log_b() -> T {0b1111111.into()} }
impl <T: From<u16>> MaskLogB<T> for usize {
fn mask_log_b() -> T {
match mem::size_of::<usize>() {
1 => 0b111,
2 => 0b1111,
4 => 0b11111,
8 => 0b111111,
16 => 0b1111111,
_ => panic!()
}.into()
}
}
pub trait MaxOnes {
#[must_use]
fn max_ones() -> usize;
}
impl MaxOnes for u8 { fn max_ones() -> usize {8} }
impl MaxOnes for u16 { fn max_ones() -> usize {16} }
impl MaxOnes for u32 { fn max_ones() -> usize {32} }
impl MaxOnes for u64 { fn max_ones() -> usize {64} }
impl MaxOnes for u128 { fn max_ones() -> usize {128} }
impl MaxOnes for usize { fn max_ones() -> usize {8 * mem::size_of::<usize>()} }
pub trait NthBit {
fn nth_bit(n: usize) -> Result<Self, BitError> where Self: Sized;
}
impl NthBit for u8 { fn nth_bit(n: usize) -> Result<Self, BitError> {bit_in_range!(u8, n); Ok(1_u8 << n)} }
impl NthBit for u16 { fn nth_bit(n: usize) -> Result<Self, BitError> {bit_in_range!(u16, n); Ok(1_u16 << n)} }
impl NthBit for u32 { fn nth_bit(n: usize) -> Result<Self, BitError> {bit_in_range!(u32, n); Ok(1_u32 << n)} }
impl NthBit for u64 { fn nth_bit(n: usize) -> Result<Self, BitError> {bit_in_range!(u64, n); Ok(1_u64 << n)} }
impl NthBit for u128 { fn nth_bit(n: usize) -> Result<Self, BitError> {bit_in_range!(u128, n); Ok(1_u128 << n)} }
impl NthBit for usize { fn nth_bit(n: usize) -> Result<Self, BitError> {bit_in_range!(usize, n); Ok(1_usize << n)} }
pub trait Hashword: BitAnd + Clone + Debug + From<<Self as Shr<usize>>::Output> + MaxOnes + PartialEq + Shr<usize> + 'static {}
impl <H: BitAnd + Clone + Debug + From<<Self as Shr<usize>>::Output> + MaxOnes + PartialEq + Shr<usize>> Hashword
for H where H: BitAnd + Clone + Debug + From<<Self as Shr<usize>>::Output> + MaxOnes + PartialEq + Shr<usize> + 'static {}
pub trait Flagword<H: Hashword>: AsUsize + BitContains + BitIndex + BitInsert + BitRemove + Clone + CountOnes + Debug + Default + TryFrom<<H as BitAnd>::Output> + LogB + MaskLogB<H> + MaxOnes + NthBit + PartialEq + 'static {}
impl <H: Hashword, F: AsUsize + BitContains + BitIndex + BitInsert + BitRemove + Clone + CountOnes + Debug + Default + TryFrom<<H as BitAnd>::Output> + LogB + MaskLogB<H> + MaxOnes + NthBit + PartialEq> Flagword<H>
for F where F: AsUsize + BitContains + BitIndex + BitInsert + BitRemove + Clone + CountOnes + Debug + Default + TryFrom<<H as BitAnd>::Output> + LogB + MaskLogB<H> + MaxOnes + NthBit + PartialEq + 'static {}
pub trait Key: Clone + Debug + Eq + PartialEq + Hash + Send + Sync + 'static {}
impl <T: Clone + Debug + Eq + PartialEq + Hash + Send + Sync + 'static> Key
for T where T: Clone + Debug + Eq + PartialEq + Hash + Send + Sync + 'static {}
pub trait Value: Clone + Debug + Send + Sync + 'static {}
impl <T: Clone + Debug + Send + Sync + 'static> Value
for T where T: Clone + Debug + Send + Sync + 'static {}
pub trait HashLike<T> {}
impl <T> HashLike<T> for T {}
pub trait HasherBv<B, V>: Default + 'static {
#[must_use]
fn hash(&self, value: &V) -> B;
}
macro_rules! hasher_bv_impl {
( $type:ty ) => {
impl <V: Default + Hash + 'static, H: Default + Hasher + 'static> HasherBv<$type, V> for H {
fn hash(&self, value: &V) -> $type {
let mut hasher = H::default();
value.hash(&mut hasher);
hasher.finish().try_into().unwrap()
}
}
};
}
hasher_bv_impl!(u8);
hasher_bv_impl!(u16);
hasher_bv_impl!(u32);
hasher_bv_impl!(u64);