chainlink 0.1.0

An arena-backed doubly linked list in 100% safe Rust.
Documentation
use crate::LinkedList;
use thunderdome::Index;

#[derive(Clone, Copy, Debug)]
pub struct IterLinks<'a, T> {
    list: &'a LinkedList<T>,
    fwd_pos: Option<Index>,
    rev_pos: Option<Index>,
}

impl<'a, T> IterLinks<'a, T> {
    pub(crate) fn new(list: &'a LinkedList<T>) -> Self {
        Self {
            list,
            fwd_pos: list.head,
            rev_pos: list.tail,
        }
    }
}

impl<'a, T> Iterator for IterLinks<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<Self::Item> {
        let node = self.list.nodes.get(self.fwd_pos?).unwrap();

        // The forward and reverse iterators are not allowed to cross as
        // specified in the std::iter::DoubleEndedIterator docs. So if
        // they do cross here, we stop the reverse iterator from advancing
        // by setting it to None.
        if node.next == self.rev_pos {
            self.rev_pos = None;
        }
        self.fwd_pos = node.next;

        Some(&node.data)
    }
}

impl<'a, T> DoubleEndedIterator for IterLinks<'a, T> {
    fn next_back(&mut self) -> Option<<Self as Iterator>::Item> {
        let node = self.list.nodes.get(self.rev_pos?).unwrap();

        // The forward and reverse iterators are not allowed to cross as
        // specified in the std::iter::DoubleEndedIterator docs. So if
        // they do cross here, we stop the forward iterator from advancing
        // by setting it to None.
        if node.prev == self.fwd_pos {
            self.fwd_pos = None;
        }
        self.rev_pos = node.prev;

        Some(&node.data)
    }
}

#[derive(Debug)]
pub struct IterLinksMut<'a, T> {
    list: &'a mut LinkedList<T>,
    fwd_pos: Option<Index>,
    rev_pos: Option<Index>,
}