use alloc::vec::Vec; #[derive(Copy, Clone)] #[repr(C, align(8))] pub struct Mask(u32, u32); impl Mask { pub fn from_idx(idx: u32) -> Mask { Mask(idx / u32::BITS, idx % u32::BITS) } } pub struct MaskSet { masks: Vec, } impl MaskSet { pub fn new() -> Self { Self { masks: Vec::new() } } pub fn contains(&self, Mask(target, test): Mask) -> bool { for Mask(idx, truth) in &self.masks { if *idx == target && ((truth & test) == 1) { return true; } } false } pub fn insert(&mut self, Mask(target, value): Mask) { for Mask(idx, truth) in &mut self.masks { if *idx == target { *truth |= value; return; } } self.masks.push(Mask(target, value)); self.masks.sort_by_key(|m| m.0); } pub fn remove(&mut self, Mask(target, test): Mask) { for (i, Mask(idx, truth)) in self.masks.iter_mut().enumerate() { if *idx == target && ((*truth & test) == 1) { *truth ^= test; if *truth == 0 { self.masks.remove(i); } return; } } } pub fn superset(&self, other: &Self) -> bool { for mask in &other.masks { if !self.contains(*mask) { return false; } } true } #[inline] pub fn subset(&self, other: &Self) -> bool { Self::superset(other, self) } pub fn disjoint(&self, other: &Self) -> bool { let mut tests = other.masks.iter(); for truth in &self.masks { 'testing: while let Some(test) = tests.next() { if test.0 == truth.0 { if (test.1 & truth.1) != 0 { return false; } break 'testing; } } if tests.len() == 0 { break; } } true } pub fn union(&mut self, other: &Self) { for mask in &other.masks { self.insert(*mask); } } pub fn intersect(&self, other: &Self) -> Self { let mut new = Vec::new(); let mut tests = other.masks.iter(); for truth in &self.masks { 'testing: while let Some(test) = tests.next() { if test.0 == truth.0 { let new_mask = test.1 & truth.1; if new_mask == 0 { break 'testing; } new.push(Mask(test.0, new_mask)); } } if tests.len() == 0 { break; } } assert!(new.is_sorted_by_key(|m| m.0)); MaskSet { masks: new } } }