| use std::rc::Rc; | use std::rc::Rc; | ||||
| use std::cell::RefCell; | |||||
| use std::cell::{Ref, RefMut, RefCell}; | |||||
| pub struct List<T> { | pub struct List<T> { | ||||
| head: Link<T>, | head: Link<T>, | ||||
| Rc::try_unwrap(old_head).ok().unwrap().into_inner().elem | 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() {} | |||||
| } | } | ||||
| } | } | ||||