Skip to content

Commit

Permalink
feat(doubly::List): Add Extend/FromIter & tests
Browse files Browse the repository at this point in the history
Included quickcheck tests and regular cargo tests for
doubly::List's FromIterator and Extend impls.
  • Loading branch information
Evan Cameron authored and hawkw committed Jan 25, 2018
1 parent e8004df commit 1dcb155
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 26 deletions.
58 changes: 52 additions & 6 deletions intruder_alarm/src/doubly/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,15 @@ pub trait Linked: Sized // + Drop
mem::replace(self.links_mut(), Links::new())
}

/// Borrow the `next` element in the list, or `None` if this is the last.
/// Borrow the `next` element in the list, or `None` if this is the
/// last.
#[inline]
fn next(&self) -> Option<&Self> {
self.links().next()
}

/// Borrow the `prev` element in the list, or `None` if this is the first.
/// Borrow the `prev` element in the list, or `None` if this is the
/// first.
#[inline]
fn prev(&self) -> Option<&Self> {
self.links().prev()
Expand All @@ -97,27 +99,39 @@ pub trait Linked: Sized // + Drop

/// Borrow the `next` linked element, or `None` if this is the last.
#[inline]
fn peek_next<T>(&self) -> Option<&T> where Self: AsRef<T> {
fn peek_next<T>(&self) -> Option<&T>
where
Self: AsRef<T>,
{
self.next().map(Self::as_ref)
}

/// Borrow the `prev` linked element, or `None` if this is the first.
#[inline]
fn peek_prev<T>(&self) -> Option<&T> where Self: AsRef<T> {
fn peek_prev<T>(&self) -> Option<&T>
where
Self: AsRef<T>,
{
self.prev().map(Self::as_ref)
}

/// Mutably borrow the `next` linked element, or `None` if this is the
/// last.
#[inline]
fn peek_next_mut<T>(&mut self) -> Option<&mut T> where Self: AsMut<T> {
fn peek_next_mut<T>(&mut self) -> Option<&mut T>
where
Self: AsMut<T>,
{
self.next_mut().map(Self::as_mut)
}

/// Mutably borrow the `prev` linked element, or `None` if this is the
/// first.
#[inline]
fn peek_prev_mut<T>(&mut self) -> Option<&mut T> where Self: AsMut<T> {
fn peek_prev_mut<T>(&mut self) -> Option<&mut T>
where
Self: AsMut<T>,
{
self.prev_mut().map(Self::as_mut)
}
}
Expand Down Expand Up @@ -383,6 +397,38 @@ where
}
}

#[cfg(any(feature = "std", test))]
use core::iter::Extend;

#[cfg(any(feature = "alloc", feature = "std", test))]
impl<T, Node> Extend<T> for List<T, Node, Box<Node>>
where
Node: From<T> + Linked,
{
#[inline]
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
for item in iter {
self.push_back(item);
}
}
}

#[cfg(any(feature = "std", test))]
use core::iter::FromIterator;

#[cfg(any(feature = "alloc", feature = "std", test))]
impl<T, Node> FromIterator<T> for List<T, Node, Box<Node>>
where
Node: From<T> + Linked,
{
#[inline]
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut list = List::new();
list.extend(iter);
list
}
}

// ===== impl Links =====

