use num::Zero;
use super::Lexicon;
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[repr(transparent)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct Set<L: Lexicon>(L::Bit);
impl<L: Lexicon> Default for Set<L> {
fn default() -> Self {
Self::new()
}
}
impl<L: Lexicon> std::fmt::Debug for Set<L> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut set = f.debug_set();
for ty in *self {
set.entry(&ty);
}
set.finish()
}
}
impl<L: Lexicon> Set<L> {
pub fn new() -> Self {
Self(L::Bit::zero())
}
pub fn from_bits(bits: L::Bit) -> Self {
Self(bits)
}
pub fn to_bits(&self) -> L::Bit {
self.0
}
pub fn insert(&mut self, ty: L) {
self.0 = self.0 | ty.to_bit();
}
pub fn remove(&mut self, ty: L) {
self.0 = self.0 & !ty.to_bit();
}
pub fn contains(&self, ty: L) -> bool {
self.0 & ty.to_bit() != L::Bit::zero()
}
pub fn contains_all(&self, other: Self) -> bool {
(self.0 & other.0) == other.0
}
pub fn is_empty(&self) -> bool {
self.0 == L::Bit::zero()
}
pub fn union(&self, other: Self) -> Self {
Self(self.0 | other.0)
}
}
impl<L: Lexicon> IntoIterator for Set<L> {
type Item = L;
type IntoIter = Iter<L>;
fn into_iter(self) -> Self::IntoIter {
Iter::new(self)
}
}
const START: usize = 129;
pub struct Iter<L: Lexicon> {
set: Set<L>,
cur: usize,
}
impl<L: Lexicon> Iter<L> {
pub fn new(set: Set<L>) -> Self {
Self { set, cur: START }
}
}
impl<L: Lexicon> Iterator for Iter<L> {
type Item = L;
fn next(&mut self) -> Option<Self::Item> {
let mut next = match self.cur {
START => L::first(),
cur => L::from_id_unchecked(cur).next()?,
};
self.cur = next.id();
while !self.set.contains(next) {
next = next.next()?;
self.cur = next.id();
}
Some(next)
}
}
#[macro_export]
macro_rules! token_set {
() => {
$crate::lex::Set::new()
};
($L:ty) => {
$crate::lex::Set::<$L>::new()
};
($L:ty { $($ty:ident)|* }) => { {
use $crate::lex::Lexicon;
let b = $( <$L>::$ty.to_bit() )|*;
$crate::lex::Set::from_bits(b)
} }
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test::TestTokenType as T;
#[test]
fn new() {
let set = Set::<T>::new();
assert!(set.is_empty());
}
#[test]
fn insert() {
let mut set = Set::<T>::new();
set.insert(T::A);
assert!(set.contains(T::A));
assert!(!set.is_empty());
assert_eq!(set, token_set!(T { A }));
}
#[test]
fn remove() {
let mut set = token_set!(T { A | B | C });
set.remove(T::B);
assert!(!set.contains(T::B));
assert_eq!(set, token_set!(T { A | C }));
}
#[test]
fn iter_empty() {
let set = token_set!(T);
let mut iter = set.into_iter();
assert_eq!(iter.next(), None);
}
#[test]
fn iter_single() {
let set = token_set!(T { A });
let mut iter = set.into_iter();
assert_eq!(iter.next(), Some(T::A));
assert_eq!(iter.next(), None);
}
#[test]
fn iter_continous() {
let set = token_set!(T { A | B | C });
let mut iter = set.into_iter();
assert_eq!(iter.next(), Some(T::A));
assert_eq!(iter.next(), Some(T::B));
assert_eq!(iter.next(), Some(T::C));
assert_eq!(iter.next(), None);
}
#[test]
fn iter_skip() {
let set = token_set!(T { A | C });
let mut iter = set.into_iter();
assert_eq!(iter.next(), Some(T::A));
assert_eq!(iter.next(), Some(T::C));
assert_eq!(iter.next(), None);
}
#[test]
fn iter_skip_many() {
let set = token_set!(T { A | C | D | G });
let mut iter = set.into_iter();
assert_eq!(iter.next(), Some(T::A));
assert_eq!(iter.next(), Some(T::C));
assert_eq!(iter.next(), Some(T::D));
assert_eq!(iter.next(), Some(T::G));
assert_eq!(iter.next(), None);
}
}