rust_examples 0.1.11

rust 的学习中的一些例子
Documentation
use std::rc::Rc;

struct Node<T> {
    element: T,
    next: Link<T>,
}
type Link<T> = Option<Rc<Node<T>>>;
pub struct List<T> {
    head: Link<T>,
}
impl<T> List<T> {
    pub fn new() -> Self {
        List { head: None }
    }
    pub fn prepend(&self, element: T) -> List<T> {
        List {
            head: Some(Rc::new(Node {
                element,
                next: self.head.clone(),
            })),
        }
    }
    pub fn tail(&self) -> Self {
        List {
            head: self.head.as_ref().and_then(|node| {
                // next本身就是Option,所以外部不能用map()
                node.next.clone()
            }),
        }
    }
    pub fn head(&self) -> Option<&T> {
        self.head.as_ref().map(|node| &node.element)
    }
    pub fn iter(&mut self) -> Iter<T> {
        Iter {
            next: self.head.as_deref(),
        }
    }
}
impl<T> Drop for List<T> {
    fn drop(&mut self) {
        let mut head = self.head.take();
        while let Some(node) = head {
            // rc对应的计数不为一,说明当前node有其他人共享,所以不因为销毁,
            // 为1时,说明这里是唯一的使用者,所以需要销毁node。
            if let Ok(mut node) = Rc::try_unwrap(node) {
                head = node.next.take();
            } else {
                break;
            }
        }
    }
}
pub struct Iter<'a, T> {
    next: Option<&'a Node<T>>,
}
impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        self.next.map(|node| {
            self.next = node.next.as_deref();
            &node.element
        })
    }
}
#[cfg(test)]
mod test {
    use super::List;
    #[test]
    pub fn basics() {
        let list = List::new();
        assert_eq!(list.head(), None);
        let list = list.prepend(1).prepend(2).prepend(3);
        assert_eq!(list.head(), Some(&3));
        let list = list.tail();
        assert_eq!(list.head(), Some(&2));
        let list = list.tail();
        assert_eq!(list.head(), Some(&1));
        let list = list.tail();
        assert_eq!(list.head(), None);
        let list = list.tail();
        assert_eq!(list.head(), None);
    }
    #[test]
    pub fn iter() {
        let list = List::new();
        let mut list = list.prepend(1).prepend(2).prepend(3);
        let mut iter = list.iter();
        assert_eq!(iter.next(), Some(&3));
        assert_eq!(iter.next(), Some(&2));
        assert_eq!(iter.next(), Some(&1));
        assert_eq!(iter.next(), None);
    }
}