use super::MAX_FILE_SIZE;
use memmap::{Mmap, Protection};
use std::io::Error as IoError;
use std::io::Write;
use std::ops::{Deref, DerefMut, Index, IndexMut};
pub const MAX_IN_MEMORY_SIZE: usize = 50 * 1024 * 1024;
enum Data {
Vector(Vec<u8>),
Mmap(Mmap),
}
pub struct Sequencer {
data: Data,
}
#[cfg_attr(feature = "cargo-clippy", allow(len_without_is_empty))]
impl Sequencer {
pub fn new_as_vector() -> Sequencer {
Sequencer { data: Data::Vector(Vec::with_capacity(MAX_IN_MEMORY_SIZE)) }
}
pub fn new_as_mmap() -> Result<Sequencer, IoError> {
Ok(Sequencer {
data: Data::Mmap(try!(Mmap::anonymous(MAX_FILE_SIZE, Protection::ReadWrite))),
})
}
pub fn len(&self) -> usize {
match self.data {
Data::Vector(ref vector) => vector.len(),
Data::Mmap(ref mmap) => mmap.len(),
}
}
#[allow(unsafe_code)]
pub fn init(&mut self, content: &[u8]) {
match self.data {
Data::Vector(ref mut vector) => vector.extend_from_slice(content),
Data::Mmap(ref mut mmap) => {
let _ = unsafe { mmap.as_mut_slice() }.write_all(&content[..]);
}
}
}
pub fn truncate(&mut self, size: usize) {
if let Data::Vector(ref mut vector) = self.data {
vector.truncate(size);
}
}
#[allow(unsafe_code)]
pub fn create_mapping(&mut self) -> Result<(), IoError> {
self.data = match self.data {
Data::Mmap(_) => return Ok(()),
Data::Vector(ref mut vector) => {
let mut mmap = try!(Mmap::anonymous(MAX_FILE_SIZE, Protection::ReadWrite));
let _ = unsafe { mmap.as_mut_slice() }.write_all(&vector[..]);
Data::Mmap(mmap)
}
};
Ok(())
}
}
#[allow(unsafe_code)]
impl Index<usize> for Sequencer {
type Output = u8;
fn index(&self, index: usize) -> &u8 {
match self.data {
Data::Vector(ref vector) => &vector[index],
Data::Mmap(ref mmap) => unsafe { &mmap.as_slice()[index] },
}
}
}
#[allow(unsafe_code)]
impl IndexMut<usize> for Sequencer {
fn index_mut(&mut self, index: usize) -> &mut u8 {
match self.data {
Data::Vector(ref mut vector) => &mut vector[index],
Data::Mmap(ref mut mmap) => unsafe { &mut mmap.as_mut_slice()[index] },
}
}
}
#[allow(unsafe_code)]
impl Deref for Sequencer {
type Target = [u8];
fn deref(&self) -> &[u8] {
match self.data {
Data::Vector(ref vector) => &*vector,
Data::Mmap(ref mmap) => unsafe { mmap.as_slice() },
}
}
}
#[allow(unsafe_code)]
impl DerefMut for Sequencer {
fn deref_mut(&mut self) -> &mut [u8] {
match self.data {
Data::Vector(ref mut vector) => &mut *vector,
Data::Mmap(ref mut mmap) => unsafe { &mut *mmap.as_mut_slice() },
}
}
}
impl Extend<u8> for Sequencer {
fn extend<I>(&mut self, iterable: I)
where
I: IntoIterator<Item = u8>,
{
if let Data::Vector(ref mut vector) = self.data {
vector.extend(iterable);
}
}
}