#![cfg_attr(nightly, deny(missing_docs))]
#![cfg_attr(nightly, feature(external_doc))]
#![cfg_attr(nightly, doc(include = "../README.md"))]
#![cfg_attr(test, deny(warnings))]
mod change;
mod iter;
pub use crate::change::Change;
pub use crate::iter::Iter;
use memory_pager::Pager;
use std::fs::File;
use std::io;
#[derive(Debug)]
pub struct Bitfield {
pub pages: Pager,
byte_length: usize,
page_length: usize,
}
impl Bitfield {
pub fn new(page_size: usize) -> Self {
assert!(page_size.is_power_of_two());
Bitfield {
pages: Pager::new(page_size),
page_length: 0,
byte_length: 0,
}
}
pub fn from_file(
file: &mut File,
page_size: usize,
offset: Option<usize>,
) -> io::Result<Self> {
let pages = Pager::from_file(file, page_size, offset)?;
let page_length = pages.len();
let byte_length = page_length * page_size;
Ok(Self {
pages,
page_length,
byte_length,
})
}
#[inline]
pub fn set(&mut self, index: usize, value: bool) -> Change {
let index_mask = index & 7;
let byte_index = (index - index_mask) / 8;
let byte = self.get_byte(byte_index);
if value {
let byte = byte | (128 >> index_mask);
self.set_byte(byte_index, byte)
} else {
let byte = byte & (255 ^ (128 >> index_mask));
self.set_byte(byte_index, byte)
}
}
#[inline]
pub fn get(&mut self, index: usize) -> bool {
let byte_offset = index & 7;
let j = (index - byte_offset) / 8;
let num = self.get_byte(j) & (128 >> byte_offset);
match num {
0 => false,
_ => true,
}
}
#[inline]
pub fn get_byte(&self, index: usize) -> u8 {
let byte_offset = self.page_mask(index);
let page_num = index / self.page_size();
match self.pages.get(page_num) {
Some(page) => page[byte_offset],
None => 0,
}
}
#[inline]
pub fn set_byte(&mut self, index: usize, byte: u8) -> Change {
let byte_offset = self.page_mask(index);
let page_num = index / self.page_size();
let page = self.pages.get_mut_or_alloc(page_num);
if index >= self.byte_length {
self.byte_length = index + 1;
}
if page[byte_offset] == byte {
Change::Unchanged
} else {
page[byte_offset] = byte;
Change::Changed
}
}
#[inline]
pub fn page_size(&self) -> usize {
self.pages.page_size()
}
#[inline]
pub fn len(&self) -> usize {
self.byte_length * 8
}
#[inline]
pub fn byte_len(&self) -> usize {
self.byte_length
}
#[inline]
pub fn page_len(&self) -> usize {
self.pages.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.pages.is_empty()
}
#[inline]
pub fn iter(&mut self) -> Iter {
Iter::new(self)
}
#[inline]
fn page_mask(&self, index: usize) -> usize {
index & (self.page_size() - 1)
}
pub fn to_bytes(&self) -> std::io::Result<Vec<u8>> {
use std::io::{Cursor, Write};
let mut all =
Cursor::new(Vec::with_capacity(self.page_len() * self.page_size()));
for index in 0..self.page_len() {
let next = self.pages.get(index);
if let Some(page) = next {
let all_offset = index * self.page_size();
all.set_position(all_offset as u64);
all.write_all(&page)?;
}
}
Ok(all.into_inner())
}
}
impl Default for Bitfield {
#[inline]
fn default() -> Self {
let page_size = 1024;
Bitfield::new(page_size)
}
}