|
|
@@ -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() {} |
|
|
|
} |
|
|
|
} |
|
|
|
|