use std::ops::Not;
use bitvec::prelude::*;
pub struct NormalSet {
pub bits: BitVec<u8, Lsb0>,
}
pub struct SmallSet {
pub bits: BitVec<u8, Lsb0>,
}
pub trait Set {
fn has(&self, r: u8) -> bool;
fn new(chars: &[u8]) -> Self;
fn size(&self) -> usize;
}
impl Set for SmallSet {
fn has(&self, r: u8) -> bool {
if (r as usize) < self.bits.len() {
self.bits[r as usize]
} else {
false
}
}
fn new(chars: &[u8]) -> Self {
let mut s = Self {
bits: bitvec![u8, Lsb0; 0; 128],
};
for i in chars {
s.bits.set(*i as usize, true);
}
s
}
fn size(&self) -> usize {
self.bits.count_ones()
}
}
impl Set for NormalSet {
fn has(&self, r: u8) -> bool {
self.bits[r as usize]
}
fn new(chars: &[u8]) -> Self {
let mut s = Self {
bits: bitvec![u8, Lsb0; 0; 256],
};
for i in chars {
s.bits.set(*i as usize, true);
}
s
}
fn size(&self) -> usize {
self.bits.count_ones()
}
}
impl NormalSet {
pub fn add(&mut self, s2: NormalSet) {
self.bits |= s2.bits;
}
pub fn complement(&self) -> NormalSet {
let mut s = Self {
bits: bitvec![u8, Lsb0; 0; 256],
};
for i in 0usize..256 {
s.bits.set(i, self.bits.get(i).unwrap().not());
}
s
}
pub fn is_small(&self) -> bool {
self.bits[128..256].count_ones() == 0
}
pub fn range(low: u8, high: u8) -> NormalSet {
let mut s = Self {
bits: bitvec![u8, Lsb0; 0; 256],
};
for i in low..=high {
s.bits.set(i as usize, true);
}
s
}
pub fn smallset(&self) -> SmallSet {
SmallSet {
bits: self.bits[0..128].to_bitvec(),
}
}
pub fn string(&self) -> String {
let mut s = String::new();
let mut inrange = false;
for b in 0..=255 {
if self.has(b) && b == 255 {
s += "\u{00ff}"; } else if self.has(b) && !inrange {
inrange = true;
if self.has(b + 1) {
s += &b.to_string();
s += "..";
}
} else if !self.has(b) && inrange {
inrange = false;
s += &b.to_string();
s += ",";
}
}
if !s.is_empty() && s.ends_with(',') {
s.pop();
}
s = "{".to_owned() + &s + "}";
s
}
pub fn sub(&self, s2: NormalSet) -> NormalSet {
let mut s = Self {
bits: bitvec![u8, Lsb0; 0; 256],
};
s.bits = !s2.bits;
s.bits &= self.bits.to_bitvec();
s
}
}