use std::fmt;
#[derive(Clone, Copy)]
pub struct ByteClasses([u8; 256]);
impl ByteClasses {
pub fn empty() -> ByteClasses {
ByteClasses([0; 256])
}
pub fn singletons() -> ByteClasses {
let mut classes = ByteClasses::empty();
for i in 0..256 {
classes.set(i as u8, i as u8);
}
classes
}
#[inline]
pub fn set(&mut self, byte: u8, class: u8) {
self.0[byte as usize] = class;
}
#[inline]
pub fn get(&self, byte: u8) -> u8 {
self.0[byte as usize]
}
#[inline]
pub fn alphabet_len(&self) -> usize {
self.0[255] as usize + 1
}
#[inline]
pub fn is_singleton(&self) -> bool {
self.alphabet_len() == 256
}
pub fn representatives(&self) -> ByteClassRepresentatives {
ByteClassRepresentatives { classes: self, byte: 0, last_class: None }
}
fn elements(&self, equiv: u8) -> ([u8; 256], usize) {
let (mut array, mut len) = ([0; 256], 0);
for b in 0..256 {
if self.get(b as u8) == equiv {
array[len] = b as u8;
len += 1;
}
}
(array, len)
}
}
impl fmt::Debug for ByteClasses {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.is_singleton() {
write!(f, "ByteClasses({{singletons}})")
} else {
write!(f, "ByteClasses(")?;
for equiv in 0..self.alphabet_len() {
let (members, len) = self.elements(equiv as u8);
write!(f, " {} => {:?}", equiv, &members[..len])?;
}
write!(f, ")")
}
}
}
#[derive(Debug)]
pub struct ByteClassRepresentatives<'a> {
classes: &'a ByteClasses,
byte: usize,
last_class: Option<u8>,
}
impl<'a> Iterator for ByteClassRepresentatives<'a> {
type Item = u8;
fn next(&mut self) -> Option<u8> {
while self.byte < 256 {
let byte = self.byte as u8;
let class = self.classes.get(byte);
self.byte += 1;
if self.last_class != Some(class) {
self.last_class = Some(class);
return Some(byte);
}
}
None
}
}
#[derive(Debug)]
pub struct ByteClassBuilder(Vec<bool>);
impl ByteClassBuilder {
pub fn new() -> ByteClassBuilder {
ByteClassBuilder(vec![false; 256])
}
pub fn set_range(&mut self, start: u8, end: u8) {
debug_assert!(start <= end);
if start > 0 {
self.0[start as usize - 1] = true;
}
self.0[end as usize] = true;
}
pub fn build(&self) -> ByteClasses {
let mut classes = ByteClasses::empty();
let mut class = 0u8;
let mut i = 0;
loop {
classes.set(i as u8, class as u8);
if i >= 255 {
break;
}
if self.0[i] {
class = class.checked_add(1).unwrap();
}
i += 1;
}
classes
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn byte_classes() {
let mut set = ByteClassBuilder::new();
set.set_range(b'a', b'z');
let classes = set.build();
assert_eq!(classes.get(0), 0);
assert_eq!(classes.get(1), 0);
assert_eq!(classes.get(2), 0);
assert_eq!(classes.get(b'a' - 1), 0);
assert_eq!(classes.get(b'a'), 1);
assert_eq!(classes.get(b'm'), 1);
assert_eq!(classes.get(b'z'), 1);
assert_eq!(classes.get(b'z' + 1), 2);
assert_eq!(classes.get(254), 2);
assert_eq!(classes.get(255), 2);
let mut set = ByteClassBuilder::new();
set.set_range(0, 2);
set.set_range(4, 6);
let classes = set.build();
assert_eq!(classes.get(0), 0);
assert_eq!(classes.get(1), 0);
assert_eq!(classes.get(2), 0);
assert_eq!(classes.get(3), 1);
assert_eq!(classes.get(4), 2);
assert_eq!(classes.get(5), 2);
assert_eq!(classes.get(6), 2);
assert_eq!(classes.get(7), 3);
assert_eq!(classes.get(255), 3);
}
#[test]
fn full_byte_classes() {
let mut set = ByteClassBuilder::new();
for i in 0..256u16 {
set.set_range(i as u8, i as u8);
}
assert_eq!(set.build().alphabet_len(), 256);
}
}