From 824bb44f929a564dc4dd0590578de3ea04789402 Mon Sep 17 00:00:00 2001 From: blake2-ppc <blake2-ppc> Date: Tue, 9 Jul 2013 16:55:04 +0200 Subject: [PATCH 01/12] dlist: A new implementation of an owned doubly-linked list This is an owned sendable linked list which allows insertion and deletion at both ends, with fast traversal through iteration, and fast append/prepend. It is indended to replace the previous managed DList with exposed list nodes. It does not match it feature by feature, but DList could grow more methods if needed. --- src/libextra/dlist.rs | 1750 ++++++++++++++++++------------------- src/libextra/serialize.rs | 16 +- 2 files changed, 851 insertions(+), 915 deletions(-) diff --git a/src/libextra/dlist.rs b/src/libextra/dlist.rs index e7dcb0fd7ce..d3132b37345 100644 --- a/src/libextra/dlist.rs +++ b/src/libextra/dlist.rs @@ -1,966 +1,902 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. + +//! A doubly-linked list with owned nodes. +//! +//! The List allows pushing and popping elements at either end. + + +// List is constructed like a singly-linked list over the field `next`. +// including the last link being None; each Node owns its `next` field. // -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! - -A doubly-linked list. Supports O(1) head, tail, count, push, pop, etc. - -# Safety note - -Do not use ==, !=, <, etc on doubly-linked lists -- it may not terminate. - -*/ +// Backlinks over List::prev are raw pointers that form a full chain in +// the reverse direction. -use std::managed; +use std::cast; +use std::cmp; +use std::util; +use std::iterator::FromIterator; -pub type DListLink<T> = Option<@mut DListNode<T>>; - -#[allow(missing_doc)] -pub struct DListNode<T> { - data: T, - linked: bool, // for assertions - prev: DListLink<T>, - next: DListLink<T>, +/// A doubly-linked list +pub struct List<T> { + priv length: uint, + priv list_head: Link<T>, + priv list_tail: Rawlink<T>, } -#[allow(missing_doc)] -pub struct DList<T> { - size: uint, - hd: DListLink<T>, - tl: DListLink<T>, +type Link<T> = Option<~Node<T>>; +type Rawlink<T> = Option<&'static Node<T>>; +// Rawlink uses &'static to have a small Option<&'> represenation. +// FIXME: Use a raw pointer like *mut Node if possible. +// FIXME: Causes infinite recursion in %? repr + +struct Node<T> { + priv next: Link<T>, + priv prev: Rawlink<T>, + priv value: T, } -impl<T> DListNode<T> { - fn assert_links(@mut self) { - match self.next { - Some(neighbour) => match neighbour.prev { - Some(me) => if !managed::mut_ptr_eq(self, me) { - fail!("Asymmetric next-link in dlist node.") - }, - None => fail!("One-way next-link in dlist node.") - }, - None => () - } - match self.prev { - Some(neighbour) => match neighbour.next { - Some(me) => if !managed::mut_ptr_eq(me, self) { - fail!("Asymmetric prev-link in dlist node.") - }, - None => fail!("One-way prev-link in dlist node.") - }, - None => () - } +/// List iterator +pub struct ForwardIterator<'self, T> { + priv list: &'self List<T>, + priv next: &'self Link<T>, +} + +/// List reverse iterator +pub struct ReverseIterator<'self, T> { + priv list: &'self List<T>, + priv next: Rawlink<T>, +} + +/// List mutable iterator +pub struct MutForwardIterator<'self, T> { + priv list: &'self mut List<T>, + priv curs: Rawlink<T>, +} + +/// List mutable reverse iterator +pub struct MutReverseIterator<'self, T> { + priv list: &'self mut List<T>, + priv next: Rawlink<T>, +} + +/// List consuming iterator +pub struct ConsumeIterator<T> { + priv list: List<T> +} + +/// List reverse consuming iterator +pub struct ConsumeRevIterator<T> { + priv list: List<T> +} + +impl<T> Container for List<T> { + /// O(1) + fn is_empty(&self) -> bool { + self.list_head.is_none() + } + /// O(1) + fn len(&self) -> uint { + self.length } } -impl<T> DListNode<T> { - /// Get the next node in the list, if there is one. - pub fn next_link(@mut self) -> DListLink<T> { - self.assert_links(); - self.next - } - /// Get the next node in the list, failing if there isn't one. - pub fn next_node(@mut self) -> @mut DListNode<T> { - match self.next_link() { - Some(nobe) => nobe, - None => fail!("This dlist node has no next neighbour.") - } - } - /// Get the previous node in the list, if there is one. - pub fn prev_link(@mut self) -> DListLink<T> { - self.assert_links(); - self.prev - } - /// Get the previous node in the list, failing if there isn't one. - pub fn prev_node(@mut self) -> @mut DListNode<T> { - match self.prev_link() { - Some(nobe) => nobe, - None => fail!("This dlist node has no previous neighbour.") - } +impl<T> Mutable for List<T> { + /// Remove all elements from the List + /// + /// O(N) + fn clear(&mut self) { + *self = List::new() } } -/// Creates a new dlist node with the given data. -pub fn new_dlist_node<T>(data: T) -> @mut DListNode<T> { - @mut DListNode { data: data, linked: false, prev: None, next: None } +/// Cast the raw link into a borrowed ref +fn resolve_rawlink<T>(lnk: &'static Node<T>) -> &mut Node<T> { + unsafe { cast::transmute_mut(lnk) } +} +fn rawlink<T>(n: &mut Node<T>) -> Rawlink<T> { + Some(unsafe { cast::transmute(n) }) } -/// Creates a new, empty dlist. -pub fn DList<T>() -> @mut DList<T> { - @mut DList { size: 0, hd: None, tl: None } -} - -/// Creates a new dlist with a single element -pub fn from_elem<T>(data: T) -> @mut DList<T> { - let list = DList(); - list.push(data); - list -} - -/// Creates a new dlist from a vector of elements, maintaining the same order -pub fn from_vec<T:Copy>(vec: &[T]) -> @mut DList<T> { - do vec.iter().fold(DList()) |list,data| { - // Iterating left-to-right -- add newly to the tail. - list.push(copy *data); - list - } -} - -/// Produce a list from a list of lists, leaving no elements behind in the -/// input. O(number of sub-lists). -pub fn concat<T>(lists: @mut DList<@mut DList<T>>) -> @mut DList<T> { - let result = DList(); - while !lists.is_empty() { - result.append(lists.pop().get()); - } - result -} - -impl<T> DList<T> { - fn new_link(data: T) -> DListLink<T> { - Some(@mut DListNode { - data: data, - linked: true, - prev: None, - next: None - }) - } - fn assert_mine(@mut self, nobe: @mut DListNode<T>) { - // These asserts could be stronger if we had node-root back-pointers, - // but those wouldn't allow for O(1) append. - if self.size == 0 { - fail!("This dlist is empty; that node can't be on it.") - } - if !nobe.linked { fail!("That node isn't linked to any dlist.") } - if !((nobe.prev.is_some() - || managed::mut_ptr_eq(self.hd.expect("headless dlist?"), - nobe)) && - (nobe.next.is_some() - || managed::mut_ptr_eq(self.tl.expect("tailless dlist?"), - nobe))) { - fail!("That node isn't on this dlist.") - } - } - fn make_mine(&self, nobe: @mut DListNode<T>) { - if nobe.prev.is_some() || nobe.next.is_some() || nobe.linked { - fail!("Cannot insert node that's already on a dlist!") - } - nobe.linked = true; - } - // Link two nodes together. If either of them are 'none', also sets - // the head and/or tail pointers appropriately. +impl<T> List<T> { + /// Create an empty List #[inline] - fn link(&mut self, before: DListLink<T>, after: DListLink<T>) { - match before { - Some(neighbour) => neighbour.next = after, - None => self.hd = after - } - match after { - Some(neighbour) => neighbour.prev = before, - None => self.tl = before - } - } - // Remove a node from the list. - fn unlink(@mut self, nobe: @mut DListNode<T>) { - self.assert_mine(nobe); - assert!(self.size > 0); - self.link(nobe.prev, nobe.next); - nobe.prev = None; // Release extraneous references. - nobe.next = None; - nobe.linked = false; - self.size -= 1; + pub fn new() -> List<T> { + List{list_head: None, list_tail: None, length: 0} } - fn add_head(@mut self, nobe: DListLink<T>) { - self.link(nobe, self.hd); // Might set tail too. - self.hd = nobe; - self.size += 1; + /// Provide a reference to the front element, or None if the list is empty + pub fn peek_front<'a>(&'a self) -> Option<&'a T> { + self.list_head.chain_ref(|x| Some(&x.value)) } - fn add_tail(@mut self, nobe: DListLink<T>) { - self.link(self.tl, nobe); // Might set head too. - self.tl = nobe; - self.size += 1; + + /// Provide a mutable reference to the front element, or None if the list is empty + pub fn peek_front_mut<'a>(&'a mut self) -> Option<&'a mut T> { + match self.list_head { + None => None, + Some(ref mut head) => Some(&mut head.value), + } } - fn insert_left(@mut self, - nobe: DListLink<T>, - neighbour: @mut DListNode<T>) { - self.assert_mine(neighbour); - assert!(self.size > 0); - self.link(neighbour.prev, nobe); - self.link(nobe, Some(neighbour)); - self.size += 1; + + /// Provide a reference to the back element, or None if the list is empty + pub fn peek_back<'a>(&'a self) -> Option<&'a T> { + match self.list_tail { + None => None, + Some(tail) => Some(&resolve_rawlink(tail).value), + } } - fn insert_right(@mut self, - neighbour: @mut DListNode<T>, - nobe: DListLink<T>) { - self.assert_mine(neighbour); - assert!(self.size > 0); - self.link(nobe, neighbour.next); - self.link(Some(neighbour), nobe); - self.size += 1; + + /// Provide a mutable reference to the back element, or None if the list is empty + pub fn peek_back_mut<'a>(&'a mut self) -> Option<&'a mut T> { + match self.list_tail { + None => None, + Some(tail) => Some(&mut resolve_rawlink(tail).value), + } + } + + /// Add an element last in the list + /// + /// O(1) + pub fn push_back(&mut self, elt: T) { + match self.list_tail { + None => return self.push_front(elt), + Some(rtail) => { + let mut new_tail = ~Node{value: elt, next: None, prev: self.list_tail}; + self.list_tail = rawlink(new_tail); + let tail = resolve_rawlink(rtail); + tail.next = Some(new_tail); + } + } + self.length += 1; + } + + /// Remove the last element and return it, or None if the list is empty + /// + /// O(1) + #[inline] + pub fn pop_back(&mut self) -> Option<T> { + match self.list_tail { + None => None, + Some(rtail) => { + self.length -= 1; + let tail = resolve_rawlink(rtail); + let tail_own = match tail.prev { + None => { + self.list_tail = None; + self.list_head.swap_unwrap() + }, + Some(rtail_prev) => { + self.list_tail = tail.prev; + resolve_rawlink(rtail_prev).next.swap_unwrap() + } + }; + Some(tail_own.value) + } + } + } + + /// Add an element first in the list + /// + /// O(1) + pub fn push_front(&mut self, elt: T) { + let mut new_head = ~Node{value: elt, next: None, prev: None}; + match self.list_head { + None => { + self.list_tail = rawlink(new_head); + self.list_head = Some(new_head); + } + Some(ref mut head) => { + head.prev = rawlink(new_head); + util::swap(head, &mut new_head); + head.next = Some(new_head); + } + } + self.length += 1; + } + + /// Remove the first element and return it, or None if the list is empty + /// + /// O(1) + pub fn pop_front(&mut self) -> Option<T> { + match self.list_head { + None => None, + ref mut head @ Some(*) => { + self.length -= 1; + match *head.swap_unwrap() { + Node{value: value, next: Some(next), prev: _} => { + let mut mnext = next; + mnext.prev = None; + *head = Some(mnext); + Some(value) + } + Node{value: value, next: None, prev: _} => { + self.list_tail = None; + *head = None; + Some(value) + } + } + } + } + } + + /// Add all elements from `other` to the end of the list + /// + /// O(1) + pub fn append(&mut self, other: List<T>) { + match self.list_tail { + None => *self = other, + Some(rtail) => { + match other { + List{list_head: None, list_tail: _, length: _} => return, + List{list_head: Some(node), list_tail: o_tail, length: o_length} => { + let mut lnk_node = node; + let tail = resolve_rawlink(rtail); + lnk_node.prev = self.list_tail; + tail.next = Some(lnk_node); + self.list_tail = o_tail; + self.length += o_length; + } + } + } + } + } + + /// Add all elements from `other` to the beginning of the list + /// + /// O(1) + pub fn prepend(&mut self, mut other: List<T>) { + util::swap(self, &mut other); + self.append(other); + } + + /// Insert `elt` before the first `x` in the list where `f(x, elt)` is true, + /// or at the end. + /// + /// O(N) + #[inline] + pub fn insert_before(&mut self, elt: T, f: &fn(&T, &T) -> bool) { + { + let mut it = self.mut_iter(); + loop { + match it.next() { + None => break, + Some(x) => if f(x, &elt) { it.insert_before(elt); return } + } + } + } + self.push_back(elt); + } + + /// Merge, using the function `f`; take `a` if `f(a, b)` is true, else `b`. + /// + /// O(max(N, M)) + pub fn merge(&mut self, mut other: List<T>, f: &fn(&T, &T) -> bool) { + { + let mut it = self.mut_iter(); + loop { + match (it.next(), other.peek_front()) { + (None , _ ) => break, + (_ , None ) => return, + (Some(x), Some(y)) => if f(x, y) { loop } + } + it.insert_before(other.pop_front().unwrap()); + } + } + self.append(other); + } + + + /// Provide a forward iterator + pub fn iter<'a>(&'a self) -> ForwardIterator<'a, T> { + ForwardIterator{list: self, next: &self.list_head} + } + + /// Provide a reverse iterator + pub fn rev_iter<'a>(&'a self) -> ReverseIterator<'a, T> { + ReverseIterator{list: self, next: self.list_tail} + } + + /// Provide a forward iterator with mutable references + pub fn mut_iter<'a>(&'a mut self) -> MutForwardIterator<'a, T> { + MutForwardIterator{list: self, curs: None} + } + + /// Provide a reverse iterator with mutable references + pub fn mut_rev_iter<'a>(&'a mut self) -> MutReverseIterator<'a, T> { + MutReverseIterator{list: self, next: self.list_tail} + } + + + /// Consume the list into an iterator yielding elements by value + pub fn consume_iter(self) -> ConsumeIterator<T> { + ConsumeIterator{list: self} + } + + /// Consume the list into an iterator yielding elements by value, in reverse + pub fn consume_rev_iter(self) -> ConsumeRevIterator<T> { + ConsumeRevIterator{list: self} } } -impl<T> DList<T> { - /** - * Iterates through the current contents. - * - * Attempts to access this dlist during iteration are allowed (to - * allow for e.g. breadth-first search with in-place enqueues), but - * removing the current node is forbidden. - */ - pub fn each(@mut self, f: &fn(v: &T) -> bool) -> bool { - let mut link = self.peek_n(); - while link.is_some() { - let nobe = link.get(); - assert!(nobe.linked); - - { - let frozen_nobe = &*nobe; - if !f(&frozen_nobe.data) { return false; } - } - - // Check (weakly) that the user didn't do a remove. - if self.size == 0 { - fail!("The dlist became empty during iteration??") - } - if !nobe.linked || - (!((nobe.prev.is_some() - || managed::mut_ptr_eq(self.hd.expect("headless dlist?"), - nobe)) - && (nobe.next.is_some() - || managed::mut_ptr_eq(self.tl.expect("tailless dlist?"), - nobe)))) { - fail!("Removing a dlist node during iteration is forbidden!") - } - link = nobe.next_link(); - } - return true; - } - - /// Get the size of the list. O(1). - pub fn len(@mut self) -> uint { self.size } - /// Returns true if the list is empty. O(1). - pub fn is_empty(@mut self) -> bool { self.len() == 0 } - - /// Add data to the head of the list. O(1). - pub fn push_head(@mut self, data: T) { - self.add_head(DList::new_link(data)); - } - /** - * Add data to the head of the list, and get the new containing - * node. O(1). - */ - pub fn push_head_n(@mut self, data: T) -> @mut DListNode<T> { - let nobe = DList::new_link(data); - self.add_head(nobe); - nobe.get() - } - /// Add data to the tail of the list. O(1). - pub fn push(@mut self, data: T) { - self.add_tail(DList::new_link(data)); - } - /** - * Add data to the tail of the list, and get the new containing - * node. O(1). - */ - pub fn push_n(@mut self, data: T) -> @mut DListNode<T> { - let nobe = DList::new_link(data); - self.add_tail(nobe); - nobe.get() - } - /** - * Insert data into the middle of the list, left of the given node. - * O(1). - */ - pub fn insert_before(@mut self, data: T, neighbour: @mut DListNode<T>) { - self.insert_left(DList::new_link(data), neighbour); - } - /** - * Insert an existing node in the middle of the list, left of the - * given node. O(1). - */ - pub fn insert_n_before(@mut self, - nobe: @mut DListNode<T>, - neighbour: @mut DListNode<T>) { - self.make_mine(nobe); - self.insert_left(Some(nobe), neighbour); - } - /** - * Insert data in the middle of the list, left of the given node, - * and get its containing node. O(1). - */ - pub fn insert_before_n(@mut self, - data: T, - neighbour: @mut DListNode<T>) - -> @mut DListNode<T> { - let nobe = DList::new_link(data); - self.insert_left(nobe, neighbour); - nobe.get() - } - /** - * Insert data into the middle of the list, right of the given node. - * O(1). - */ - pub fn insert_after(@mut self, data: T, neighbour: @mut DListNode<T>) { - self.insert_right(neighbour, DList::new_link(data)); - } - /** - * Insert an existing node in the middle of the list, right of the - * given node. O(1). - */ - pub fn insert_n_after(@mut self, - nobe: @mut DListNode<T>, - neighbour: @mut DListNode<T>) { - self.make_mine(nobe); - self.insert_right(neighbour, Some(nobe)); - } - /** - * Insert data in the middle of the list, right of the given node, - * and get its containing node. O(1). - */ - pub fn insert_after_n(@mut self, - data: T, - neighbour: @mut DListNode<T>) - -> @mut DListNode<T> { - let nobe = DList::new_link(data); - self.insert_right(neighbour, nobe); - nobe.get() - } - - /// Remove a node from the head of the list. O(1). - pub fn pop_n(@mut self) -> DListLink<T> { - let hd = self.peek_n(); - hd.map(|nobe| self.unlink(*nobe)); - hd - } - /// Remove a node from the tail of the list. O(1). - pub fn pop_tail_n(@mut self) -> DListLink<T> { - let tl = self.peek_tail_n(); - tl.map(|nobe| self.unlink(*nobe)); - tl - } - /// Get the node at the list's head. O(1). - pub fn peek_n(@mut self) -> DListLink<T> { self.hd } - /// Get the node at the list's tail. O(1). - pub fn peek_tail_n(@mut self) -> DListLink<T> { self.tl } - - /// Get the node at the list's head, failing if empty. O(1). - pub fn head_n(@mut self) -> @mut DListNode<T> { - match self.hd { - Some(nobe) => nobe, - None => fail!("Attempted to get the head of an empty dlist.") - } - } - /// Get the node at the list's tail, failing if empty. O(1). - pub fn tail_n(@mut self) -> @mut DListNode<T> { - match self.tl { - Some(nobe) => nobe, - None => fail!("Attempted to get the tail of an empty dlist.") - } - } - - /// Remove a node from anywhere in the list. O(1). - pub fn remove(@mut self, nobe: @mut DListNode<T>) { self.unlink(nobe); } - - /** - * Empty another list onto the end of this list, joining this list's tail - * to the other list's head. O(1). - */ - pub fn append(@mut self, them: @mut DList<T>) { - if managed::mut_ptr_eq(self, them) { - fail!("Cannot append a dlist to itself!") - } - if them.len() > 0 { - self.link(self.tl, them.hd); - self.tl = them.tl; - self.size += them.size; - them.size = 0; - them.hd = None; - them.tl = None; - } - } - /** - * Empty another list onto the start of this list, joining the other - * list's tail to this list's head. O(1). - */ - pub fn prepend(@mut self, them: @mut DList<T>) { - if managed::mut_ptr_eq(self, them) { - fail!("Cannot prepend a dlist to itself!") - } - if them.len() > 0 { - self.link(them.tl, self.hd); - self.hd = them.hd; - self.size += them.size; - them.size = 0; - them.hd = None; - them.tl = None; - } - } - - /// Reverse the list's elements in place. O(n). - pub fn reverse(@mut self) { - do self.hd.while_some |nobe| { - let next_nobe = nobe.next; - self.remove(nobe); - self.make_mine(nobe); - self.add_head(Some(nobe)); - next_nobe - } - } - - /** - * Remove everything from the list. This is important because the cyclic - * links won't otherwise be automatically refcounted-collected. O(n). - */ - pub fn clear(@mut self) { - // Cute as it would be to simply detach the list and proclaim "O(1)!", - // the GC would still be a hidden O(n). Better to be honest about it. - while !self.is_empty() { - let _ = self.pop_n(); - } - } - - /// Iterate over nodes. - pub fn each_node(@mut self, f: &fn(@mut DListNode<T>) -> bool) -> bool { - let mut link = self.peek_n(); - while link.is_some() { - let nobe = link.get(); - if !f(nobe) { return false; } - link = nobe.next_link(); - } - return true; - } - - /// Check data structure integrity. O(n). - pub fn assert_consistent(@mut self) { - if self.hd.is_none() || self.tl.is_none() { - assert!(self.hd.is_none() && self.tl.is_none()); - } - // iterate forwards - let mut count = 0; - let mut link = self.peek_n(); - let mut rabbit = link; - while link.is_some() { - let nobe = link.get(); - assert!(nobe.linked); - // check cycle - if rabbit.is_some() { - rabbit = rabbit.get().next; - } - if rabbit.is_some() { - rabbit = rabbit.get().next; - } - if rabbit.is_some() { - assert!(!managed::mut_ptr_eq(rabbit.get(), nobe)); - } - // advance - link = nobe.next_link(); - count += 1; - } - assert_eq!(count, self.len()); - // iterate backwards - some of this is probably redundant. - link = self.peek_tail_n(); - rabbit = link; - while link.is_some() { - let nobe = link.get(); - assert!(nobe.linked); - // check cycle - if rabbit.is_some() { - rabbit = rabbit.get().prev; - } - if rabbit.is_some() { - rabbit = rabbit.get().prev; - } - if rabbit.is_some() { - assert!(!managed::mut_ptr_eq(rabbit.get(), nobe)); - } - // advance - link = nobe.prev_link(); - count -= 1; - } - assert_eq!(count, 0); +/// Insert sorted in ascending order +/// +/// O(N) +impl<T: cmp::TotalOrd> List<T> { + fn insert_ordered(&mut self, elt: T) { + self.insert_before(elt, |a, b| a.cmp(b) != cmp::Less); } } -impl<T:Copy> DList<T> { - /// Remove data from the head of the list. O(1). - pub fn pop(@mut self) -> Option<T> { - self.pop_n().map(|nobe| copy nobe.data) +impl<'self, A> Iterator<&'self A> for ForwardIterator<'self, A> { + #[inline] + fn next(&mut self) -> Option<&'self A> { + match *self.next { + None => None, + Some(ref next) => { + self.next = &next.next; + Some(&next.value) + } + } } - /// Remove data from the tail of the list. O(1). - pub fn pop_tail(@mut self) -> Option<T> { - self.pop_tail_n().map(|nobe| copy nobe.data) + fn size_hint(&self) -> (uint, Option<uint>) { + (0, Some(self.list.length)) + } +} + +// MutForwardIterator is different because it implements ListInsertCursor, +// and can modify the list during traversal, used in insert_when and merge. +impl<'self, A> Iterator<&'self mut A> for MutForwardIterator<'self, A> { + #[inline] + fn next(&mut self) -> Option<&'self mut A> { + match self.curs { + None => { + match self.list.list_head { + None => None, + Some(ref mut head) => { + self.curs = rawlink(&mut **head); + Some(&mut head.value) + } + } + } + Some(rcurs) => { + match resolve_rawlink(rcurs).next { + None => None, + Some(ref mut head) => { + self.curs = rawlink(&mut **head); + Some(&mut head.value) + } + } + } + } } - /// Get data at the list's head. O(1). - pub fn peek(@mut self) -> Option<T> { - self.peek_n().map(|nobe| copy nobe.data) + fn size_hint(&self) -> (uint, Option<uint>) { + (0, Some(self.list.length)) + } +} + +impl<'self, A> Iterator<&'self A> for ReverseIterator<'self, A> { + #[inline] + fn next(&mut self) -> Option<&'self A> { + match self.next { + None => None, + Some(rnext) => { + let prev = resolve_rawlink(rnext); + self.next = prev.prev; + Some(&prev.value) + } + } } - /// Get data at the list's tail. O(1). - pub fn peek_tail(@mut self) -> Option<T> { - self.peek_tail_n().map (|nobe| copy nobe.data) + fn size_hint(&self) -> (uint, Option<uint>) { + (0, Some(self.list.length)) + } +} + +impl<'self, A> Iterator<&'self mut A> for MutReverseIterator<'self, A> { + #[inline] + fn next(&mut self) -> Option<&'self mut A> { + match self.next { + None => None, + Some(rnext) => { + let prev = resolve_rawlink(rnext); + self.next = prev.prev; + Some(&mut prev.value) + } + } } - /// Get data at the list's head, failing if empty. O(1). - pub fn head(@mut self) -> T { copy self.head_n().data } + fn size_hint(&self) -> (uint, Option<uint>) { + (0, Some(self.list.length)) + } +} - /// Get data at the list's tail, failing if empty. O(1). - pub fn tail(@mut self) -> T { copy self.tail_n().data } +// XXX: Should this be `pub`? +trait ListInsertCursor<A> { + /// Insert `elt` just previous to the most recently yielded element + fn insert_before(&mut self, elt: A); +} + +impl<'self, A> ListInsertCursor<A> for MutForwardIterator<'self, A> { + fn insert_before(&mut self, elt: A) { + match self.curs { + None => self.list.push_front(elt), + Some(rcurs) => { + let node = resolve_rawlink(rcurs); + let prev_node = match node.prev { + None => return self.list.push_front(elt), // at head + Some(rprev) => resolve_rawlink(rprev), + }; + let mut node_own = prev_node.next.swap_unwrap(); + let mut ins_node = ~Node{value: elt, + next: None, + prev: rawlink(prev_node)}; + node_own.prev = rawlink(ins_node); + ins_node.next = Some(node_own); + prev_node.next = Some(ins_node); + self.list.length += 1; + } + } + } +} + +impl<A> Iterator<A> for ConsumeIterator<A> { + fn next(&mut self) -> Option<A> { self.list.pop_front() } + fn size_hint(&self) -> (uint, Option<uint>) { + (self.list.length, Some(self.list.length)) + } +} + +impl<A> Iterator<A> for ConsumeRevIterator<A> { + fn next(&mut self) -> Option<A> { self.list.pop_back() } + fn size_hint(&self) -> (uint, Option<uint>) { + (self.list.length, Some(self.list.length)) + } +} + +impl<A, T: Iterator<A>> FromIterator<A, T> for List<A> { + fn from_iterator(iterator: &mut T) -> List<A> { + let mut ret = List::new(); + for iterator.advance |elt| { ret.push_back(elt); } + ret + } +} + +impl<A: Eq> Eq for List<A> { + fn eq(&self, other: &List<A>) -> bool { + self.len() == other.len() && + self.iter().zip(other.iter()).all(|(a, b)| a.eq(b)) + } + fn ne(&self, other: &List<A>) -> bool { + !self.eq(other) + } +} + +impl<A: Clone> Clone for List<A> { + fn clone(&self) -> List<A> { + self.iter().transform(|x| x.clone()).collect() + } } #[cfg(test)] -mod tests { +fn check_links<T>(list: &List<T>) { + let mut len = 0u; + let mut last_ptr: Option<&Node<T>> = None; + let mut node_ptr: &Node<T>; + match list.list_head { + None => { assert_eq!(0u, list.length); return } + Some(ref node) => node_ptr = &**node, + } + loop { + match (last_ptr, node_ptr.prev) { + (None , None ) => {} + (None , _ ) => fail!("prev link for list_head"), + (Some(p), Some(pptr)) => { + assert_eq!((p as *Node<T>) as uint, pptr as *Node<T> as uint); + } + _ => fail!("prev link is none, not good"), + } + match node_ptr.next { + Some(ref next) => { + last_ptr = Some(node_ptr); + node_ptr = &**next; + len += 1; + } + None => { + len += 1; + break; + } + } + } + assert_eq!(len, list.length); +} + +#[test] +fn test_basic() { + let mut m = List::new::<~int>(); + assert_eq!(m.pop_front(), None); + assert_eq!(m.pop_back(), None); + assert_eq!(m.pop_front(), None); + m.push_front(~1); + assert_eq!(m.pop_front(), Some(~1)); + m.push_back(~2); + m.push_back(~3); + assert_eq!(m.len(), 2); + assert_eq!(m.pop_front(), Some(~2)); + assert_eq!(m.pop_front(), Some(~3)); + assert_eq!(m.len(), 0); + assert_eq!(m.pop_front(), None); + m.push_back(~1); + m.push_back(~3); + m.push_back(~5); + m.push_back(~7); + assert_eq!(m.pop_front(), Some(~1)); + + let mut n = List::new(); + n.push_front(2); + n.push_front(3); + { + assert_eq!(n.peek_front().unwrap(), &3); + let x = n.peek_front_mut().unwrap(); + assert_eq!(*x, 3); + *x = 0; + } + { + assert_eq!(n.peek_back().unwrap(), &2); + let y = n.peek_back_mut().unwrap(); + assert_eq!(*y, 2); + *y = 1; + } + assert_eq!(n.pop_front(), Some(0)); + assert_eq!(n.pop_front(), Some(1)); +} + +#[cfg(test)] +fn generate_test() -> List<int> { + list_from(&[0,1,2,3,4,5,6]) +} + +#[cfg(test)] +fn list_from<T: Copy>(v: &[T]) -> List<T> { + v.iter().transform(|x| copy *x).collect() +} + +#[test] +fn test_append() { + { + let mut m = List::new(); + let mut n = List::new(); + n.push_back(2); + m.append(n); + assert_eq!(m.len(), 1); + assert_eq!(m.pop_back(), Some(2)); + check_links(&m); + } + { + let mut m = List::new(); + let n = List::new(); + m.push_back(2); + m.append(n); + assert_eq!(m.len(), 1); + assert_eq!(m.pop_back(), Some(2)); + check_links(&m); + } + + let v = ~[1,2,3,4,5]; + let u = ~[9,8,1,2,3,4,5]; + let mut m = list_from(v); + m.append(list_from(u)); + check_links(&m); + let sum = v + u; + assert_eq!(sum.len(), m.len()); + for sum.consume_iter().advance |elt| { + assert_eq!(m.pop_front(), Some(elt)) + } +} + +#[test] +fn test_prepend() { + { + let mut m = List::new(); + let mut n = List::new(); + n.push_back(2); + m.prepend(n); + assert_eq!(m.len(), 1); + assert_eq!(m.pop_back(), Some(2)); + check_links(&m); + } + + let v = ~[1,2,3,4,5]; + let u = ~[9,8,1,2,3,4,5]; + let mut m = list_from(v); + m.prepend(list_from(u)); + check_links(&m); + let sum = u + v; + assert_eq!(sum.len(), m.len()); + for sum.consume_iter().advance |elt| { + assert_eq!(m.pop_front(), Some(elt)) + } +} + +#[test] +fn test_iterator() { + let m = generate_test(); + for m.iter().enumerate().advance |(i, elt)| { + assert_eq!(i as int, *elt); + } + let mut n = List::new(); + assert_eq!(n.iter().next(), None); + n.push_front(4); + let mut it = n.iter(); + assert_eq!(it.next().unwrap(), &4); + assert_eq!(it.next(), None); +} + +#[test] +fn test_rev_iter() { + let m = generate_test(); + for m.rev_iter().enumerate().advance |(i, elt)| { + assert_eq!((6 - i) as int, *elt); + } + let mut n = List::new(); + assert_eq!(n.rev_iter().next(), None); + n.push_front(4); + let mut it = n.rev_iter(); + assert_eq!(it.next().unwrap(), &4); + assert_eq!(it.next(), None); +} + +#[test] +fn test_mut_iter() { + let mut m = generate_test(); + let mut len = m.len(); + for m.mut_iter().enumerate().advance |(i, elt)| { + assert_eq!(i as int, *elt); + len -= 1; + } + assert_eq!(len, 0); + let mut n = List::new(); + assert!(n.mut_iter().next().is_none()); + n.push_front(4); + let mut it = n.mut_iter(); + assert!(it.next().is_some()); + assert!(it.next().is_none()); +} + +#[test] +fn test_list_cursor() { + let mut m = generate_test(); + let len = m.len(); + { + let mut it = m.mut_iter(); + loop { + match it.next() { + None => break, + Some(elt) => it.insert_before(*elt * 2), + } + } + } + assert_eq!(m.len(), len * 2); + check_links(&m); +} + +#[test] +fn test_merge() { + let mut m = list_from([0, 1, 3, 5, 6, 7, 2]); + let n = list_from([-1, 0, 0, 7, 7, 9]); + let len = m.len() + n.len(); + m.merge(n, |a, b| a <= b); + assert_eq!(m.len(), len); + check_links(&m); + let res = m.consume_iter().collect::<~[int]>(); + assert_eq!(res, ~[-1, 0, 0, 1, 0, 3, 5, 6, 7, 2, 7, 7, 9]); +} + +#[test] +fn test_insert_ordered() { + let mut n = List::new(); + n.insert_ordered(1); + assert_eq!(n.len(), 1); + assert_eq!(n.pop_front(), Some(1)); + + let mut m = List::new(); + m.push_back(2); + m.push_back(4); + m.insert_ordered(3); + check_links(&m); + assert_eq!(~[2,3,4], m.consume_iter().collect::<~[int]>()); +} + +#[test] +fn test_mut_rev_iter() { + let mut m = generate_test(); + for m.mut_rev_iter().enumerate().advance |(i, elt)| { + assert_eq!((6-i) as int, *elt); + } + let mut n = List::new(); + assert!(n.mut_rev_iter().next().is_none()); + n.push_front(4); + let mut it = n.mut_rev_iter(); + assert!(it.next().is_some()); + assert!(it.next().is_none()); +} + +#[test] +fn test_send() { + let n = list_from([1,2,3]); + do spawn { + check_links(&n); + assert_eq!(~[&1,&2,&3], n.iter().collect::<~[&int]>()); + } +} + +#[test] +fn test_eq() { + let mut n: List<u8> = list_from([]); + let mut m = list_from([]); + assert_eq!(&n, &m); + n.push_front(1); + assert!(n != m); + m.push_back(1); + assert_eq!(&n, &m); +} + +#[test] +fn test_fuzz() { + for 25.times { + fuzz_test(3); + fuzz_test(16); + fuzz_test(189); + } +} + +#[cfg(test)] +fn fuzz_test(sz: int) { + use std::rand; + use std::int; + + let mut m = List::new::<int>(); + let mut v = ~[]; + for int::range(0i, sz) |i| { + check_links(&m); + let r: u8 = rand::random(); + match r % 6 { + 0 => { + m.pop_back(); + if v.len() > 0 { v.pop(); } + } + 1 => { + m.pop_front(); + if v.len() > 0 { v.shift(); } + } + 2 | 4 => { + m.push_front(-i); + v.unshift(-i); + } + 3 | 5 | _ => { + m.push_back(i); + v.push(i); + } + } + } + + check_links(&m); + + let mut i = 0u; + for m.consume_iter().zip(v.iter()).advance |(a, &b)| { + i += 1; + assert_eq!(a, b); + } + assert_eq!(i, v.len()); +} + +#[cfg(test)] +mod test_bench { + use extra::test; use super::*; - #[test] - fn test_dlist_concat() { - let a = from_vec([1,2]); - let b = from_vec([3,4]); - let c = from_vec([5,6]); - let d = from_vec([7,8]); - let ab = from_vec([a,b]); - let cd = from_vec([c,d]); - let abcd = concat(concat(from_vec([ab,cd]))); - abcd.assert_consistent(); assert_eq!(abcd.len(), 8); - abcd.assert_consistent(); assert_eq!(abcd.pop().get(), 1); - abcd.assert_consistent(); assert_eq!(abcd.pop().get(), 2); - abcd.assert_consistent(); assert_eq!(abcd.pop().get(), 3); - abcd.assert_consistent(); assert_eq!(abcd.pop().get(), 4); - abcd.assert_consistent(); assert_eq!(abcd.pop().get(), 5); - abcd.assert_consistent(); assert_eq!(abcd.pop().get(), 6); - abcd.assert_consistent(); assert_eq!(abcd.pop().get(), 7); - abcd.assert_consistent(); assert_eq!(abcd.pop().get(), 8); - abcd.assert_consistent(); assert!(abcd.is_empty()); - } - #[test] - fn test_dlist_append() { - let a = from_vec([1,2,3]); - let b = from_vec([4,5,6]); - a.append(b); - assert_eq!(a.len(), 6); - assert_eq!(b.len(), 0); - b.assert_consistent(); - a.assert_consistent(); assert_eq!(a.pop().get(), 1); - a.assert_consistent(); assert_eq!(a.pop().get(), 2); - a.assert_consistent(); assert_eq!(a.pop().get(), 3); - a.assert_consistent(); assert_eq!(a.pop().get(), 4); - a.assert_consistent(); assert_eq!(a.pop().get(), 5); - a.assert_consistent(); assert_eq!(a.pop().get(), 6); - a.assert_consistent(); assert!(a.is_empty()); - } - #[test] - fn test_dlist_append_empty() { - let a = from_vec([1,2,3]); - let b = DList::<int>(); - a.append(b); - assert_eq!(a.len(), 3); - assert_eq!(b.len(), 0); - b.assert_consistent(); - a.assert_consistent(); assert_eq!(a.pop().get(), 1); - a.assert_consistent(); assert_eq!(a.pop().get(), 2); - a.assert_consistent(); assert_eq!(a.pop().get(), 3); - a.assert_consistent(); assert!(a.is_empty()); - } - #[test] - fn test_dlist_append_to_empty() { - let a = DList::<int>(); - let b = from_vec([4,5,6]); - a.append(b); - assert_eq!(a.len(), 3); - assert_eq!(b.len(), 0); - b.assert_consistent(); - a.assert_consistent(); assert_eq!(a.pop().get(), 4); - a.assert_consistent(); assert_eq!(a.pop().get(), 5); - a.assert_consistent(); assert_eq!(a.pop().get(), 6); - a.assert_consistent(); assert!(a.is_empty()); - } - #[test] - fn test_dlist_append_two_empty() { - let a = DList::<int>(); - let b = DList::<int>(); - a.append(b); - assert_eq!(a.len(), 0); - assert_eq!(b.len(), 0); - b.assert_consistent(); - a.assert_consistent(); - } - #[test] - #[ignore(cfg(windows))] - #[should_fail] - fn test_dlist_append_self() { - let a = DList::<int>(); - a.append(a); - } - #[test] - #[ignore(cfg(windows))] - #[should_fail] - fn test_dlist_prepend_self() { - let a = DList::<int>(); - a.prepend(a); - } - #[test] - fn test_dlist_prepend() { - let a = from_vec([1,2,3]); - let b = from_vec([4,5,6]); - b.prepend(a); - assert_eq!(a.len(), 0); - assert_eq!(b.len(), 6); - a.assert_consistent(); - b.assert_consistent(); assert_eq!(b.pop().get(), 1); - b.assert_consistent(); assert_eq!(b.pop().get(), 2); - b.assert_consistent(); assert_eq!(b.pop().get(), 3); - b.assert_consistent(); assert_eq!(b.pop().get(), 4); - b.assert_consistent(); assert_eq!(b.pop().get(), 5); - b.assert_consistent(); assert_eq!(b.pop().get(), 6); - b.assert_consistent(); assert!(b.is_empty()); - } - #[test] - fn test_dlist_reverse() { - let a = from_vec([5,4,3,2,1]); - a.reverse(); - assert_eq!(a.len(), 5); - a.assert_consistent(); assert_eq!(a.pop().get(), 1); - a.assert_consistent(); assert_eq!(a.pop().get(), 2); - a.assert_consistent(); assert_eq!(a.pop().get(), 3); - a.assert_consistent(); assert_eq!(a.pop().get(), 4); - a.assert_consistent(); assert_eq!(a.pop().get(), 5); - a.assert_consistent(); assert!(a.is_empty()); - } - #[test] - fn test_dlist_reverse_empty() { - let a = DList::<int>(); - a.reverse(); - assert_eq!(a.len(), 0); - a.assert_consistent(); - } - #[test] - fn test_dlist_each_node() { - let a = from_vec([1,2,4,5]); - for a.each_node |nobe| { - if nobe.data > 3 { - a.insert_before(3, nobe); - } + #[bench] + fn bench_collect_into(b: &mut test::BenchHarness) { + let v = &[0, ..64]; + do b.iter { + let _: List<int> = v.iter().transform(|&x|x).collect(); } - assert_eq!(a.len(), 6); - a.assert_consistent(); assert_eq!(a.pop().get(), 1); - a.assert_consistent(); assert_eq!(a.pop().get(), 2); - a.assert_consistent(); assert_eq!(a.pop().get(), 3); - a.assert_consistent(); assert_eq!(a.pop().get(), 4); - a.assert_consistent(); assert_eq!(a.pop().get(), 3); - a.assert_consistent(); assert_eq!(a.pop().get(), 5); - a.assert_consistent(); assert!(a.is_empty()); } - #[test] - fn test_dlist_clear() { - let a = from_vec([5,4,3,2,1]); - a.clear(); - assert_eq!(a.len(), 0); - a.assert_consistent(); - } - #[test] - fn test_dlist_is_empty() { - let empty = DList::<int>(); - let full1 = from_vec([1,2,3]); - assert!(empty.is_empty()); - assert!(!full1.is_empty()); - } - #[test] - fn test_dlist_head_tail() { - let l = from_vec([1,2,3]); - assert_eq!(l.head(), 1); - assert_eq!(l.tail(), 3); - assert_eq!(l.len(), 3); - } - #[test] - fn test_dlist_pop() { - let l = from_vec([1,2,3]); - assert_eq!(l.pop().get(), 1); - assert_eq!(l.tail(), 3); - assert_eq!(l.head(), 2); - assert_eq!(l.pop().get(), 2); - assert_eq!(l.tail(), 3); - assert_eq!(l.head(), 3); - assert_eq!(l.pop().get(), 3); - assert!(l.is_empty()); - assert!(l.pop().is_none()); - } - #[test] - fn test_dlist_pop_tail() { - let l = from_vec([1,2,3]); - assert_eq!(l.pop_tail().get(), 3); - assert_eq!(l.tail(), 2); - assert_eq!(l.head(), 1); - assert_eq!(l.pop_tail().get(), 2); - assert_eq!(l.tail(), 1); - assert_eq!(l.head(), 1); - assert_eq!(l.pop_tail().get(), 1); - assert!(l.is_empty()); - assert!(l.pop_tail().is_none()); - } - #[test] - fn test_dlist_push() { - let l = DList::<int>(); - l.push(1); - assert_eq!(l.head(), 1); - assert_eq!(l.tail(), 1); - l.push(2); - assert_eq!(l.head(), 1); - assert_eq!(l.tail(), 2); - l.push(3); - assert_eq!(l.head(), 1); - assert_eq!(l.tail(), 3); - assert_eq!(l.len(), 3); - } - #[test] - fn test_dlist_push_head() { - let l = DList::<int>(); - l.push_head(3); - assert_eq!(l.head(), 3); - assert_eq!(l.tail(), 3); - l.push_head(2); - assert_eq!(l.head(), 2); - assert_eq!(l.tail(), 3); - l.push_head(1); - assert_eq!(l.head(), 1); - assert_eq!(l.tail(), 3); - assert_eq!(l.len(), 3); - } - #[test] - fn test_dlist_break_early() { - let l = from_vec([1,2,3,4,5]); - let mut x = 0; - for l.each |i| { - x += 1; - if (*i == 3) { break; } + #[bench] + fn bench_collect_into_vec(b: &mut test::BenchHarness) { + let v = &[0, ..64]; + do b.iter { + let _: ~[int] = v.iter().transform(|&x|x).collect(); } - assert_eq!(x, 3); } - #[test] - fn test_dlist_remove_head() { - let l = DList::<int>(); - l.assert_consistent(); let one = l.push_n(1); - l.assert_consistent(); let _two = l.push_n(2); - l.assert_consistent(); let _three = l.push_n(3); - l.assert_consistent(); assert_eq!(l.len(), 3); - l.assert_consistent(); l.remove(one); - l.assert_consistent(); assert_eq!(l.len(), 2); - l.assert_consistent(); assert_eq!(l.head(), 2); - l.assert_consistent(); assert_eq!(l.tail(), 3); - l.assert_consistent(); assert_eq!(l.pop().get(), 2); - l.assert_consistent(); assert_eq!(l.pop().get(), 3); - l.assert_consistent(); assert!(l.is_empty()); + + #[bench] + fn bench_push_front(b: &mut test::BenchHarness) { + let mut m = List::new::<int>(); + do b.iter { + m.push_front(0); + } } - #[test] - fn test_dlist_remove_mid() { - let l = DList::<int>(); - l.assert_consistent(); let _one = l.push_n(1); - l.assert_consistent(); let two = l.push_n(2); - l.assert_consistent(); let _three = l.push_n(3); - l.assert_consistent(); assert_eq!(l.len(), 3); - l.assert_consistent(); l.remove(two); - l.assert_consistent(); assert_eq!(l.len(), 2); - l.assert_consistent(); assert_eq!(l.head(), 1); - l.assert_consistent(); assert_eq!(l.tail(), 3); - l.assert_consistent(); assert_eq!(l.pop().get(), 1); - l.assert_consistent(); assert_eq!(l.pop().get(), 3); - l.assert_consistent(); assert!(l.is_empty()); + #[bench] + fn bench_push_front_vec_size10(b: &mut test::BenchHarness) { + let mut m = ~[0, ..10]; + do b.iter { + m.unshift(0); + m.pop(); // to keep it fair, dont' grow the vec + } } - #[test] - fn test_dlist_remove_tail() { - let l = DList::<int>(); - l.assert_consistent(); let _one = l.push_n(1); - l.assert_consistent(); let _two = l.push_n(2); - l.assert_consistent(); let three = l.push_n(3); - l.assert_consistent(); assert_eq!(l.len(), 3); - l.assert_consistent(); l.remove(three); - l.assert_consistent(); assert_eq!(l.len(), 2); - l.assert_consistent(); assert_eq!(l.head(), 1); - l.assert_consistent(); assert_eq!(l.tail(), 2); - l.assert_consistent(); assert_eq!(l.pop().get(), 1); - l.assert_consistent(); assert_eq!(l.pop().get(), 2); - l.assert_consistent(); assert!(l.is_empty()); + + #[bench] + fn bench_push_back(b: &mut test::BenchHarness) { + let mut m = List::new::<int>(); + do b.iter { + m.push_back(0); + } } - #[test] - fn test_dlist_remove_one_two() { - let l = DList::<int>(); - l.assert_consistent(); let one = l.push_n(1); - l.assert_consistent(); let two = l.push_n(2); - l.assert_consistent(); let _three = l.push_n(3); - l.assert_consistent(); assert_eq!(l.len(), 3); - l.assert_consistent(); l.remove(one); - l.assert_consistent(); l.remove(two); - // and through and through, the vorpal blade went snicker-snack - l.assert_consistent(); assert_eq!(l.len(), 1); - l.assert_consistent(); assert_eq!(l.head(), 3); - l.assert_consistent(); assert_eq!(l.tail(), 3); - l.assert_consistent(); assert_eq!(l.pop().get(), 3); - l.assert_consistent(); assert!(l.is_empty()); + #[bench] + fn bench_push_back_vec(b: &mut test::BenchHarness) { + let mut m = ~[]; + do b.iter { + m.push(0); + } } - #[test] - fn test_dlist_remove_one_three() { - let l = DList::<int>(); - l.assert_consistent(); let one = l.push_n(1); - l.assert_consistent(); let _two = l.push_n(2); - l.assert_consistent(); let three = l.push_n(3); - l.assert_consistent(); assert_eq!(l.len(), 3); - l.assert_consistent(); l.remove(one); - l.assert_consistent(); l.remove(three); - l.assert_consistent(); assert_eq!(l.len(), 1); - l.assert_consistent(); assert_eq!(l.head(), 2); - l.assert_consistent(); assert_eq!(l.tail(), 2); - l.assert_consistent(); assert_eq!(l.pop().get(), 2); - l.assert_consistent(); assert!(l.is_empty()); + + #[bench] + fn bench_push_back_pop_back(b: &mut test::BenchHarness) { + let mut m = List::new::<int>(); + do b.iter { + m.push_back(0); + m.pop_back(); + } } - #[test] - fn test_dlist_remove_two_three() { - let l = DList::<int>(); - l.assert_consistent(); let _one = l.push_n(1); - l.assert_consistent(); let two = l.push_n(2); - l.assert_consistent(); let three = l.push_n(3); - l.assert_consistent(); assert_eq!(l.len(), 3); - l.assert_consistent(); l.remove(two); - l.assert_consistent(); l.remove(three); - l.assert_consistent(); assert_eq!(l.len(), 1); - l.assert_consistent(); assert_eq!(l.head(), 1); - l.assert_consistent(); assert_eq!(l.tail(), 1); - l.assert_consistent(); assert_eq!(l.pop().get(), 1); - l.assert_consistent(); assert!(l.is_empty()); + #[bench] + fn bench_push_back_pop_back_vec(b: &mut test::BenchHarness) { + let mut m = ~[]; + do b.iter { + m.push(0); + m.pop(); + } } - #[test] - fn test_dlist_remove_all() { - let l = DList::<int>(); - l.assert_consistent(); let one = l.push_n(1); - l.assert_consistent(); let two = l.push_n(2); - l.assert_consistent(); let three = l.push_n(3); - l.assert_consistent(); assert_eq!(l.len(), 3); - l.assert_consistent(); l.remove(two); - l.assert_consistent(); l.remove(three); - l.assert_consistent(); l.remove(one); // Twenty-three is number one! - l.assert_consistent(); assert!(l.peek().is_none()); - l.assert_consistent(); assert!(l.is_empty()); + + #[bench] + fn bench_iter(b: &mut test::BenchHarness) { + let v = &[0, ..128]; + let m: List<int> = v.iter().transform(|&x|x).collect(); + do b.iter { + for m.iter().advance |_| {} + } } - #[test] - fn test_dlist_insert_n_before() { - let l = DList::<int>(); - l.assert_consistent(); let _one = l.push_n(1); - l.assert_consistent(); let two = l.push_n(2); - l.assert_consistent(); let three = new_dlist_node(3); - l.assert_consistent(); assert_eq!(l.len(), 2); - l.assert_consistent(); l.insert_n_before(three, two); - l.assert_consistent(); assert_eq!(l.len(), 3); - l.assert_consistent(); assert_eq!(l.head(), 1); - l.assert_consistent(); assert_eq!(l.tail(), 2); - l.assert_consistent(); assert_eq!(l.pop().get(), 1); - l.assert_consistent(); assert_eq!(l.pop().get(), 3); - l.assert_consistent(); assert_eq!(l.pop().get(), 2); - l.assert_consistent(); assert!(l.is_empty()); + #[bench] + fn bench_iter_mut(b: &mut test::BenchHarness) { + let v = &[0, ..128]; + let mut m: List<int> = v.iter().transform(|&x|x).collect(); + do b.iter { + for m.mut_iter().advance |_| {} + } } - #[test] - fn test_dlist_insert_n_after() { - let l = DList::<int>(); - l.assert_consistent(); let one = l.push_n(1); - l.assert_consistent(); let _two = l.push_n(2); - l.assert_consistent(); let three = new_dlist_node(3); - l.assert_consistent(); assert_eq!(l.len(), 2); - l.assert_consistent(); l.insert_n_after(three, one); - l.assert_consistent(); assert_eq!(l.len(), 3); - l.assert_consistent(); assert_eq!(l.head(), 1); - l.assert_consistent(); assert_eq!(l.tail(), 2); - l.assert_consistent(); assert_eq!(l.pop().get(), 1); - l.assert_consistent(); assert_eq!(l.pop().get(), 3); - l.assert_consistent(); assert_eq!(l.pop().get(), 2); - l.assert_consistent(); assert!(l.is_empty()); + #[bench] + fn bench_iter_rev(b: &mut test::BenchHarness) { + let v = &[0, ..128]; + let m: List<int> = v.iter().transform(|&x|x).collect(); + do b.iter { + for m.rev_iter().advance |_| {} + } } - #[test] - fn test_dlist_insert_before_head() { - let l = DList::<int>(); - l.assert_consistent(); let one = l.push_n(1); - l.assert_consistent(); let _two = l.push_n(2); - l.assert_consistent(); assert_eq!(l.len(), 2); - l.assert_consistent(); l.insert_before(3, one); - l.assert_consistent(); assert_eq!(l.len(), 3); - l.assert_consistent(); assert_eq!(l.head(), 3); - l.assert_consistent(); assert_eq!(l.tail(), 2); - l.assert_consistent(); assert_eq!(l.pop().get(), 3); - l.assert_consistent(); assert_eq!(l.pop().get(), 1); - l.assert_consistent(); assert_eq!(l.pop().get(), 2); - l.assert_consistent(); assert!(l.is_empty()); + #[bench] + fn bench_iter_mut_rev(b: &mut test::BenchHarness) { + let v = &[0, ..128]; + let mut m: List<int> = v.iter().transform(|&x|x).collect(); + do b.iter { + for m.mut_rev_iter().advance |_| {} + } } - #[test] - fn test_dlist_insert_after_tail() { - let l = DList::<int>(); - l.assert_consistent(); let _one = l.push_n(1); - l.assert_consistent(); let two = l.push_n(2); - l.assert_consistent(); assert_eq!(l.len(), 2); - l.assert_consistent(); l.insert_after(3, two); - l.assert_consistent(); assert_eq!(l.len(), 3); - l.assert_consistent(); assert_eq!(l.head(), 1); - l.assert_consistent(); assert_eq!(l.tail(), 3); - l.assert_consistent(); assert_eq!(l.pop().get(), 1); - l.assert_consistent(); assert_eq!(l.pop().get(), 2); - l.assert_consistent(); assert_eq!(l.pop().get(), 3); - l.assert_consistent(); assert!(l.is_empty()); - } - #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_dlist_asymmetric_link() { - let l = DList::<int>(); - let _one = l.push_n(1); - let two = l.push_n(2); - two.prev = None; - l.assert_consistent(); - } - #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_dlist_cyclic_list() { - let l = DList::<int>(); - let one = l.push_n(1); - let _two = l.push_n(2); - let three = l.push_n(3); - three.next = Some(one); - one.prev = Some(three); - l.assert_consistent(); - } - #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_dlist_headless() { - DList::<int>().head(); - } - #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_dlist_insert_already_present_before() { - let l = DList::<int>(); - let one = l.push_n(1); - let two = l.push_n(2); - l.insert_n_before(two, one); - } - #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_dlist_insert_already_present_after() { - let l = DList::<int>(); - let one = l.push_n(1); - let two = l.push_n(2); - l.insert_n_after(one, two); - } - #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_dlist_insert_before_orphan() { - let l = DList::<int>(); - let one = new_dlist_node(1); - let two = new_dlist_node(2); - l.insert_n_before(one, two); - } - #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_dlist_insert_after_orphan() { - let l = DList::<int>(); - let one = new_dlist_node(1); - let two = new_dlist_node(2); - l.insert_n_after(two, one); + #[bench] + fn bench_iter_vec(b: &mut test::BenchHarness) { + let v = &[0, ..128]; + do b.iter { + for v.iter().advance |_| {} + } } } + diff --git a/src/libextra/serialize.rs b/src/libextra/serialize.rs index b1383948bf7..5a9072a68d8 100644 --- a/src/libextra/serialize.rs +++ b/src/libextra/serialize.rs @@ -24,7 +24,7 @@ use std::trie::{TrieMap, TrieSet}; use std::uint; use std::vec; use deque::Deque; -use dlist::DList; +use dlist::List; use treemap::{TreeMap, TreeSet}; pub trait Encoder { @@ -652,11 +652,11 @@ impl< impl< S: Encoder, T: Encodable<S> + Copy -> Encodable<S> for @mut DList<T> { +> Encodable<S> for List<T> { fn encode(&self, s: &mut S) { - do s.emit_seq(self.size) |s| { + do s.emit_seq(self.len()) |s| { let mut i = 0; - for self.each |e| { + for self.iter().advance |e| { s.emit_seq_elt(i, |s| e.encode(s)); i += 1; } @@ -664,12 +664,12 @@ impl< } } -impl<D:Decoder,T:Decodable<D>> Decodable<D> for @mut DList<T> { - fn decode(d: &mut D) -> @mut DList<T> { - let list = DList(); +impl<D:Decoder,T:Decodable<D>> Decodable<D> for List<T> { + fn decode(d: &mut D) -> List<T> { + let mut list = List::new(); do d.read_seq |d, len| { for uint::range(0, len) |i| { - list.push(d.read_seq_elt(i, |d| Decodable::decode(d))); + list.push_back(d.read_seq_elt(i, |d| Decodable::decode(d))); } } list From f97e64083b10e06286eb621f9dff918362e03fc1 Mon Sep 17 00:00:00 2001 From: blake2-ppc <blake2-ppc> Date: Tue, 9 Jul 2013 16:55:04 +0200 Subject: [PATCH 02/12] dlist: Implement size_hint properly for all iterators --- src/libextra/dlist.rs | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/libextra/dlist.rs b/src/libextra/dlist.rs index d3132b37345..ed8ba8105b1 100644 --- a/src/libextra/dlist.rs +++ b/src/libextra/dlist.rs @@ -39,24 +39,28 @@ struct Node<T> { pub struct ForwardIterator<'self, T> { priv list: &'self List<T>, priv next: &'self Link<T>, + priv nelem: uint, } /// List reverse iterator pub struct ReverseIterator<'self, T> { priv list: &'self List<T>, priv next: Rawlink<T>, + priv nelem: uint, } /// List mutable iterator pub struct MutForwardIterator<'self, T> { priv list: &'self mut List<T>, priv curs: Rawlink<T>, + priv nelem: uint, } /// List mutable reverse iterator pub struct MutReverseIterator<'self, T> { priv list: &'self mut List<T>, priv next: Rawlink<T>, + priv nelem: uint, } /// List consuming iterator @@ -287,22 +291,22 @@ impl<T> List<T> { /// Provide a forward iterator pub fn iter<'a>(&'a self) -> ForwardIterator<'a, T> { - ForwardIterator{list: self, next: &self.list_head} + ForwardIterator{nelem: self.len(), list: self, next: &self.list_head} } /// Provide a reverse iterator pub fn rev_iter<'a>(&'a self) -> ReverseIterator<'a, T> { - ReverseIterator{list: self, next: self.list_tail} + ReverseIterator{nelem: self.len(), list: self, next: self.list_tail} } /// Provide a forward iterator with mutable references pub fn mut_iter<'a>(&'a mut self) -> MutForwardIterator<'a, T> { - MutForwardIterator{list: self, curs: None} + MutForwardIterator{nelem: self.len(), list: self, curs: None} } /// Provide a reverse iterator with mutable references pub fn mut_rev_iter<'a>(&'a mut self) -> MutReverseIterator<'a, T> { - MutReverseIterator{list: self, next: self.list_tail} + MutReverseIterator{nelem: self.len(), list: self, next: self.list_tail} } @@ -332,6 +336,7 @@ impl<'self, A> Iterator<&'self A> for ForwardIterator<'self, A> { match *self.next { None => None, Some(ref next) => { + self.nelem -= 1; self.next = &next.next; Some(&next.value) } @@ -339,7 +344,7 @@ impl<'self, A> Iterator<&'self A> for ForwardIterator<'self, A> { } fn size_hint(&self) -> (uint, Option<uint>) { - (0, Some(self.list.length)) + (self.nelem, Some(self.nelem)) } } @@ -353,6 +358,7 @@ impl<'self, A> Iterator<&'self mut A> for MutForwardIterator<'self, A> { match self.list.list_head { None => None, Some(ref mut head) => { + self.nelem -= 1; self.curs = rawlink(&mut **head); Some(&mut head.value) } @@ -362,6 +368,7 @@ impl<'self, A> Iterator<&'self mut A> for MutForwardIterator<'self, A> { match resolve_rawlink(rcurs).next { None => None, Some(ref mut head) => { + self.nelem -= 1; self.curs = rawlink(&mut **head); Some(&mut head.value) } @@ -371,7 +378,7 @@ impl<'self, A> Iterator<&'self mut A> for MutForwardIterator<'self, A> { } fn size_hint(&self) -> (uint, Option<uint>) { - (0, Some(self.list.length)) + (self.nelem, Some(self.nelem)) } } @@ -381,6 +388,7 @@ impl<'self, A> Iterator<&'self A> for ReverseIterator<'self, A> { match self.next { None => None, Some(rnext) => { + self.nelem -= 1; let prev = resolve_rawlink(rnext); self.next = prev.prev; Some(&prev.value) @@ -389,7 +397,7 @@ impl<'self, A> Iterator<&'self A> for ReverseIterator<'self, A> { } fn size_hint(&self) -> (uint, Option<uint>) { - (0, Some(self.list.length)) + (self.nelem, Some(self.nelem)) } } @@ -399,6 +407,7 @@ impl<'self, A> Iterator<&'self mut A> for MutReverseIterator<'self, A> { match self.next { None => None, Some(rnext) => { + self.nelem -= 1; let prev = resolve_rawlink(rnext); self.next = prev.prev; Some(&mut prev.value) @@ -407,7 +416,7 @@ impl<'self, A> Iterator<&'self mut A> for MutReverseIterator<'self, A> { } fn size_hint(&self) -> (uint, Option<uint>) { - (0, Some(self.list.length)) + (self.nelem, Some(self.nelem)) } } @@ -628,7 +637,9 @@ fn test_iterator() { assert_eq!(n.iter().next(), None); n.push_front(4); let mut it = n.iter(); + assert_eq!(it.size_hint(), (1, Some(1))); assert_eq!(it.next().unwrap(), &4); + assert_eq!(it.size_hint(), (0, Some(0))); assert_eq!(it.next(), None); } @@ -642,7 +653,9 @@ fn test_rev_iter() { assert_eq!(n.rev_iter().next(), None); n.push_front(4); let mut it = n.rev_iter(); + assert_eq!(it.size_hint(), (1, Some(1))); assert_eq!(it.next().unwrap(), &4); + assert_eq!(it.size_hint(), (0, Some(0))); assert_eq!(it.next(), None); } @@ -659,7 +672,9 @@ fn test_mut_iter() { assert!(n.mut_iter().next().is_none()); n.push_front(4); let mut it = n.mut_iter(); + assert_eq!(it.size_hint(), (1, Some(1))); assert!(it.next().is_some()); + assert_eq!(it.size_hint(), (0, Some(0))); assert!(it.next().is_none()); } From 7b1c57713d331266d632c4fa11d4cdfaaa895ac7 Mon Sep 17 00:00:00 2001 From: blake2-ppc <blake2-ppc> Date: Wed, 10 Jul 2013 03:49:32 +0200 Subject: [PATCH 03/12] dlist: Introduce a struct Rawlink mimicing Option<T> for a raw pointer Rawlink<T> holds a *mut T pointer and can convert itself to Option<&mut T>. The null pointer is of course None. --- src/libextra/dlist.rs | 135 +++++++++++++++++++++++------------------- 1 file changed, 73 insertions(+), 62 deletions(-) diff --git a/src/libextra/dlist.rs b/src/libextra/dlist.rs index ed8ba8105b1..b197ea83fdc 100644 --- a/src/libextra/dlist.rs +++ b/src/libextra/dlist.rs @@ -13,6 +13,7 @@ use std::cast; use std::cmp; +use std::ptr; use std::util; use std::iterator::FromIterator; @@ -20,18 +21,15 @@ use std::iterator::FromIterator; pub struct List<T> { priv length: uint, priv list_head: Link<T>, - priv list_tail: Rawlink<T>, + priv list_tail: Rawlink<Node<T>>, } type Link<T> = Option<~Node<T>>; -type Rawlink<T> = Option<&'static Node<T>>; -// Rawlink uses &'static to have a small Option<&'> represenation. -// FIXME: Use a raw pointer like *mut Node if possible. -// FIXME: Causes infinite recursion in %? repr +struct Rawlink<T> { priv p: *mut T } struct Node<T> { priv next: Link<T>, - priv prev: Rawlink<T>, + priv prev: Rawlink<Node<T>>, priv value: T, } @@ -45,21 +43,21 @@ pub struct ForwardIterator<'self, T> { /// List reverse iterator pub struct ReverseIterator<'self, T> { priv list: &'self List<T>, - priv next: Rawlink<T>, + priv next: Rawlink<Node<T>>, priv nelem: uint, } /// List mutable iterator pub struct MutForwardIterator<'self, T> { priv list: &'self mut List<T>, - priv curs: Rawlink<T>, + priv curs: Rawlink<Node<T>>, priv nelem: uint, } /// List mutable reverse iterator pub struct MutReverseIterator<'self, T> { priv list: &'self mut List<T>, - priv next: Rawlink<T>, + priv next: Rawlink<Node<T>>, priv nelem: uint, } @@ -73,6 +71,33 @@ pub struct ConsumeRevIterator<T> { priv list: List<T> } +/// Rawlink is a type like Option<T> but for holding a raw pointer +impl<T> Rawlink<T> { + /// Like Option::None for Rawlink + fn none() -> Rawlink<T> { + Rawlink{p: ptr::mut_null()} + } + + /// Like Option::Some for Rawlink + fn some(n: &mut T) -> Rawlink<T> { + Rawlink{p: ptr::to_mut_unsafe_ptr(n)} + } + + /// Convert the `Rawlink` into an Option value + fn resolve_immut(&self) -> Option<&T> { + unsafe { self.p.to_option() } + } + + /// Convert the `Rawlink` into an Option value + fn resolve(&mut self) -> Option<&mut T> { + if self.p.is_null() { + None + } else { + Some(unsafe { cast::transmute(self.p) }) + } + } +} + impl<T> Container for List<T> { /// O(1) fn is_empty(&self) -> bool { @@ -93,19 +118,11 @@ impl<T> Mutable for List<T> { } } -/// Cast the raw link into a borrowed ref -fn resolve_rawlink<T>(lnk: &'static Node<T>) -> &mut Node<T> { - unsafe { cast::transmute_mut(lnk) } -} -fn rawlink<T>(n: &mut Node<T>) -> Rawlink<T> { - Some(unsafe { cast::transmute(n) }) -} - impl<T> List<T> { /// Create an empty List #[inline] pub fn new() -> List<T> { - List{list_head: None, list_tail: None, length: 0} + List{list_head: None, list_tail: Rawlink::none(), length: 0} } /// Provide a reference to the front element, or None if the list is empty @@ -123,17 +140,17 @@ impl<T> List<T> { /// Provide a reference to the back element, or None if the list is empty pub fn peek_back<'a>(&'a self) -> Option<&'a T> { - match self.list_tail { + match self.list_tail.resolve_immut() { None => None, - Some(tail) => Some(&resolve_rawlink(tail).value), + Some(tail) => Some(&tail.value), } } /// Provide a mutable reference to the back element, or None if the list is empty pub fn peek_back_mut<'a>(&'a mut self) -> Option<&'a mut T> { - match self.list_tail { + match self.list_tail.resolve() { None => None, - Some(tail) => Some(&mut resolve_rawlink(tail).value), + Some(tail) => Some(&mut tail.value), } } @@ -141,12 +158,11 @@ impl<T> List<T> { /// /// O(1) pub fn push_back(&mut self, elt: T) { - match self.list_tail { + match self.list_tail.resolve() { None => return self.push_front(elt), - Some(rtail) => { + Some(tail) => { let mut new_tail = ~Node{value: elt, next: None, prev: self.list_tail}; - self.list_tail = rawlink(new_tail); - let tail = resolve_rawlink(rtail); + self.list_tail = Rawlink::some(new_tail); tail.next = Some(new_tail); } } @@ -158,19 +174,18 @@ impl<T> List<T> { /// O(1) #[inline] pub fn pop_back(&mut self) -> Option<T> { - match self.list_tail { + match self.list_tail.resolve() { None => None, - Some(rtail) => { + Some(tail) => { self.length -= 1; - let tail = resolve_rawlink(rtail); - let tail_own = match tail.prev { + let tail_own = match tail.prev.resolve() { None => { - self.list_tail = None; + self.list_tail = Rawlink::none(); self.list_head.swap_unwrap() }, - Some(rtail_prev) => { + Some(tail_prev) => { self.list_tail = tail.prev; - resolve_rawlink(rtail_prev).next.swap_unwrap() + tail_prev.next.swap_unwrap() } }; Some(tail_own.value) @@ -182,14 +197,14 @@ impl<T> List<T> { /// /// O(1) pub fn push_front(&mut self, elt: T) { - let mut new_head = ~Node{value: elt, next: None, prev: None}; + let mut new_head = ~Node{value: elt, next: None, prev: Rawlink::none()}; match self.list_head { None => { - self.list_tail = rawlink(new_head); + self.list_tail = Rawlink::some(new_head); self.list_head = Some(new_head); } Some(ref mut head) => { - head.prev = rawlink(new_head); + head.prev = Rawlink::some(new_head); util::swap(head, &mut new_head); head.next = Some(new_head); } @@ -208,12 +223,12 @@ impl<T> List<T> { match *head.swap_unwrap() { Node{value: value, next: Some(next), prev: _} => { let mut mnext = next; - mnext.prev = None; + mnext.prev = Rawlink::none(); *head = Some(mnext); Some(value) } Node{value: value, next: None, prev: _} => { - self.list_tail = None; + self.list_tail = Rawlink::none(); *head = None; Some(value) } @@ -226,14 +241,13 @@ impl<T> List<T> { /// /// O(1) pub fn append(&mut self, other: List<T>) { - match self.list_tail { + match self.list_tail.resolve() { None => *self = other, - Some(rtail) => { + Some(tail) => { match other { List{list_head: None, list_tail: _, length: _} => return, List{list_head: Some(node), list_tail: o_tail, length: o_length} => { let mut lnk_node = node; - let tail = resolve_rawlink(rtail); lnk_node.prev = self.list_tail; tail.next = Some(lnk_node); self.list_tail = o_tail; @@ -301,7 +315,7 @@ impl<T> List<T> { /// Provide a forward iterator with mutable references pub fn mut_iter<'a>(&'a mut self) -> MutForwardIterator<'a, T> { - MutForwardIterator{nelem: self.len(), list: self, curs: None} + MutForwardIterator{nelem: self.len(), list: self, curs: Rawlink::none()} } /// Provide a reverse iterator with mutable references @@ -353,23 +367,23 @@ impl<'self, A> Iterator<&'self A> for ForwardIterator<'self, A> { impl<'self, A> Iterator<&'self mut A> for MutForwardIterator<'self, A> { #[inline] fn next(&mut self) -> Option<&'self mut A> { - match self.curs { + match self.curs.resolve() { None => { match self.list.list_head { None => None, Some(ref mut head) => { self.nelem -= 1; - self.curs = rawlink(&mut **head); + self.curs = Rawlink::some(*head); Some(&mut head.value) } } } - Some(rcurs) => { - match resolve_rawlink(rcurs).next { + Some(curs) => { + match curs.next { None => None, Some(ref mut head) => { self.nelem -= 1; - self.curs = rawlink(&mut **head); + self.curs = Rawlink::some(*head); Some(&mut head.value) } } @@ -385,11 +399,10 @@ impl<'self, A> Iterator<&'self mut A> for MutForwardIterator<'self, A> { impl<'self, A> Iterator<&'self A> for ReverseIterator<'self, A> { #[inline] fn next(&mut self) -> Option<&'self A> { - match self.next { + match self.next.resolve() { None => None, - Some(rnext) => { + Some(prev) => { self.nelem -= 1; - let prev = resolve_rawlink(rnext); self.next = prev.prev; Some(&prev.value) } @@ -404,11 +417,10 @@ impl<'self, A> Iterator<&'self A> for ReverseIterator<'self, A> { impl<'self, A> Iterator<&'self mut A> for MutReverseIterator<'self, A> { #[inline] fn next(&mut self) -> Option<&'self mut A> { - match self.next { + match self.next.resolve() { None => None, - Some(rnext) => { + Some(prev) => { self.nelem -= 1; - let prev = resolve_rawlink(rnext); self.next = prev.prev; Some(&mut prev.value) } @@ -428,19 +440,18 @@ trait ListInsertCursor<A> { impl<'self, A> ListInsertCursor<A> for MutForwardIterator<'self, A> { fn insert_before(&mut self, elt: A) { - match self.curs { + match self.curs.resolve() { None => self.list.push_front(elt), - Some(rcurs) => { - let node = resolve_rawlink(rcurs); - let prev_node = match node.prev { + Some(node) => { + let prev_node = match node.prev.resolve() { None => return self.list.push_front(elt), // at head - Some(rprev) => resolve_rawlink(rprev), + Some(prev) => prev, }; let mut node_own = prev_node.next.swap_unwrap(); let mut ins_node = ~Node{value: elt, next: None, - prev: rawlink(prev_node)}; - node_own.prev = rawlink(ins_node); + prev: Rawlink::some(prev_node)}; + node_own.prev = Rawlink::some(ins_node); ins_node.next = Some(node_own); prev_node.next = Some(ins_node); self.list.length += 1; @@ -497,11 +508,11 @@ fn check_links<T>(list: &List<T>) { Some(ref node) => node_ptr = &**node, } loop { - match (last_ptr, node_ptr.prev) { + match (last_ptr, node_ptr.prev.resolve_immut()) { (None , None ) => {} (None , _ ) => fail!("prev link for list_head"), (Some(p), Some(pptr)) => { - assert_eq!((p as *Node<T>) as uint, pptr as *Node<T> as uint); + assert_eq!(p as *Node<T>, pptr as *Node<T>); } _ => fail!("prev link is none, not good"), } From 8d06efb8ea0857844f856ab5fd87aed89d4bf718 Mon Sep 17 00:00:00 2001 From: blake2-ppc <blake2-ppc> Date: Wed, 10 Jul 2013 03:49:32 +0200 Subject: [PATCH 04/12] dlist: Collect a common pattern into link_with_prev() --- src/libextra/dlist.rs | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/libextra/dlist.rs b/src/libextra/dlist.rs index b197ea83fdc..46a3a7d6e15 100644 --- a/src/libextra/dlist.rs +++ b/src/libextra/dlist.rs @@ -98,6 +98,12 @@ impl<T> Rawlink<T> { } } +/// Set the .prev field on `next`, then return `Some(next)` +fn link_with_prev<T>(mut next: ~Node<T>, prev: Rawlink<Node<T>>) -> Link<T> { + next.prev = prev; + Some(next) +} + impl<T> Container for List<T> { /// O(1) fn is_empty(&self) -> bool { @@ -216,20 +222,17 @@ impl<T> List<T> { /// /// O(1) pub fn pop_front(&mut self) -> Option<T> { - match self.list_head { + match util::replace(&mut self.list_head, None) { None => None, - ref mut head @ Some(*) => { + Some(old_head) => { self.length -= 1; - match *head.swap_unwrap() { + match *old_head { Node{value: value, next: Some(next), prev: _} => { - let mut mnext = next; - mnext.prev = Rawlink::none(); - *head = Some(mnext); + self.list_head = link_with_prev(next, Rawlink::none()); Some(value) } Node{value: value, next: None, prev: _} => { self.list_tail = Rawlink::none(); - *head = None; Some(value) } } @@ -247,9 +250,7 @@ impl<T> List<T> { match other { List{list_head: None, list_tail: _, length: _} => return, List{list_head: Some(node), list_tail: o_tail, length: o_length} => { - let mut lnk_node = node; - lnk_node.prev = self.list_tail; - tail.next = Some(lnk_node); + tail.next = link_with_prev(node, self.list_tail); self.list_tail = o_tail; self.length += o_length; } @@ -447,13 +448,10 @@ impl<'self, A> ListInsertCursor<A> for MutForwardIterator<'self, A> { None => return self.list.push_front(elt), // at head Some(prev) => prev, }; - let mut node_own = prev_node.next.swap_unwrap(); - let mut ins_node = ~Node{value: elt, - next: None, - prev: Rawlink::some(prev_node)}; - node_own.prev = Rawlink::some(ins_node); - ins_node.next = Some(node_own); - prev_node.next = Some(ins_node); + let mut ins_node = ~Node{value: elt, next: None, prev: Rawlink::none()}; + let node_own = prev_node.next.swap_unwrap(); + ins_node.next = link_with_prev(node_own, Rawlink::some(ins_node)); + prev_node.next = link_with_prev(ins_node, Rawlink::some(prev_node)); self.list.length += 1; } } From 4fa69ab97ca4a5d570eec28c0ef979cd829686c6 Mon Sep 17 00:00:00 2001 From: blake2-ppc <blake2-ppc> Date: Wed, 10 Jul 2013 03:49:32 +0200 Subject: [PATCH 05/12] dlist: Put all tests into a tests module The exception is the function check_links which needs access to struct Node (which is not pub). --- src/libextra/dlist.rs | 556 +++++++++++++++++++++--------------------- 1 file changed, 277 insertions(+), 279 deletions(-) diff --git a/src/libextra/dlist.rs b/src/libextra/dlist.rs index 46a3a7d6e15..7cca33dbbd3 100644 --- a/src/libextra/dlist.rs +++ b/src/libextra/dlist.rs @@ -497,7 +497,7 @@ impl<A: Clone> Clone for List<A> { } #[cfg(test)] -fn check_links<T>(list: &List<T>) { +pub fn check_links<T>(list: &List<T>) { let mut len = 0u; let mut last_ptr: Option<&Node<T>> = None; let mut node_ptr: &Node<T>; @@ -529,296 +529,294 @@ fn check_links<T>(list: &List<T>) { assert_eq!(len, list.length); } -#[test] -fn test_basic() { - let mut m = List::new::<~int>(); - assert_eq!(m.pop_front(), None); - assert_eq!(m.pop_back(), None); - assert_eq!(m.pop_front(), None); - m.push_front(~1); - assert_eq!(m.pop_front(), Some(~1)); - m.push_back(~2); - m.push_back(~3); - assert_eq!(m.len(), 2); - assert_eq!(m.pop_front(), Some(~2)); - assert_eq!(m.pop_front(), Some(~3)); - assert_eq!(m.len(), 0); - assert_eq!(m.pop_front(), None); - m.push_back(~1); - m.push_back(~3); - m.push_back(~5); - m.push_back(~7); - assert_eq!(m.pop_front(), Some(~1)); - - let mut n = List::new(); - n.push_front(2); - n.push_front(3); - { - assert_eq!(n.peek_front().unwrap(), &3); - let x = n.peek_front_mut().unwrap(); - assert_eq!(*x, 3); - *x = 0; - } - { - assert_eq!(n.peek_back().unwrap(), &2); - let y = n.peek_back_mut().unwrap(); - assert_eq!(*y, 2); - *y = 1; - } - assert_eq!(n.pop_front(), Some(0)); - assert_eq!(n.pop_front(), Some(1)); -} - #[cfg(test)] -fn generate_test() -> List<int> { - list_from(&[0,1,2,3,4,5,6]) -} - -#[cfg(test)] -fn list_from<T: Copy>(v: &[T]) -> List<T> { - v.iter().transform(|x| copy *x).collect() -} - -#[test] -fn test_append() { - { - let mut m = List::new(); - let mut n = List::new(); - n.push_back(2); - m.append(n); - assert_eq!(m.len(), 1); - assert_eq!(m.pop_back(), Some(2)); - check_links(&m); - } - { - let mut m = List::new(); - let n = List::new(); - m.push_back(2); - m.append(n); - assert_eq!(m.len(), 1); - assert_eq!(m.pop_back(), Some(2)); - check_links(&m); - } - - let v = ~[1,2,3,4,5]; - let u = ~[9,8,1,2,3,4,5]; - let mut m = list_from(v); - m.append(list_from(u)); - check_links(&m); - let sum = v + u; - assert_eq!(sum.len(), m.len()); - for sum.consume_iter().advance |elt| { - assert_eq!(m.pop_front(), Some(elt)) - } -} - -#[test] -fn test_prepend() { - { - let mut m = List::new(); - let mut n = List::new(); - n.push_back(2); - m.prepend(n); - assert_eq!(m.len(), 1); - assert_eq!(m.pop_back(), Some(2)); - check_links(&m); - } - - let v = ~[1,2,3,4,5]; - let u = ~[9,8,1,2,3,4,5]; - let mut m = list_from(v); - m.prepend(list_from(u)); - check_links(&m); - let sum = u + v; - assert_eq!(sum.len(), m.len()); - for sum.consume_iter().advance |elt| { - assert_eq!(m.pop_front(), Some(elt)) - } -} - -#[test] -fn test_iterator() { - let m = generate_test(); - for m.iter().enumerate().advance |(i, elt)| { - assert_eq!(i as int, *elt); - } - let mut n = List::new(); - assert_eq!(n.iter().next(), None); - n.push_front(4); - let mut it = n.iter(); - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(it.next().unwrap(), &4); - assert_eq!(it.size_hint(), (0, Some(0))); - assert_eq!(it.next(), None); -} - -#[test] -fn test_rev_iter() { - let m = generate_test(); - for m.rev_iter().enumerate().advance |(i, elt)| { - assert_eq!((6 - i) as int, *elt); - } - let mut n = List::new(); - assert_eq!(n.rev_iter().next(), None); - n.push_front(4); - let mut it = n.rev_iter(); - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(it.next().unwrap(), &4); - assert_eq!(it.size_hint(), (0, Some(0))); - assert_eq!(it.next(), None); -} - -#[test] -fn test_mut_iter() { - let mut m = generate_test(); - let mut len = m.len(); - for m.mut_iter().enumerate().advance |(i, elt)| { - assert_eq!(i as int, *elt); - len -= 1; - } - assert_eq!(len, 0); - let mut n = List::new(); - assert!(n.mut_iter().next().is_none()); - n.push_front(4); - let mut it = n.mut_iter(); - assert_eq!(it.size_hint(), (1, Some(1))); - assert!(it.next().is_some()); - assert_eq!(it.size_hint(), (0, Some(0))); - assert!(it.next().is_none()); -} - -#[test] -fn test_list_cursor() { - let mut m = generate_test(); - let len = m.len(); - { - let mut it = m.mut_iter(); - loop { - match it.next() { - None => break, - Some(elt) => it.insert_before(*elt * 2), - } - } - } - assert_eq!(m.len(), len * 2); - check_links(&m); -} - -#[test] -fn test_merge() { - let mut m = list_from([0, 1, 3, 5, 6, 7, 2]); - let n = list_from([-1, 0, 0, 7, 7, 9]); - let len = m.len() + n.len(); - m.merge(n, |a, b| a <= b); - assert_eq!(m.len(), len); - check_links(&m); - let res = m.consume_iter().collect::<~[int]>(); - assert_eq!(res, ~[-1, 0, 0, 1, 0, 3, 5, 6, 7, 2, 7, 7, 9]); -} - -#[test] -fn test_insert_ordered() { - let mut n = List::new(); - n.insert_ordered(1); - assert_eq!(n.len(), 1); - assert_eq!(n.pop_front(), Some(1)); - - let mut m = List::new(); - m.push_back(2); - m.push_back(4); - m.insert_ordered(3); - check_links(&m); - assert_eq!(~[2,3,4], m.consume_iter().collect::<~[int]>()); -} - -#[test] -fn test_mut_rev_iter() { - let mut m = generate_test(); - for m.mut_rev_iter().enumerate().advance |(i, elt)| { - assert_eq!((6-i) as int, *elt); - } - let mut n = List::new(); - assert!(n.mut_rev_iter().next().is_none()); - n.push_front(4); - let mut it = n.mut_rev_iter(); - assert!(it.next().is_some()); - assert!(it.next().is_none()); -} - -#[test] -fn test_send() { - let n = list_from([1,2,3]); - do spawn { - check_links(&n); - assert_eq!(~[&1,&2,&3], n.iter().collect::<~[&int]>()); - } -} - -#[test] -fn test_eq() { - let mut n: List<u8> = list_from([]); - let mut m = list_from([]); - assert_eq!(&n, &m); - n.push_front(1); - assert!(n != m); - m.push_back(1); - assert_eq!(&n, &m); -} - -#[test] -fn test_fuzz() { - for 25.times { - fuzz_test(3); - fuzz_test(16); - fuzz_test(189); - } -} - -#[cfg(test)] -fn fuzz_test(sz: int) { +mod tests { + use super::*; use std::rand; use std::int; + use extra::test; - let mut m = List::new::<int>(); - let mut v = ~[]; - for int::range(0i, sz) |i| { + #[test] + fn test_basic() { + let mut m = List::new::<~int>(); + assert_eq!(m.pop_front(), None); + assert_eq!(m.pop_back(), None); + assert_eq!(m.pop_front(), None); + m.push_front(~1); + assert_eq!(m.pop_front(), Some(~1)); + m.push_back(~2); + m.push_back(~3); + assert_eq!(m.len(), 2); + assert_eq!(m.pop_front(), Some(~2)); + assert_eq!(m.pop_front(), Some(~3)); + assert_eq!(m.len(), 0); + assert_eq!(m.pop_front(), None); + m.push_back(~1); + m.push_back(~3); + m.push_back(~5); + m.push_back(~7); + assert_eq!(m.pop_front(), Some(~1)); + + let mut n = List::new(); + n.push_front(2); + n.push_front(3); + { + assert_eq!(n.peek_front().unwrap(), &3); + let x = n.peek_front_mut().unwrap(); + assert_eq!(*x, 3); + *x = 0; + } + { + assert_eq!(n.peek_back().unwrap(), &2); + let y = n.peek_back_mut().unwrap(); + assert_eq!(*y, 2); + *y = 1; + } + assert_eq!(n.pop_front(), Some(0)); + assert_eq!(n.pop_front(), Some(1)); + } + + #[cfg(test)] + fn generate_test() -> List<int> { + list_from(&[0,1,2,3,4,5,6]) + } + + #[cfg(test)] + fn list_from<T: Copy>(v: &[T]) -> List<T> { + v.iter().transform(|x| copy *x).collect() + } + + #[test] + fn test_append() { + { + let mut m = List::new(); + let mut n = List::new(); + n.push_back(2); + m.append(n); + assert_eq!(m.len(), 1); + assert_eq!(m.pop_back(), Some(2)); + check_links(&m); + } + { + let mut m = List::new(); + let n = List::new(); + m.push_back(2); + m.append(n); + assert_eq!(m.len(), 1); + assert_eq!(m.pop_back(), Some(2)); + check_links(&m); + } + + let v = ~[1,2,3,4,5]; + let u = ~[9,8,1,2,3,4,5]; + let mut m = list_from(v); + m.append(list_from(u)); check_links(&m); - let r: u8 = rand::random(); - match r % 6 { - 0 => { - m.pop_back(); - if v.len() > 0 { v.pop(); } - } - 1 => { - m.pop_front(); - if v.len() > 0 { v.shift(); } - } - 2 | 4 => { - m.push_front(-i); - v.unshift(-i); - } - 3 | 5 | _ => { - m.push_back(i); - v.push(i); - } + let sum = v + u; + assert_eq!(sum.len(), m.len()); + for sum.consume_iter().advance |elt| { + assert_eq!(m.pop_front(), Some(elt)) } } - check_links(&m); + #[test] + fn test_prepend() { + { + let mut m = List::new(); + let mut n = List::new(); + n.push_back(2); + m.prepend(n); + assert_eq!(m.len(), 1); + assert_eq!(m.pop_back(), Some(2)); + check_links(&m); + } - let mut i = 0u; - for m.consume_iter().zip(v.iter()).advance |(a, &b)| { - i += 1; - assert_eq!(a, b); + let v = ~[1,2,3,4,5]; + let u = ~[9,8,1,2,3,4,5]; + let mut m = list_from(v); + m.prepend(list_from(u)); + check_links(&m); + let sum = u + v; + assert_eq!(sum.len(), m.len()); + for sum.consume_iter().advance |elt| { + assert_eq!(m.pop_front(), Some(elt)) + } } - assert_eq!(i, v.len()); -} -#[cfg(test)] -mod test_bench { - use extra::test; + #[test] + fn test_iterator() { + let m = generate_test(); + for m.iter().enumerate().advance |(i, elt)| { + assert_eq!(i as int, *elt); + } + let mut n = List::new(); + assert_eq!(n.iter().next(), None); + n.push_front(4); + let mut it = n.iter(); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next().unwrap(), &4); + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); + } - use super::*; + #[test] + fn test_rev_iter() { + let m = generate_test(); + for m.rev_iter().enumerate().advance |(i, elt)| { + assert_eq!((6 - i) as int, *elt); + } + let mut n = List::new(); + assert_eq!(n.rev_iter().next(), None); + n.push_front(4); + let mut it = n.rev_iter(); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next().unwrap(), &4); + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); + } + + #[test] + fn test_mut_iter() { + let mut m = generate_test(); + let mut len = m.len(); + for m.mut_iter().enumerate().advance |(i, elt)| { + assert_eq!(i as int, *elt); + len -= 1; + } + assert_eq!(len, 0); + let mut n = List::new(); + assert!(n.mut_iter().next().is_none()); + n.push_front(4); + let mut it = n.mut_iter(); + assert_eq!(it.size_hint(), (1, Some(1))); + assert!(it.next().is_some()); + assert_eq!(it.size_hint(), (0, Some(0))); + assert!(it.next().is_none()); + } + + #[test] + fn test_list_cursor() { + let mut m = generate_test(); + let len = m.len(); + { + let mut it = m.mut_iter(); + loop { + match it.next() { + None => break, + Some(elt) => it.insert_before(*elt * 2), + } + } + } + assert_eq!(m.len(), len * 2); + check_links(&m); + } + + #[test] + fn test_merge() { + let mut m = list_from([0, 1, 3, 5, 6, 7, 2]); + let n = list_from([-1, 0, 0, 7, 7, 9]); + let len = m.len() + n.len(); + m.merge(n, |a, b| a <= b); + assert_eq!(m.len(), len); + check_links(&m); + let res = m.consume_iter().collect::<~[int]>(); + assert_eq!(res, ~[-1, 0, 0, 1, 0, 3, 5, 6, 7, 2, 7, 7, 9]); + } + + #[test] + fn test_insert_ordered() { + let mut n = List::new(); + n.insert_ordered(1); + assert_eq!(n.len(), 1); + assert_eq!(n.pop_front(), Some(1)); + + let mut m = List::new(); + m.push_back(2); + m.push_back(4); + m.insert_ordered(3); + check_links(&m); + assert_eq!(~[2,3,4], m.consume_iter().collect::<~[int]>()); + } + + #[test] + fn test_mut_rev_iter() { + let mut m = generate_test(); + for m.mut_rev_iter().enumerate().advance |(i, elt)| { + assert_eq!((6-i) as int, *elt); + } + let mut n = List::new(); + assert!(n.mut_rev_iter().next().is_none()); + n.push_front(4); + let mut it = n.mut_rev_iter(); + assert!(it.next().is_some()); + assert!(it.next().is_none()); + } + + #[test] + fn test_send() { + let n = list_from([1,2,3]); + do spawn { + check_links(&n); + assert_eq!(~[&1,&2,&3], n.iter().collect::<~[&int]>()); + } + } + + #[test] + fn test_eq() { + let mut n: List<u8> = list_from([]); + let mut m = list_from([]); + assert_eq!(&n, &m); + n.push_front(1); + assert!(n != m); + m.push_back(1); + assert_eq!(&n, &m); + } + + #[test] + fn test_fuzz() { + for 25.times { + fuzz_test(3); + fuzz_test(16); + fuzz_test(189); + } + } + + #[cfg(test)] + fn fuzz_test(sz: int) { + let mut m = List::new::<int>(); + let mut v = ~[]; + for int::range(0i, sz) |i| { + check_links(&m); + let r: u8 = rand::random(); + match r % 6 { + 0 => { + m.pop_back(); + if v.len() > 0 { v.pop(); } + } + 1 => { + m.pop_front(); + if v.len() > 0 { v.shift(); } + } + 2 | 4 => { + m.push_front(-i); + v.unshift(-i); + } + 3 | 5 | _ => { + m.push_back(i); + v.push(i); + } + } + } + + check_links(&m); + + let mut i = 0u; + for m.consume_iter().zip(v.iter()).advance |(a, &b)| { + i += 1; + assert_eq!(a, b); + } + assert_eq!(i, v.len()); + } #[bench] fn bench_collect_into(b: &mut test::BenchHarness) { From 92842d6516d2c5d92bad553585340f2ae3284308 Mon Sep 17 00:00:00 2001 From: blake2-ppc <blake2-ppc> Date: Wed, 10 Jul 2013 03:49:32 +0200 Subject: [PATCH 06/12] dlist: Expose ListInsertion trait with insert_before and peek_next An iterator that allows mutating the list is very useful but needs care to not be unsound. ListIteration exposes only insert_before (used for insert_ordered) and peek_next so far. --- src/libextra/dlist.rs | 47 ++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/src/libextra/dlist.rs b/src/libextra/dlist.rs index 7cca33dbbd3..5722e39eb0f 100644 --- a/src/libextra/dlist.rs +++ b/src/libextra/dlist.rs @@ -272,7 +272,7 @@ impl<T> List<T> { /// /// O(N) #[inline] - pub fn insert_before(&mut self, elt: T, f: &fn(&T, &T) -> bool) { + pub fn insert_when(&mut self, elt: T, f: &fn(&T, &T) -> bool) { { let mut it = self.mut_iter(); loop { @@ -341,7 +341,7 @@ impl<T> List<T> { /// O(N) impl<T: cmp::TotalOrd> List<T> { fn insert_ordered(&mut self, elt: T) { - self.insert_before(elt, |a, b| a.cmp(b) != cmp::Less); + self.insert_when(elt, |a, b| a.cmp(b) != cmp::Less); } } @@ -363,7 +363,7 @@ impl<'self, A> Iterator<&'self A> for ForwardIterator<'self, A> { } } -// MutForwardIterator is different because it implements ListInsertCursor, +// MutForwardIterator is different because it implements ListInsertion, // and can modify the list during traversal, used in insert_when and merge. impl<'self, A> Iterator<&'self mut A> for MutForwardIterator<'self, A> { #[inline] @@ -433,19 +433,22 @@ impl<'self, A> Iterator<&'self mut A> for MutReverseIterator<'self, A> { } } -// XXX: Should this be `pub`? -trait ListInsertCursor<A> { +/// Allow mutating the List while iterating +pub trait ListInsertion<A> { /// Insert `elt` just previous to the most recently yielded element fn insert_before(&mut self, elt: A); + + /// Provide a reference to the next element, without changing the iterator + fn peek_next<'a>(&'a mut self) -> Option<&'a mut A>; } -impl<'self, A> ListInsertCursor<A> for MutForwardIterator<'self, A> { +impl<'self, A> ListInsertion<A> for MutForwardIterator<'self, A> { fn insert_before(&mut self, elt: A) { match self.curs.resolve() { - None => self.list.push_front(elt), + None => { self.list.push_front(elt); self.next(); } Some(node) => { let prev_node = match node.prev.resolve() { - None => return self.list.push_front(elt), // at head + None => return self.list.push_front(elt), Some(prev) => prev, }; let mut ins_node = ~Node{value: elt, next: None, prev: Rawlink::none()}; @@ -456,6 +459,16 @@ impl<'self, A> ListInsertCursor<A> for MutForwardIterator<'self, A> { } } } + + fn peek_next<'a>(&'a mut self) -> Option<&'a mut A> { + match self.curs.resolve() { + None => self.list.peek_front_mut(), + Some(curs) => match curs.next { + None => None, + Some(ref mut node) => Some(&mut node.value), + } + } + } } impl<A> Iterator<A> for ConsumeIterator<A> { @@ -695,20 +708,30 @@ mod tests { } #[test] - fn test_list_cursor() { - let mut m = generate_test(); + fn test_insert_prev() { + let mut m = list_from(&[0,2,4,6,8]); let len = m.len(); { let mut it = m.mut_iter(); + it.insert_before(-2); loop { match it.next() { None => break, - Some(elt) => it.insert_before(*elt * 2), + Some(elt) => { + it.insert_before(*elt + 1); + match it.peek_next() { + Some(x) => assert_eq!(*x, *elt + 2), + None => assert_eq!(8, *elt), + } + } } } + it.insert_before(0); + it.insert_before(1); } - assert_eq!(m.len(), len * 2); check_links(&m); + assert_eq!(m.len(), 3 + len * 2); + assert_eq!(m.consume_iter().collect::<~[int]>(), ~[-2,1,0,3,2,5,4,7,6,9,0,1,8]); } #[test] From 6a95e49fc5bad1367f597bf0eeab7197c9ca226a Mon Sep 17 00:00:00 2001 From: blake2-ppc <blake2-ppc> Date: Wed, 10 Jul 2013 15:27:14 +0200 Subject: [PATCH 07/12] extra: Add mod container with trait Deque --- src/libextra/container.rs | 40 +++++++++++++++++++++++++++++++++++++++ src/libextra/extra.rs | 1 + 2 files changed, 41 insertions(+) create mode 100644 src/libextra/container.rs diff --git a/src/libextra/container.rs b/src/libextra/container.rs new file mode 100644 index 00000000000..fe622289b29 --- /dev/null +++ b/src/libextra/container.rs @@ -0,0 +1,40 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Container traits for extra + +use std::container::Mutable; + +/// A double-ended sequence that allows querying, insertion and deletion at both ends. +pub trait Deque<T> : Mutable { + /// Provide a reference to the front element, or None if the sequence is empty + fn front<'a>(&'a self) -> Option<&'a T>; + + /// Provide a mutable reference to the front element, or None if the sequence is empty + fn front_mut<'a>(&'a mut self) -> Option<&'a mut T>; + + /// Provide a reference to the back element, or None if the sequence is empty + fn back<'a>(&'a self) -> Option<&'a T>; + + /// Provide a mutable reference to the back element, or None if the sequence is empty + fn back_mut<'a>(&'a mut self) -> Option<&'a mut T>; + + /// Insert an element first in the sequence + fn push_front(&mut self, elt: T); + + /// Insert an element last in the sequence + fn push_back(&mut self, elt: T); + + /// Remove the last element and return it, or None if the sequence is empty + fn pop_back(&mut self) -> Option<T>; + + /// Remove the first element and return it, or None if the sequence is empty + fn pop_front(&mut self) -> Option<T>; +} diff --git a/src/libextra/extra.rs b/src/libextra/extra.rs index 7bec1d600b4..18322fcda59 100644 --- a/src/libextra/extra.rs +++ b/src/libextra/extra.rs @@ -67,6 +67,7 @@ pub mod flatpipes; // Collections +pub mod container; pub mod bitv; pub mod deque; pub mod fun_treemap; From 7052371e39268c08067048654a4e115ac86cc51b Mon Sep 17 00:00:00 2001 From: blake2-ppc <blake2-ppc> Date: Wed, 10 Jul 2013 15:27:14 +0200 Subject: [PATCH 08/12] extra: Rename deque::Deque to ringbuf::RingBuf and impl trait Deque Let RingBuf have a logical name for a concrete type, and Deque is used for the Deque trait (implemented by RingBuf and dlist). --- src/libextra/extra.rs | 2 +- src/libextra/{deque.rs => ringbuf.rs} | 421 ++++++++++++++------------ src/libextra/serialize.rs | 13 +- src/test/bench/graph500-bfs.rs | 11 +- src/test/run-pass/issue-2383.rs | 7 +- 5 files changed, 239 insertions(+), 215 deletions(-) rename src/libextra/{deque.rs => ringbuf.rs} (60%) diff --git a/src/libextra/extra.rs b/src/libextra/extra.rs index 18322fcda59..66ee52f53db 100644 --- a/src/libextra/extra.rs +++ b/src/libextra/extra.rs @@ -69,9 +69,9 @@ pub mod flatpipes; pub mod container; pub mod bitv; -pub mod deque; pub mod fun_treemap; pub mod list; +pub mod ringbuf; pub mod priority_queue; pub mod smallintmap; diff --git a/src/libextra/deque.rs b/src/libextra/ringbuf.rs similarity index 60% rename from src/libextra/deque.rs rename to src/libextra/ringbuf.rs index 9ce5e2c7ba2..28eab9d9012 100644 --- a/src/libextra/deque.rs +++ b/src/libextra/ringbuf.rs @@ -11,31 +11,34 @@ //! A double-ended queue implemented as a circular buffer use std::num; +use std::util; use std::uint; use std::vec; use std::iterator::FromIterator; +use container::Deque; + static INITIAL_CAPACITY: uint = 8u; // 2^3 static MINIMUM_CAPACITY: uint = 2u; #[allow(missing_doc)] #[deriving(Clone)] -pub struct Deque<T> { +pub struct RingBuf<T> { priv nelts: uint, priv lo: uint, priv elts: ~[Option<T>] } -impl<T> Container for Deque<T> { - /// Return the number of elements in the deque +impl<T> Container for RingBuf<T> { + /// Return the number of elements in the RingBuf fn len(&self) -> uint { self.nelts } - /// Return true if the deque contains no elements + /// Return true if the RingBufcontains no elements fn is_empty(&self) -> bool { self.len() == 0 } } -impl<T> Mutable for Deque<T> { - /// Clear the deque, removing all values. +impl<T> Mutable for RingBuf<T> { + /// Clear the RingBuf, removing all values. fn clear(&mut self) { for self.elts.mut_iter().advance |x| { *x = None } self.nelts = 0; @@ -43,68 +46,50 @@ impl<T> Mutable for Deque<T> { } } -impl<T> Deque<T> { - /// Create an empty Deque - pub fn new() -> Deque<T> { - Deque::with_capacity(INITIAL_CAPACITY) +impl<T> Deque<T> for RingBuf<T> { + /// Return a reference to the first element in the RingBuf + fn front<'a>(&'a self) -> Option<&'a T> { + if self.nelts > 0 { Some(self.get(0)) } else { None } } - /// Create an empty Deque with space for at least `n` elements. - pub fn with_capacity(n: uint) -> Deque<T> { - Deque{nelts: 0, lo: 0, - elts: vec::from_fn(num::max(MINIMUM_CAPACITY, n), |_| None)} + /// Return a mutable reference to the first element in the RingBuf + fn front_mut<'a>(&'a mut self) -> Option<&'a mut T> { + if self.nelts > 0 { Some(self.get_mut(0)) } else { None } } - /// Return a reference to the first element in the deque - /// - /// Fails if the deque is empty - pub fn peek_front<'a>(&'a self) -> &'a T { get(self.elts, self.raw_index(0)) } + /// Return a reference to the last element in the RingBuf + fn back<'a>(&'a self) -> Option<&'a T> { + if self.nelts > 0 { Some(self.get(self.nelts - 1)) } else { None } + } - /// Return a reference to the last element in the deque - /// - /// Fails if the deque is empty - pub fn peek_back<'a>(&'a self) -> &'a T { - if self.nelts > 0 { - get(self.elts, self.raw_index(self.nelts - 1)) - } else { - fail!("peek_back: empty deque"); + /// Return a mutable reference to the last element in the RingBuf + fn back_mut<'a>(&'a mut self) -> Option<&'a mut T> { + if self.nelts > 0 { Some(self.get_mut(self.nelts - 1)) } else { None } + } + + /// Remove and return the first element in the RingBuf, or None if it is empty + fn pop_front(&mut self) -> Option<T> { + let result = util::replace(&mut self.elts[self.lo], None); + if result.is_some() { + self.lo = (self.lo + 1u) % self.elts.len(); + self.nelts -= 1u; } - } - - /// Retrieve an element in the deque by index - /// - /// Fails if there is no element with the given index - pub fn get<'a>(&'a self, i: int) -> &'a T { - let idx = (self.lo + (i as uint)) % self.elts.len(); - get(self.elts, idx) - } - - /// Remove and return the first element in the deque - /// - /// Fails if the deque is empty - pub fn pop_front(&mut self) -> T { - let result = self.elts[self.lo].swap_unwrap(); - self.lo = (self.lo + 1u) % self.elts.len(); - self.nelts -= 1u; result } - /// Return index in underlying vec for a given logical element index - fn raw_index(&self, idx: uint) -> uint { - raw_index(self.lo, self.elts.len(), idx) + /// Remove and return the last element in the RingBuf, or None if it is empty + fn pop_back(&mut self) -> Option<T> { + if self.nelts > 0 { + self.nelts -= 1; + let hi = self.raw_index(self.nelts); + util::replace(&mut self.elts[hi], None) + } else { + None + } } - /// Remove and return the last element in the deque - /// - /// Fails if the deque is empty - pub fn pop_back(&mut self) -> T { - self.nelts -= 1; - let hi = self.raw_index(self.nelts); - self.elts[hi].swap_unwrap() - } - - /// Prepend an element to the deque - pub fn add_front(&mut self, t: T) { + /// Prepend an element to the RingBuf + fn push_front(&mut self, t: T) { if self.nelts == self.elts.len() { grow(self.nelts, &mut self.lo, &mut self.elts); } @@ -115,8 +100,8 @@ impl<T> Deque<T> { self.nelts += 1u; } - /// Append an element to the deque - pub fn add_back(&mut self, t: T) { + /// Append an element to the RingBuf + fn push_back(&mut self, t: T) { if self.nelts == self.elts.len() { grow(self.nelts, &mut self.lo, &mut self.elts); } @@ -124,8 +109,48 @@ impl<T> Deque<T> { self.elts[hi] = Some(t); self.nelts += 1u; } +} - /// Reserve capacity for exactly `n` elements in the given deque, +impl<T> RingBuf<T> { + /// Create an empty RingBuf + pub fn new() -> RingBuf<T> { + RingBuf::with_capacity(INITIAL_CAPACITY) + } + + /// Create an empty RingBuf with space for at least `n` elements. + pub fn with_capacity(n: uint) -> RingBuf<T> { + RingBuf{nelts: 0, lo: 0, + elts: vec::from_fn(num::max(MINIMUM_CAPACITY, n), |_| None)} + } + + /// Retrieve an element in the RingBuf by index + /// + /// Fails if there is no element with the given index + pub fn get<'a>(&'a self, i: uint) -> &'a T { + let idx = self.raw_index(i); + match self.elts[idx] { + None => fail!(), + Some(ref v) => v + } + } + + /// Retrieve an element in the RingBuf by index + /// + /// Fails if there is no element with the given index + pub fn get_mut<'a>(&'a mut self, i: uint) -> &'a mut T { + let idx = self.raw_index(i); + match self.elts[idx] { + None => fail!(), + Some(ref mut v) => v + } + } + + /// Return index in underlying vec for a given logical element index + fn raw_index(&self, idx: uint) -> uint { + raw_index(self.lo, self.elts.len(), idx) + } + + /// Reserve capacity for exactly `n` elements in the given RingBuf, /// doing nothing if `self`'s capacity is already equal to or greater /// than the requested capacity /// @@ -136,7 +161,7 @@ impl<T> Deque<T> { self.elts.reserve(n); } - /// Reserve capacity for at least `n` elements in the given deque, + /// Reserve capacity for at least `n` elements in the given RingBuf, /// over-allocating in case the caller needs to reserve additional /// space. /// @@ -151,24 +176,24 @@ impl<T> Deque<T> { } /// Front-to-back iterator. - pub fn iter<'a>(&'a self) -> DequeIterator<'a, T> { - DequeIterator{index: 0, nelts: self.nelts, elts: self.elts, lo: self.lo} + pub fn iter<'a>(&'a self) -> RingBufIterator<'a, T> { + RingBufIterator{index: 0, nelts: self.nelts, elts: self.elts, lo: self.lo} } /// Front-to-back iterator which returns mutable values. - pub fn mut_iter<'a>(&'a mut self) -> DequeMutIterator<'a, T> { - DequeMutIterator{index: 0, nelts: self.nelts, elts: self.elts, lo: self.lo} + pub fn mut_iter<'a>(&'a mut self) -> RingBufMutIterator<'a, T> { + RingBufMutIterator{index: 0, nelts: self.nelts, elts: self.elts, lo: self.lo} } /// Back-to-front iterator. - pub fn rev_iter<'a>(&'a self) -> DequeRevIterator<'a, T> { - DequeRevIterator{index: self.nelts-1, nelts: self.nelts, elts: self.elts, + pub fn rev_iter<'a>(&'a self) -> RingBufRevIterator<'a, T> { + RingBufRevIterator{index: self.nelts-1, nelts: self.nelts, elts: self.elts, lo: self.lo} } /// Back-to-front iterator which returns mutable values. - pub fn mut_rev_iter<'a>(&'a mut self) -> DequeMutRevIterator<'a, T> { - DequeMutRevIterator{index: self.nelts-1, nelts: self.nelts, elts: self.elts, + pub fn mut_rev_iter<'a>(&'a mut self) -> RingBufMutRevIterator<'a, T> { + RingBufMutRevIterator{index: self.nelts-1, nelts: self.nelts, elts: self.elts, lo: self.lo} } } @@ -190,41 +215,41 @@ macro_rules! iterator { } } -/// Deque iterator -pub struct DequeIterator<'self, T> { +/// RingBuf iterator +pub struct RingBufIterator<'self, T> { priv lo: uint, priv nelts: uint, priv index: uint, priv elts: &'self [Option<T>], } -iterator!{impl DequeIterator -> &'self T, get_ref, 1} +iterator!{impl RingBufIterator -> &'self T, get_ref, 1} -/// Deque reverse iterator -pub struct DequeRevIterator<'self, T> { +/// RingBuf reverse iterator +pub struct RingBufRevIterator<'self, T> { priv lo: uint, priv nelts: uint, priv index: uint, priv elts: &'self [Option<T>], } -iterator!{impl DequeRevIterator -> &'self T, get_ref, -1} +iterator!{impl RingBufRevIterator -> &'self T, get_ref, -1} -/// Deque mutable iterator -pub struct DequeMutIterator<'self, T> { +/// RingBuf mutable iterator +pub struct RingBufMutIterator<'self, T> { priv lo: uint, priv nelts: uint, priv index: uint, priv elts: &'self mut [Option<T>], } -iterator!{impl DequeMutIterator -> &'self mut T, get_mut_ref, 1} +iterator!{impl RingBufMutIterator -> &'self mut T, get_mut_ref, 1} -/// Deque mutable reverse iterator -pub struct DequeMutRevIterator<'self, T> { +/// RingBuf mutable reverse iterator +pub struct RingBufMutRevIterator<'self, T> { priv lo: uint, priv nelts: uint, priv index: uint, priv elts: &'self mut [Option<T>], } -iterator!{impl DequeMutRevIterator -> &'self mut T, get_mut_ref, -1} +iterator!{impl RingBufMutRevIterator -> &'self mut T, get_mut_ref, -1} /// Grow is only called on full elts, so nelts is also len(elts), unlike /// elsewhere. @@ -261,10 +286,6 @@ fn grow<T>(nelts: uint, loptr: &mut uint, elts: &mut ~[Option<T>]) { } } -fn get<'r, T>(elts: &'r [Option<T>], i: uint) -> &'r T { - match elts[i] { Some(ref t) => t, _ => fail!() } -} - /// Return index in underlying vec for a given logical element index fn raw_index(lo: uint, len: uint, index: uint) -> uint { if lo >= len - index { @@ -274,21 +295,21 @@ fn raw_index(lo: uint, len: uint, index: uint) -> uint { } } -impl<A: Eq> Eq for Deque<A> { - fn eq(&self, other: &Deque<A>) -> bool { +impl<A: Eq> Eq for RingBuf<A> { + fn eq(&self, other: &RingBuf<A>) -> bool { self.nelts == other.nelts && self.iter().zip(other.iter()).all(|(a, b)| a.eq(b)) } - fn ne(&self, other: &Deque<A>) -> bool { + fn ne(&self, other: &RingBuf<A>) -> bool { !self.eq(other) } } -impl<A, T: Iterator<A>> FromIterator<A, T> for Deque<A> { - fn from_iterator(iterator: &mut T) -> Deque<A> { - let mut deq = Deque::new(); +impl<A, T: Iterator<A>> FromIterator<A, T> for RingBuf<A> { + fn from_iterator(iterator: &mut T) -> RingBuf<A> { + let mut deq = RingBuf::new(); for iterator.advance |elt| { - deq.add_back(elt); + deq.push_back(elt); } deq } @@ -304,38 +325,38 @@ mod tests { #[test] fn test_simple() { - let mut d = Deque::new(); + let mut d = RingBuf::new(); assert_eq!(d.len(), 0u); - d.add_front(17); - d.add_front(42); - d.add_back(137); + d.push_front(17); + d.push_front(42); + d.push_back(137); assert_eq!(d.len(), 3u); - d.add_back(137); + d.push_back(137); assert_eq!(d.len(), 4u); - debug!(d.peek_front()); - assert_eq!(*d.peek_front(), 42); - debug!(d.peek_back()); - assert_eq!(*d.peek_back(), 137); - let mut i: int = d.pop_front(); + debug!(d.front()); + assert_eq!(*d.front().unwrap(), 42); + debug!(d.back()); + assert_eq!(*d.back().unwrap(), 137); + let mut i = d.pop_front(); debug!(i); - assert_eq!(i, 42); + assert_eq!(i, Some(42)); i = d.pop_back(); debug!(i); - assert_eq!(i, 137); + assert_eq!(i, Some(137)); i = d.pop_back(); debug!(i); - assert_eq!(i, 137); + assert_eq!(i, Some(137)); i = d.pop_back(); debug!(i); - assert_eq!(i, 17); + assert_eq!(i, Some(17)); assert_eq!(d.len(), 0u); - d.add_back(3); + d.push_back(3); assert_eq!(d.len(), 1u); - d.add_front(2); + d.push_front(2); assert_eq!(d.len(), 2u); - d.add_back(4); + d.push_back(4); assert_eq!(d.len(), 3u); - d.add_front(1); + d.push_front(1); assert_eq!(d.len(), 4u); debug!(d.get(0)); debug!(d.get(1)); @@ -354,28 +375,28 @@ mod tests { let c: @int = @64; let d: @int = @175; - let mut deq = Deque::new(); + let mut deq = RingBuf::new(); assert_eq!(deq.len(), 0); - deq.add_front(a); - deq.add_front(b); - deq.add_back(c); + deq.push_front(a); + deq.push_front(b); + deq.push_back(c); assert_eq!(deq.len(), 3); - deq.add_back(d); + deq.push_back(d); assert_eq!(deq.len(), 4); - assert_eq!(*deq.peek_front(), b); - assert_eq!(*deq.peek_back(), d); - assert_eq!(deq.pop_front(), b); - assert_eq!(deq.pop_back(), d); - assert_eq!(deq.pop_back(), c); - assert_eq!(deq.pop_back(), a); + assert_eq!(deq.front(), Some(&b)); + assert_eq!(deq.back(), Some(&d)); + assert_eq!(deq.pop_front(), Some(b)); + assert_eq!(deq.pop_back(), Some(d)); + assert_eq!(deq.pop_back(), Some(c)); + assert_eq!(deq.pop_back(), Some(a)); assert_eq!(deq.len(), 0); - deq.add_back(c); + deq.push_back(c); assert_eq!(deq.len(), 1); - deq.add_front(b); + deq.push_front(b); assert_eq!(deq.len(), 2); - deq.add_back(d); + deq.push_back(d); assert_eq!(deq.len(), 3); - deq.add_front(a); + deq.push_front(a); assert_eq!(deq.len(), 4); assert_eq!(*deq.get(0), a); assert_eq!(*deq.get(1), b); @@ -385,28 +406,28 @@ mod tests { #[cfg(test)] fn test_parameterized<T:Copy + Eq>(a: T, b: T, c: T, d: T) { - let mut deq = Deque::new(); + let mut deq = RingBuf::new(); assert_eq!(deq.len(), 0); - deq.add_front(copy a); - deq.add_front(copy b); - deq.add_back(copy c); + deq.push_front(copy a); + deq.push_front(copy b); + deq.push_back(copy c); assert_eq!(deq.len(), 3); - deq.add_back(copy d); + deq.push_back(copy d); assert_eq!(deq.len(), 4); - assert_eq!(copy *deq.peek_front(), copy b); - assert_eq!(copy *deq.peek_back(), copy d); - assert_eq!(deq.pop_front(), copy b); - assert_eq!(deq.pop_back(), copy d); - assert_eq!(deq.pop_back(), copy c); - assert_eq!(deq.pop_back(), copy a); + assert_eq!(deq.front(), Some(&b)); + assert_eq!(deq.back(), Some(&d)); + assert_eq!(deq.pop_front(), Some(copy b)); + assert_eq!(deq.pop_back(), Some(copy d)); + assert_eq!(deq.pop_back(), Some(copy c)); + assert_eq!(deq.pop_back(), Some(copy a)); assert_eq!(deq.len(), 0); - deq.add_back(copy c); + deq.push_back(copy c); assert_eq!(deq.len(), 1); - deq.add_front(copy b); + deq.push_front(copy b); assert_eq!(deq.len(), 2); - deq.add_back(copy d); + deq.push_back(copy d); assert_eq!(deq.len(), 3); - deq.add_front(copy a); + deq.push_front(copy a); assert_eq!(deq.len(), 4); assert_eq!(copy *deq.get(0), copy a); assert_eq!(copy *deq.get(1), copy b); @@ -415,23 +436,23 @@ mod tests { } #[test] - fn test_add_front_grow() { - let mut deq = Deque::new(); - for int::range(0, 66) |i| { - deq.add_front(i); + fn test_push_front_grow() { + let mut deq = RingBuf::new(); + for uint::range(0, 66) |i| { + deq.push_front(i); } assert_eq!(deq.len(), 66); - for int::range(0, 66) |i| { + for uint::range(0, 66) |i| { assert_eq!(*deq.get(i), 65 - i); } - let mut deq = Deque::new(); - for int::range(0, 66) |i| { - deq.add_back(i); + let mut deq = RingBuf::new(); + for uint::range(0, 66) |i| { + deq.push_back(i); } - for int::range(0, 66) |i| { + for uint::range(0, 66) |i| { assert_eq!(*deq.get(i), i); } } @@ -439,32 +460,32 @@ mod tests { #[bench] fn bench_new(b: &mut test::BenchHarness) { do b.iter { - let _ = Deque::new::<u64>(); + let _ = RingBuf::new::<u64>(); } } #[bench] - fn bench_add_back(b: &mut test::BenchHarness) { - let mut deq = Deque::new(); + fn bench_push_back(b: &mut test::BenchHarness) { + let mut deq = RingBuf::new(); do b.iter { - deq.add_back(0); + deq.push_back(0); } } #[bench] - fn bench_add_front(b: &mut test::BenchHarness) { - let mut deq = Deque::new(); + fn bench_push_front(b: &mut test::BenchHarness) { + let mut deq = RingBuf::new(); do b.iter { - deq.add_front(0); + deq.push_front(0); } } #[bench] fn bench_grow(b: &mut test::BenchHarness) { - let mut deq = Deque::new(); + let mut deq = RingBuf::new(); do b.iter { for 65.times { - deq.add_front(1); + deq.push_front(1); } } } @@ -518,77 +539,77 @@ mod tests { #[test] fn test_with_capacity() { - let mut d = Deque::with_capacity(0); - d.add_back(1); + let mut d = RingBuf::with_capacity(0); + d.push_back(1); assert_eq!(d.len(), 1); - let mut d = Deque::with_capacity(50); - d.add_back(1); + let mut d = RingBuf::with_capacity(50); + d.push_back(1); assert_eq!(d.len(), 1); } #[test] fn test_reserve() { - let mut d = Deque::new(); - d.add_back(0u64); + let mut d = RingBuf::new(); + d.push_back(0u64); d.reserve(50); assert_eq!(d.elts.capacity(), 50); - let mut d = Deque::new(); - d.add_back(0u32); + let mut d = RingBuf::new(); + d.push_back(0u32); d.reserve(50); assert_eq!(d.elts.capacity(), 50); } #[test] fn test_reserve_at_least() { - let mut d = Deque::new(); - d.add_back(0u64); + let mut d = RingBuf::new(); + d.push_back(0u64); d.reserve_at_least(50); assert_eq!(d.elts.capacity(), 64); - let mut d = Deque::new(); - d.add_back(0u32); + let mut d = RingBuf::new(); + d.push_back(0u32); d.reserve_at_least(50); assert_eq!(d.elts.capacity(), 64); } #[test] fn test_iter() { - let mut d = Deque::new(); + let mut d = RingBuf::new(); assert_eq!(d.iter().next(), None); for int::range(0,5) |i| { - d.add_back(i); + d.push_back(i); } assert_eq!(d.iter().collect::<~[&int]>(), ~[&0,&1,&2,&3,&4]); for int::range(6,9) |i| { - d.add_front(i); + d.push_front(i); } assert_eq!(d.iter().collect::<~[&int]>(), ~[&8,&7,&6,&0,&1,&2,&3,&4]); } #[test] fn test_rev_iter() { - let mut d = Deque::new(); + let mut d = RingBuf::new(); assert_eq!(d.rev_iter().next(), None); for int::range(0,5) |i| { - d.add_back(i); + d.push_back(i); } assert_eq!(d.rev_iter().collect::<~[&int]>(), ~[&4,&3,&2,&1,&0]); for int::range(6,9) |i| { - d.add_front(i); + d.push_front(i); } assert_eq!(d.rev_iter().collect::<~[&int]>(), ~[&4,&3,&2,&1,&0,&6,&7,&8]); } #[test] fn test_mut_iter() { - let mut d = Deque::new(); + let mut d = RingBuf::new(); assert!(d.mut_iter().next().is_none()); for uint::range(0,3) |i| { - d.add_front(i); + d.push_front(i); } for d.mut_iter().enumerate().advance |(i, elt)| { @@ -607,11 +628,11 @@ mod tests { #[test] fn test_mut_rev_iter() { - let mut d = Deque::new(); + let mut d = RingBuf::new(); assert!(d.mut_rev_iter().next().is_none()); for uint::range(0,3) |i| { - d.add_front(i); + d.push_front(i); } for d.mut_rev_iter().enumerate().advance |(i, elt)| { @@ -632,12 +653,12 @@ mod tests { fn test_from_iterator() { use std::iterator; let v = ~[1,2,3,4,5,6,7]; - let deq: Deque<int> = v.iter().transform(|&x| x).collect(); + let deq: RingBuf<int> = v.iter().transform(|&x| x).collect(); let u: ~[int] = deq.iter().transform(|&x| x).collect(); assert_eq!(u, v); let mut seq = iterator::Counter::new(0u, 2).take_(256); - let deq: Deque<uint> = seq.collect(); + let deq: RingBuf<uint> = seq.collect(); for deq.iter().enumerate().advance |(i, &x)| { assert_eq!(2*i, x); } @@ -646,11 +667,11 @@ mod tests { #[test] fn test_clone() { - let mut d = Deque::new(); - d.add_front(17); - d.add_front(42); - d.add_back(137); - d.add_back(137); + let mut d = RingBuf::new(); + d.push_front(17); + d.push_front(42); + d.push_back(137); + d.push_back(137); assert_eq!(d.len(), 4u); let mut e = d.clone(); assert_eq!(e.len(), 4u); @@ -663,22 +684,22 @@ mod tests { #[test] fn test_eq() { - let mut d = Deque::new(); - assert_eq!(&d, &Deque::with_capacity(0)); - d.add_front(137); - d.add_front(17); - d.add_front(42); - d.add_back(137); - let mut e = Deque::with_capacity(0); - e.add_back(42); - e.add_back(17); - e.add_back(137); - e.add_back(137); + let mut d = RingBuf::new(); + assert_eq!(&d, &RingBuf::with_capacity(0)); + d.push_front(137); + d.push_front(17); + d.push_front(42); + d.push_back(137); + let mut e = RingBuf::with_capacity(0); + e.push_back(42); + e.push_back(17); + e.push_back(137); + e.push_back(137); assert_eq!(&e, &d); e.pop_back(); - e.add_back(0); + e.push_back(0); assert!(e != d); e.clear(); - assert_eq!(e, Deque::new()); + assert_eq!(e, RingBuf::new()); } } diff --git a/src/libextra/serialize.rs b/src/libextra/serialize.rs index 5a9072a68d8..f185f7d7321 100644 --- a/src/libextra/serialize.rs +++ b/src/libextra/serialize.rs @@ -23,7 +23,8 @@ use std::hashmap::{HashMap, HashSet}; use std::trie::{TrieMap, TrieSet}; use std::uint; use std::vec; -use deque::Deque; +use ringbuf::RingBuf; +use container::Deque; use dlist::List; use treemap::{TreeMap, TreeSet}; @@ -679,7 +680,7 @@ impl<D:Decoder,T:Decodable<D>> Decodable<D> for List<T> { impl< S: Encoder, T: Encodable<S> -> Encodable<S> for Deque<T> { +> Encodable<S> for RingBuf<T> { fn encode(&self, s: &mut S) { do s.emit_seq(self.len()) |s| { for self.iter().enumerate().advance |(i, e)| { @@ -689,12 +690,12 @@ impl< } } -impl<D:Decoder,T:Decodable<D>> Decodable<D> for Deque<T> { - fn decode(d: &mut D) -> Deque<T> { - let mut deque = Deque::new(); +impl<D:Decoder,T:Decodable<D>> Decodable<D> for RingBuf<T> { + fn decode(d: &mut D) -> RingBuf<T> { + let mut deque = RingBuf::new(); do d.read_seq |d, len| { for uint::range(0, len) |i| { - deque.add_back(d.read_seq_elt(i, |d| Decodable::decode(d))); + deque.push_back(d.read_seq_elt(i, |d| Decodable::decode(d))); } } deque diff --git a/src/test/bench/graph500-bfs.rs b/src/test/bench/graph500-bfs.rs index dbb8da1ebd7..f0ffa3237b5 100644 --- a/src/test/bench/graph500-bfs.rs +++ b/src/test/bench/graph500-bfs.rs @@ -19,7 +19,8 @@ An implementation of the Graph500 Breadth First Search problem in Rust. extern mod extra; use extra::arc; use extra::time; -use extra::deque::Deque; +use extra::ringbuf::RingBuf; +use extra::container::Deque; use extra::par; use std::hashmap::HashSet; use std::num::abs; @@ -133,18 +134,18 @@ fn bfs(graph: graph, key: node_id) -> bfs_result { let mut marks : ~[node_id] = vec::from_elem(graph.len(), -1i64); - let mut q = Deque::new(); + let mut q = RingBuf::new(); - q.add_back(key); + q.push_back(key); marks[key] = key; while !q.is_empty() { - let t = q.pop_front(); + let t = q.pop_front().unwrap(); do graph[t].iter().advance |k| { if marks[*k] == -1i64 { marks[*k] = t; - q.add_back(*k); + q.push_back(*k); } true }; diff --git a/src/test/run-pass/issue-2383.rs b/src/test/run-pass/issue-2383.rs index 9d870168802..0314c7fed02 100644 --- a/src/test/run-pass/issue-2383.rs +++ b/src/test/run-pass/issue-2383.rs @@ -11,9 +11,10 @@ // except according to those terms. extern mod extra; -use extra::deque::Deque; +use extra::ringbuf::RingBuf; +use extra::container::Deque; pub fn main() { - let mut q = Deque::new(); - q.add_back(10); + let mut q = RingBuf::new(); + q.push_back(10); } From 24d2d7b5bb4b046429f293ff5c2cde4d14dfac8b Mon Sep 17 00:00:00 2001 From: blake2-ppc <blake2-ppc> Date: Wed, 10 Jul 2013 15:27:15 +0200 Subject: [PATCH 09/12] dlist: Implement trait Deque --- src/libextra/dlist.rs | 47 +++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/libextra/dlist.rs b/src/libextra/dlist.rs index 5722e39eb0f..edbcdc1ff76 100644 --- a/src/libextra/dlist.rs +++ b/src/libextra/dlist.rs @@ -10,13 +10,14 @@ // Backlinks over List::prev are raw pointers that form a full chain in // the reverse direction. - use std::cast; use std::cmp; use std::ptr; use std::util; use std::iterator::FromIterator; +use container::Deque; + /// A doubly-linked list pub struct List<T> { priv length: uint, @@ -124,20 +125,14 @@ impl<T> Mutable for List<T> { } } -impl<T> List<T> { - /// Create an empty List - #[inline] - pub fn new() -> List<T> { - List{list_head: None, list_tail: Rawlink::none(), length: 0} - } - +impl<T> Deque<T> for List<T> { /// Provide a reference to the front element, or None if the list is empty - pub fn peek_front<'a>(&'a self) -> Option<&'a T> { + fn front<'a>(&'a self) -> Option<&'a T> { self.list_head.chain_ref(|x| Some(&x.value)) } /// Provide a mutable reference to the front element, or None if the list is empty - pub fn peek_front_mut<'a>(&'a mut self) -> Option<&'a mut T> { + fn front_mut<'a>(&'a mut self) -> Option<&'a mut T> { match self.list_head { None => None, Some(ref mut head) => Some(&mut head.value), @@ -145,7 +140,7 @@ impl<T> List<T> { } /// Provide a reference to the back element, or None if the list is empty - pub fn peek_back<'a>(&'a self) -> Option<&'a T> { + fn back<'a>(&'a self) -> Option<&'a T> { match self.list_tail.resolve_immut() { None => None, Some(tail) => Some(&tail.value), @@ -153,7 +148,7 @@ impl<T> List<T> { } /// Provide a mutable reference to the back element, or None if the list is empty - pub fn peek_back_mut<'a>(&'a mut self) -> Option<&'a mut T> { + fn back_mut<'a>(&'a mut self) -> Option<&'a mut T> { match self.list_tail.resolve() { None => None, Some(tail) => Some(&mut tail.value), @@ -163,7 +158,7 @@ impl<T> List<T> { /// Add an element last in the list /// /// O(1) - pub fn push_back(&mut self, elt: T) { + fn push_back(&mut self, elt: T) { match self.list_tail.resolve() { None => return self.push_front(elt), Some(tail) => { @@ -179,7 +174,7 @@ impl<T> List<T> { /// /// O(1) #[inline] - pub fn pop_back(&mut self) -> Option<T> { + fn pop_back(&mut self) -> Option<T> { match self.list_tail.resolve() { None => None, Some(tail) => { @@ -202,7 +197,7 @@ impl<T> List<T> { /// Add an element first in the list /// /// O(1) - pub fn push_front(&mut self, elt: T) { + fn push_front(&mut self, elt: T) { let mut new_head = ~Node{value: elt, next: None, prev: Rawlink::none()}; match self.list_head { None => { @@ -221,7 +216,7 @@ impl<T> List<T> { /// Remove the first element and return it, or None if the list is empty /// /// O(1) - pub fn pop_front(&mut self) -> Option<T> { + fn pop_front(&mut self) -> Option<T> { match util::replace(&mut self.list_head, None) { None => None, Some(old_head) => { @@ -239,6 +234,14 @@ impl<T> List<T> { } } } +} + +impl<T> List<T> { + /// Create an empty List + #[inline] + pub fn new() -> List<T> { + List{list_head: None, list_tail: Rawlink::none(), length: 0} + } /// Add all elements from `other` to the end of the list /// @@ -292,7 +295,7 @@ impl<T> List<T> { { let mut it = self.mut_iter(); loop { - match (it.next(), other.peek_front()) { + match (it.next(), other.front()) { (None , _ ) => break, (_ , None ) => return, (Some(x), Some(y)) => if f(x, y) { loop } @@ -462,7 +465,7 @@ impl<'self, A> ListInsertion<A> for MutForwardIterator<'self, A> { fn peek_next<'a>(&'a mut self) -> Option<&'a mut A> { match self.curs.resolve() { - None => self.list.peek_front_mut(), + None => self.list.front_mut(), Some(curs) => match curs.next { None => None, Some(ref mut node) => Some(&mut node.value), @@ -574,14 +577,14 @@ mod tests { n.push_front(2); n.push_front(3); { - assert_eq!(n.peek_front().unwrap(), &3); - let x = n.peek_front_mut().unwrap(); + assert_eq!(n.front().unwrap(), &3); + let x = n.front_mut().unwrap(); assert_eq!(*x, 3); *x = 0; } { - assert_eq!(n.peek_back().unwrap(), &2); - let y = n.peek_back_mut().unwrap(); + assert_eq!(n.back().unwrap(), &2); + let y = n.back_mut().unwrap(); assert_eq!(*y, 2); *y = 1; } From a8e7bdd142e6cc0cac89a88eef3bbadceb5e6489 Mon Sep 17 00:00:00 2001 From: blake2-ppc <blake2-ppc> Date: Wed, 10 Jul 2013 16:06:09 +0200 Subject: [PATCH 10/12] dlist: Fix license header --- src/libextra/dlist.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libextra/dlist.rs b/src/libextra/dlist.rs index edbcdc1ff76..969340ffeaa 100644 --- a/src/libextra/dlist.rs +++ b/src/libextra/dlist.rs @@ -1,3 +1,12 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. //! A doubly-linked list with owned nodes. //! From b2b88b326d476425f66d1def14aef3fd286d5aec Mon Sep 17 00:00:00 2001 From: blake2-ppc <blake2-ppc> Date: Thu, 11 Jul 2013 15:47:52 +0200 Subject: [PATCH 11/12] dlist: Name the type DList for doubly-linked list --- src/libextra/dlist.rs | 134 +++++++++++++++++++------------------- src/libextra/serialize.rs | 10 +-- 2 files changed, 72 insertions(+), 72 deletions(-) diff --git a/src/libextra/dlist.rs b/src/libextra/dlist.rs index 969340ffeaa..18629f8597c 100644 --- a/src/libextra/dlist.rs +++ b/src/libextra/dlist.rs @@ -10,13 +10,13 @@ //! A doubly-linked list with owned nodes. //! -//! The List allows pushing and popping elements at either end. +//! The DList allows pushing and popping elements at either end. -// List is constructed like a singly-linked list over the field `next`. +// DList is constructed like a singly-linked list over the field `next`. // including the last link being None; each Node owns its `next` field. // -// Backlinks over List::prev are raw pointers that form a full chain in +// Backlinks over DList::prev are raw pointers that form a full chain in // the reverse direction. use std::cast; @@ -28,7 +28,7 @@ use std::iterator::FromIterator; use container::Deque; /// A doubly-linked list -pub struct List<T> { +pub struct DList<T> { priv length: uint, priv list_head: Link<T>, priv list_tail: Rawlink<Node<T>>, @@ -43,42 +43,42 @@ struct Node<T> { priv value: T, } -/// List iterator +/// DList iterator pub struct ForwardIterator<'self, T> { - priv list: &'self List<T>, + priv list: &'self DList<T>, priv next: &'self Link<T>, priv nelem: uint, } -/// List reverse iterator +/// DList reverse iterator pub struct ReverseIterator<'self, T> { - priv list: &'self List<T>, + priv list: &'self DList<T>, priv next: Rawlink<Node<T>>, priv nelem: uint, } -/// List mutable iterator +/// DList mutable iterator pub struct MutForwardIterator<'self, T> { - priv list: &'self mut List<T>, + priv list: &'self mut DList<T>, priv curs: Rawlink<Node<T>>, priv nelem: uint, } -/// List mutable reverse iterator +/// DList mutable reverse iterator pub struct MutReverseIterator<'self, T> { - priv list: &'self mut List<T>, + priv list: &'self mut DList<T>, priv next: Rawlink<Node<T>>, priv nelem: uint, } -/// List consuming iterator +/// DList consuming iterator pub struct ConsumeIterator<T> { - priv list: List<T> + priv list: DList<T> } -/// List reverse consuming iterator +/// DList reverse consuming iterator pub struct ConsumeRevIterator<T> { - priv list: List<T> + priv list: DList<T> } /// Rawlink is a type like Option<T> but for holding a raw pointer @@ -114,7 +114,7 @@ fn link_with_prev<T>(mut next: ~Node<T>, prev: Rawlink<Node<T>>) -> Link<T> { Some(next) } -impl<T> Container for List<T> { +impl<T> Container for DList<T> { /// O(1) fn is_empty(&self) -> bool { self.list_head.is_none() @@ -125,16 +125,16 @@ impl<T> Container for List<T> { } } -impl<T> Mutable for List<T> { - /// Remove all elements from the List +impl<T> Mutable for DList<T> { + /// Remove all elements from the DList /// /// O(N) fn clear(&mut self) { - *self = List::new() + *self = DList::new() } } -impl<T> Deque<T> for List<T> { +impl<T> Deque<T> for DList<T> { /// Provide a reference to the front element, or None if the list is empty fn front<'a>(&'a self) -> Option<&'a T> { self.list_head.chain_ref(|x| Some(&x.value)) @@ -245,23 +245,23 @@ impl<T> Deque<T> for List<T> { } } -impl<T> List<T> { - /// Create an empty List +impl<T> DList<T> { + /// Create an empty DList #[inline] - pub fn new() -> List<T> { - List{list_head: None, list_tail: Rawlink::none(), length: 0} + pub fn new() -> DList<T> { + DList{list_head: None, list_tail: Rawlink::none(), length: 0} } /// Add all elements from `other` to the end of the list /// /// O(1) - pub fn append(&mut self, other: List<T>) { + pub fn append(&mut self, other: DList<T>) { match self.list_tail.resolve() { None => *self = other, Some(tail) => { match other { - List{list_head: None, list_tail: _, length: _} => return, - List{list_head: Some(node), list_tail: o_tail, length: o_length} => { + DList{list_head: None, list_tail: _, length: _} => return, + DList{list_head: Some(node), list_tail: o_tail, length: o_length} => { tail.next = link_with_prev(node, self.list_tail); self.list_tail = o_tail; self.length += o_length; @@ -274,7 +274,7 @@ impl<T> List<T> { /// Add all elements from `other` to the beginning of the list /// /// O(1) - pub fn prepend(&mut self, mut other: List<T>) { + pub fn prepend(&mut self, mut other: DList<T>) { util::swap(self, &mut other); self.append(other); } @@ -300,7 +300,7 @@ impl<T> List<T> { /// Merge, using the function `f`; take `a` if `f(a, b)` is true, else `b`. /// /// O(max(N, M)) - pub fn merge(&mut self, mut other: List<T>, f: &fn(&T, &T) -> bool) { + pub fn merge(&mut self, mut other: DList<T>, f: &fn(&T, &T) -> bool) { { let mut it = self.mut_iter(); loop { @@ -351,7 +351,7 @@ impl<T> List<T> { /// Insert sorted in ascending order /// /// O(N) -impl<T: cmp::TotalOrd> List<T> { +impl<T: cmp::TotalOrd> DList<T> { fn insert_ordered(&mut self, elt: T) { self.insert_when(elt, |a, b| a.cmp(b) != cmp::Less); } @@ -445,7 +445,7 @@ impl<'self, A> Iterator<&'self mut A> for MutReverseIterator<'self, A> { } } -/// Allow mutating the List while iterating +/// Allow mutating the DList while iterating pub trait ListInsertion<A> { /// Insert `elt` just previous to the most recently yielded element fn insert_before(&mut self, elt: A); @@ -497,32 +497,32 @@ impl<A> Iterator<A> for ConsumeRevIterator<A> { } } -impl<A, T: Iterator<A>> FromIterator<A, T> for List<A> { - fn from_iterator(iterator: &mut T) -> List<A> { - let mut ret = List::new(); +impl<A, T: Iterator<A>> FromIterator<A, T> for DList<A> { + fn from_iterator(iterator: &mut T) -> DList<A> { + let mut ret = DList::new(); for iterator.advance |elt| { ret.push_back(elt); } ret } } -impl<A: Eq> Eq for List<A> { - fn eq(&self, other: &List<A>) -> bool { +impl<A: Eq> Eq for DList<A> { + fn eq(&self, other: &DList<A>) -> bool { self.len() == other.len() && self.iter().zip(other.iter()).all(|(a, b)| a.eq(b)) } - fn ne(&self, other: &List<A>) -> bool { + fn ne(&self, other: &DList<A>) -> bool { !self.eq(other) } } -impl<A: Clone> Clone for List<A> { - fn clone(&self) -> List<A> { +impl<A: Clone> Clone for DList<A> { + fn clone(&self) -> DList<A> { self.iter().transform(|x| x.clone()).collect() } } #[cfg(test)] -pub fn check_links<T>(list: &List<T>) { +pub fn check_links<T>(list: &DList<T>) { let mut len = 0u; let mut last_ptr: Option<&Node<T>> = None; let mut node_ptr: &Node<T>; @@ -563,7 +563,7 @@ mod tests { #[test] fn test_basic() { - let mut m = List::new::<~int>(); + let mut m = DList::new::<~int>(); assert_eq!(m.pop_front(), None); assert_eq!(m.pop_back(), None); assert_eq!(m.pop_front(), None); @@ -582,7 +582,7 @@ mod tests { m.push_back(~7); assert_eq!(m.pop_front(), Some(~1)); - let mut n = List::new(); + let mut n = DList::new(); n.push_front(2); n.push_front(3); { @@ -602,20 +602,20 @@ mod tests { } #[cfg(test)] - fn generate_test() -> List<int> { + fn generate_test() -> DList<int> { list_from(&[0,1,2,3,4,5,6]) } #[cfg(test)] - fn list_from<T: Copy>(v: &[T]) -> List<T> { + fn list_from<T: Copy>(v: &[T]) -> DList<T> { v.iter().transform(|x| copy *x).collect() } #[test] fn test_append() { { - let mut m = List::new(); - let mut n = List::new(); + let mut m = DList::new(); + let mut n = DList::new(); n.push_back(2); m.append(n); assert_eq!(m.len(), 1); @@ -623,8 +623,8 @@ mod tests { check_links(&m); } { - let mut m = List::new(); - let n = List::new(); + let mut m = DList::new(); + let n = DList::new(); m.push_back(2); m.append(n); assert_eq!(m.len(), 1); @@ -647,8 +647,8 @@ mod tests { #[test] fn test_prepend() { { - let mut m = List::new(); - let mut n = List::new(); + let mut m = DList::new(); + let mut n = DList::new(); n.push_back(2); m.prepend(n); assert_eq!(m.len(), 1); @@ -674,7 +674,7 @@ mod tests { for m.iter().enumerate().advance |(i, elt)| { assert_eq!(i as int, *elt); } - let mut n = List::new(); + let mut n = DList::new(); assert_eq!(n.iter().next(), None); n.push_front(4); let mut it = n.iter(); @@ -690,7 +690,7 @@ mod tests { for m.rev_iter().enumerate().advance |(i, elt)| { assert_eq!((6 - i) as int, *elt); } - let mut n = List::new(); + let mut n = DList::new(); assert_eq!(n.rev_iter().next(), None); n.push_front(4); let mut it = n.rev_iter(); @@ -709,7 +709,7 @@ mod tests { len -= 1; } assert_eq!(len, 0); - let mut n = List::new(); + let mut n = DList::new(); assert!(n.mut_iter().next().is_none()); n.push_front(4); let mut it = n.mut_iter(); @@ -760,12 +760,12 @@ mod tests { #[test] fn test_insert_ordered() { - let mut n = List::new(); + let mut n = DList::new(); n.insert_ordered(1); assert_eq!(n.len(), 1); assert_eq!(n.pop_front(), Some(1)); - let mut m = List::new(); + let mut m = DList::new(); m.push_back(2); m.push_back(4); m.insert_ordered(3); @@ -779,7 +779,7 @@ mod tests { for m.mut_rev_iter().enumerate().advance |(i, elt)| { assert_eq!((6-i) as int, *elt); } - let mut n = List::new(); + let mut n = DList::new(); assert!(n.mut_rev_iter().next().is_none()); n.push_front(4); let mut it = n.mut_rev_iter(); @@ -798,7 +798,7 @@ mod tests { #[test] fn test_eq() { - let mut n: List<u8> = list_from([]); + let mut n: DList<u8> = list_from([]); let mut m = list_from([]); assert_eq!(&n, &m); n.push_front(1); @@ -818,7 +818,7 @@ mod tests { #[cfg(test)] fn fuzz_test(sz: int) { - let mut m = List::new::<int>(); + let mut m = DList::new::<int>(); let mut v = ~[]; for int::range(0i, sz) |i| { check_links(&m); @@ -857,7 +857,7 @@ mod tests { fn bench_collect_into(b: &mut test::BenchHarness) { let v = &[0, ..64]; do b.iter { - let _: List<int> = v.iter().transform(|&x|x).collect(); + let _: DList<int> = v.iter().transform(|&x|x).collect(); } } #[bench] @@ -870,7 +870,7 @@ mod tests { #[bench] fn bench_push_front(b: &mut test::BenchHarness) { - let mut m = List::new::<int>(); + let mut m = DList::new::<int>(); do b.iter { m.push_front(0); } @@ -886,7 +886,7 @@ mod tests { #[bench] fn bench_push_back(b: &mut test::BenchHarness) { - let mut m = List::new::<int>(); + let mut m = DList::new::<int>(); do b.iter { m.push_back(0); } @@ -901,7 +901,7 @@ mod tests { #[bench] fn bench_push_back_pop_back(b: &mut test::BenchHarness) { - let mut m = List::new::<int>(); + let mut m = DList::new::<int>(); do b.iter { m.push_back(0); m.pop_back(); @@ -919,7 +919,7 @@ mod tests { #[bench] fn bench_iter(b: &mut test::BenchHarness) { let v = &[0, ..128]; - let m: List<int> = v.iter().transform(|&x|x).collect(); + let m: DList<int> = v.iter().transform(|&x|x).collect(); do b.iter { for m.iter().advance |_| {} } @@ -927,7 +927,7 @@ mod tests { #[bench] fn bench_iter_mut(b: &mut test::BenchHarness) { let v = &[0, ..128]; - let mut m: List<int> = v.iter().transform(|&x|x).collect(); + let mut m: DList<int> = v.iter().transform(|&x|x).collect(); do b.iter { for m.mut_iter().advance |_| {} } @@ -935,7 +935,7 @@ mod tests { #[bench] fn bench_iter_rev(b: &mut test::BenchHarness) { let v = &[0, ..128]; - let m: List<int> = v.iter().transform(|&x|x).collect(); + let m: DList<int> = v.iter().transform(|&x|x).collect(); do b.iter { for m.rev_iter().advance |_| {} } @@ -943,7 +943,7 @@ mod tests { #[bench] fn bench_iter_mut_rev(b: &mut test::BenchHarness) { let v = &[0, ..128]; - let mut m: List<int> = v.iter().transform(|&x|x).collect(); + let mut m: DList<int> = v.iter().transform(|&x|x).collect(); do b.iter { for m.mut_rev_iter().advance |_| {} } diff --git a/src/libextra/serialize.rs b/src/libextra/serialize.rs index f185f7d7321..9fec58e7495 100644 --- a/src/libextra/serialize.rs +++ b/src/libextra/serialize.rs @@ -25,7 +25,7 @@ use std::uint; use std::vec; use ringbuf::RingBuf; use container::Deque; -use dlist::List; +use dlist::DList; use treemap::{TreeMap, TreeSet}; pub trait Encoder { @@ -653,7 +653,7 @@ impl< impl< S: Encoder, T: Encodable<S> + Copy -> Encodable<S> for List<T> { +> Encodable<S> for DList<T> { fn encode(&self, s: &mut S) { do s.emit_seq(self.len()) |s| { let mut i = 0; @@ -665,9 +665,9 @@ impl< } } -impl<D:Decoder,T:Decodable<D>> Decodable<D> for List<T> { - fn decode(d: &mut D) -> List<T> { - let mut list = List::new(); +impl<D:Decoder,T:Decodable<D>> Decodable<D> for DList<T> { + fn decode(d: &mut D) -> DList<T> { + let mut list = DList::new(); do d.read_seq |d, len| { for uint::range(0, len) |i| { list.push_back(d.read_seq_elt(i, |d| Decodable::decode(d))); From 0f9b9a5fb7348471e9d51bcc298667c71647e0e1 Mon Sep 17 00:00:00 2001 From: blake2-ppc <blake2-ppc> Date: Thu, 11 Jul 2013 16:17:51 +0200 Subject: [PATCH 12/12] extra: Mention extra::container::Deque trait in doc for RingBuf and DList --- src/libextra/dlist.rs | 5 ++++- src/libextra/ringbuf.rs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libextra/dlist.rs b/src/libextra/dlist.rs index 18629f8597c..fc6d05fcb58 100644 --- a/src/libextra/dlist.rs +++ b/src/libextra/dlist.rs @@ -11,6 +11,9 @@ //! A doubly-linked list with owned nodes. //! //! The DList allows pushing and popping elements at either end. +//! +//! DList implements the trait Deque. It should be imported with `use +//! extra::container::Deque`. // DList is constructed like a singly-linked list over the field `next`. @@ -27,7 +30,7 @@ use std::iterator::FromIterator; use container::Deque; -/// A doubly-linked list +/// A doubly-linked list. pub struct DList<T> { priv length: uint, priv list_head: Link<T>, diff --git a/src/libextra/ringbuf.rs b/src/libextra/ringbuf.rs index 28eab9d9012..1d429a18a5c 100644 --- a/src/libextra/ringbuf.rs +++ b/src/libextra/ringbuf.rs @@ -9,6 +9,9 @@ // except according to those terms. //! A double-ended queue implemented as a circular buffer +//! +//! RingBuf implements the trait Deque. It should be imported with `use +//! extra::container::Deque`. use std::num; use std::util; @@ -21,7 +24,7 @@ use container::Deque; static INITIAL_CAPACITY: uint = 8u; // 2^3 static MINIMUM_CAPACITY: uint = 2u; -#[allow(missing_doc)] +/// RingBuf is a circular buffer that implements Deque. #[deriving(Clone)] pub struct RingBuf<T> { priv nelts: uint,