#![no_std]
use core::fmt::{Debug, Display};
use core::ops::Shl;
use core::str::FromStr;
mod operators;
mod serialize;
mod macros;
mod sealed {
use core::ops::{Not, BitAnd, BitOr, BitXor, BitAndAssign, BitOrAssign, BitXorAssign, AddAssign};
use core::ops::{Shl, Shr};
use core::fmt::LowerHex;
macro_rules! impl_num {
($($ty: ty),*) => {
$(impl Number for $ty {
const ZERO: Self = 0;
const ONE: Self = 1;
})*
};
}
pub trait Number: Sized + Eq + Copy + LowerHex +
Not<Output=Self> + AddAssign +
BitAnd<Output=Self> + BitOr<Output=Self> + BitXor<Output=Self> +
BitAndAssign + BitOrAssign + BitXorAssign{
const ZERO: Self;
const ONE: Self;
}
impl_num!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize);
pub trait Shift<T>: Sized {
fn ashl(self, n: T) -> Self;
fn ashr(self, n: T) -> Self;
}
macro_rules! impl_shift {
($($unsigned: ty, $signed: ty),*) => {
$(
impl<T> Shift<T> for $unsigned where Self: Shl<T, Output=Self> + Shr<T, Output=Self>{
fn ashl(self, n: T) -> Self {
self << n
}
fn ashr(self, n: T) -> Self {
self >> n
}
}
impl<T> Shift<T> for $signed where $unsigned: Shl<T, Output=$unsigned> + Shr<T, Output=$unsigned> {
fn ashl(self, n: T) -> Self {
(((self as $unsigned) << n) as $signed)
}
fn ashr(self, n: T) -> Self {
(((self as $unsigned) >> n) as $signed)
}
}
)*
};
}
impl_shift!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize);
}
use sealed::{Number, Shift};
pub trait ReprEnum: Sized + Into<Self::Repr>{
type Repr: TryInto<Self> + Number;
type FlagsRepr: Shl<Self::Repr, Output = Self::FlagsRepr> + Number + Shift<Self::Repr> + Shift<u32>;
}
#[derive(Clone, Copy, Hash)]
pub struct ESet<T: ReprEnum, const SEP: char='|'>(T::FlagsRepr);
impl<T: ReprEnum, const S: char> ESet<T, S>{
pub const NONE: Self = Self(T::FlagsRepr::ZERO);
#[inline]
#[must_use]
pub fn new(item: T) -> Self{
Self(T::FlagsRepr::ONE << item.into())
}
#[inline]
#[must_use]
pub fn new_flags<TIter>(item: impl IntoIterator<Item = TIter>) -> Self where Self: FromIterator<TIter>{
Self::from_iter(item)
}
#[inline]
#[must_use]
pub fn is_empty(&self) -> bool{
self.0 == T::FlagsRepr::ZERO
}
#[inline]
#[must_use]
pub fn contains(&self, item: T) -> bool{
self.0 & (T::FlagsRepr::ONE.ashl(item.into())) != T::FlagsRepr::ZERO
}
#[inline]
pub fn insert(&mut self, item: T) -> &mut Self{
self.0 |= T::FlagsRepr::ONE.ashl(item.into());
self
}
#[inline]
pub fn remove(&mut self, item: T) -> &mut Self{
self.0 ^= self.0 & (T::FlagsRepr::ONE.ashl(item.into()));
self
}
#[inline]
#[must_use]
pub fn with(self, item: T) -> Self{
Self(self.0 | (T::FlagsRepr::ONE << item.into()))
}
#[inline]
#[must_use]
pub fn without(self, item: T) -> Self{
Self(self.0 ^ (self.0 & (T::FlagsRepr::ONE << item.into())))
}
#[inline]
#[must_use]
pub const fn with_separator<const SEP: char>(self) -> ESet<T, SEP>{
ESet(self.0)
}
#[inline]
#[must_use]
pub fn iter(&self) -> ESetIter<T, S>{
self.into_iter()
}
}
impl<T: ReprEnum, const S: char> Default for ESet<T, S>{
fn default() -> Self {
Self::NONE
}
}
pub struct ESetIter<T: ReprEnum, const SEP: char> {
flag: T::FlagsRepr,
cursor: T::Repr,
}
impl<T: ReprEnum, const S: char> Iterator for ESetIter<T, S> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.flag == T::FlagsRepr::ZERO {
None
} else if self.flag & T::FlagsRepr::ONE == T::FlagsRepr::ONE {
let result = self.cursor.try_into();
self.flag = self.flag.ashr(1);
self.cursor += T::Repr::ONE;
Some(result.ok()?)
} else {
self.flag = self.flag.ashr(1);
self.cursor += T::Repr::ONE;
self.next()
}
}
}
impl<T: ReprEnum, const S: char> IntoIterator for ESet<T, S> {
type Item = T;
type IntoIter = ESetIter<T, S>;
fn into_iter(self) -> Self::IntoIter {
ESetIter {
flag: self.0,
cursor: T::Repr::ZERO,
}
}
}
impl<T: ReprEnum, const S: char> IntoIterator for &ESet<T, S> {
type Item = T;
type IntoIter = ESetIter<T, S>;
fn into_iter(self) -> Self::IntoIter {
ESetIter {
flag: self.0,
cursor: T::Repr::ZERO,
}
}
}
impl<T: ReprEnum, const S: char> FromIterator<T> for ESet<T, S> {
fn from_iter<A: IntoIterator<Item = T>>(iter: A) -> Self {
let mut result = Self::NONE;
for i in iter{
result.0 |= Self::new(i).0;
}
result
}
}
impl<'t, T: ReprEnum, const S: char> FromIterator<&'t T> for ESet<T, S> where T: 't + Copy{
fn from_iter<A: IntoIterator<Item = &'t T>>(iter: A) -> Self {
let mut result = Self::NONE;
for i in iter{
result.0 |= Self::new(*i).0;
}
result
}
}
impl<T: ReprEnum, const S: char> Debug for ESet<T, S> where T: Debug{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut set = f.debug_set();
for item in self.iter() {
set.entry(&item);
}
set.finish()
}
}
impl<T: ReprEnum, const S: char> Display for ESet<T, S> where T: Display{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut iter = self.into_iter();
if let Some(first) = iter.next(){
first.fmt(f)?;
}
for item in iter {
<char as Display>::fmt(&S, f)?;
item.fmt(f)?;
}
Ok(())
}
}
impl<T: ReprEnum, const S: char> FromStr for ESet<T, S> where T: FromStr{
type Err = T::Err;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut result = Self::NONE;
for slice in s.split(S){
result.0 |= Self::new(T::from_str(slice)?).0;
}
Ok(result)
}
}