#![cfg_attr(feature = "nightly", deny(missing_docs))]
#![cfg_attr(feature = "nightly", feature(external_doc))]
#![cfg_attr(feature = "nightly", doc(include = "../README.md"))]
#![cfg_attr(test, deny(warnings))]
extern crate memory_pager;
mod change;
mod iter;
pub use change::Change;
pub use iter::Iter;
use memory_pager::Pager;
#[derive(Debug)]
pub struct Bitfield {
pub pages: Pager,
length: usize,
page_length: usize,
}
impl Default for Bitfield {
#[inline]
fn default() -> Self {
let page_size = 1024;
Bitfield::new(page_size)
}
}
impl Bitfield {
pub fn new(page_size: usize) -> Self {
assert!(is_power_of_two(page_size));
Bitfield {
pages: Pager::new(page_size),
page_length: 0,
length: 0,
}
}
#[inline]
pub fn set(&mut self, index: usize, value: bool) -> Change {
let masked_index = index & 7;
let j = (index - masked_index) / 8;
let b = self.get_byte(j);
if value {
self.set_byte(j, b | (128 >> masked_index))
} else {
self.set_byte(j, b & (255 ^ (128 >> masked_index)))
}
}
#[inline]
pub fn get(&mut self, index: usize) -> bool {
let masked_index = index & 7;
let j = (index - masked_index) / 8;
let num = self.get_byte(j) & (128 >> masked_index);
match num {
0 => false,
_ => true,
}
}
#[inline]
pub fn get_byte(&self, index: usize) -> u8 {
let masked_index = self.page_mask(index);
let page_num = index / self.page_size();
match self.pages.get(page_num) {
Some(page) => page[masked_index],
None => 0,
}
}
#[inline]
pub fn set_byte(&mut self, index: usize, byte: u8) -> Change {
let masked_index = self.page_mask(index);
let page_num = (index - masked_index) / self.page_size();
let page = self.pages.get_mut_or_alloc(page_num);
if index >= self.length {
self.length = index + 1;
}
if page[masked_index] == byte {
return Change::Unchanged;
}
page[masked_index] = byte;
if index >= self.length {
self.length = index + 1;
}
Change::Changed
}
#[inline]
pub fn page_size(&self) -> usize {
self.pages.page_size()
}
#[inline]
pub fn len(&self) -> usize {
self.length
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn iter(&mut self) -> Iter {
Iter {
inner: self,
cursor: 0,
}
}
#[inline]
fn page_mask(&self, index: usize) -> usize {
index & self.page_size() - 1
}
}
#[inline]
fn is_power_of_two(x: usize) -> bool {
x.count_ones() == 1
}