use std::{ u16 };
use std::slice::BinarySearchResult::{ Found, NotFound };
use iter::RoaringIterator;
use container::Container;
mod util;
mod iter;
mod store;
mod container;
pub struct RoaringBitmap {
containers: Vec<Container>,
}
impl RoaringBitmap {
pub fn new() -> Self {
RoaringBitmap { containers: Vec::new() }
}
pub fn insert(&mut self, value: u32) -> bool {
let (key, index) = calc_loc(value);
let container = match self.containers.as_slice().binary_search(|container| key.cmp(&container.key())) {
Found(loc) => &mut self.containers[loc],
NotFound(loc) => {
self.containers.insert(loc, Container::new(key));
&mut self.containers[loc]
},
};
container.insert(index)
}
pub fn remove(&mut self, value: u32) -> bool {
let (key, index) = calc_loc(value);
match self.containers.as_slice().binary_search(|container| key.cmp(&container.key())) {
Found(loc) => {
if self.containers[loc].remove(index) {
if self.containers[loc].len() == 0 {
self.containers.remove(loc);
}
true
} else {
false
}
}
_ => false,
}
}
pub fn contains(&self, value: u32) -> bool {
let (key, index) = calc_loc(value);
match self.containers.as_slice().binary_search(|container| key.cmp(&container.key())) {
Found(loc) => self.containers[loc].contains(index),
NotFound(_) => false,
}
}
pub fn clear(&mut self) {
self.containers.clear();
}
pub fn is_empty(&self) -> bool {
self.containers.is_empty()
}
pub fn len(&self) -> uint {
self.containers
.iter()
.map(|container| container.len() as uint)
.fold(0, |sum, len| sum + len)
}
pub fn iter<'a>(&'a self) -> RoaringIterator<'a> {
RoaringIterator::new(box self.containers.iter())
}
pub fn is_disjoint(&self, other: &Self) -> bool {
let result: bool;
let mut iter1 = self.containers.iter();
let mut iter2 = other.containers.iter();
let mut container1 = iter1.next();
let mut container2 = iter2.next();
loop {
match (container1, container2) {
(Some(c1), Some(c2)) => {
match (c1.key(), c2.key()) {
(key1, key2) if key1 == key2 => {
if !c1.is_disjoint(c2) {
result = false;
break;
}
container1 = iter1.next();
container2 = iter2.next();
},
(key1, key2) if key1 < key2 => container1 = iter1.next(),
(key1, key2) if key1 > key2 => container2 = iter2.next(),
(_, _) => panic!(),
}
},
(_, _) => {
result = true;
break;
},
}
}
result
}
pub fn is_subset(&self, other: &Self) -> bool {
let result: bool;
let mut iter1 = self.containers.iter();
let mut iter2 = other.containers.iter();
let mut container1 = iter1.next();
let mut container2 = iter2.next();
loop {
match (container1, container2) {
(Some(c1), Some(c2)) =>
match (c1.key(), c2.key()) {
(key1, key2) if key1 == key2 => {
if !c1.is_subset(c2) {
result = false;
break;
}
container1 = iter1.next();
container2 = iter2.next();
},
(key1, key2) if key1 < key2 => {
result = false;
break;
},
(key1, key2) if key1 > key2 => container2 = iter2.next(),
(_, _) => panic!(),
},
(None, _) => {
result = true;
break;
},
(_, None) => {
result = false;
break;
},
}
}
result
}
}
impl FromIterator<u32> for RoaringBitmap {
fn from_iter<I: Iterator<u32>>(iterator: I) -> RoaringBitmap {
let mut rb = RoaringBitmap::new();
rb.extend(iterator);
rb
}
}
impl Extend<u32> for RoaringBitmap {
fn extend<I: Iterator<u32>>(&mut self, mut iterator: I) {
for value in iterator {
self.insert(value);
}
}
}
#[inline]
fn calc_loc(index: u32) -> (u16, u16) { ((index >> u16::BITS) as u16, index as u16) }
#[cfg(test)]
mod test {
use std::{ u16, u32 };
use super::{ calc_loc };
#[test]
fn test_calc_location() {
assert_eq!((0, 0), calc_loc(0));
assert_eq!((0, 1), calc_loc(1));
assert_eq!((0, u16::MAX - 1), calc_loc(u16::MAX as u32 - 1));
assert_eq!((0, u16::MAX), calc_loc(u16::MAX as u32));
assert_eq!((1, 0), calc_loc(u16::MAX as u32 + 1));
assert_eq!((1, 1), calc_loc(u16::MAX as u32 + 2));
assert_eq!((u16::MAX, u16::MAX - 1), calc_loc(u32::MAX - 1));
assert_eq!((u16::MAX, u16::MAX), calc_loc(u32::MAX));
}
}