use crate::{
indices::BitIdx,
order::BitOrder,
store::BitStore,
};
use core::{
fmt::Debug,
sync::atomic::Ordering,
};
use radium::{
Radium,
marker::BitOps,
};
pub trait BitAccess<T>: Debug + Radium<T> + Sized
where T: BitStore + BitOps + Sized {
#[inline(always)]
fn clear_bit<O>(&self, place: BitIdx<T>)
where O: BitOrder {
self.fetch_and(!*O::mask(place), Ordering::Relaxed);
}
fn clear_bits(&self, mask: T) {
self.fetch_and(mask, Ordering::Relaxed);
}
#[inline(always)]
fn set_bit<O>(&self, place: BitIdx<T>)
where O: BitOrder {
self.fetch_or(*O::mask(place), Ordering::Relaxed);
}
fn set_bits(&self, mask: T) {
self.fetch_or(mask, Ordering::Relaxed);
}
#[inline(always)]
fn invert_bit<O>(&self, place: BitIdx<T>)
where O: BitOrder {
self.fetch_xor(*O::mask(place), Ordering::Relaxed);
}
#[inline]
fn get<O>(&self, place: BitIdx<T>) -> bool
where O: BitOrder {
<Self as BitAccess<T>>::load(&self) & *O::mask(place) != T::FALSE
}
#[inline]
fn set<O>(&self, place: BitIdx<T>, value: bool)
where O: BitOrder {
if value {
self.set_bit::<O>(place);
}
else {
self.clear_bit::<O>(place);
}
}
fn load(&self) -> T {
Radium::load(self, Ordering::Relaxed)
}
fn store(&self, value: T) {
Radium::store(self, value, Ordering::Relaxed)
}
#[allow(clippy::mut_from_ref)] unsafe fn as_slice_mut(this: &[Self]) -> &mut [T] {
&mut *(this as *const [Self] as *const [T] as *mut [T])
}
}
impl<T, R> BitAccess<T> for R
where T: BitStore + BitOps, R: Debug + Radium<T> {}