use std::io::Error as IoError;
use std::io::ErrorKind as IoErrorKind;
use std::io::Write;
use std::ops::{Deref, DerefMut, Index, IndexMut};
use memmap::{Mmap, Protection};
use super::MAX_FILE_SIZE;
pub const MAX_IN_MEMORY_SIZE: usize = 50 * 1024 * 1024;
pub struct Sequencer {
vector: Option<Vec<u8>>,
mmap: Option<Mmap>,
}
#[cfg_attr(feature="clippy", allow(len_without_is_empty))]
impl Sequencer {
pub fn new_as_vector() -> Sequencer {
Sequencer {
vector: Some(Vec::with_capacity(MAX_IN_MEMORY_SIZE)),
mmap: None,
}
}
pub fn new_as_mmap() -> Result<Sequencer, IoError> {
Ok(Sequencer {
vector: None,
mmap: Some(try!(Mmap::anonymous(MAX_FILE_SIZE, Protection::ReadWrite))),
})
}
pub fn len(&self) -> usize {
match self.vector {
Some(ref vector) => vector.len(),
None => {
match self.mmap {
Some(ref mmap) => mmap.len(),
None => 0usize,
}
}
}
}
#[allow(unsafe_code)]
pub fn init(&mut self, content: &[u8]) {
match self.vector {
Some(ref mut vector) => {
for ch in content {
vector.push(*ch);
}
}
None => {
if let Some(ref mut mmap) = self.mmap {
let _ = unsafe { mmap.as_mut_slice() }.write_all(&content[..]);
}
}
}
}
pub fn truncate(&mut self, size: usize) {
if let Some(ref mut vector) = self.vector {
vector.truncate(size);
}
}
#[allow(unsafe_code)]
pub fn create_mapping(&mut self) -> Result<(), IoError> {
if self.mmap.is_some() {
return Ok(());
}
match self.vector {
Some(ref mut vector) => {
let mut mmap = try!(Mmap::anonymous(MAX_FILE_SIZE, Protection::ReadWrite));
let _ = unsafe { mmap.as_mut_slice() }.write_all(&vector[..]);
self.mmap = Some(mmap);
}
None => {
return Err(IoError::new(IoErrorKind::WriteZero,
"Failed to create mapping from uninitialised vector."))
}
};
if self.mmap.is_some() {
self.vector = None;
}
Ok(())
}
pub fn to_vec(&self) -> Vec<u8> {
match self.vector {
Some(ref vector) => vector.clone(),
None => Vec::<u8>::new(),
}
}
}
#[allow(unsafe_code)]
impl Index<usize> for Sequencer {
type Output = u8;
fn index(&self, index: usize) -> &u8 {
match self.vector {
Some(ref vector) => &vector[index],
None => {
match self.mmap {
Some(ref mmap) => unsafe { &mmap.as_slice()[index] },
None => panic!("Uninitialised"),
}
}
}
}
}
#[allow(unsafe_code)]
impl IndexMut<usize> for Sequencer {
fn index_mut(&mut self, index: usize) -> &mut u8 {
match self.vector {
Some(ref mut vector) => &mut vector[index],
None => {
match self.mmap {
Some(ref mut mmap) => unsafe { &mut mmap.as_mut_slice()[index] },
None => panic!("Uninitialised"),
}
}
}
}
}
#[allow(unsafe_code)]
impl Deref for Sequencer {
type Target = [u8];
fn deref(&self) -> &[u8] {
match self.vector {
Some(ref vector) => &*vector,
None => {
match self.mmap {
Some(ref mmap) => unsafe { mmap.as_slice() },
None => panic!("Uninitialised"),
}
}
}
}
}
#[allow(unsafe_code)]
impl DerefMut for Sequencer {
fn deref_mut(&mut self) -> &mut [u8] {
match self.vector {
Some(ref mut vector) => &mut *vector,
None => {
match self.mmap {
Some(ref mut mmap) => unsafe { &mut *mmap.as_mut_slice() },
None => panic!("Uninitialised"),
}
}
}
}
}
impl Extend<u8> for Sequencer {
fn extend<I>(&mut self, iterable: I)
where I: IntoIterator<Item = u8>
{
if let Some(ref mut vector) = self.vector {
vector.extend(iterable);
}
}
}