tuple_storage 0.1.1

A type-safe and small table engine for any Tuple of Ints
Documentation

use super::*;

use std::slice::from_raw_parts;


pub struct MmapWriter<'a> {
    mmap: &'a mut MmapMut,
    offset: usize,
}
impl<'a> MmapWriter<'a> {
    pub fn new(mmap: &mut MmapMut) -> MmapWriter {
        Self::at_offset(mmap, 0)
    }
    pub fn at_offset(mmap: &mut MmapMut, offset: usize) -> MmapWriter {
        MmapWriter {
            mmap,
            offset,
        }
    }

    /// Only use with Integers
    pub fn append<T: Sized + Copy>(&mut self, data: &T) {
        let size = size_of::<T>();
        let end = self.offset + size;
        //println!("copy {}..{} ({}) to mmap ({})", self.offset, end, size, self.mmap.len());

        if let Some(range) = self.mmap.get_mut(self.offset..end) {
            let ptr = data as *const T as *const u8;
            let src = unsafe { from_raw_parts(ptr, size) };

            range.copy_from_slice(&src);

            self.offset = end;
        } else {
            panic!("MmapWriter::append() not enough file space")
        }
    }

    pub fn append_slice<T: Sized + Copy>(&mut self, data: &[T]) {
        let size = size_of::<T>() * data.len();
        let end = self.offset + size;
        //println!("copy {}..{} ({}) to mmap ({})", self.offset, end, size, self.mmap.len());

        if let Some(range) = self.mmap.get_mut(self.offset..end) {
            let ptr = data as *const [T] as *const u8;
            let src = unsafe { from_raw_parts(ptr, size) };

            range.copy_from_slice(&src);

            self.offset = end;
        } else {
            panic!("MmapWriter::append() not enough file space")
        }
    }
}

pub struct MmapReader {
    mmap: Mmap,
    offset: usize,
}
impl<'a> MmapReader {
    pub fn new(file: &File) -> io::Result<MmapReader> {
        Self::at_offset(file, 0)
    }
    pub fn at_offset(file: &File, offset: usize) -> io::Result<MmapReader> {
        let mmap = unsafe { Mmap::map(file)? };
        Ok(MmapReader {
            mmap,
            offset,
        })
    }

    /// Only use with Integers
    pub fn get<'b : 'a, T: Sized + Copy>(&mut self) -> &'b T {
        let size = size_of::<T>();
        let end = self.offset + size;
        //println!("read {}..{} ({}) from mmap ({})", self.offset, end, size, self.mmap.len());

        if let Some(range) = self.mmap.get(self.offset..end) {
            let data = range.as_ptr() as *const T;

            self.offset = end;

            unsafe {
                return data.as_ref().expect("reading from mapped file, can not be null");
            }
        } else {
            panic!("MmapReader::get() not enough file space")
        }
    }

    pub fn get_slice<'b : 'a, T: Sized + Copy>(&mut self, n_elements: usize) -> &[T] {
        let size = size_of::<T>();
        let end = self.offset + size * n_elements;
        //println!("read {}..{} ({}) from mmap ({})", self.offset, end, size, self.mmap.len());

        if let Some(range) = self.mmap.get(self.offset..end) {
            let ptr = range.as_ptr() as *const T;

            self.offset = end;

            unsafe {
                return from_raw_parts(ptr, n_elements);
            }
        } else {
            panic!("MmapReader::get_slice() not enough file space")
        }
    }

    pub fn get_str_slice<'b : 'a>(&mut self, n_elements: usize) -> &str {
        let slice = self.get_slice(n_elements);
        std::str::from_utf8(slice).unwrap()
    }
}