alixt 0.1.0

A doubly-linked list with advansed bookmarking capabilities
Documentation
#![allow(unused)]
mod node;
use node::*;

#[derive(Default)]
pub struct AList<T> {
    head: Option<StrongNode<T>>,
    tail: Option<WeakNode<T>>,
    len: usize,
}

impl<T> AList<T> {
    pub fn new() -> Self {
        AList { head: None, tail: None, len: 0 }
    }
    pub fn from(data: T) -> Self {
        let node = Node::new(data);
        AList {
            tail: Some(Rc::downgrade(&node)),
            head: Some(node),
            len: 1,
        }
    }
    pub fn len(&self) -> usize {
        self.len
    }
    pub fn is_empty(&self) -> bool {
        self.len == 0
    }
    pub fn map_head<C: FnOnce(&T) -> R, R>(&self, closure: C) -> Option<R> {
        self.head.as_ref().map(|rc| {
            closure(rc.borrow().data())
        })
    }
    pub fn push(&mut self, data: T) {
        let mut new_head = Node::new_head(data, self.head.clone());
        if let Some(node) = self.head.as_mut() {
            node.borrow_mut().set_prev(Some(Rc::clone(&new_head)));
        } else {
            self.tail = Some(Rc::downgrade(&new_head));
        }
        self.head = Some(new_head);
        self.len += 1;
    }
    pub fn pop(&mut self) -> Option<T> {
        let mut node = Rc::try_unwrap(self.head.take()?)
            .map(|wrapper| { wrapper.into_inner() })
            .unwrap_or_else(|_| {
                panic!("head should have no other owners. If you see this, it's a bug.")
            });
        self.head = node
            .take_next()
            .inspect(|new_head| {
                new_head.borrow_mut().clear_prev();
            });
        if self.head.is_none() {
            self.tail = None
        }
        self.len -= 1;
        Some(node.into_data())
    }
    pub fn push_back(&mut self, data: T) {
        match self.tail.as_mut() {
            Some(tail) => {
                let old_tail = tail.upgrade();
                let node = Node::new_tail(data, old_tail.clone());
                self.tail = Some(Rc::downgrade(&node));
                old_tail.unwrap().borrow_mut().set_next(Some(node.clone()));
            },
            None if self.head.is_none() => {
                let node = Node::new(data);
                self.tail = Some(Rc::downgrade(&node));
                self.head = Some(node);
            },
            None => { panic!("If tail is None, head should also be None. If you reached this, it's a bug.")},
        }
        self.len += 1;
    }
    pub fn pop_back(&mut self) -> Option<T> {
        self.tail.as_ref()?;
        let mut tail = self
            .tail
            .take()
            .and_then(|weak| weak.upgrade())
            .unwrap();
        let new_tail = tail.borrow_mut().take_prev();
        if new_tail.is_none() { self.head.take(); }
        self.tail = new_tail.as_ref().map(|rc| {
            rc.borrow_mut().clear_next();
            Rc::downgrade(rc)
        });
        self.len -= 1;
        Some(Rc::try_unwrap(tail)
            .unwrap_or_else(|_| {
                panic!("Nothing should own this node, if you see this it's a bug")
            })
            .into_inner()
            .into_data())
    }
}