termit 0.7.0

Terminal UI over crossterm
Documentation
use memmapix::MmapMut;
use std::{
    marker::PhantomData,
    ops::{Deref, DerefMut},
    ptr,
};

/// memmap backed vec-like buffer
///
/// Attention: drop() is not called on de-allocated items! (truncate, clear, replace)
///
/// mmap vec does not allocate the requested memory on creation, only when written to.
#[derive(Debug)]
pub struct MmapVec<T> {
    map: MmapMut,
    len: usize,
    tsize: usize,
    phantom: PhantomData<T>,
}
impl<T> Default for MmapVec<T> {
    fn default() -> Self {
        Self::new(0)
    }
}

impl MmapVec<u8> {
    pub fn zeroed(len: usize) -> Self {
        let mut me = Self::new(len);
        me.len = len;
        me
    }
}

impl<T> MmapVec<T> {
    pub fn new(capacity: usize) -> Self {
        let tsize = std::mem::size_of::<T>();
        let tlen = capacity.checked_mul(tsize).expect("buffer tlen");
        let map = MmapMut::map_anon(tlen).expect("anonymous map buffer");
        //map.advise(rustix::mm::Advice::Random).expect("advise random access");
        Self {
            map,
            len: 0,
            tsize,
            phantom: PhantomData,
        }
    }
    pub fn clear(&mut self) {
        // copy paste from Vec
        let elems: *mut [T] = self as &mut [T];

        // SAFETY:
        // - `elems` comes directly from `as_mut_slice` and is therefore valid.
        // - Setting `self.len` before calling `drop_in_place` means that,
        //   if an element's `Drop` impl panics, the vector's `Drop` impl will
        //   do nothing (leaking the rest of the elements) instead of dropping
        //   some twice.
        unsafe {
            self.len = 0;
            ptr::drop_in_place(elems);
        }
    }
    pub fn truncate(&mut self, len: usize) {
        // copy paste from Vec
        // This is safe because:
        //
        // * the slice passed to `drop_in_place` is valid; the `len > self.len`
        //   case avoids creating an invalid slice, and
        // * the `len` of the vector is shrunk before calling `drop_in_place`,
        //   such that no value will be dropped twice in case `drop_in_place`
        //   were to panic once (if it panics twice, the program aborts).
        unsafe {
            // Note: It's intentional that this is `>` and not `>=`.
            //       Changing it to `>=` has negative performance
            //       implications in some cases. See #78884 for more.
            if len > self.len {
                return;
            }
            let remaining_len = self.len - len;
            let s = ptr::slice_from_raw_parts_mut(self.as_mut_ptr().add(len), remaining_len);
            self.len = len;
            ptr::drop_in_place(s);
        }
    }
    pub fn resize(&mut self, len: usize, value: T)
    where
        T: Clone,
    {
        if len <= self.len {
            return self.truncate(len);
        }
        if len > self.capacity() {
            panic!("New size must fit into the allocated buffer.");
        }
        for _ in self.len + 1..len {
            self.push(value.clone());
        }
        self.push(value);
    }
    pub fn len(&self) -> usize {
        self.len
    }
    fn capacity(&self) -> usize {
        self.map.len() / self.tsize
    }
    pub fn push(&mut self, item: T) -> &mut T {
        let pos = self.len;
        self.len += 1;
        self[pos] = item;
        &mut self[pos]
    }
}

impl<T> Deref for MmapVec<T> {
    type Target = [T];

    fn deref(&self) -> &Self::Target {
        let tlen = self.len.checked_mul(self.tsize).expect("buffer len");
        let mapslice = &self.map[0..tlen];
        let (prefix, slice, suffix) = unsafe {
            // it is safe because we always align to T size
            // and we track occupied space with len
            // and no one else has access to the map
            mapslice.align_to::<T>()
        };
        debug_assert_eq!(prefix.len(), 0);
        debug_assert_eq!(suffix.len(), 0);
        slice
    }
}
impl<T> DerefMut for MmapVec<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        let tlen = self.len.checked_mul(self.tsize).expect("buffer len");
        let mapslice = &mut self.map[0..tlen];
        let (prefix, slice, suffix) = unsafe {
            // it is safe because we always align to T size
            // and we track occupied space with len
            // and no one else has access to the map
            mapslice.align_to_mut::<T>()
        };
        debug_assert_eq!(prefix.len(), 0);
        debug_assert_eq!(suffix.len(), 0);
        slice
    }
}

#[test]
fn test_vec() {
    let mut sut = MmapVec::new(1);
    sut.push(b"CDE".to_owned());
    let buf = &sut.map[..];
    assert_eq!(buf, b"CDE");
}