use core::cmp;
use core::fmt;
use core::hash::{Hash, Hasher};
use core::marker::PhantomData;
use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Sub, SubAssign};
use crate::bits::Bits;
use crate::bits_mut::BitsMut;
use crate::bits_owned::BitsOwned;
use crate::endian::{DefaultEndian, Endian, LittleEndian};
#[repr(transparent)]
pub struct Set<T, E = DefaultEndian>
where
T: ?Sized,
{
_shift: PhantomData<E>,
bits: T,
}
impl<T> Set<T> {
#[inline]
pub const fn new(bits: T) -> Self {
Self::new_in(bits)
}
}
impl<T> Set<T, LittleEndian> {
#[inline]
pub const fn new_le(bits: T) -> Self {
Self::new_in(bits)
}
}
impl<T, E> Set<T, E> {
#[inline]
pub const fn new_in(bits: T) -> Self {
Self {
_shift: PhantomData,
bits,
}
}
#[inline]
pub fn into_bits(self) -> T {
self.bits
}
}
impl<T> Set<T>
where
T: ?Sized,
{
#[inline]
pub fn from_ref<U>(bits: &U) -> &Self
where
U: ?Sized + AsRef<T>,
{
unsafe { &*(bits.as_ref() as *const _ as *const _) }
}
#[inline]
pub fn from_mut<U>(bits: &mut U) -> &mut Self
where
U: ?Sized + AsMut<T>,
{
unsafe { &mut *(bits.as_mut() as *mut _ as *mut _) }
}
}
impl<T> Set<T, LittleEndian>
where
T: ?Sized,
{
#[inline]
pub fn from_ref_le<U>(bits: &U) -> &Self
where
U: ?Sized + AsRef<T>,
{
unsafe { &*(bits.as_ref() as *const _ as *const _) }
}
#[inline]
pub fn from_mut_le<U>(bits: &mut U) -> &mut Self
where
U: ?Sized + AsMut<T>,
{
unsafe { &mut *(bits.as_mut() as *mut _ as *mut _) }
}
}
impl<T, E> Default for Set<T, E>
where
T: BitsOwned,
E: Endian,
{
#[inline]
fn default() -> Self {
Self::new_in(T::ZEROS)
}
}
impl<T, U> Bits for Set<T, U>
where
T: ?Sized + Bits,
U: Endian,
{
type IterOnes<'a> = T::IterOnesIn<'a, U>
where
Self: 'a;
type IterOnesIn<'a, E> = T::IterOnesIn<'a, E>
where
Self: 'a,
E: Endian;
type IterZeros<'a> = T::IterZerosIn<'a, U>
where
Self: 'a;
type IterZerosIn<'a, E> = T::IterZerosIn<'a, E>
where
Self: 'a,
E: Endian;
#[inline]
fn count_ones(&self) -> u32 {
self.bits.count_ones()
}
#[inline]
fn count_zeros(&self) -> u32 {
self.bits.count_zeros()
}
#[inline]
fn bits_capacity(&self) -> u32 {
self.bits.bits_capacity()
}
#[inline]
fn all_ones(&self) -> bool {
self.bits.all_ones()
}
#[inline]
fn all_zeros(&self) -> bool {
self.bits.all_zeros()
}
#[inline]
fn test_bit(&self, index: u32) -> bool {
self.bits.test_bit_in::<U>(index)
}
#[inline]
fn test_bit_in<E>(&self, index: u32) -> bool
where
E: Endian,
{
self.bits.test_bit_in::<E>(index)
}
#[inline]
fn iter_ones(&self) -> Self::IterOnes<'_> {
self.bits.iter_ones_in()
}
#[inline]
fn iter_ones_in<E>(&self) -> Self::IterOnesIn<'_, E>
where
E: Endian,
{
self.bits.iter_ones_in()
}
#[inline]
fn iter_zeros(&self) -> Self::IterZeros<'_> {
self.bits.iter_zeros_in()
}
#[inline]
fn iter_zeros_in<E>(&self) -> Self::IterZerosIn<'_, E>
where
E: Endian,
{
self.bits.iter_zeros_in()
}
}
impl<T, U> BitsMut for Set<T, U>
where
T: ?Sized + BitsMut,
U: Endian,
{
#[inline]
fn set_bit_in<E>(&mut self, index: u32)
where
E: Endian,
{
self.bits.set_bit_in::<E>(index);
}
#[inline]
fn set_bit(&mut self, index: u32) {
self.bits.set_bit_in::<U>(index);
}
#[inline]
fn clear_bit_in<E>(&mut self, index: u32)
where
E: Endian,
{
self.bits.clear_bit_in::<E>(index);
}
#[inline]
fn clear_bit(&mut self, index: u32) {
self.bits.clear_bit_in::<U>(index);
}
#[inline]
fn clear_bits(&mut self) {
self.bits.clear_bits();
}
#[inline]
fn union_assign(&mut self, other: &Self) {
self.bits.union_assign(&other.bits);
}
#[inline]
fn conjunction_assign(&mut self, other: &Self) {
self.bits.conjunction_assign(&other.bits);
}
#[inline]
fn difference_assign(&mut self, other: &Self) {
self.bits.difference_assign(&other.bits);
}
#[inline]
fn symmetric_difference_assign(&mut self, other: &Self) {
self.bits.symmetric_difference_assign(&other.bits);
}
}
impl<T, U> BitsOwned for Set<T, U>
where
T: BitsOwned,
U: Endian,
{
const BITS: u32 = T::BITS;
const ONES: Self = Self::new_in(T::ONES);
const ZEROS: Self = Self::new_in(T::ZEROS);
type IntoIterOnes = T::IntoIterOnesIn<U>;
type IntoIterOnesIn<E> = T::IntoIterOnesIn<E> where E: Endian;
type IntoIterZeros = T::IntoIterZerosIn<U>;
type IntoIterZerosIn<E> = T::IntoIterZerosIn<E> where E: Endian;
#[inline]
fn zeros() -> Self {
Self::new_in(T::ZEROS)
}
#[inline]
fn ones() -> Self {
Self::new_in(T::ONES)
}
#[inline]
fn with_bit_in<E>(self, bit: u32) -> Self
where
E: Endian,
{
Self::new_in(self.bits.with_bit_in::<E>(bit))
}
#[inline]
fn with_bit(self, bit: u32) -> Self {
Self::new_in(self.bits.with_bit_in::<U>(bit))
}
#[inline]
fn without_bit_in<E>(self, bit: u32) -> Self
where
E: Endian,
{
Self::new_in(self.bits.without_bit_in::<E>(bit))
}
#[inline]
fn without_bit(self, bit: u32) -> Self {
Self::new_in(self.bits.without_bit_in::<U>(bit))
}
#[inline]
fn union(self, other: Self) -> Self {
Self::new_in(self.bits.union(other.bits))
}
#[inline]
fn conjunction(self, other: Self) -> Self {
Self::new_in(self.bits.conjunction(other.bits))
}
#[inline]
fn difference(self, other: Self) -> Self {
Self::new_in(self.bits.difference(other.bits))
}
#[inline]
fn symmetric_difference(self, other: Self) -> Self {
Self::new_in(self.bits.symmetric_difference(other.bits))
}
#[inline]
fn into_iter_ones(self) -> Self::IntoIterOnes {
self.bits.into_iter_ones_in()
}
#[inline]
fn into_iter_ones_in<E>(self) -> Self::IntoIterOnesIn<E>
where
E: Endian,
{
self.bits.into_iter_ones_in()
}
#[inline]
fn into_iter_zeros(self) -> Self::IntoIterZeros {
self.bits.into_iter_zeros_in()
}
#[inline]
fn into_iter_zeros_in<E>(self) -> Self::IntoIterZerosIn<E>
where
E: Endian,
{
self.bits.into_iter_zeros_in()
}
}
impl<T, E> Clone for Set<T, E>
where
T: Clone,
{
#[inline]
fn clone(&self) -> Self {
Self::new_in(self.bits.clone())
}
}
impl<T, E> Copy for Set<T, E> where T: Copy {}
impl<T, E> fmt::Debug for Set<T, E>
where
T: ?Sized + Bits,
E: Endian,
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_set().entries(self.iter_ones_in::<E>()).finish()
}
}
impl<T, U, E> cmp::PartialEq<U> for Set<T, E>
where
T: ?Sized + Bits,
U: ?Sized + Bits,
E: Endian,
{
#[inline]
fn eq(&self, other: &U) -> bool {
self.iter_ones_in::<E>().eq(other.iter_ones_in::<E>())
}
}
impl<T, E> cmp::Eq for Set<T, E>
where
T: ?Sized + Bits,
E: Endian,
{
}
impl<T, U, E> cmp::PartialOrd<U> for Set<T, E>
where
T: ?Sized + Bits,
U: ?Sized + Bits,
E: Endian,
{
#[inline]
fn partial_cmp(&self, other: &U) -> Option<cmp::Ordering> {
self.iter_ones_in::<E>()
.partial_cmp(other.iter_ones_in::<E>())
}
}
impl<T, E> cmp::Ord for Set<T, E>
where
T: ?Sized + Bits,
E: Endian,
{
#[inline]
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.iter_ones_in::<E>().cmp(other.iter_ones_in::<E>())
}
}
impl<T, E> Hash for Set<T, E>
where
T: ?Sized + Hash,
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.bits.hash(state);
}
}
impl<T, E> IntoIterator for Set<T, E>
where
T: BitsOwned,
E: Endian,
{
type IntoIter = T::IntoIterOnesIn<E>;
type Item = <Self::IntoIter as Iterator>::Item;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.bits.into_iter_ones_in()
}
}
impl<'a, T, E> IntoIterator for &'a Set<T, E>
where
T: ?Sized + Bits,
E: Endian,
{
type IntoIter = T::IterOnesIn<'a, E>;
type Item = <Self::IntoIter as Iterator>::Item;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter_ones_in::<E>()
}
}
impl<T, E> From<T> for Set<T, E>
where
T: BitsOwned,
E: Endian,
{
#[inline]
fn from(bits: T) -> Self {
Self::new_in(bits)
}
}
macro_rules! owned_ops {
($trait:ident::$n:ident, $name:ident<$t:ident, $s:ident>, $fn:ident) => {
impl<$t, $s> $trait<$name<$t, $s>> for $name<$t, $s>
where
$t: BitsOwned,
$s: Endian,
{
type Output = $name<$t, $s>;
#[inline]
fn $n(self, rhs: $name<$t, $s>) -> Self::Output {
$name::new_in(self.bits.$fn(rhs.bits))
}
}
impl<$t, $s> $trait<&$name<$t, $s>> for $name<$t, $s>
where
$t: Copy + BitsOwned,
$s: Endian,
{
type Output = $name<$t, $s>;
#[inline]
fn $n(self, rhs: &$name<$t, $s>) -> Self::Output {
$name::new_in(self.bits.$fn(rhs.bits))
}
}
impl<$t, $s> $trait<$name<$t, $s>> for &$name<$t, $s>
where
$t: Copy + BitsOwned,
$s: Endian,
{
type Output = $name<$t, $s>;
#[inline]
fn $n(self, rhs: $name<$t, $s>) -> Self::Output {
$name::new_in(self.bits.$fn(rhs.bits))
}
}
impl<$t, $s> $trait<&$name<$t, $s>> for &$name<$t, $s>
where
$t: Copy + BitsOwned,
$s: Endian,
{
type Output = $name<$t, $s>;
#[inline]
fn $n(self, rhs: &$name<$t, $s>) -> Self::Output {
$name::new_in(self.bits.$fn(rhs.bits))
}
}
};
}
macro_rules! assign_ops {
($trait:ident::$n:ident, $name:ident<$t:ident, $s:ident>, $fn:ident) => {
impl<$t, $s> $trait<$name<$t, $s>> for $name<$t, $s>
where
$t: BitsMut,
{
#[inline]
fn $n(&mut self, rhs: $name<$t, $s>) {
self.bits.$fn(&rhs.bits);
}
}
impl<$t, $s> $trait<&$name<$t, $s>> for $name<$t, $s>
where
$t: BitsMut,
{
#[inline]
fn $n(&mut self, rhs: &$name<$t, $s>) {
self.bits.$fn(&rhs.bits);
}
}
impl<$t, $s> $trait<&$name<$t, $s>> for &mut $name<$t, $s>
where
$t: BitsMut,
{
#[inline]
fn $n(&mut self, rhs: &$name<$t, $s>) {
self.bits.$fn(&rhs.bits);
}
}
};
}
owned_ops!(BitOr::bitor, Set<T, E>, union);
assign_ops!(BitOrAssign::bitor_assign, Set<T, E>, union_assign);
owned_ops!(BitAnd::bitand, Set<T, E>, conjunction);
assign_ops!(BitAndAssign::bitand_assign, Set<T, E>, conjunction_assign);
owned_ops!(BitXor::bitxor, Set<T, E>, symmetric_difference);
assign_ops!(
BitXorAssign::bitxor_assign,
Set<T, E>,
symmetric_difference_assign
);
owned_ops!(Sub::sub, Set<T, E>, difference);
assign_ops!(SubAssign::sub_assign, Set<T, E>, difference_assign);