sharc 0.1.2

Simple, high-speed archiver using the density compression library
Documentation
use crate::reader::Reader::{Buffer, MemoryMap};
use memmap2::Mmap;
use std::fs::File;
use std::io::{Read, Result};
use std::ops::{Index, Range};

const MEMORY_MAP_THRESHOLD: usize = 16 * 1024;

pub enum Reader {
    MemoryMap(Mmap, usize),
    Buffer(Vec<u8>, usize),
}

impl Reader {
    pub fn new(mut file: File) -> Result<Self> {
        let metadata = file.metadata()?;
        let file_size = usize::try_from(metadata.len()).unwrap();
        if file_size < MEMORY_MAP_THRESHOLD {
            let mut buffer = Vec::with_capacity(file_size);
            file.read_to_end(&mut buffer)?;
            Ok(Buffer(buffer, 0))
        } else {
            Ok(MemoryMap(unsafe { Mmap::map(&file)? }, 0))
        }
    }

    pub fn len(&self) -> usize {
        match self {
            MemoryMap(memory_map, _) => { memory_map.len() }
            Buffer(buffer, _) => { buffer.len() }
        }
    }

    pub fn bytes_at(&self, offset: usize, size: usize) -> &[u8] {
        match self {
            MemoryMap(memory_map, _) => { &memory_map[offset..offset + size] }
            Buffer(buffer, _) => { &buffer[offset..offset + size] }
        }
    }

    pub fn read_bytes(&mut self, size: usize) -> &[u8] {
        match self {
            MemoryMap(memory_map, cursor) => {
                let out = &memory_map[*cursor..*cursor + size];
                *cursor += size;
                out
            }
            Buffer(buffer, cursor) => {
                let out = &buffer[*cursor..*cursor + size];
                *cursor += size;
                out
            }
        }
    }

    pub fn get_cursor(&self) -> usize {
        match self {
            MemoryMap(_, cursor) => { *cursor }
            Buffer(_, cursor) => { *cursor }
        }
    }
}

impl Index<Range<usize>> for Reader {
    type Output = [u8];

    fn index(&self, range: Range<usize>) -> &Self::Output {
        match self {
            MemoryMap(memory_map, _) => { &memory_map[range] }
            Buffer(buffer, _) => { &buffer[range] }
        }
    }
}