mod into_iter;
pub use into_iter::IntoIter;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Matches {
data: Vec<u64>,
}
impl Matches {
#[must_use]
pub fn new() -> Self {
Self::with_capacity(1)
}
#[must_use]
pub fn with_capacity(capacity: usize) -> Self {
let blocks = capacity.div_ceil(64);
Self { data: vec![0; blocks] }
}
#[inline]
#[must_use]
pub fn contains(&self, index: usize) -> bool {
(self.data[index >> 6] & mask(index)) != 0
}
#[inline]
pub fn add(&mut self, index: usize) {
let block = self.resolve(index);
self.data[block] |= mask(index);
}
#[inline]
pub fn clear(&mut self) {
self.data.fill(0);
}
pub fn union(&mut self, other: &Self) {
for (a, b) in self.data.iter_mut().zip(&other.data) {
*a |= *b;
}
}
pub fn intersect(&mut self, other: &Self) {
for (a, b) in self.data.iter_mut().zip(&other.data) {
*a &= *b;
}
}
#[inline]
#[must_use]
pub fn has_any(&self, other: &Self) -> bool {
let mut iter = self.data.iter().zip(&other.data);
iter.any(|(a, b)| (*a & *b) != 0)
}
#[inline]
#[must_use]
pub fn has_all(&self, other: &Self) -> bool {
let mut iter = self.data.iter().zip(&other.data);
iter.all(|(a, b)| (*a & *b) == *b)
}
fn resolve(&mut self, index: usize) -> usize {
let block = index >> 6;
if block >= self.data.len() {
let blocks = block + 1;
self.data.resize(blocks, 0);
}
block
}
}
#[allow(clippy::must_use_candidate)]
impl Matches {
#[inline]
pub fn len(&self) -> usize {
let iter = self.data.iter();
iter.map(|block| block.count_ones() as usize).sum()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.data.iter().all(|&block| block == 0)
}
}
impl FromIterator<usize> for Matches {
#[inline]
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = usize>,
{
let mut matches = Matches::new();
for index in iter {
matches.add(index);
}
matches
}
}
impl Default for Matches {
fn default() -> Self {
Self::new()
}
}
#[inline]
const fn mask(index: usize) -> u64 {
1 << (index & 63)
}