1. use std::mem;
    2. struct Node{
    3. elem : i32,
    4. next : Link,
    5. }
    6. enum Link{
    7. Empty,
    8. More(Box<Node>),
    9. }
    10. pub struct List{
    11. head: Link,
    12. }
    13. impl List{
    14. pub fn new() -> List{
    15. List { head: Link::Empty }
    16. }
    17. pub fn push(&mut self,val : i32){
    18. let node = Node{
    19. elem: val,
    20. next: mem::replace(&mut self.head,Link::Empty),
    21. };
    22. self.head = Link::More(Box::new(node));
    23. }
    24. pub fn pop(&mut self) -> Option<i32>{
    25. match mem::replace(&mut self.head,Link::Empty){
    26. Link::Empty => None,
    27. Link::More(ref mut node) => {
    28. mem::swap(&mut self.head,&mut node.next);
    29. Some(node.elem)
    30. }
    31. }
    32. }
    33. }
    34. impl Drop for List {
    35. fn drop(&mut self) {
    36. let mut cur_link = mem::replace(&mut self.head, Link::Empty);
    37. // `while let` == "do this thing until this pattern doesn't match"
    38. while let Link::More(mut boxed_node) = cur_link {
    39. cur_link = mem::replace(&mut boxed_node.next, Link::Empty);
    40. // boxed_node goes out of scope and gets dropped here;
    41. // but its Node's `next` field has been set to Link::Empty
    42. // so no unbounded recursion occurs.
    43. }
    44. }
    45. }
    46. pub mod test {
    47. use super::List;
    48. #[test]
    49. fn basic(){
    50. base();
    51. }
    52. pub fn base() {
    53. let mut list = List::new();
    54. // Check empty list behaves right
    55. assert_eq!(list.pop(), None);
    56. // Populate list
    57. list.push(1);
    58. list.push(2);
    59. list.push(3);
    60. // Check normal removal
    61. assert_eq!(list.pop(), Some(3));
    62. assert_eq!(list.pop(), Some(2));
    63. // Push some more just to make sure nothing's corrupted
    64. list.push(4);
    65. list.push(5);
    66. // Check normal removal
    67. assert_eq!(list.pop(), Some(5));
    68. assert_eq!(list.pop(), Some(4));
    69. // Check exhaustion
    70. assert_eq!(list.pop(), Some(1));
    71. assert_eq!(list.pop(), None);
    72. }
    73. }
    1. mod first;
    2. fn main(){
    3. first::test::base();
    4. second::test::base();
    5. }