impl<T> Links<T> {
Expand Down
82 changes: 62 additions & 20 deletions intruder_alarm/src/doubly/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// Copyright (c) 2015-2017 Eliza Weisman
// Released under the terms of the MIT license. See `LICENSE` in the root
// directory of this repository for more information.
//
//

use super::*;
use super::Linked;
Expand All @@ -17,6 +17,8 @@ pub struct NumberedNode {
links: Links<NumberedNode>,
}

pub type NumberedList = List<usize, NumberedNode, Box<NumberedNode>>;

impl NumberedNode {
pub fn new(number: usize) -> Self {
NumberedNode {
Expand Down Expand Up @@ -78,8 +80,7 @@ mod boxed {

#[test]
fn not_empty_after_first_push() {
let mut list =
List::<usize, NumberedNode, Box<NumberedNode>>::new();
let mut list = NumberedList::new();

assert_eq!(list.head(), None);
assert_eq!(list.tail(), None);
Expand All @@ -94,8 +95,7 @@ mod boxed {

#[test]
fn contents_after_first_push() {
let mut list =
List::<usize, NumberedNode, Box<NumberedNode>>::new();
let mut list = NumberedList::new();
assert_eq!(list.head(), None);
assert_eq!(list.tail(), None);

Expand All @@ -107,8 +107,7 @@ mod boxed {

#[test]
fn head_tail_equal_after_first_push() {
let mut list =
List::<usize, NumberedNode, Box<NumberedNode>>::new();
let mut list = NumberedList::new();
assert_eq!(list.head(), list.tail());

list.push_front_node(Box::new(NumberedNode::new(444)));
Expand All @@ -118,8 +117,7 @@ mod boxed {

#[test]
fn head_tail_not_equal_after_second_push() {
let mut list =
List::<usize, NumberedNode, Box<NumberedNode>>::new();
let mut list = NumberedList::new();

list.push_front_node(Box::new(NumberedNode::new(444)));
list.push_front_node(Box::new(NumberedNode::new(555)));
Expand All @@ -130,7 +128,7 @@ mod boxed {

#[test]
fn head_tail_not_same_second_push() {
let mut list = List::<usize, NumberedNode, Box<NumberedNode>>::new();
let mut list = NumberedList::new();
let a = 444;
let b = 555;

Expand All @@ -142,7 +140,7 @@ mod boxed {

quickcheck! {
fn push_front_node_order(x: usize, xs: Vec<usize>) -> TestResult {
let mut list = List::<usize, NumberedNode, Box<NumberedNode>>::new();
let mut list = NumberedList::new();
list.push_front_node(Box::new(NumberedNode::new(x)));
let mut result = TestResult::passed();
for x_2 in xs {
Expand All @@ -156,7 +154,7 @@ mod boxed {
}

fn not_empty_after_push(n: usize) -> bool {
let mut list = List::<usize, NumberedNode, Box<NumberedNode>>::new();
let mut list = NumberedList::new();

assert_eq!(list.head(), None);
assert_eq!(list.tail(), None);
Expand All @@ -167,11 +165,10 @@ mod boxed {
list.push_front(n);

!list.is_empty() && list.len() == 1

}

fn contents_after_first_push(n: usize) -> bool {
let mut list = List::<usize, NumberedNode, Box<NumberedNode>>::new();
let mut list = NumberedList::new();
assert_eq!(list.head(), None);
assert_eq!(list.tail(), None);
list.push_front(n);
Expand All @@ -180,7 +177,7 @@ mod boxed {
}

fn linked_peek_prev_next(a: usize, b: usize) -> bool {
let mut list = List::<usize, NumberedNode, Box<NumberedNode>>::new();
let mut list = NumberedList::new();

list.push_back(a);
list.push_back(b);
Expand All @@ -190,11 +187,29 @@ mod boxed {
&& list.tail().unwrap().peek_prev() == Some(&a)
&& list.tail().unwrap().peek_next() == None
}

fn extend_sum_len(ys: Vec<usize>, xs: Vec<usize>) -> bool {
let mut list = NumberedList::new();
let total = ys.len() + xs.len();
for y in ys {
list.push_back(y);
}
list.extend(xs);

list.len() == total
}

fn from_iter_len(xs: Vec<usize>) -> bool {
let lx = xs.len();
let list = NumberedList::from_iter(xs);

list.len() == lx
}
}

#[test]
fn contents_after_push_nodes() {
let mut list = List::<usize, NumberedNode, Box<NumberedNode>>::new();
let mut list = NumberedList::new();

list.push_front_node(Box::new(NumberedNode::new(0)));
list.push_front_node(Box::new(NumberedNode::new(1)));
Expand All @@ -215,7 +230,7 @@ mod boxed {

#[test]
fn test_pop_front_node() {
let mut list = List::<usize, NumberedNode, Box<NumberedNode>>::new();
let mut list = NumberedList::new();

assert_eq!(list.head(), None);
assert_eq!(list.tail(), None);
Expand Down Expand Up @@ -252,7 +267,7 @@ mod boxed {

#[test]
fn test_pop_back_node() {
let mut list = List::<usize, NumberedNode, Box<NumberedNode>>::new();
let mut list = NumberedList::new();

assert_eq!(list.head(), None);
assert_eq!(list.tail(), None);
Expand Down Expand Up @@ -289,7 +304,7 @@ mod boxed {

#[test]
fn test_pop_front() {
let mut list = List::<usize, NumberedNode, Box<NumberedNode>>::new();
let mut list = NumberedList::new();

assert_eq!(list.head(), None);
assert_eq!(list.tail(), None);
Expand Down Expand Up @@ -326,7 +341,7 @@ mod boxed {

#[test]
fn test_pop_back() {
let mut list = List::<usize, NumberedNode, Box<NumberedNode>>::new();
let mut list = NumberedList::new();

assert_eq!(list.head(), None);
assert_eq!(list.tail(), None);
Expand Down Expand Up @@ -360,4 +375,31 @@ mod boxed {
assert!(list.is_empty());
assert_eq!(list.pop_back(), None);
}

#[test]
fn test_extend() {
let mut list = NumberedList::new();

list.push_back(0);
list.push_back(1);

assert_eq!(list.tail().unwrap().number, 1);
assert_eq!(list.head().unwrap().number, 0);

let ext = vec![3, 4];
list.extend(ext);

assert_eq!(list.tail().unwrap().number, 4);
assert_eq!(list.head().unwrap().number, 0);
}

#[test]
fn test_fromiter() {
let list_a = (0..10).into_iter();
let mut nlist = NumberedList::from_iter(list_a);

for i in 0..10 {
assert_eq!(nlist.pop_front().unwrap(), i);
}
}
}

0 comments on commit 1dcb155

Please sign in to comment.