| @@ -1,5 +1,5 @@ | |||
| use std::rc::Rc; | |||
| use std::cell::RefCell; | |||
| use std::cell::{Ref, RefMut, RefCell}; | |||
| pub struct List<T> { | |||
| head: Link<T>, | |||
| @@ -59,39 +59,86 @@ impl<T> List<T> { | |||
| Rc::try_unwrap(old_head).ok().unwrap().into_inner().elem | |||
| }) | |||
| } | |||
| } | |||
| impl<T> Drop for List<T> { | |||
| fn drop(&mut self) { | |||
| while self.pop_front().is_some() {} | |||
| pub fn peek_front(&self) -> Option<Ref<T>> { | |||
| self.head.as_ref().map(|node| { | |||
| Ref::map(node.borrow(), |node| &node.elem) | |||
| }) | |||
| } | |||
| pub fn push_back(&mut self, elem: T) { | |||
| let new_tail = Node::new(elem); | |||
| match self.tail.take() { | |||
| Some(old_tail) => { | |||
| old_tail.borrow_mut().next = Some(new_tail.clone()); | |||
| new_tail.borrow_mut().prev = Some(old_tail); | |||
| self.tail = Some(new_tail); | |||
| } | |||
| None => { | |||
| self.head = Some(new_tail.clone()); | |||
| self.tail = Some(new_tail); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| #[cfg(test)] | |||
| mod test { | |||
| use super::List; | |||
| pub fn pop_back(&mut self) -> Option<T> { | |||
| self.tail.take().map(|old_tail| { | |||
| match old_tail.borrow_mut().prev.take() { | |||
| Some(new_tail) => { | |||
| new_tail.borrow_mut().next.take(); | |||
| self.tail = Some(new_tail); | |||
| } | |||
| None => { | |||
| self.head.take(); | |||
| } | |||
| } | |||
| Rc::try_unwrap(old_tail).ok().unwrap().into_inner().elem | |||
| }) | |||
| } | |||
| #[test] | |||
| fn basics() { | |||
| let mut list = List::new(); | |||
| pub fn peek_back(&self) -> Option<Ref<T>> { | |||
| self.tail.as_ref().map(|node| { | |||
| Ref::map(node.borrow(), |node| &node.elem) | |||
| }) | |||
| } | |||
| pub fn peek_back_mut(&mut self) -> Option<RefMut<T>> { | |||
| self.tail.as_ref().map(|node| { | |||
| RefMut::map(node.borrow_mut(), |node| &mut node.elem) | |||
| }) | |||
| } | |||
| assert_eq!(list.pop_front(), None); | |||
| pub fn peek_front_mut(&mut self) -> Option<RefMut<T>> { | |||
| self.head.as_ref().map(|node| { | |||
| RefMut::map(node.borrow_mut(), |node| &mut node.elem) | |||
| }) | |||
| } | |||
| } | |||
| list.push_front(1); | |||
| list.push_front(2); | |||
| list.push_front(3); | |||
| pub struct IntoIter<T>(List<T>); | |||
| assert_eq!(list.pop_front(), Some(3)); | |||
| assert_eq!(list.pop_front(), Some(2)); | |||
| impl<T> List<T> { | |||
| pub fn into_iter(self) -> IntoIter<T> { | |||
| IntoIter(self) | |||
| } | |||
| } | |||
| list.push_front(4); | |||
| list.push_front(5); | |||
| impl<T> Iterator for IntoIter<T> { | |||
| type Item = T; | |||
| fn next(&mut self) -> Option<T> { | |||
| self.0.pop_front() | |||
| } | |||
| } | |||
| assert_eq!(list.pop_front(), Some(5)); | |||
| assert_eq!(list.pop_front(), Some(4)); | |||
| impl<T> DoubleEndedIterator for IntoIter<T> { | |||
| fn next_back(&mut self) -> Option<T> { | |||
| self.0.pop_back() | |||
| } | |||
| } | |||
| assert_eq!(list.pop_front(), Some(1)); | |||
| assert_eq!(list.pop_front(), None); | |||
| impl<T> Drop for List<T> { | |||
| fn drop(&mut self) { | |||
| while self.pop_front().is_some() {} | |||
| } | |||
| } | |||