an OK linked list (chapter 2)
This commit is contained in:
parent
5dbb93455c
commit
6fa0997b0f
@ -1 +1,2 @@
|
|||||||
pub mod bad;
|
pub mod bad;
|
||||||
|
pub mod ok;
|
||||||
|
|||||||
202
src/ok.rs
Normal file
202
src/ok.rs
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
pub struct List <T> {
|
||||||
|
head: Link<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
type Link <T> = Option<Box<Node<T>>>;
|
||||||
|
|
||||||
|
struct Node <T> {
|
||||||
|
val: T,
|
||||||
|
next: Link<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl <T> List<T> {
|
||||||
|
pub fn new () -> Self {
|
||||||
|
List { head: None }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push (&mut self, val: T) {
|
||||||
|
let new_node = Box::new(Node { val, 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.val
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn peek (&self) -> Option<&T> {
|
||||||
|
self.head.as_ref().map(|node| &node.val)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn peek_mut (&mut self) -> Option<&mut T> {
|
||||||
|
self.head.as_mut().map(|node| &mut node.val)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_iter (self) -> IntoIter<T> {
|
||||||
|
IntoIter(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter (&self) -> Iter<T> {
|
||||||
|
Iter { next: self.head.as_deref() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter_mut (&mut self) -> IterMut<T> {
|
||||||
|
IterMut { next: self.head.as_deref_mut() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <T> Drop for List<T> {
|
||||||
|
fn drop (&mut self) {
|
||||||
|
let mut cur_link = self.head.take();
|
||||||
|
while let Some(mut boxed_node) = cur_link {
|
||||||
|
cur_link = boxed_node.next.take();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub struct IntoIter <T> (List<T>);
|
||||||
|
|
||||||
|
pub struct Iter <'a, T> {
|
||||||
|
next: Option<&'a Node<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IterMut <'a, T> {
|
||||||
|
next: Option<&'a mut Node<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <T> Iterator for IntoIter<T> {
|
||||||
|
type Item = T;
|
||||||
|
fn next (&mut self) -> Option<Self::Item> {
|
||||||
|
self.0.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <'a, T> Iterator for Iter <'a, T> {
|
||||||
|
type Item = &'a T;
|
||||||
|
|
||||||
|
fn next (&mut self) -> Option<Self::Item> {
|
||||||
|
self.next.map(|node| {
|
||||||
|
self.next = node.next.as_deref();
|
||||||
|
&node.val
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl <'a, T> Iterator for IterMut <'a, T> {
|
||||||
|
type Item = &'a mut T;
|
||||||
|
|
||||||
|
fn next (&mut self) -> Option<Self::Item> {
|
||||||
|
self.next.take().map(|node| {
|
||||||
|
self.next = node.next.as_deref_mut();
|
||||||
|
&mut node.val
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[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();
|
||||||
|
|
||||||
|
// Check empty list behaves right
|
||||||
|
assert_eq!(list.peek(), None);
|
||||||
|
|
||||||
|
// Populate list
|
||||||
|
list.push(2);
|
||||||
|
list.push(3);
|
||||||
|
|
||||||
|
// Check normal peek
|
||||||
|
assert_eq!(list.peek(), Some(&3));
|
||||||
|
assert_eq!(list.pop(), Some(3));
|
||||||
|
assert_eq!(list.peek(), Some(&2));
|
||||||
|
assert_eq!(list.pop(), Some(2));
|
||||||
|
|
||||||
|
// Check exhaustion
|
||||||
|
assert_eq!(list.peek(), None);
|
||||||
|
assert_eq!(list.pop(), None);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn peek_mut () {
|
||||||
|
let mut list = List::new();
|
||||||
|
|
||||||
|
// Check empty list behaves right
|
||||||
|
assert_eq!(list.peek(), None);
|
||||||
|
|
||||||
|
// Populate list
|
||||||
|
list.push(3);
|
||||||
|
|
||||||
|
assert_eq!(list.peek(), Some(&3));
|
||||||
|
*list.peek_mut().unwrap() = 5;
|
||||||
|
assert_eq!(list.pop(), Some(5));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn into_iter () {
|
||||||
|
let mut list = List::new();
|
||||||
|
list.push(1); list.push(2); list.push(3);
|
||||||
|
|
||||||
|
let mut iter = list.into_iter();
|
||||||
|
assert_eq!(iter.next(), Some(3));
|
||||||
|
assert_eq!(iter.next(), Some(2));
|
||||||
|
assert_eq!(iter.next(), Some(1));
|
||||||
|
assert_eq!(iter.next(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn iter_mut() {
|
||||||
|
let mut list = List::new();
|
||||||
|
list.push(1); list.push(2); list.push(3);
|
||||||
|
|
||||||
|
let mut iter = list.iter_mut();
|
||||||
|
assert_eq!(iter.next(), Some(&mut 3));
|
||||||
|
assert_eq!(iter.next(), Some(&mut 2));
|
||||||
|
assert_eq!(iter.next(), Some(&mut 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user