use crate::repr::EnumSetTypeRepr;
use crate::traits::{EnumSetType, EnumSetTypePrivate};
use crate::{EnumSet, EnumSetTypeWithRepr};
use core::cmp::Ordering;
use core::fmt::{Debug, Display, Formatter};
use core::hash::{Hash, Hasher};
use core::iter::Sum;
use core::ops::{
BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Sub, SubAssign,
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub enum MixedValue<T: EnumSetType> {
Valid(T),
Invalid(u32),
}
impl<T: EnumSetType> MixedValue<T> {
fn from_bit(b: u32) -> MixedValue<T> {
if T::ALL_BITS.has_bit(b) {
unsafe { MixedValue::Valid(T::enum_from_u32(b)) }
} else {
MixedValue::Invalid(b)
}
}
}
impl<T: EnumSetType> Debug for MixedValue<T>
where T: Debug
{
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
MixedValue::Valid(v) => v.fmt(f),
MixedValue::Invalid(b) => write!(f, "[{b}]"),
}
}
}
impl<T: EnumSetType> Display for MixedValue<T>
where T: Display
{
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
MixedValue::Valid(v) => v.fmt(f),
MixedValue::Invalid(b) => write!(f, "[{b}]"),
}
}
}
#[cfg(feature = "defmt")]
impl<T: EnumSetType + defmt::Format> defmt::Format for MixedValue<T> {
fn format(&self, f: defmt::Formatter) {
match self {
MixedValue::Valid(v) => defmt::write!(f, "{}", v),
MixedValue::Invalid(b) => defmt::write!(f, "[{}]", b),
}
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
#[repr(transparent)]
pub struct MixedEnumSet<T: EnumSetTypeWithRepr> {
pub(crate) repr: <T as EnumSetTypePrivate>::Repr,
}
impl<T: EnumSetTypeWithRepr> MixedEnumSet<T> {
const EMPTY_REPR: Self = MixedEnumSet { repr: <T as EnumSetTypePrivate>::Repr::EMPTY };
const ALL_REPR: Self = MixedEnumSet { repr: T::ALL_BITS };
#[inline(always)]
pub const fn new() -> Self {
Self::EMPTY_REPR
}
#[inline(always)]
pub const fn empty() -> Self {
Self::EMPTY_REPR
}
#[inline(always)]
pub const fn all() -> Self {
Self::ALL_REPR
}
#[inline(always)]
pub const fn variant_count() -> u32 {
T::VARIANT_COUNT
}
set_common_methods!(T, <T as EnumSetTypePrivate>::Repr);
#[inline(always)]
pub fn complement(&self) -> Self {
Self { repr: !self.repr & T::ALL_BITS }
}
#[inline(always)]
pub fn full_complement(&self) -> Self {
Self { repr: !self.repr }
}
#[inline(always)]
pub fn valid_len(&self) -> usize {
(self.repr & T::ALL_BITS).count_ones() as usize
}
#[inline(always)]
pub fn has_unknown_bits(&self) -> bool {
!(self.repr & !T::ALL_BITS).is_empty()
}
#[inline(always)]
pub fn has_bit(&self, value: u32) -> bool {
self.repr.has_bit(value)
}
#[inline(always)]
pub fn insert_bit(&mut self, value: u32) -> bool {
let contains = !self.has_bit(value);
self.repr.add_bit(value);
contains
}
#[inline(always)]
pub fn remove_bit(&mut self, value: u32) -> bool {
let contains = self.has_bit(value);
self.repr.remove_bit(value);
contains
}
#[inline(always)]
pub fn insert_all(&mut self, other: impl Into<Self>) {
self.repr = self.repr | other.into().repr
}
#[inline(always)]
pub fn remove_all(&mut self, other: impl Into<Self>) {
self.repr = self.repr.and_not(other.into().repr);
}
}
set_common_impls!(MixedEnumSet, EnumSetTypeWithRepr);
impl<T: EnumSetTypeWithRepr> PartialEq<MixedEnumSet<T>> for EnumSet<T> {
fn eq(&self, other: &MixedEnumSet<T>) -> bool {
self.repr == other.repr
}
}
impl<T: EnumSetTypeWithRepr> PartialEq<EnumSet<T>> for MixedEnumSet<T> {
fn eq(&self, other: &EnumSet<T>) -> bool {
self.repr == other.repr
}
}
#[cfg(feature = "defmt")]
impl<T: EnumSetTypeWithRepr + defmt::Format> defmt::Format for MixedEnumSet<T> {
fn format(&self, f: defmt::Formatter) {
let mut i = self.iter();
if let Some(v) = i.next() {
defmt::write!(f, "{}", v);
for v in i {
defmt::write!(f, " | {}", v);
}
}
}
}
#[cfg(feature = "serde")]
impl<T: EnumSetTypeWithRepr> Serialize for MixedEnumSet<T>
where <T as EnumSetTypeWithRepr>::Repr: Serialize
{
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.repr.serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'de, T: EnumSetTypeWithRepr> Deserialize<'de> for MixedEnumSet<T>
where <T as EnumSetTypeWithRepr>::Repr: Deserialize<'de>
{
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
<T as EnumSetTypeWithRepr>::Repr::deserialize(deserializer).map(|x| Self { repr: x })
}
}
impl<T: EnumSetTypeWithRepr> MixedEnumSet<T> {
#[inline(always)]
pub const fn as_repr(&self) -> <T as EnumSetTypeWithRepr>::Repr {
self.repr
}
#[inline(always)]
pub fn from_repr(bits: <T as EnumSetTypeWithRepr>::Repr) -> Self {
Self { repr: bits }
}
#[inline(always)]
pub fn from_repr_truncated(bits: <T as EnumSetTypeWithRepr>::Repr) -> Self {
let mask = Self::all().as_repr();
let bits = bits & mask;
MixedEnumSet { repr: bits }
}
pub fn as_enumset(&self) -> EnumSet<T> {
self.try_as_enumset()
.expect("Bitset contains invalid variants.")
}
pub fn try_as_enumset(&self) -> Option<EnumSet<T>> {
if self.has_unknown_bits() {
None
} else {
Some(EnumSet { repr: self.repr })
}
}
pub fn as_enumset_truncate(&self) -> EnumSet<T> {
EnumSet { repr: self.repr & T::ALL_BITS }
}
}
impl<T: EnumSetTypeWithRepr, const N: usize> From<[T; N]> for MixedEnumSet<T> {
fn from(value: [T; N]) -> Self {
let mut new = MixedEnumSet::new();
for elem in value {
new.insert(elem);
}
new
}
}
impl<T: EnumSetTypeWithRepr> From<EnumSet<T>> for MixedEnumSet<T> {
fn from(value: EnumSet<T>) -> Self {
MixedEnumSet { repr: value.repr }
}
}
#[derive(Clone, Debug)]
pub struct MixedEnumSetIter<T: EnumSetType> {
iter: <T::Repr as EnumSetTypeRepr>::Iter,
}
impl<T: EnumSetTypeWithRepr> MixedEnumSetIter<T> {
fn new(set: MixedEnumSet<T>) -> MixedEnumSetIter<T> {
MixedEnumSetIter { iter: set.repr.iter() }
}
}
impl<T: EnumSetTypeWithRepr> MixedEnumSet<T> {
pub fn iter(&self) -> MixedEnumSetIter<T> {
MixedEnumSetIter::new(*self)
}
}
impl<T: EnumSetTypeWithRepr> Iterator for MixedEnumSetIter<T> {
type Item = MixedValue<T>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|x| MixedValue::from_bit(x))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<T: EnumSetTypeWithRepr> DoubleEndedIterator for MixedEnumSetIter<T> {
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back().map(|x| MixedValue::from_bit(x))
}
}
impl<T: EnumSetTypeWithRepr> ExactSizeIterator for MixedEnumSetIter<T> {}
set_iterator_impls!(MixedEnumSet, EnumSetTypeWithRepr);
impl<T: EnumSetTypeWithRepr> IntoIterator for MixedEnumSet<T> {
type Item = MixedValue<T>;
type IntoIter = MixedEnumSetIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<T: EnumSetTypeWithRepr> Extend<EnumSet<T>> for MixedEnumSet<T> {
fn extend<I: IntoIterator<Item = EnumSet<T>>>(&mut self, iter: I) {
iter.into_iter().for_each(|v| {
self.insert_all(v);
});
}
}
impl<'a, T: EnumSetTypeWithRepr> Extend<&'a EnumSet<T>> for MixedEnumSet<T> {
fn extend<I: IntoIterator<Item = &'a EnumSet<T>>>(&mut self, iter: I) {
iter.into_iter().for_each(|v| {
self.insert_all(*v);
});
}
}
impl<T: EnumSetTypeWithRepr> FromIterator<EnumSet<T>> for MixedEnumSet<T> {
fn from_iter<I: IntoIterator<Item = EnumSet<T>>>(iter: I) -> Self {
let mut set = MixedEnumSet::default();
set.extend(iter);
set
}
}
impl<'a, T: 'a + EnumSetTypeWithRepr> FromIterator<&'a EnumSet<T>> for MixedEnumSet<T> {
fn from_iter<I: IntoIterator<Item = &'a EnumSet<T>>>(iter: I) -> Self {
let mut set = MixedEnumSet::default();
set.extend(iter);
set
}
}
impl<'a, T: EnumSetTypeWithRepr> Sum<EnumSet<T>> for MixedEnumSet<T> {
fn sum<I: Iterator<Item = EnumSet<T>>>(iter: I) -> Self {
iter.fold(MixedEnumSet::empty(), |a, v| a | v)
}
}
impl<'a, T: EnumSetTypeWithRepr> Sum<&'a EnumSet<T>> for MixedEnumSet<T> {
fn sum<I: Iterator<Item = &'a EnumSet<T>>>(iter: I) -> Self {
iter.fold(MixedEnumSet::empty(), |a, v| a | *v)
}
}