Browse Source

Option;Generic;Peek;

runningwater 2 years ago
parent
commit
323b050481
3 changed files with 107 additions and 1 deletions
  1. 1 1
      src/first.rs
  2. 1 0
      src/lib.rs
  3. 105 0
      src/second.rs

+ 1 - 1
src/first.rs

@@ -43,7 +43,7 @@ impl Default for List {
 impl Drop for List {
     fn drop(&mut self) {
         let mut cur_link = mem::replace(&mut self.head, Link::Empty);
-        
+
         // `while let` == "do this thing until this pattern doesn't match"
         while let Link::More(mut boxed_node) = cur_link {
             cur_link = mem::replace(&mut boxed_node.next, Link::Empty);

+ 1 - 0
src/lib.rs

@@ -1 +1,2 @@
 pub mod first;
+pub mod second;

+ 105 - 0
src/second.rs

@@ -0,0 +1,105 @@
+/// `List` 列表
+pub struct List<T> {
+    head: Link<T>,
+}
+struct Node<T> {
+    elem: T,
+    next: Link<T>,
+}
+type Link<T> = Option<Box<Node<T>>>;
+
+impl<T> List<T> {
+    pub fn new() -> Self {
+        List { head: None }
+    }
+    pub fn push(&mut self, elem: T) {
+        let new_node = Box::new(Node {
+            elem: elem,
+            next: self.head.take(),
+        });
+
+        self.head = Some(new_node);
+    }
+    pub fn pop(&mut self) -> Option<T> {
+        self.head.take().map(|node| {
+            self.head = node.next;
+            node.elem
+        })
+    }
+    pub fn peek(&self) -> Option<&T> {
+        self.head.as_ref().map(|node| &node.elem)
+    }
+    pub fn peek_mut(&mut self) -> Option<&mut T> {
+        self.head.as_mut().map(|node| &mut node.elem)
+    }
+}
+impl<T> Default for List<T> {
+    fn default() -> Self {
+        Self { head: None }
+    }
+}
+impl<T> Drop for List<T> {
+    fn drop(&mut self) {
+        let mut cur_link = self.head.take();
+
+        // `while let` == "do this thing until this pattern doesn't match"
+        while let Some(mut boxed_node) = cur_link {
+            cur_link = boxed_node.next.take();
+            // boxed_node goes out of scope and gets dropped here;
+            // but its Node's `next` field has been set to Link::Empty
+            // so no unbounded recursion occurs.
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::List;
+
+    #[test]
+    fn basics() {
+        let mut list = List::new();
+
+        // Check empty list behaves right
+        assert_eq!(list.pop(), None);
+
+        // Populate list
+        list.push(1);
+        list.push(2);
+        list.push(3);
+
+        // Check normal removal
+        assert_eq!(list.pop(), Some(3));
+        assert_eq!(list.pop(), Some(2));
+
+        // Push some more just to make sure nothing's corrupted
+        list.push(4);
+        list.push(5);
+
+        // Check normal removal
+        assert_eq!(list.pop(), Some(5));
+        assert_eq!(list.pop(), Some(4));
+
+        // Check exhaustion
+        assert_eq!(list.pop(), Some(1));
+        assert_eq!(list.pop(), None);
+    }
+    #[test]
+    fn peek() {
+        let mut list = List::new();
+
+        assert_eq!(list.peek(), None);
+        assert_eq!(list.peek_mut(), None);
+        list.push(1);
+        list.push(2);
+        list.push(3);
+
+        assert_eq!(list.peek(), Some(3).as_ref());
+        assert_eq!(list.peek_mut(), Some(3).as_mut());
+
+        list.peek_mut().map(|node| *node = 42);
+
+        assert_eq!(list.peek(), Some(&42));
+        assert_eq!(list.pop(), Some(42));
+    }
+}