diff --git a/src/lib.rs b/src/lib.rs index 1aef305..59eb7c7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,2 @@ pub mod bad; +pub mod ok; diff --git a/src/ok.rs b/src/ok.rs new file mode 100644 index 0000000..9a20893 --- /dev/null +++ b/src/ok.rs @@ -0,0 +1,202 @@ +pub struct List { + head: Link +} + +type Link = Option>>; + +struct Node { + val: T, + next: Link +} + + +impl List { + 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 { + 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 { + IntoIter(self) + } + + pub fn iter (&self) -> Iter { + Iter { next: self.head.as_deref() } + } + + pub fn iter_mut (&mut self) -> IterMut { + IterMut { next: self.head.as_deref_mut() } + } +} + +impl Drop for List { + 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 (List); + +pub struct Iter <'a, T> { + next: Option<&'a Node>, +} + +pub struct IterMut <'a, T> { + next: Option<&'a mut Node>, +} + +impl Iterator for IntoIter { + type Item = T; + fn next (&mut self) -> Option { + self.0.pop() + } +} + +impl <'a, T> Iterator for Iter <'a, T> { + type Item = &'a T; + + fn next (&mut self) -> Option { + 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.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)); + } + + +}