use roaring::RoaringBitmap;
use crate::surrogate::Surrogate;
#[derive(Debug, Clone, PartialEq)]
pub struct SurrogateBitmap(pub RoaringBitmap);
impl SurrogateBitmap {
pub fn new() -> Self {
Self(RoaringBitmap::new())
}
pub fn contains(&self, surrogate: Surrogate) -> bool {
self.0.contains(surrogate.0)
}
pub fn insert(&mut self, surrogate: Surrogate) {
self.0.insert(surrogate.0);
}
pub fn remove(&mut self, surrogate: Surrogate) {
self.0.remove(surrogate.0);
}
pub fn len(&self) -> u64 {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = Surrogate> + '_ {
self.0.iter().map(Surrogate)
}
}
impl Default for SurrogateBitmap {
fn default() -> Self {
Self::new()
}
}
impl FromIterator<Surrogate> for SurrogateBitmap {
fn from_iter<I: IntoIterator<Item = Surrogate>>(iter: I) -> Self {
let mut inner = RoaringBitmap::new();
for s in iter {
inner.insert(s.0);
}
Self(inner)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_is_empty() {
let b = SurrogateBitmap::new();
assert!(b.is_empty());
assert_eq!(b.len(), 0);
}
#[test]
fn insert_and_contains() {
let mut b = SurrogateBitmap::new();
b.insert(Surrogate(1));
b.insert(Surrogate(100));
assert!(b.contains(Surrogate(1)));
assert!(b.contains(Surrogate(100)));
assert!(!b.contains(Surrogate(2)));
assert_eq!(b.len(), 2);
}
#[test]
fn remove_is_noop_when_absent() {
let mut b = SurrogateBitmap::new();
b.remove(Surrogate(99));
assert!(b.is_empty());
}
#[test]
fn from_iter_deduplicates() {
let b = SurrogateBitmap::from_iter([Surrogate(1), Surrogate(1), Surrogate(2)]);
assert_eq!(b.len(), 2);
}
#[test]
fn iter_yields_ascending_order() {
let b = SurrogateBitmap::from_iter([Surrogate(5), Surrogate(1), Surrogate(3)]);
let v: Vec<u32> = b.iter().map(|s| s.0).collect();
assert_eq!(v, vec![1, 3, 5]);
}
#[test]
fn large_bitmap_roundtrip() {
let b = SurrogateBitmap::from_iter((1u32..=10_000).map(Surrogate));
assert_eq!(b.len(), 10_000);
assert!(b.contains(Surrogate(1)));
assert!(b.contains(Surrogate(10_000)));
assert!(!b.contains(Surrogate(10_001)));
}
}