viffy 0.1.5

SoA + SIMD automata generator
Documentation
use std::{cell::{Ref, RefCell}, rc::Rc};

pub struct DenseLinkedListPool<T: Sized + DenseLinkedListNodeTrait> {
    list: Vec<T>,
    freelist: Vec<usize>,
}
impl<T: Sized + DenseLinkedListNodeTrait> DenseLinkedListPool<T> {
    /// Initializes the list with 1 single scratch used for invalid accesses
    pub fn new(scratch: T) -> Self {
        Self{
            list: vec![scratch],
            freelist: Vec::new(),
        }
    }
    /// Creates a new node, returns the id of said node
    fn create_node(&mut self, data: T) -> usize {
        if let Some(id) = self.freelist.pop() {
            id
        } else {
            self.list.push(data);
            self.list.len() - 1
        }
    }
    fn create_in_between(&mut self, data: T, prev: usize, next: usize) -> usize {
        let node = self.create_node(data);
        if prev != 0 && next != 0 {
            assert_eq!(self.list[prev].get_next_index(), next);
            assert_eq!(self.list[next].get_prev_index(), prev);
        }
        if prev != 0 {
            self.link_bidir_node(prev, node);
        }
        if next != 0 {
            self.link_bidir_node(node, next);
        }
        node
    }
    fn get(&self, id: usize) -> &T {
        &self.list[id]
    }
    fn get_mut(&mut self, id: usize) -> &mut T {
        &mut self.list[id]
    }
    #[inline]
    fn remove_node(&mut self, id: usize) {
        self.freelist.push(id);
    }
    #[inline]
    fn unlink_prev_node(&mut self, at: usize) {
        self.list[at].set_next_index(0);
    }
    #[inline]
    fn unlink_next_node(&mut self, at: usize) {
        self.list[at].set_next_index(0);
    }
    #[inline]
    fn link_bidir_node(&mut self, prev: usize, next: usize) {
        self.list[next].set_prev_index(prev);
        self.list[prev].set_next_index(next);
    }
    /// Links a node with itself
    #[inline]
    fn link_circular(&mut self, at: usize) {
        self.list[at].set_prev_index(at);
        self.list[at].set_next_index(at);
    }
}

pub trait DenseLinkedListNodeTrait {
    fn get_next_index(&self) -> usize;
    fn set_next_index(&mut self, data: usize);
    fn get_prev_index(&self) -> usize;
    fn set_prev_index(&mut self, data: usize);
}

/// Root always keeps a circular prev reference to the last element, or itself
pub struct DenseLinkedList<T: Sized + DenseLinkedListNodeTrait> {
    pool: *mut DenseLinkedListPool<T>,
    root: usize,
}
impl<T: Sized + DenseLinkedListNodeTrait> DenseLinkedList<T> {
    pub fn new(pool: *mut DenseLinkedListPool<T>, data: T) -> Self {
        let root = pool.create_node(data);
        pool.link_circular(root);
        Self{
            pool,
            root
        }
    }
    /// SAFETY: Must be created by the same pool
    pub fn append(&mut self, other: Self) {
        let mut pool = self.pool.borrow_mut();
        let prev = pool.get(self.root).get_prev_index(); //last element of our list
        assert_ne!(prev, 0);
        pool.link_bidir_node(prev, other.root); //first element of their list, link them together
    }
    /// Insert at either the front or the end
    pub fn insert_end<const AT_FRONT: bool>(&mut self, data: T) {
        let mut pool = self.pool.borrow_mut();
        let prev = pool.get(self.root).get_prev_index();
        assert_ne!(prev, 0);
        let node = pool.create_in_between(data, prev, self.root);
        if AT_FRONT {
            self.root = node;
        }
    }
    #[inline]
    pub fn back(&self) -> &T {
        self.pool.borrow().get(self.root)
    }
    #[inline]
    pub fn back_mut(&mut self) -> &mut T {
        self.pool.borrow_mut().get_mut(self.root)
    }
    pub fn iter(&self) -> DenseLinkedListIterator<T> {
        DenseLinkedListIterator{
            list: &self,
            pool: self.pool.as_ptr(),
            index: self.root
        }
    }
}

pub struct DenseLinkedListIterator<'a, T: Sized + DenseLinkedListNodeTrait> {
    list: &'a DenseLinkedList<T>,
    pool: *mut DenseLinkedListPool<T>,
    index: usize,
}
impl<'a, T: Sized + DenseLinkedListNodeTrait> Iterator for DenseLinkedListIterator<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<Self::Item> {
        if self.index != 0 {
            let node = unsafe { self.pool.as_ref().unwrap().get(self.index) };
            self.index = node.get_next_index();
            if self.index == self.list.root {
                None
            } else {
                Some(node)
            }
        } else {
            None
        }
    }
}