Deprecate the rev_iter pattern in all places where a DoubleEndedIterator is provided (everywhere but treemap)
This commit deprecates rev_iter, mut_rev_iter, move_rev_iter everywhere (except treemap) and also
deprecates related functions like rsplit, rev_components, and rev_str_components. In every case,
these functions can be replaced with the non-reversed form followed by a call to .rev(). To make this
more concrete, a translation table for all functional changes necessary follows:
* container.rev_iter() -> container.iter().rev()
* container.mut_rev_iter() -> container.mut_iter().rev()
* container.move_rev_iter() -> container.move_iter().rev()
* sliceorstr.rsplit(sep) -> sliceorstr.split(sep).rev()
* path.rev_components() -> path.components().rev()
* path.rev_str_components() -> path.str_components().rev()
In terms of the type system, this change also deprecates any specialized reversed iterator types (except
in treemap), opting instead to use Rev directly if any type annotations are needed. However, since
methods directly returning reversed iterators are now discouraged, the need for such annotations should
be small. However, in those cases, the general pattern for conversion is to take whatever follows Rev in
the original reversed name and surround it with Rev<>:
* RevComponents<'a> -> Rev<Components<'a>>
* RevStrComponents<'a> -> Rev<StrComponents<'a>>
* RevItems<'a, T> -> Rev<Items<'a, T>>
* etc.
The reasoning behind this change is that it makes the standard API much simpler without reducing readability,
performance, or power. The presence of functions such as rev_iter adds more boilerplate code to libraries
(all of which simply call .iter().rev()), clutters up the documentation, and only helps code by saving two
characters. Additionally, the numerous type synonyms that were used to make the type signatures look nice
like RevItems add even more boilerplate and clutter up the docs even more. With this change, all that cruft
goes away.
[breaking-change]
2014-04-20 23:59:12 -05:00
|
|
|
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 18:48:01 -06:00
|
|
|
// 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.
|
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
//! A double-ended queue implemented as a circular buffer.
|
2013-07-11 09:17:51 -05:00
|
|
|
//!
|
2014-08-04 05:48:39 -05:00
|
|
|
//! `RingBuf` implements the trait `Deque`. It should be imported with
|
|
|
|
//! `use collections::Deque`.
|
2013-05-17 17:28:44 -05:00
|
|
|
|
std: Recreate a `collections` module
As with the previous commit with `librand`, this commit shuffles around some
`collections` code. The new state of the world is similar to that of librand:
* The libcollections crate now only depends on libcore and liballoc.
* The standard library has a new module, `std::collections`. All functionality
of libcollections is reexported through this module.
I would like to stress that this change is purely cosmetic. There are very few
alterations to these primitives.
There are a number of notable points about the new organization:
* std::{str, slice, string, vec} all moved to libcollections. There is no reason
that these primitives shouldn't be necessarily usable in a freestanding
context that has allocation. These are all reexported in their usual places in
the standard library.
* The `hashmap`, and transitively the `lru_cache`, modules no longer reside in
`libcollections`, but rather in libstd. The reason for this is because the
`HashMap::new` contructor requires access to the OSRng for initially seeding
the hash map. Beyond this requirement, there is no reason that the hashmap
could not move to libcollections.
I do, however, have a plan to move the hash map to the collections module. The
`HashMap::new` function could be altered to require that the `H` hasher
parameter ascribe to the `Default` trait, allowing the entire `hashmap` module
to live in libcollections. The key idea would be that the default hasher would
be different in libstd. Something along the lines of:
// src/libstd/collections/mod.rs
pub type HashMap<K, V, H = RandomizedSipHasher> =
core_collections::HashMap<K, V, H>;
This is not possible today because you cannot invoke static methods through
type aliases. If we modified the compiler, however, to allow invocation of
static methods through type aliases, then this type definition would
essentially be switching the default hasher from `SipHasher` in libcollections
to a libstd-defined `RandomizedSipHasher` type. This type's `Default`
implementation would randomly seed the `SipHasher` instance, and otherwise
perform the same as `SipHasher`.
This future state doesn't seem incredibly far off, but until that time comes,
the hashmap module will live in libstd to not compromise on functionality.
* In preparation for the hashmap moving to libcollections, the `hash` module has
moved from libstd to libcollections. A previously snapshotted commit enables a
distinct `Writer` trait to live in the `hash` module which `Hash`
implementations are now parameterized over.
Due to using a custom trait, the `SipHasher` implementation has lost its
specialized methods for writing integers. These can be re-added
backwards-compatibly in the future via default methods if necessary, but the
FNV hashing should satisfy much of the need for speedier hashing.
A list of breaking changes:
* HashMap::{get, get_mut} no longer fails with the key formatted into the error
message with `{:?}`, instead, a generic message is printed. With backtraces,
it should still be not-too-hard to track down errors.
* The HashMap, HashSet, and LruCache types are now available through
std::collections instead of the collections crate.
* Manual implementations of hash should be parameterized over `hash::Writer`
instead of just `Writer`.
[breaking-change]
2014-05-29 20:50:12 -05:00
|
|
|
use core::prelude::*;
|
|
|
|
|
|
|
|
use core::cmp;
|
2014-06-09 02:30:04 -05:00
|
|
|
use core::default::Default;
|
std: Recreate a `collections` module
As with the previous commit with `librand`, this commit shuffles around some
`collections` code. The new state of the world is similar to that of librand:
* The libcollections crate now only depends on libcore and liballoc.
* The standard library has a new module, `std::collections`. All functionality
of libcollections is reexported through this module.
I would like to stress that this change is purely cosmetic. There are very few
alterations to these primitives.
There are a number of notable points about the new organization:
* std::{str, slice, string, vec} all moved to libcollections. There is no reason
that these primitives shouldn't be necessarily usable in a freestanding
context that has allocation. These are all reexported in their usual places in
the standard library.
* The `hashmap`, and transitively the `lru_cache`, modules no longer reside in
`libcollections`, but rather in libstd. The reason for this is because the
`HashMap::new` contructor requires access to the OSRng for initially seeding
the hash map. Beyond this requirement, there is no reason that the hashmap
could not move to libcollections.
I do, however, have a plan to move the hash map to the collections module. The
`HashMap::new` function could be altered to require that the `H` hasher
parameter ascribe to the `Default` trait, allowing the entire `hashmap` module
to live in libcollections. The key idea would be that the default hasher would
be different in libstd. Something along the lines of:
// src/libstd/collections/mod.rs
pub type HashMap<K, V, H = RandomizedSipHasher> =
core_collections::HashMap<K, V, H>;
This is not possible today because you cannot invoke static methods through
type aliases. If we modified the compiler, however, to allow invocation of
static methods through type aliases, then this type definition would
essentially be switching the default hasher from `SipHasher` in libcollections
to a libstd-defined `RandomizedSipHasher` type. This type's `Default`
implementation would randomly seed the `SipHasher` instance, and otherwise
perform the same as `SipHasher`.
This future state doesn't seem incredibly far off, but until that time comes,
the hashmap module will live in libstd to not compromise on functionality.
* In preparation for the hashmap moving to libcollections, the `hash` module has
moved from libstd to libcollections. A previously snapshotted commit enables a
distinct `Writer` trait to live in the `hash` module which `Hash`
implementations are now parameterized over.
Due to using a custom trait, the `SipHasher` implementation has lost its
specialized methods for writing integers. These can be re-added
backwards-compatibly in the future via default methods if necessary, but the
FNV hashing should satisfy much of the need for speedier hashing.
A list of breaking changes:
* HashMap::{get, get_mut} no longer fails with the key formatted into the error
message with `{:?}`, instead, a generic message is printed. With backtraces,
it should still be not-too-hard to track down errors.
* The HashMap, HashSet, and LruCache types are now available through
std::collections instead of the collections crate.
* Manual implementations of hash should be parameterized over `hash::Writer`
instead of just `Writer`.
[breaking-change]
2014-05-29 20:50:12 -05:00
|
|
|
use core::fmt;
|
2014-07-26 22:18:56 -05:00
|
|
|
use core::iter;
|
2014-07-26 21:33:47 -05:00
|
|
|
use std::hash::{Writer, Hash};
|
2013-05-05 23:42:54 -05:00
|
|
|
|
2014-08-12 22:31:30 -05:00
|
|
|
use {Deque, Mutable, MutableSeq};
|
std: Recreate a `collections` module
As with the previous commit with `librand`, this commit shuffles around some
`collections` code. The new state of the world is similar to that of librand:
* The libcollections crate now only depends on libcore and liballoc.
* The standard library has a new module, `std::collections`. All functionality
of libcollections is reexported through this module.
I would like to stress that this change is purely cosmetic. There are very few
alterations to these primitives.
There are a number of notable points about the new organization:
* std::{str, slice, string, vec} all moved to libcollections. There is no reason
that these primitives shouldn't be necessarily usable in a freestanding
context that has allocation. These are all reexported in their usual places in
the standard library.
* The `hashmap`, and transitively the `lru_cache`, modules no longer reside in
`libcollections`, but rather in libstd. The reason for this is because the
`HashMap::new` contructor requires access to the OSRng for initially seeding
the hash map. Beyond this requirement, there is no reason that the hashmap
could not move to libcollections.
I do, however, have a plan to move the hash map to the collections module. The
`HashMap::new` function could be altered to require that the `H` hasher
parameter ascribe to the `Default` trait, allowing the entire `hashmap` module
to live in libcollections. The key idea would be that the default hasher would
be different in libstd. Something along the lines of:
// src/libstd/collections/mod.rs
pub type HashMap<K, V, H = RandomizedSipHasher> =
core_collections::HashMap<K, V, H>;
This is not possible today because you cannot invoke static methods through
type aliases. If we modified the compiler, however, to allow invocation of
static methods through type aliases, then this type definition would
essentially be switching the default hasher from `SipHasher` in libcollections
to a libstd-defined `RandomizedSipHasher` type. This type's `Default`
implementation would randomly seed the `SipHasher` instance, and otherwise
perform the same as `SipHasher`.
This future state doesn't seem incredibly far off, but until that time comes,
the hashmap module will live in libstd to not compromise on functionality.
* In preparation for the hashmap moving to libcollections, the `hash` module has
moved from libstd to libcollections. A previously snapshotted commit enables a
distinct `Writer` trait to live in the `hash` module which `Hash`
implementations are now parameterized over.
Due to using a custom trait, the `SipHasher` implementation has lost its
specialized methods for writing integers. These can be re-added
backwards-compatibly in the future via default methods if necessary, but the
FNV hashing should satisfy much of the need for speedier hashing.
A list of breaking changes:
* HashMap::{get, get_mut} no longer fails with the key formatted into the error
message with `{:?}`, instead, a generic message is printed. With backtraces,
it should still be not-too-hard to track down errors.
* The HashMap, HashSet, and LruCache types are now available through
std::collections instead of the collections crate.
* Manual implementations of hash should be parameterized over `hash::Writer`
instead of just `Writer`.
[breaking-change]
2014-05-29 20:50:12 -05:00
|
|
|
use vec::Vec;
|
2013-07-10 08:27:14 -05:00
|
|
|
|
2013-07-05 22:42:45 -05:00
|
|
|
static INITIAL_CAPACITY: uint = 8u; // 2^3
|
|
|
|
static MINIMUM_CAPACITY: uint = 2u;
|
2013-02-16 16:55:55 -06:00
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// `RingBuf` is a circular buffer that implements `Deque`.
|
2013-07-06 08:27:32 -05:00
|
|
|
#[deriving(Clone)]
|
2013-07-10 08:27:14 -05:00
|
|
|
pub struct RingBuf<T> {
|
2014-03-27 17:10:04 -05:00
|
|
|
nelts: uint,
|
|
|
|
lo: uint,
|
2014-04-05 00:45:42 -05:00
|
|
|
elts: Vec<Option<T>>
|
2012-01-11 05:49:33 -06:00
|
|
|
}
|
2010-07-20 20:03:09 -05:00
|
|
|
|
2014-05-19 13:32:09 -05:00
|
|
|
impl<T> Collection for RingBuf<T> {
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Returns the number of elements in the `RingBuf`.
|
2013-06-23 22:44:11 -05:00
|
|
|
fn len(&self) -> uint { self.nelts }
|
2013-02-16 16:55:55 -06:00
|
|
|
}
|
2010-07-20 20:03:09 -05:00
|
|
|
|
2013-07-10 08:27:14 -05:00
|
|
|
impl<T> Mutable for RingBuf<T> {
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Clears the `RingBuf`, removing all values.
|
2013-02-16 17:55:25 -06:00
|
|
|
fn clear(&mut self) {
|
2013-08-03 11:45:23 -05:00
|
|
|
for x in self.elts.mut_iter() { *x = None }
|
2013-02-16 17:55:25 -06:00
|
|
|
self.nelts = 0;
|
|
|
|
self.lo = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-10 08:27:14 -05:00
|
|
|
impl<T> Deque<T> for RingBuf<T> {
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Returns a reference to the first element in the `RingBuf`.
|
2013-07-10 08:27:14 -05:00
|
|
|
fn front<'a>(&'a self) -> Option<&'a T> {
|
2014-08-11 18:47:46 -05:00
|
|
|
if self.nelts > 0 { Some(&self[0]) } else { None }
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Returns a mutable reference to the first element in the `RingBuf`.
|
2013-07-10 08:27:14 -05:00
|
|
|
fn front_mut<'a>(&'a mut self) -> Option<&'a mut T> {
|
|
|
|
if self.nelts > 0 { Some(self.get_mut(0)) } else { None }
|
2013-04-10 15:14:06 -05:00
|
|
|
}
|
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Returns a reference to the last element in the `RingBuf`.
|
2013-07-10 08:27:14 -05:00
|
|
|
fn back<'a>(&'a self) -> Option<&'a T> {
|
2014-08-11 18:47:46 -05:00
|
|
|
if self.nelts > 0 { Some(&self[self.nelts - 1]) } else { None }
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
2013-04-10 15:14:06 -05:00
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Returns a mutable reference to the last element in the `RingBuf`.
|
2013-07-10 08:27:14 -05:00
|
|
|
fn back_mut<'a>(&'a mut self) -> Option<&'a mut T> {
|
2014-06-13 22:48:09 -05:00
|
|
|
let nelts = self.nelts;
|
|
|
|
if nelts > 0 { Some(self.get_mut(nelts - 1)) } else { None }
|
2013-04-10 15:14:06 -05:00
|
|
|
}
|
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Removes and returns the first element in the `RingBuf`, or `None` if it
|
|
|
|
/// is empty.
|
2013-07-10 08:27:14 -05:00
|
|
|
fn pop_front(&mut self) -> Option<T> {
|
2014-04-05 00:45:42 -05:00
|
|
|
let result = self.elts.get_mut(self.lo).take();
|
2013-07-10 08:27:14 -05:00
|
|
|
if result.is_some() {
|
|
|
|
self.lo = (self.lo + 1u) % self.elts.len();
|
|
|
|
self.nelts -= 1u;
|
|
|
|
}
|
2013-02-16 18:43:29 -06:00
|
|
|
result
|
|
|
|
}
|
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Prepends an element to the `RingBuf`.
|
2013-07-10 08:27:14 -05:00
|
|
|
fn push_front(&mut self, t: T) {
|
2013-07-05 22:42:45 -05:00
|
|
|
if self.nelts == self.elts.len() {
|
2013-07-05 22:42:45 -05:00
|
|
|
grow(self.nelts, &mut self.lo, &mut self.elts);
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
2013-02-16 16:55:55 -06:00
|
|
|
if self.lo == 0u {
|
|
|
|
self.lo = self.elts.len() - 1u;
|
|
|
|
} else { self.lo -= 1u; }
|
2014-04-05 00:45:42 -05:00
|
|
|
*self.elts.get_mut(self.lo) = Some(t);
|
2013-02-16 16:55:55 -06:00
|
|
|
self.nelts += 1u;
|
|
|
|
}
|
2014-07-11 20:08:46 -05:00
|
|
|
}
|
2011-07-12 16:20:15 -05:00
|
|
|
|
2014-07-11 20:08:46 -05:00
|
|
|
impl<T> MutableSeq<T> for RingBuf<T> {
|
|
|
|
fn push(&mut self, t: T) {
|
2013-07-05 22:42:45 -05:00
|
|
|
if self.nelts == self.elts.len() {
|
2013-07-05 22:42:45 -05:00
|
|
|
grow(self.nelts, &mut self.lo, &mut self.elts);
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
2013-07-05 22:42:45 -05:00
|
|
|
let hi = self.raw_index(self.nelts);
|
2014-04-05 00:45:42 -05:00
|
|
|
*self.elts.get_mut(hi) = Some(t);
|
2013-02-16 16:55:55 -06:00
|
|
|
self.nelts += 1u;
|
2010-07-20 20:03:09 -05:00
|
|
|
}
|
2014-07-11 20:08:46 -05:00
|
|
|
fn pop(&mut self) -> Option<T> {
|
|
|
|
if self.nelts > 0 {
|
|
|
|
self.nelts -= 1;
|
|
|
|
let hi = self.raw_index(self.nelts);
|
|
|
|
self.elts.get_mut(hi).take()
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
2014-07-11 12:12:38 -05:00
|
|
|
}
|
|
|
|
|
2014-06-09 02:30:04 -05:00
|
|
|
impl<T> Default for RingBuf<T> {
|
|
|
|
#[inline]
|
|
|
|
fn default() -> RingBuf<T> { RingBuf::new() }
|
|
|
|
}
|
|
|
|
|
2013-07-10 08:27:14 -05:00
|
|
|
impl<T> RingBuf<T> {
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Creates an empty `RingBuf`.
|
2013-07-10 08:27:14 -05:00
|
|
|
pub fn new() -> RingBuf<T> {
|
|
|
|
RingBuf::with_capacity(INITIAL_CAPACITY)
|
|
|
|
}
|
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Creates an empty `RingBuf` with space for at least `n` elements.
|
2013-07-10 08:27:14 -05:00
|
|
|
pub fn with_capacity(n: uint) -> RingBuf<T> {
|
|
|
|
RingBuf{nelts: 0, lo: 0,
|
2014-04-05 00:45:42 -05:00
|
|
|
elts: Vec::from_fn(cmp::max(MINIMUM_CAPACITY, n), |_| None)}
|
2013-07-10 08:27:14 -05:00
|
|
|
}
|
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Retrieva an element in the `RingBuf` by index.
|
2013-07-10 08:27:14 -05:00
|
|
|
///
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Fails if there is no element with the given index.
|
2014-07-17 18:19:51 -05:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
2014-08-02 01:39:39 -05:00
|
|
|
/// #![allow(deprecated)]
|
|
|
|
///
|
2014-07-17 18:19:51 -05:00
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf = RingBuf::new();
|
|
|
|
/// buf.push(3i);
|
|
|
|
/// buf.push(4);
|
|
|
|
/// buf.push(5);
|
|
|
|
/// assert_eq!(buf.get(1), &4);
|
|
|
|
/// ```
|
2014-08-02 01:39:39 -05:00
|
|
|
#[deprecated = "prefer using indexing, e.g., ringbuf[0]"]
|
2013-07-10 08:27:14 -05:00
|
|
|
pub fn get<'a>(&'a self, i: uint) -> &'a T {
|
|
|
|
let idx = self.raw_index(i);
|
2014-08-11 18:47:46 -05:00
|
|
|
match self.elts[idx] {
|
2013-10-21 15:08:31 -05:00
|
|
|
None => fail!(),
|
2013-07-10 08:27:14 -05:00
|
|
|
Some(ref v) => v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Retrieves an element in the `RingBuf` by index.
|
2013-07-10 08:27:14 -05:00
|
|
|
///
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Fails if there is no element with the given index.
|
2014-07-17 18:19:51 -05:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf = RingBuf::new();
|
|
|
|
/// buf.push(3i);
|
|
|
|
/// buf.push(4);
|
|
|
|
/// buf.push(5);
|
|
|
|
/// *buf.get_mut(1) = 7;
|
2014-08-02 01:39:39 -05:00
|
|
|
/// assert_eq!(buf[1], 7);
|
2014-07-17 18:19:51 -05:00
|
|
|
/// ```
|
2013-07-10 08:27:14 -05:00
|
|
|
pub fn get_mut<'a>(&'a mut self, i: uint) -> &'a mut T {
|
|
|
|
let idx = self.raw_index(i);
|
2014-04-05 00:45:42 -05:00
|
|
|
match *self.elts.get_mut(idx) {
|
2013-10-21 15:08:31 -05:00
|
|
|
None => fail!(),
|
2013-07-10 08:27:14 -05:00
|
|
|
Some(ref mut v) => v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Swaps elements at indices `i` and `j`.
|
2013-09-26 02:19:26 -05:00
|
|
|
///
|
|
|
|
/// `i` and `j` may be equal.
|
|
|
|
///
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Fails if there is no element with either index.
|
2014-07-17 18:19:51 -05:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf = RingBuf::new();
|
|
|
|
/// buf.push(3i);
|
|
|
|
/// buf.push(4);
|
|
|
|
/// buf.push(5);
|
|
|
|
/// buf.swap(0, 2);
|
2014-08-02 01:39:39 -05:00
|
|
|
/// assert_eq!(buf[0], 5);
|
|
|
|
/// assert_eq!(buf[2], 3);
|
2014-07-17 18:19:51 -05:00
|
|
|
/// ```
|
2013-09-26 02:19:26 -05:00
|
|
|
pub fn swap(&mut self, i: uint, j: uint) {
|
|
|
|
assert!(i < self.len());
|
|
|
|
assert!(j < self.len());
|
|
|
|
let ri = self.raw_index(i);
|
|
|
|
let rj = self.raw_index(j);
|
2014-04-05 00:45:42 -05:00
|
|
|
self.elts.as_mut_slice().swap(ri, rj);
|
2013-09-26 02:19:26 -05:00
|
|
|
}
|
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Returns the index in the underlying `Vec` for a given logical element
|
|
|
|
/// index.
|
2013-07-10 08:27:14 -05:00
|
|
|
fn raw_index(&self, idx: uint) -> uint {
|
|
|
|
raw_index(self.lo, self.elts.len(), idx)
|
|
|
|
}
|
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Reserves capacity for exactly `n` elements in the given `RingBuf`,
|
2013-05-27 13:47:38 -05:00
|
|
|
/// doing nothing if `self`'s capacity is already equal to or greater
|
2014-08-04 05:48:39 -05:00
|
|
|
/// than the requested capacity.
|
2014-01-31 07:03:20 -06:00
|
|
|
pub fn reserve_exact(&mut self, n: uint) {
|
|
|
|
self.elts.reserve_exact(n);
|
2013-05-27 13:47:38 -05:00
|
|
|
}
|
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Reserves capacity for at least `n` elements in the given `RingBuf`,
|
2013-05-27 13:47:38 -05:00
|
|
|
/// over-allocating in case the caller needs to reserve additional
|
|
|
|
/// space.
|
|
|
|
///
|
|
|
|
/// Do nothing if `self`'s capacity is already equal to or greater
|
|
|
|
/// than the requested capacity.
|
2014-01-31 07:03:20 -06:00
|
|
|
pub fn reserve(&mut self, n: uint) {
|
|
|
|
self.elts.reserve(n);
|
2013-05-27 13:47:38 -05:00
|
|
|
}
|
2013-06-25 14:08:47 -05:00
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Returns a front-to-back iterator.
|
2014-07-17 18:19:51 -05:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf = RingBuf::new();
|
|
|
|
/// buf.push(5i);
|
|
|
|
/// buf.push(3);
|
|
|
|
/// buf.push(4);
|
|
|
|
/// assert_eq!(buf.iter().collect::<Vec<&int>>().as_slice(), &[&5, &3, &4]);
|
|
|
|
/// ```
|
2014-01-14 21:32:24 -06:00
|
|
|
pub fn iter<'a>(&'a self) -> Items<'a, T> {
|
2014-04-05 00:45:42 -05:00
|
|
|
Items{index: 0, rindex: self.nelts, lo: self.lo, elts: self.elts.as_slice()}
|
2013-06-25 14:08:47 -05:00
|
|
|
}
|
2013-06-26 17:14:35 -05:00
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Returns a front-to-back iterator which returns mutable references.
|
2014-07-17 18:19:51 -05:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf = RingBuf::new();
|
|
|
|
/// buf.push(5i);
|
|
|
|
/// buf.push(3);
|
|
|
|
/// buf.push(4);
|
|
|
|
/// for num in buf.mut_iter() {
|
|
|
|
/// *num = *num - 2;
|
|
|
|
/// }
|
|
|
|
/// assert_eq!(buf.mut_iter().collect::<Vec<&mut int>>().as_slice(), &[&mut 3, &mut 1, &mut 2]);
|
|
|
|
/// ```
|
2014-01-14 21:32:24 -06:00
|
|
|
pub fn mut_iter<'a>(&'a mut self) -> MutItems<'a, T> {
|
2013-11-16 16:29:39 -06:00
|
|
|
let start_index = raw_index(self.lo, self.elts.len(), 0);
|
|
|
|
let end_index = raw_index(self.lo, self.elts.len(), self.nelts);
|
|
|
|
|
|
|
|
// Divide up the array
|
|
|
|
if end_index <= start_index {
|
|
|
|
// Items to iterate goes from:
|
|
|
|
// start_index to self.elts.len()
|
|
|
|
// and then
|
|
|
|
// 0 to end_index
|
2013-12-01 11:19:39 -06:00
|
|
|
let (temp, remaining1) = self.elts.mut_split_at(start_index);
|
|
|
|
let (remaining2, _) = temp.mut_split_at(end_index);
|
2014-01-14 21:32:24 -06:00
|
|
|
MutItems { remaining1: remaining1,
|
2013-11-16 16:29:39 -06:00
|
|
|
remaining2: remaining2,
|
|
|
|
nelts: self.nelts }
|
|
|
|
} else {
|
|
|
|
// Items to iterate goes from start_index to end_index:
|
2013-12-01 11:19:39 -06:00
|
|
|
let (empty, elts) = self.elts.mut_split_at(0);
|
2013-11-16 16:29:39 -06:00
|
|
|
let remaining1 = elts.mut_slice(start_index, end_index);
|
2014-01-14 21:32:24 -06:00
|
|
|
MutItems { remaining1: remaining1,
|
2013-11-16 16:29:39 -06:00
|
|
|
remaining2: empty,
|
|
|
|
nelts: self.nelts }
|
|
|
|
}
|
2013-06-25 14:08:47 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// `RingBuf` iterator.
|
2014-01-14 21:32:24 -06:00
|
|
|
pub struct Items<'a, T> {
|
2014-03-27 17:10:04 -05:00
|
|
|
lo: uint,
|
|
|
|
index: uint,
|
|
|
|
rindex: uint,
|
|
|
|
elts: &'a [Option<T>],
|
2013-11-16 16:29:39 -06:00
|
|
|
}
|
2013-07-14 15:30:22 -05:00
|
|
|
|
2014-01-14 21:32:24 -06:00
|
|
|
impl<'a, T> Iterator<&'a T> for Items<'a, T> {
|
2013-11-16 16:29:39 -06:00
|
|
|
#[inline]
|
2013-12-10 01:16:18 -06:00
|
|
|
fn next(&mut self) -> Option<&'a T> {
|
2013-11-16 16:29:39 -06:00
|
|
|
if self.index == self.rindex {
|
|
|
|
return None;
|
2013-06-26 10:38:29 -05:00
|
|
|
}
|
2013-11-16 16:29:39 -06:00
|
|
|
let raw_index = raw_index(self.lo, self.elts.len(), self.index);
|
|
|
|
self.index += 1;
|
|
|
|
Some(self.elts[raw_index].get_ref())
|
2013-06-26 10:38:29 -05:00
|
|
|
}
|
|
|
|
|
2013-11-16 16:29:39 -06:00
|
|
|
#[inline]
|
|
|
|
fn size_hint(&self) -> (uint, Option<uint>) {
|
|
|
|
let len = self.rindex - self.index;
|
|
|
|
(len, Some(len))
|
2013-07-15 18:13:26 -05:00
|
|
|
}
|
2013-06-25 14:08:47 -05:00
|
|
|
}
|
|
|
|
|
2014-01-14 21:32:24 -06:00
|
|
|
impl<'a, T> DoubleEndedIterator<&'a T> for Items<'a, T> {
|
2013-11-16 16:29:39 -06:00
|
|
|
#[inline]
|
2013-12-10 01:16:18 -06:00
|
|
|
fn next_back(&mut self) -> Option<&'a T> {
|
2013-11-16 16:29:39 -06:00
|
|
|
if self.index == self.rindex {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
self.rindex -= 1;
|
|
|
|
let raw_index = raw_index(self.lo, self.elts.len(), self.rindex);
|
|
|
|
Some(self.elts[raw_index].get_ref())
|
|
|
|
}
|
2013-06-25 14:08:47 -05:00
|
|
|
}
|
2013-06-26 10:38:29 -05:00
|
|
|
|
2014-01-14 21:32:24 -06:00
|
|
|
impl<'a, T> ExactSize<&'a T> for Items<'a, T> {}
|
2013-09-01 11:20:24 -05:00
|
|
|
|
2014-01-14 21:32:24 -06:00
|
|
|
impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> {
|
2013-07-29 13:16:26 -05:00
|
|
|
#[inline]
|
|
|
|
fn indexable(&self) -> uint { self.rindex - self.index }
|
|
|
|
|
|
|
|
#[inline]
|
2014-04-22 00:15:42 -05:00
|
|
|
fn idx(&mut self, j: uint) -> Option<&'a T> {
|
2013-07-29 13:16:26 -05:00
|
|
|
if j >= self.indexable() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
let raw_index = raw_index(self.lo, self.elts.len(), self.index + j);
|
|
|
|
Some(self.elts[raw_index].get_ref())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// `RingBuf` mutable iterator.
|
2014-01-14 21:32:24 -06:00
|
|
|
pub struct MutItems<'a, T> {
|
2014-03-27 17:10:04 -05:00
|
|
|
remaining1: &'a mut [Option<T>],
|
|
|
|
remaining2: &'a mut [Option<T>],
|
|
|
|
nelts: uint,
|
2013-11-16 16:29:39 -06:00
|
|
|
}
|
|
|
|
|
2014-01-14 21:32:24 -06:00
|
|
|
impl<'a, T> Iterator<&'a mut T> for MutItems<'a, T> {
|
2013-11-16 16:29:39 -06:00
|
|
|
#[inline]
|
2014-08-07 01:59:12 -05:00
|
|
|
#[allow(deprecated)] // mut_shift_ref
|
2013-12-10 01:16:18 -06:00
|
|
|
fn next(&mut self) -> Option<&'a mut T> {
|
2013-11-16 16:29:39 -06:00
|
|
|
if self.nelts == 0 {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
let r = if self.remaining1.len() > 0 {
|
|
|
|
&mut self.remaining1
|
|
|
|
} else {
|
|
|
|
assert!(self.remaining2.len() > 0);
|
|
|
|
&mut self.remaining2
|
|
|
|
};
|
|
|
|
self.nelts -= 1;
|
2014-01-25 11:00:46 -06:00
|
|
|
Some(r.mut_shift_ref().unwrap().get_mut_ref())
|
2013-11-16 16:29:39 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn size_hint(&self) -> (uint, Option<uint>) {
|
|
|
|
(self.nelts, Some(self.nelts))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-14 21:32:24 -06:00
|
|
|
impl<'a, T> DoubleEndedIterator<&'a mut T> for MutItems<'a, T> {
|
2013-11-16 16:29:39 -06:00
|
|
|
#[inline]
|
2014-08-07 01:59:12 -05:00
|
|
|
#[allow(deprecated)] // mut_shift_ref
|
2013-12-10 01:16:18 -06:00
|
|
|
fn next_back(&mut self) -> Option<&'a mut T> {
|
2013-11-16 16:29:39 -06:00
|
|
|
if self.nelts == 0 {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
let r = if self.remaining2.len() > 0 {
|
|
|
|
&mut self.remaining2
|
|
|
|
} else {
|
|
|
|
assert!(self.remaining1.len() > 0);
|
|
|
|
&mut self.remaining1
|
|
|
|
};
|
|
|
|
self.nelts -= 1;
|
2014-01-25 14:33:31 -06:00
|
|
|
Some(r.mut_pop_ref().unwrap().get_mut_ref())
|
2013-11-16 16:29:39 -06:00
|
|
|
}
|
2013-06-25 14:08:47 -05:00
|
|
|
}
|
2012-01-11 05:49:33 -06:00
|
|
|
|
2014-01-14 21:32:24 -06:00
|
|
|
impl<'a, T> ExactSize<&'a mut T> for MutItems<'a, T> {}
|
2013-09-01 11:20:24 -05:00
|
|
|
|
2013-02-16 16:55:55 -06:00
|
|
|
/// Grow is only called on full elts, so nelts is also len(elts), unlike
|
|
|
|
/// elsewhere.
|
2014-04-05 00:45:42 -05:00
|
|
|
fn grow<T>(nelts: uint, loptr: &mut uint, elts: &mut Vec<Option<T>>) {
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(nelts, elts.len());
|
2013-07-05 22:42:45 -05:00
|
|
|
let lo = *loptr;
|
2014-08-06 20:11:13 -05:00
|
|
|
elts.reserve(nelts * 2);
|
|
|
|
let newlen = elts.capacity();
|
2013-02-16 16:55:55 -06:00
|
|
|
|
2013-07-05 22:42:45 -05:00
|
|
|
/* fill with None */
|
2014-08-06 20:11:13 -05:00
|
|
|
for _ in range(elts.len(), newlen) {
|
2013-07-05 22:42:45 -05:00
|
|
|
elts.push(None);
|
|
|
|
}
|
2013-07-05 22:42:45 -05:00
|
|
|
|
|
|
|
/*
|
|
|
|
Move the shortest half into the newly reserved area.
|
|
|
|
lo ---->|
|
|
|
|
nelts ----------->|
|
|
|
|
[o o o|o o o o o]
|
|
|
|
A [. . .|o o o o o o o o|. . . . .]
|
|
|
|
B [o o o|. . . . . . . .|o o o o o]
|
|
|
|
*/
|
|
|
|
|
|
|
|
assert!(newlen - nelts/2 >= nelts);
|
|
|
|
if lo <= (nelts - lo) { // A
|
2013-08-03 11:45:23 -05:00
|
|
|
for i in range(0u, lo) {
|
2014-04-05 00:45:42 -05:00
|
|
|
elts.as_mut_slice().swap(i, nelts + i);
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
|
|
|
} else { // B
|
2013-08-03 11:45:23 -05:00
|
|
|
for i in range(lo, nelts) {
|
2014-04-05 00:45:42 -05:00
|
|
|
elts.as_mut_slice().swap(i, newlen - nelts + i);
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
|
|
|
*loptr += newlen - nelts;
|
2013-02-16 16:55:55 -06:00
|
|
|
}
|
|
|
|
}
|
2013-01-22 10:44:24 -06:00
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Returns the index in the underlying `Vec` for a given logical element index.
|
2013-07-05 22:42:45 -05:00
|
|
|
fn raw_index(lo: uint, len: uint, index: uint) -> uint {
|
|
|
|
if lo >= len - index {
|
|
|
|
lo + index - len
|
|
|
|
} else {
|
|
|
|
lo + index
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-29 19:45:07 -05:00
|
|
|
impl<A: PartialEq> PartialEq for RingBuf<A> {
|
2013-07-10 08:27:14 -05:00
|
|
|
fn eq(&self, other: &RingBuf<A>) -> bool {
|
2013-07-06 08:27:32 -05:00
|
|
|
self.nelts == other.nelts &&
|
|
|
|
self.iter().zip(other.iter()).all(|(a, b)| a.eq(b))
|
|
|
|
}
|
2013-07-10 08:27:14 -05:00
|
|
|
fn ne(&self, other: &RingBuf<A>) -> bool {
|
2013-07-06 08:27:32 -05:00
|
|
|
!self.eq(other)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-01 15:05:03 -05:00
|
|
|
impl<A: Eq> Eq for RingBuf<A> {}
|
|
|
|
|
2014-07-26 22:18:56 -05:00
|
|
|
impl<A: PartialOrd> PartialOrd for RingBuf<A> {
|
|
|
|
fn partial_cmp(&self, other: &RingBuf<A>) -> Option<Ordering> {
|
|
|
|
iter::order::partial_cmp(self.iter(), other.iter())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-01 15:22:48 -05:00
|
|
|
impl<A: Ord> Ord for RingBuf<A> {
|
|
|
|
#[inline]
|
|
|
|
fn cmp(&self, other: &RingBuf<A>) -> Ordering {
|
|
|
|
iter::order::cmp(self.iter(), other.iter())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-26 21:33:47 -05:00
|
|
|
impl<S: Writer, A: Hash<S>> Hash<S> for RingBuf<A> {
|
|
|
|
fn hash(&self, state: &mut S) {
|
2014-07-27 11:37:32 -05:00
|
|
|
self.len().hash(state);
|
2014-07-26 21:33:47 -05:00
|
|
|
for elt in self.iter() {
|
|
|
|
elt.hash(state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-02 01:39:39 -05:00
|
|
|
impl<A> Index<uint, A> for RingBuf<A> {
|
|
|
|
#[inline]
|
2014-08-11 18:47:46 -05:00
|
|
|
#[allow(deprecated)]
|
2014-08-02 01:39:39 -05:00
|
|
|
fn index<'a>(&'a self, i: &uint) -> &'a A {
|
|
|
|
self.get(*i)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME(#12825) Indexing will always try IndexMut first and that causes issues.
|
|
|
|
/*impl<A> IndexMut<uint, A> for RingBuf<A> {
|
|
|
|
#[inline]
|
|
|
|
fn index_mut<'a>(&'a mut self, index: &uint) -> &'a mut A {
|
|
|
|
self.get_mut(*index)
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
|
std: Move the iterator param on FromIterator and Extendable to the method.
If they are on the trait then it is extremely annoying to use them as
generic parameters to a function, e.g. with the iterator param on the trait
itself, if one was to pass an Extendable<int> to a function that filled it
either from a Range or a Map<VecIterator>, one needs to write something
like:
fn foo<E: Extendable<int, Range<int>> +
Extendable<int, Map<&'self int, int, VecIterator<int>>>
(e: &mut E, ...) { ... }
since using a generic, i.e. `foo<E: Extendable<int, I>, I: Iterator<int>>`
means that `foo` takes 2 type parameters, and the caller has to specify them
(which doesn't work anyway, as they'll mismatch with the iterators used in
`foo` itself).
This patch changes it to:
fn foo<E: Extendable<int>>(e: &mut E, ...) { ... }
2013-08-13 08:08:14 -05:00
|
|
|
impl<A> FromIterator<A> for RingBuf<A> {
|
2014-03-30 23:45:55 -05:00
|
|
|
fn from_iter<T: Iterator<A>>(iterator: T) -> RingBuf<A> {
|
2013-07-29 19:06:49 -05:00
|
|
|
let (lower, _) = iterator.size_hint();
|
|
|
|
let mut deq = RingBuf::with_capacity(lower);
|
|
|
|
deq.extend(iterator);
|
|
|
|
deq
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
std: Move the iterator param on FromIterator and Extendable to the method.
If they are on the trait then it is extremely annoying to use them as
generic parameters to a function, e.g. with the iterator param on the trait
itself, if one was to pass an Extendable<int> to a function that filled it
either from a Range or a Map<VecIterator>, one needs to write something
like:
fn foo<E: Extendable<int, Range<int>> +
Extendable<int, Map<&'self int, int, VecIterator<int>>>
(e: &mut E, ...) { ... }
since using a generic, i.e. `foo<E: Extendable<int, I>, I: Iterator<int>>`
means that `foo` takes 2 type parameters, and the caller has to specify them
(which doesn't work anyway, as they'll mismatch with the iterators used in
`foo` itself).
This patch changes it to:
fn foo<E: Extendable<int>>(e: &mut E, ...) { ... }
2013-08-13 08:08:14 -05:00
|
|
|
impl<A> Extendable<A> for RingBuf<A> {
|
2014-03-20 08:12:56 -05:00
|
|
|
fn extend<T: Iterator<A>>(&mut self, mut iterator: T) {
|
|
|
|
for elt in iterator {
|
2014-08-11 18:47:46 -05:00
|
|
|
self.push(elt);
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
std: Recreate a `collections` module
As with the previous commit with `librand`, this commit shuffles around some
`collections` code. The new state of the world is similar to that of librand:
* The libcollections crate now only depends on libcore and liballoc.
* The standard library has a new module, `std::collections`. All functionality
of libcollections is reexported through this module.
I would like to stress that this change is purely cosmetic. There are very few
alterations to these primitives.
There are a number of notable points about the new organization:
* std::{str, slice, string, vec} all moved to libcollections. There is no reason
that these primitives shouldn't be necessarily usable in a freestanding
context that has allocation. These are all reexported in their usual places in
the standard library.
* The `hashmap`, and transitively the `lru_cache`, modules no longer reside in
`libcollections`, but rather in libstd. The reason for this is because the
`HashMap::new` contructor requires access to the OSRng for initially seeding
the hash map. Beyond this requirement, there is no reason that the hashmap
could not move to libcollections.
I do, however, have a plan to move the hash map to the collections module. The
`HashMap::new` function could be altered to require that the `H` hasher
parameter ascribe to the `Default` trait, allowing the entire `hashmap` module
to live in libcollections. The key idea would be that the default hasher would
be different in libstd. Something along the lines of:
// src/libstd/collections/mod.rs
pub type HashMap<K, V, H = RandomizedSipHasher> =
core_collections::HashMap<K, V, H>;
This is not possible today because you cannot invoke static methods through
type aliases. If we modified the compiler, however, to allow invocation of
static methods through type aliases, then this type definition would
essentially be switching the default hasher from `SipHasher` in libcollections
to a libstd-defined `RandomizedSipHasher` type. This type's `Default`
implementation would randomly seed the `SipHasher` instance, and otherwise
perform the same as `SipHasher`.
This future state doesn't seem incredibly far off, but until that time comes,
the hashmap module will live in libstd to not compromise on functionality.
* In preparation for the hashmap moving to libcollections, the `hash` module has
moved from libstd to libcollections. A previously snapshotted commit enables a
distinct `Writer` trait to live in the `hash` module which `Hash`
implementations are now parameterized over.
Due to using a custom trait, the `SipHasher` implementation has lost its
specialized methods for writing integers. These can be re-added
backwards-compatibly in the future via default methods if necessary, but the
FNV hashing should satisfy much of the need for speedier hashing.
A list of breaking changes:
* HashMap::{get, get_mut} no longer fails with the key formatted into the error
message with `{:?}`, instead, a generic message is printed. With backtraces,
it should still be not-too-hard to track down errors.
* The HashMap, HashSet, and LruCache types are now available through
std::collections instead of the collections crate.
* Manual implementations of hash should be parameterized over `hash::Writer`
instead of just `Writer`.
[breaking-change]
2014-05-29 20:50:12 -05:00
|
|
|
impl<T: fmt::Show> fmt::Show for RingBuf<T> {
|
2014-06-04 09:15:04 -05:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
try!(write!(f, "["));
|
|
|
|
|
|
|
|
for (i, e) in self.iter().enumerate() {
|
|
|
|
if i != 0 { try!(write!(f, ", ")); }
|
|
|
|
try!(write!(f, "{}", *e));
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, "]")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-17 21:05:07 -06:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2014-02-28 03:23:06 -06:00
|
|
|
use std::fmt::Show;
|
2014-05-29 21:03:06 -05:00
|
|
|
use std::prelude::*;
|
2014-06-11 21:33:52 -05:00
|
|
|
use std::gc::{GC, Gc};
|
2014-07-26 21:33:47 -05:00
|
|
|
use std::hash;
|
2014-05-29 21:03:06 -05:00
|
|
|
use test::Bencher;
|
|
|
|
use test;
|
|
|
|
|
2014-07-14 16:45:10 -05:00
|
|
|
use {Deque, Mutable, MutableSeq};
|
2014-01-07 00:33:50 -06:00
|
|
|
use super::RingBuf;
|
2014-05-29 21:03:06 -05:00
|
|
|
use vec::Vec;
|
2012-12-27 20:24:18 -06:00
|
|
|
|
2012-01-17 21:05:07 -06:00
|
|
|
#[test]
|
|
|
|
fn test_simple() {
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut d = RingBuf::new();
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(d.len(), 0u);
|
2014-04-21 16:58:52 -05:00
|
|
|
d.push_front(17i);
|
|
|
|
d.push_front(42i);
|
2013-07-10 08:27:14 -05:00
|
|
|
d.push_back(137);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(d.len(), 3u);
|
2013-07-10 08:27:14 -05:00
|
|
|
d.push_back(137);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(d.len(), 4u);
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("{:?}", d.front());
|
2013-07-10 08:27:14 -05:00
|
|
|
assert_eq!(*d.front().unwrap(), 42);
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("{:?}", d.back());
|
2013-07-10 08:27:14 -05:00
|
|
|
assert_eq!(*d.back().unwrap(), 137);
|
|
|
|
let mut i = d.pop_front();
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("{:?}", i);
|
2013-07-10 08:27:14 -05:00
|
|
|
assert_eq!(i, Some(42));
|
2012-01-17 21:05:07 -06:00
|
|
|
i = d.pop_back();
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("{:?}", i);
|
2013-07-10 08:27:14 -05:00
|
|
|
assert_eq!(i, Some(137));
|
2012-01-17 21:05:07 -06:00
|
|
|
i = d.pop_back();
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("{:?}", i);
|
2013-07-10 08:27:14 -05:00
|
|
|
assert_eq!(i, Some(137));
|
2012-01-17 21:05:07 -06:00
|
|
|
i = d.pop_back();
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("{:?}", i);
|
2013-07-10 08:27:14 -05:00
|
|
|
assert_eq!(i, Some(17));
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(d.len(), 0u);
|
2013-07-10 08:27:14 -05:00
|
|
|
d.push_back(3);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(d.len(), 1u);
|
2013-07-10 08:27:14 -05:00
|
|
|
d.push_front(2);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(d.len(), 2u);
|
2013-07-10 08:27:14 -05:00
|
|
|
d.push_back(4);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(d.len(), 3u);
|
2013-07-10 08:27:14 -05:00
|
|
|
d.push_front(1);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(d.len(), 4u);
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("{:?}", d.get(0));
|
|
|
|
debug!("{:?}", d.get(1));
|
|
|
|
debug!("{:?}", d.get(2));
|
|
|
|
debug!("{:?}", d.get(3));
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(*d.get(0), 1);
|
|
|
|
assert_eq!(*d.get(1), 2);
|
|
|
|
assert_eq!(*d.get(2), 3);
|
|
|
|
assert_eq!(*d.get(3), 4);
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
|
|
|
|
2012-09-13 00:09:55 -05:00
|
|
|
#[test]
|
|
|
|
fn test_boxes() {
|
2014-06-11 21:33:52 -05:00
|
|
|
let a: Gc<int> = box(GC) 5;
|
|
|
|
let b: Gc<int> = box(GC) 72;
|
|
|
|
let c: Gc<int> = box(GC) 64;
|
|
|
|
let d: Gc<int> = box(GC) 175;
|
2012-09-13 00:09:55 -05:00
|
|
|
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut deq = RingBuf::new();
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(deq.len(), 0);
|
2013-07-10 08:27:14 -05:00
|
|
|
deq.push_front(a);
|
|
|
|
deq.push_front(b);
|
|
|
|
deq.push_back(c);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(deq.len(), 3);
|
2013-07-10 08:27:14 -05:00
|
|
|
deq.push_back(d);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(deq.len(), 4);
|
2013-07-10 08:27:14 -05:00
|
|
|
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));
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(deq.len(), 0);
|
2013-07-10 08:27:14 -05:00
|
|
|
deq.push_back(c);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(deq.len(), 1);
|
2013-07-10 08:27:14 -05:00
|
|
|
deq.push_front(b);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(deq.len(), 2);
|
2013-07-10 08:27:14 -05:00
|
|
|
deq.push_back(d);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(deq.len(), 3);
|
2013-07-10 08:27:14 -05:00
|
|
|
deq.push_front(a);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(deq.len(), 4);
|
|
|
|
assert_eq!(*deq.get(0), a);
|
|
|
|
assert_eq!(*deq.get(1), b);
|
|
|
|
assert_eq!(*deq.get(2), c);
|
|
|
|
assert_eq!(*deq.get(3), d);
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
|
|
|
|
2013-05-01 18:32:37 -05:00
|
|
|
#[cfg(test)]
|
2014-05-29 19:45:07 -05:00
|
|
|
fn test_parameterized<T:Clone + PartialEq + Show>(a: T, b: T, c: T, d: T) {
|
2013-07-12 23:05:59 -05:00
|
|
|
let mut deq = RingBuf::new();
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(deq.len(), 0);
|
2013-07-12 23:05:59 -05:00
|
|
|
deq.push_front(a.clone());
|
|
|
|
deq.push_front(b.clone());
|
|
|
|
deq.push_back(c.clone());
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(deq.len(), 3);
|
2013-07-12 23:05:59 -05:00
|
|
|
deq.push_back(d.clone());
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(deq.len(), 4);
|
2013-08-03 18:59:24 -05:00
|
|
|
assert_eq!((*deq.front().unwrap()).clone(), b.clone());
|
|
|
|
assert_eq!((*deq.back().unwrap()).clone(), d.clone());
|
|
|
|
assert_eq!(deq.pop_front().unwrap(), b.clone());
|
|
|
|
assert_eq!(deq.pop_back().unwrap(), d.clone());
|
|
|
|
assert_eq!(deq.pop_back().unwrap(), c.clone());
|
|
|
|
assert_eq!(deq.pop_back().unwrap(), a.clone());
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(deq.len(), 0);
|
2013-07-12 23:05:59 -05:00
|
|
|
deq.push_back(c.clone());
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(deq.len(), 1);
|
2013-07-12 23:05:59 -05:00
|
|
|
deq.push_front(b.clone());
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(deq.len(), 2);
|
2013-07-12 23:05:59 -05:00
|
|
|
deq.push_back(d.clone());
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(deq.len(), 3);
|
2013-07-12 23:05:59 -05:00
|
|
|
deq.push_front(a.clone());
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(deq.len(), 4);
|
2013-07-02 14:47:32 -05:00
|
|
|
assert_eq!((*deq.get(0)).clone(), a.clone());
|
|
|
|
assert_eq!((*deq.get(1)).clone(), b.clone());
|
|
|
|
assert_eq!((*deq.get(2)).clone(), c.clone());
|
|
|
|
assert_eq!((*deq.get(3)).clone(), d.clone());
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
|
|
|
|
2013-07-05 22:42:45 -05:00
|
|
|
#[test]
|
2013-07-10 08:27:14 -05:00
|
|
|
fn test_push_front_grow() {
|
|
|
|
let mut deq = RingBuf::new();
|
2013-08-03 11:45:23 -05:00
|
|
|
for i in range(0u, 66) {
|
2013-07-10 08:27:14 -05:00
|
|
|
deq.push_front(i);
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
|
|
|
assert_eq!(deq.len(), 66);
|
|
|
|
|
2013-08-03 11:45:23 -05:00
|
|
|
for i in range(0u, 66) {
|
2013-07-05 22:42:45 -05:00
|
|
|
assert_eq!(*deq.get(i), 65 - i);
|
|
|
|
}
|
|
|
|
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut deq = RingBuf::new();
|
2013-08-03 11:45:23 -05:00
|
|
|
for i in range(0u, 66) {
|
2013-07-10 08:27:14 -05:00
|
|
|
deq.push_back(i);
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
|
|
|
|
2013-08-03 11:45:23 -05:00
|
|
|
for i in range(0u, 66) {
|
2013-07-05 22:42:45 -05:00
|
|
|
assert_eq!(*deq.get(i), i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-02 01:39:39 -05:00
|
|
|
#[test]
|
|
|
|
fn test_index() {
|
|
|
|
let mut deq = RingBuf::new();
|
|
|
|
for i in range(1u, 4) {
|
|
|
|
deq.push_front(i);
|
|
|
|
}
|
|
|
|
assert_eq!(deq[1], 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_fail]
|
|
|
|
fn test_index_out_of_bounds() {
|
|
|
|
let mut deq = RingBuf::new();
|
|
|
|
for i in range(1u, 4) {
|
|
|
|
deq.push_front(i);
|
|
|
|
}
|
|
|
|
deq[3];
|
|
|
|
}
|
|
|
|
|
2013-07-05 22:42:45 -05:00
|
|
|
#[bench]
|
2014-03-31 20:16:35 -05:00
|
|
|
fn bench_new(b: &mut test::Bencher) {
|
2013-11-21 21:20:48 -06:00
|
|
|
b.iter(|| {
|
2013-08-08 13:38:10 -05:00
|
|
|
let _: RingBuf<u64> = RingBuf::new();
|
2013-11-21 21:20:48 -06:00
|
|
|
})
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-03-31 20:16:35 -05:00
|
|
|
fn bench_push_back(b: &mut test::Bencher) {
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut deq = RingBuf::new();
|
2013-11-21 21:20:48 -06:00
|
|
|
b.iter(|| {
|
2014-06-27 14:30:25 -05:00
|
|
|
deq.push_back(0i);
|
2013-11-21 21:20:48 -06:00
|
|
|
})
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-03-31 20:16:35 -05:00
|
|
|
fn bench_push_front(b: &mut test::Bencher) {
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut deq = RingBuf::new();
|
2013-11-21 21:20:48 -06:00
|
|
|
b.iter(|| {
|
2014-06-27 14:30:25 -05:00
|
|
|
deq.push_front(0i);
|
2013-11-21 21:20:48 -06:00
|
|
|
})
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-03-31 20:16:35 -05:00
|
|
|
fn bench_grow(b: &mut test::Bencher) {
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut deq = RingBuf::new();
|
2013-11-21 21:20:48 -06:00
|
|
|
b.iter(|| {
|
2014-04-21 16:58:52 -05:00
|
|
|
for _ in range(0i, 65) {
|
2014-06-27 14:30:25 -05:00
|
|
|
deq.push_front(1i);
|
2014-01-29 18:20:34 -06:00
|
|
|
}
|
2013-11-21 21:20:48 -06:00
|
|
|
})
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
|
|
|
|
2014-05-29 19:45:07 -05:00
|
|
|
#[deriving(Clone, PartialEq, Show)]
|
2013-07-02 14:47:32 -05:00
|
|
|
enum Taggy {
|
|
|
|
One(int),
|
|
|
|
Two(int, int),
|
|
|
|
Three(int, int, int),
|
|
|
|
}
|
2012-01-17 21:05:07 -06:00
|
|
|
|
2014-05-29 19:45:07 -05:00
|
|
|
#[deriving(Clone, PartialEq, Show)]
|
2012-08-11 09:08:42 -05:00
|
|
|
enum Taggypar<T> {
|
2013-07-02 14:47:32 -05:00
|
|
|
Onepar(int),
|
|
|
|
Twopar(int, int),
|
|
|
|
Threepar(int, int, int),
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
|
|
|
|
2014-05-29 19:45:07 -05:00
|
|
|
#[deriving(Clone, PartialEq, Show)]
|
2013-01-22 10:44:24 -06:00
|
|
|
struct RecCy {
|
|
|
|
x: int,
|
|
|
|
y: int,
|
2013-01-25 18:57:39 -06:00
|
|
|
t: Taggy
|
2012-09-19 20:00:26 -05:00
|
|
|
}
|
2012-09-13 00:09:55 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_param_int() {
|
|
|
|
test_parameterized::<int>(5, 72, 64, 175);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_param_at_int() {
|
2014-06-11 21:33:52 -05:00
|
|
|
test_parameterized::<Gc<int>>(box(GC) 5, box(GC) 72,
|
|
|
|
box(GC) 64, box(GC) 175);
|
2012-09-13 00:09:55 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_param_taggy() {
|
2013-06-26 17:14:35 -05:00
|
|
|
test_parameterized::<Taggy>(One(1), Two(1, 2), Three(1, 2, 3), Two(17, 42));
|
2012-09-13 00:09:55 -05:00
|
|
|
}
|
2012-01-17 21:05:07 -06:00
|
|
|
|
2012-09-13 00:09:55 -05:00
|
|
|
#[test]
|
|
|
|
fn test_param_taggypar() {
|
|
|
|
test_parameterized::<Taggypar<int>>(Onepar::<int>(1),
|
2012-08-11 09:08:42 -05:00
|
|
|
Twopar::<int>(1, 2),
|
|
|
|
Threepar::<int>(1, 2, 3),
|
|
|
|
Twopar::<int>(17, 42));
|
2012-09-13 00:09:55 -05:00
|
|
|
}
|
2012-01-17 21:05:07 -06:00
|
|
|
|
2012-09-13 00:09:55 -05:00
|
|
|
#[test]
|
|
|
|
fn test_param_reccy() {
|
2013-01-22 10:44:24 -06:00
|
|
|
let reccy1 = RecCy { x: 1, y: 2, t: One(1) };
|
|
|
|
let reccy2 = RecCy { x: 345, y: 2, t: Two(1, 2) };
|
|
|
|
let reccy3 = RecCy { x: 1, y: 777, t: Three(1, 2, 3) };
|
|
|
|
let reccy4 = RecCy { x: 19, y: 252, t: Two(17, 42) };
|
2012-09-13 00:09:55 -05:00
|
|
|
test_parameterized::<RecCy>(reccy1, reccy2, reccy3, reccy4);
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
2013-03-29 20:02:44 -05:00
|
|
|
|
2013-07-05 22:42:45 -05:00
|
|
|
#[test]
|
|
|
|
fn test_with_capacity() {
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut d = RingBuf::with_capacity(0);
|
2014-06-27 14:30:25 -05:00
|
|
|
d.push_back(1i);
|
2013-07-05 22:42:45 -05:00
|
|
|
assert_eq!(d.len(), 1);
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut d = RingBuf::with_capacity(50);
|
2014-06-27 14:30:25 -05:00
|
|
|
d.push_back(1i);
|
2013-07-05 22:42:45 -05:00
|
|
|
assert_eq!(d.len(), 1);
|
2014-08-06 20:11:13 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_with_capacity_non_power_two() {
|
|
|
|
let mut d3 = RingBuf::with_capacity(3);
|
|
|
|
d3.push(1i);
|
|
|
|
|
|
|
|
// X = None, | = lo
|
|
|
|
// [|1, X, X]
|
|
|
|
assert_eq!(d3.pop_front(), Some(1));
|
|
|
|
// [X, |X, X]
|
|
|
|
assert_eq!(d3.front(), None);
|
|
|
|
|
|
|
|
// [X, |3, X]
|
|
|
|
d3.push(3);
|
|
|
|
// [X, |3, 6]
|
|
|
|
d3.push(6);
|
|
|
|
// [X, X, |6]
|
|
|
|
assert_eq!(d3.pop_front(), Some(3));
|
|
|
|
|
|
|
|
// Pushing the lo past half way point to trigger
|
|
|
|
// the 'B' scenario for growth
|
|
|
|
// [9, X, |6]
|
|
|
|
d3.push(9);
|
|
|
|
// [9, 12, |6]
|
|
|
|
d3.push(12);
|
|
|
|
|
|
|
|
d3.push(15);
|
|
|
|
// There used to be a bug here about how the
|
|
|
|
// RingBuf made growth assumptions about the
|
|
|
|
// underlying Vec which didn't hold and lead
|
|
|
|
// to corruption.
|
|
|
|
// (Vec grows to next power of two)
|
|
|
|
//good- [9, 12, 15, X, X, X, X, |6]
|
|
|
|
//bug- [15, 12, X, X, X, |6, X, X]
|
|
|
|
assert_eq!(d3.pop_front(), Some(6));
|
|
|
|
|
|
|
|
// Which leads us to the following state which
|
|
|
|
// would be a failure case.
|
|
|
|
//bug- [15, 12, X, X, X, X, |X, X]
|
|
|
|
assert_eq!(d3.front(), Some(&9));
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
|
|
|
|
2013-05-27 13:47:38 -05:00
|
|
|
#[test]
|
2014-01-31 07:03:20 -06:00
|
|
|
fn test_reserve_exact() {
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut d = RingBuf::new();
|
|
|
|
d.push_back(0u64);
|
2014-01-31 07:03:20 -06:00
|
|
|
d.reserve_exact(50);
|
2013-06-27 09:40:47 -05:00
|
|
|
assert_eq!(d.elts.capacity(), 50);
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut d = RingBuf::new();
|
|
|
|
d.push_back(0u32);
|
2014-01-31 07:03:20 -06:00
|
|
|
d.reserve_exact(50);
|
2013-06-27 09:40:47 -05:00
|
|
|
assert_eq!(d.elts.capacity(), 50);
|
2013-05-27 13:47:38 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2014-01-31 07:03:20 -06:00
|
|
|
fn test_reserve() {
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut d = RingBuf::new();
|
|
|
|
d.push_back(0u64);
|
2014-01-31 07:03:20 -06:00
|
|
|
d.reserve(50);
|
2013-06-27 09:40:47 -05:00
|
|
|
assert_eq!(d.elts.capacity(), 64);
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut d = RingBuf::new();
|
|
|
|
d.push_back(0u32);
|
2014-01-31 07:03:20 -06:00
|
|
|
d.reserve(50);
|
2013-06-27 09:40:47 -05:00
|
|
|
assert_eq!(d.elts.capacity(), 64);
|
2013-05-27 13:47:38 -05:00
|
|
|
}
|
|
|
|
|
2013-09-26 02:19:26 -05:00
|
|
|
#[test]
|
|
|
|
fn test_swap() {
|
2014-04-21 16:58:52 -05:00
|
|
|
let mut d: RingBuf<int> = range(0i, 5).collect();
|
2013-09-26 02:19:26 -05:00
|
|
|
d.pop_front();
|
|
|
|
d.swap(0, 3);
|
2014-04-05 00:45:42 -05:00
|
|
|
assert_eq!(d.iter().map(|&x|x).collect::<Vec<int>>(), vec!(4, 2, 3, 1));
|
2013-09-26 02:19:26 -05:00
|
|
|
}
|
|
|
|
|
2013-06-26 09:04:44 -05:00
|
|
|
#[test]
|
|
|
|
fn test_iter() {
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut d = RingBuf::new();
|
2013-07-05 22:42:45 -05:00
|
|
|
assert_eq!(d.iter().next(), None);
|
2013-07-14 15:30:22 -05:00
|
|
|
assert_eq!(d.iter().size_hint(), (0, Some(0)));
|
2013-07-05 22:42:45 -05:00
|
|
|
|
2014-04-21 16:58:52 -05:00
|
|
|
for i in range(0i, 5) {
|
2013-07-10 08:27:14 -05:00
|
|
|
d.push_back(i);
|
2013-06-26 09:04:44 -05:00
|
|
|
}
|
2014-08-04 07:19:02 -05:00
|
|
|
{
|
|
|
|
let b: &[_] = &[&0,&1,&2,&3,&4];
|
|
|
|
assert_eq!(d.iter().collect::<Vec<&int>>().as_slice(), b);
|
|
|
|
}
|
2013-06-26 17:14:35 -05:00
|
|
|
|
2014-04-21 16:58:52 -05:00
|
|
|
for i in range(6i, 9) {
|
2013-07-10 08:27:14 -05:00
|
|
|
d.push_front(i);
|
2013-06-26 09:04:44 -05:00
|
|
|
}
|
2014-08-04 07:19:02 -05:00
|
|
|
{
|
|
|
|
let b: &[_] = &[&8,&7,&6,&0,&1,&2,&3,&4];
|
|
|
|
assert_eq!(d.iter().collect::<Vec<&int>>().as_slice(), b);
|
|
|
|
}
|
2013-07-14 15:30:22 -05:00
|
|
|
|
|
|
|
let mut it = d.iter();
|
|
|
|
let mut len = d.len();
|
|
|
|
loop {
|
|
|
|
match it.next() {
|
|
|
|
None => break,
|
|
|
|
_ => { len -= 1; assert_eq!(it.size_hint(), (len, Some(len))) }
|
|
|
|
}
|
|
|
|
}
|
2013-06-26 09:04:44 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_rev_iter() {
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut d = RingBuf::new();
|
Deprecate the rev_iter pattern in all places where a DoubleEndedIterator is provided (everywhere but treemap)
This commit deprecates rev_iter, mut_rev_iter, move_rev_iter everywhere (except treemap) and also
deprecates related functions like rsplit, rev_components, and rev_str_components. In every case,
these functions can be replaced with the non-reversed form followed by a call to .rev(). To make this
more concrete, a translation table for all functional changes necessary follows:
* container.rev_iter() -> container.iter().rev()
* container.mut_rev_iter() -> container.mut_iter().rev()
* container.move_rev_iter() -> container.move_iter().rev()
* sliceorstr.rsplit(sep) -> sliceorstr.split(sep).rev()
* path.rev_components() -> path.components().rev()
* path.rev_str_components() -> path.str_components().rev()
In terms of the type system, this change also deprecates any specialized reversed iterator types (except
in treemap), opting instead to use Rev directly if any type annotations are needed. However, since
methods directly returning reversed iterators are now discouraged, the need for such annotations should
be small. However, in those cases, the general pattern for conversion is to take whatever follows Rev in
the original reversed name and surround it with Rev<>:
* RevComponents<'a> -> Rev<Components<'a>>
* RevStrComponents<'a> -> Rev<StrComponents<'a>>
* RevItems<'a, T> -> Rev<Items<'a, T>>
* etc.
The reasoning behind this change is that it makes the standard API much simpler without reducing readability,
performance, or power. The presence of functions such as rev_iter adds more boilerplate code to libraries
(all of which simply call .iter().rev()), clutters up the documentation, and only helps code by saving two
characters. Additionally, the numerous type synonyms that were used to make the type signatures look nice
like RevItems add even more boilerplate and clutter up the docs even more. With this change, all that cruft
goes away.
[breaking-change]
2014-04-20 23:59:12 -05:00
|
|
|
assert_eq!(d.iter().rev().next(), None);
|
2013-07-05 22:42:45 -05:00
|
|
|
|
2014-04-21 16:58:52 -05:00
|
|
|
for i in range(0i, 5) {
|
2013-07-10 08:27:14 -05:00
|
|
|
d.push_back(i);
|
2013-06-26 09:04:44 -05:00
|
|
|
}
|
2014-08-04 07:19:02 -05:00
|
|
|
{
|
|
|
|
let b: &[_] = &[&4,&3,&2,&1,&0];
|
|
|
|
assert_eq!(d.iter().rev().collect::<Vec<&int>>().as_slice(), b);
|
|
|
|
}
|
2013-06-26 17:14:35 -05:00
|
|
|
|
2014-04-21 16:58:52 -05:00
|
|
|
for i in range(6i, 9) {
|
2013-07-10 08:27:14 -05:00
|
|
|
d.push_front(i);
|
2013-06-26 09:04:44 -05:00
|
|
|
}
|
2014-08-04 07:19:02 -05:00
|
|
|
let b: &[_] = &[&4,&3,&2,&1,&0,&6,&7,&8];
|
|
|
|
assert_eq!(d.iter().rev().collect::<Vec<&int>>().as_slice(), b);
|
2013-06-26 09:04:44 -05:00
|
|
|
}
|
2013-07-05 22:42:45 -05:00
|
|
|
|
2013-11-16 16:29:39 -06:00
|
|
|
#[test]
|
|
|
|
fn test_mut_rev_iter_wrap() {
|
|
|
|
let mut d = RingBuf::with_capacity(3);
|
Deprecate the rev_iter pattern in all places where a DoubleEndedIterator is provided (everywhere but treemap)
This commit deprecates rev_iter, mut_rev_iter, move_rev_iter everywhere (except treemap) and also
deprecates related functions like rsplit, rev_components, and rev_str_components. In every case,
these functions can be replaced with the non-reversed form followed by a call to .rev(). To make this
more concrete, a translation table for all functional changes necessary follows:
* container.rev_iter() -> container.iter().rev()
* container.mut_rev_iter() -> container.mut_iter().rev()
* container.move_rev_iter() -> container.move_iter().rev()
* sliceorstr.rsplit(sep) -> sliceorstr.split(sep).rev()
* path.rev_components() -> path.components().rev()
* path.rev_str_components() -> path.str_components().rev()
In terms of the type system, this change also deprecates any specialized reversed iterator types (except
in treemap), opting instead to use Rev directly if any type annotations are needed. However, since
methods directly returning reversed iterators are now discouraged, the need for such annotations should
be small. However, in those cases, the general pattern for conversion is to take whatever follows Rev in
the original reversed name and surround it with Rev<>:
* RevComponents<'a> -> Rev<Components<'a>>
* RevStrComponents<'a> -> Rev<StrComponents<'a>>
* RevItems<'a, T> -> Rev<Items<'a, T>>
* etc.
The reasoning behind this change is that it makes the standard API much simpler without reducing readability,
performance, or power. The presence of functions such as rev_iter adds more boilerplate code to libraries
(all of which simply call .iter().rev()), clutters up the documentation, and only helps code by saving two
characters. Additionally, the numerous type synonyms that were used to make the type signatures look nice
like RevItems add even more boilerplate and clutter up the docs even more. With this change, all that cruft
goes away.
[breaking-change]
2014-04-20 23:59:12 -05:00
|
|
|
assert!(d.mut_iter().rev().next().is_none());
|
2013-11-16 16:29:39 -06:00
|
|
|
|
2014-04-21 16:58:52 -05:00
|
|
|
d.push_back(1i);
|
2013-11-16 16:29:39 -06:00
|
|
|
d.push_back(2);
|
|
|
|
d.push_back(3);
|
|
|
|
assert_eq!(d.pop_front(), Some(1));
|
|
|
|
d.push_back(4);
|
|
|
|
|
Deprecate the rev_iter pattern in all places where a DoubleEndedIterator is provided (everywhere but treemap)
This commit deprecates rev_iter, mut_rev_iter, move_rev_iter everywhere (except treemap) and also
deprecates related functions like rsplit, rev_components, and rev_str_components. In every case,
these functions can be replaced with the non-reversed form followed by a call to .rev(). To make this
more concrete, a translation table for all functional changes necessary follows:
* container.rev_iter() -> container.iter().rev()
* container.mut_rev_iter() -> container.mut_iter().rev()
* container.move_rev_iter() -> container.move_iter().rev()
* sliceorstr.rsplit(sep) -> sliceorstr.split(sep).rev()
* path.rev_components() -> path.components().rev()
* path.rev_str_components() -> path.str_components().rev()
In terms of the type system, this change also deprecates any specialized reversed iterator types (except
in treemap), opting instead to use Rev directly if any type annotations are needed. However, since
methods directly returning reversed iterators are now discouraged, the need for such annotations should
be small. However, in those cases, the general pattern for conversion is to take whatever follows Rev in
the original reversed name and surround it with Rev<>:
* RevComponents<'a> -> Rev<Components<'a>>
* RevStrComponents<'a> -> Rev<StrComponents<'a>>
* RevItems<'a, T> -> Rev<Items<'a, T>>
* etc.
The reasoning behind this change is that it makes the standard API much simpler without reducing readability,
performance, or power. The presence of functions such as rev_iter adds more boilerplate code to libraries
(all of which simply call .iter().rev()), clutters up the documentation, and only helps code by saving two
characters. Additionally, the numerous type synonyms that were used to make the type signatures look nice
like RevItems add even more boilerplate and clutter up the docs even more. With this change, all that cruft
goes away.
[breaking-change]
2014-04-20 23:59:12 -05:00
|
|
|
assert_eq!(d.mut_iter().rev().map(|x| *x).collect::<Vec<int>>(),
|
2014-04-05 00:45:42 -05:00
|
|
|
vec!(4, 3, 2));
|
2013-11-16 16:29:39 -06:00
|
|
|
}
|
|
|
|
|
2013-07-05 22:42:45 -05:00
|
|
|
#[test]
|
|
|
|
fn test_mut_iter() {
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut d = RingBuf::new();
|
2013-07-05 22:42:45 -05:00
|
|
|
assert!(d.mut_iter().next().is_none());
|
|
|
|
|
2013-08-03 11:45:23 -05:00
|
|
|
for i in range(0u, 3) {
|
2013-07-10 08:27:14 -05:00
|
|
|
d.push_front(i);
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
|
|
|
|
2013-08-03 11:45:23 -05:00
|
|
|
for (i, elt) in d.mut_iter().enumerate() {
|
2013-07-05 22:42:45 -05:00
|
|
|
assert_eq!(*elt, 2 - i);
|
|
|
|
*elt = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
let mut it = d.mut_iter();
|
|
|
|
assert_eq!(*it.next().unwrap(), 0);
|
|
|
|
assert_eq!(*it.next().unwrap(), 1);
|
|
|
|
assert_eq!(*it.next().unwrap(), 2);
|
|
|
|
assert!(it.next().is_none());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_mut_rev_iter() {
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut d = RingBuf::new();
|
Deprecate the rev_iter pattern in all places where a DoubleEndedIterator is provided (everywhere but treemap)
This commit deprecates rev_iter, mut_rev_iter, move_rev_iter everywhere (except treemap) and also
deprecates related functions like rsplit, rev_components, and rev_str_components. In every case,
these functions can be replaced with the non-reversed form followed by a call to .rev(). To make this
more concrete, a translation table for all functional changes necessary follows:
* container.rev_iter() -> container.iter().rev()
* container.mut_rev_iter() -> container.mut_iter().rev()
* container.move_rev_iter() -> container.move_iter().rev()
* sliceorstr.rsplit(sep) -> sliceorstr.split(sep).rev()
* path.rev_components() -> path.components().rev()
* path.rev_str_components() -> path.str_components().rev()
In terms of the type system, this change also deprecates any specialized reversed iterator types (except
in treemap), opting instead to use Rev directly if any type annotations are needed. However, since
methods directly returning reversed iterators are now discouraged, the need for such annotations should
be small. However, in those cases, the general pattern for conversion is to take whatever follows Rev in
the original reversed name and surround it with Rev<>:
* RevComponents<'a> -> Rev<Components<'a>>
* RevStrComponents<'a> -> Rev<StrComponents<'a>>
* RevItems<'a, T> -> Rev<Items<'a, T>>
* etc.
The reasoning behind this change is that it makes the standard API much simpler without reducing readability,
performance, or power. The presence of functions such as rev_iter adds more boilerplate code to libraries
(all of which simply call .iter().rev()), clutters up the documentation, and only helps code by saving two
characters. Additionally, the numerous type synonyms that were used to make the type signatures look nice
like RevItems add even more boilerplate and clutter up the docs even more. With this change, all that cruft
goes away.
[breaking-change]
2014-04-20 23:59:12 -05:00
|
|
|
assert!(d.mut_iter().rev().next().is_none());
|
2013-07-05 22:42:45 -05:00
|
|
|
|
2013-08-03 11:45:23 -05:00
|
|
|
for i in range(0u, 3) {
|
2013-07-10 08:27:14 -05:00
|
|
|
d.push_front(i);
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
|
|
|
|
Deprecate the rev_iter pattern in all places where a DoubleEndedIterator is provided (everywhere but treemap)
This commit deprecates rev_iter, mut_rev_iter, move_rev_iter everywhere (except treemap) and also
deprecates related functions like rsplit, rev_components, and rev_str_components. In every case,
these functions can be replaced with the non-reversed form followed by a call to .rev(). To make this
more concrete, a translation table for all functional changes necessary follows:
* container.rev_iter() -> container.iter().rev()
* container.mut_rev_iter() -> container.mut_iter().rev()
* container.move_rev_iter() -> container.move_iter().rev()
* sliceorstr.rsplit(sep) -> sliceorstr.split(sep).rev()
* path.rev_components() -> path.components().rev()
* path.rev_str_components() -> path.str_components().rev()
In terms of the type system, this change also deprecates any specialized reversed iterator types (except
in treemap), opting instead to use Rev directly if any type annotations are needed. However, since
methods directly returning reversed iterators are now discouraged, the need for such annotations should
be small. However, in those cases, the general pattern for conversion is to take whatever follows Rev in
the original reversed name and surround it with Rev<>:
* RevComponents<'a> -> Rev<Components<'a>>
* RevStrComponents<'a> -> Rev<StrComponents<'a>>
* RevItems<'a, T> -> Rev<Items<'a, T>>
* etc.
The reasoning behind this change is that it makes the standard API much simpler without reducing readability,
performance, or power. The presence of functions such as rev_iter adds more boilerplate code to libraries
(all of which simply call .iter().rev()), clutters up the documentation, and only helps code by saving two
characters. Additionally, the numerous type synonyms that were used to make the type signatures look nice
like RevItems add even more boilerplate and clutter up the docs even more. With this change, all that cruft
goes away.
[breaking-change]
2014-04-20 23:59:12 -05:00
|
|
|
for (i, elt) in d.mut_iter().rev().enumerate() {
|
2013-07-05 22:42:45 -05:00
|
|
|
assert_eq!(*elt, i);
|
|
|
|
*elt = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
Deprecate the rev_iter pattern in all places where a DoubleEndedIterator is provided (everywhere but treemap)
This commit deprecates rev_iter, mut_rev_iter, move_rev_iter everywhere (except treemap) and also
deprecates related functions like rsplit, rev_components, and rev_str_components. In every case,
these functions can be replaced with the non-reversed form followed by a call to .rev(). To make this
more concrete, a translation table for all functional changes necessary follows:
* container.rev_iter() -> container.iter().rev()
* container.mut_rev_iter() -> container.mut_iter().rev()
* container.move_rev_iter() -> container.move_iter().rev()
* sliceorstr.rsplit(sep) -> sliceorstr.split(sep).rev()
* path.rev_components() -> path.components().rev()
* path.rev_str_components() -> path.str_components().rev()
In terms of the type system, this change also deprecates any specialized reversed iterator types (except
in treemap), opting instead to use Rev directly if any type annotations are needed. However, since
methods directly returning reversed iterators are now discouraged, the need for such annotations should
be small. However, in those cases, the general pattern for conversion is to take whatever follows Rev in
the original reversed name and surround it with Rev<>:
* RevComponents<'a> -> Rev<Components<'a>>
* RevStrComponents<'a> -> Rev<StrComponents<'a>>
* RevItems<'a, T> -> Rev<Items<'a, T>>
* etc.
The reasoning behind this change is that it makes the standard API much simpler without reducing readability,
performance, or power. The presence of functions such as rev_iter adds more boilerplate code to libraries
(all of which simply call .iter().rev()), clutters up the documentation, and only helps code by saving two
characters. Additionally, the numerous type synonyms that were used to make the type signatures look nice
like RevItems add even more boilerplate and clutter up the docs even more. With this change, all that cruft
goes away.
[breaking-change]
2014-04-20 23:59:12 -05:00
|
|
|
let mut it = d.mut_iter().rev();
|
2013-07-05 22:42:45 -05:00
|
|
|
assert_eq!(*it.next().unwrap(), 0);
|
|
|
|
assert_eq!(*it.next().unwrap(), 1);
|
|
|
|
assert_eq!(*it.next().unwrap(), 2);
|
|
|
|
assert!(it.next().is_none());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-05 22:42:45 -05:00
|
|
|
#[test]
|
2014-03-30 23:45:55 -05:00
|
|
|
fn test_from_iter() {
|
2013-09-08 10:01:16 -05:00
|
|
|
use std::iter;
|
2014-04-21 16:58:52 -05:00
|
|
|
let v = vec!(1i,2,3,4,5,6,7);
|
2013-08-09 22:09:47 -05:00
|
|
|
let deq: RingBuf<int> = v.iter().map(|&x| x).collect();
|
2014-04-05 00:45:42 -05:00
|
|
|
let u: Vec<int> = deq.iter().map(|&x| x).collect();
|
2013-07-05 22:42:45 -05:00
|
|
|
assert_eq!(u, v);
|
|
|
|
|
2013-09-08 10:01:16 -05:00
|
|
|
let mut seq = iter::count(0u, 2).take(256);
|
2013-07-10 08:27:14 -05:00
|
|
|
let deq: RingBuf<uint> = seq.collect();
|
2013-08-03 11:45:23 -05:00
|
|
|
for (i, &x) in deq.iter().enumerate() {
|
2013-07-05 22:42:45 -05:00
|
|
|
assert_eq!(2*i, x);
|
|
|
|
}
|
|
|
|
assert_eq!(deq.len(), 256);
|
|
|
|
}
|
2013-07-06 08:27:32 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_clone() {
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut d = RingBuf::new();
|
2014-04-21 16:58:52 -05:00
|
|
|
d.push_front(17i);
|
2013-07-10 08:27:14 -05:00
|
|
|
d.push_front(42);
|
|
|
|
d.push_back(137);
|
|
|
|
d.push_back(137);
|
2013-07-06 08:27:32 -05:00
|
|
|
assert_eq!(d.len(), 4u);
|
|
|
|
let mut e = d.clone();
|
|
|
|
assert_eq!(e.len(), 4u);
|
|
|
|
while !d.is_empty() {
|
|
|
|
assert_eq!(d.pop_back(), e.pop_back());
|
|
|
|
}
|
|
|
|
assert_eq!(d.len(), 0u);
|
|
|
|
assert_eq!(e.len(), 0u);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_eq() {
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut d = RingBuf::new();
|
2014-02-28 03:23:06 -06:00
|
|
|
assert!(d == RingBuf::with_capacity(0));
|
2014-04-21 16:58:52 -05:00
|
|
|
d.push_front(137i);
|
2013-07-10 08:27:14 -05:00
|
|
|
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);
|
2014-02-28 03:23:06 -06:00
|
|
|
assert!(&e == &d);
|
2013-07-06 08:27:32 -05:00
|
|
|
e.pop_back();
|
2013-07-10 08:27:14 -05:00
|
|
|
e.push_back(0);
|
2013-07-06 08:27:32 -05:00
|
|
|
assert!(e != d);
|
|
|
|
e.clear();
|
2014-02-28 03:23:06 -06:00
|
|
|
assert!(e == RingBuf::new());
|
2013-07-06 08:27:32 -05:00
|
|
|
}
|
2014-06-04 09:15:04 -05:00
|
|
|
|
2014-07-26 21:33:47 -05:00
|
|
|
#[test]
|
|
|
|
fn test_hash() {
|
|
|
|
let mut x = RingBuf::new();
|
|
|
|
let mut y = RingBuf::new();
|
|
|
|
|
|
|
|
x.push(1i);
|
|
|
|
x.push(2);
|
|
|
|
x.push(3);
|
|
|
|
|
|
|
|
y.push(0i);
|
|
|
|
y.push(1i);
|
|
|
|
y.pop_front();
|
|
|
|
y.push(2);
|
|
|
|
y.push(3);
|
|
|
|
|
|
|
|
assert!(hash::hash(&x) == hash::hash(&y));
|
|
|
|
}
|
|
|
|
|
2014-07-26 22:18:56 -05:00
|
|
|
#[test]
|
|
|
|
fn test_ord() {
|
|
|
|
let x = RingBuf::new();
|
|
|
|
let mut y = RingBuf::new();
|
|
|
|
y.push(1i);
|
|
|
|
y.push(2);
|
|
|
|
y.push(3);
|
|
|
|
assert!(x < y);
|
|
|
|
assert!(y > x);
|
|
|
|
assert!(x <= x);
|
|
|
|
assert!(x >= x);
|
|
|
|
}
|
|
|
|
|
2014-06-04 09:15:04 -05:00
|
|
|
#[test]
|
|
|
|
fn test_show() {
|
2014-04-21 16:58:52 -05:00
|
|
|
let ringbuf: RingBuf<int> = range(0i, 10).collect();
|
2014-06-04 09:15:04 -05:00
|
|
|
assert!(format!("{}", ringbuf).as_slice() == "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
|
|
|
|
|
|
|
|
let ringbuf: RingBuf<&str> = vec!["just", "one", "test", "more"].iter()
|
|
|
|
.map(|&s| s)
|
|
|
|
.collect();
|
|
|
|
assert!(format!("{}", ringbuf).as_slice() == "[just, one, test, more]");
|
|
|
|
}
|
2012-07-03 12:52:32 -05:00
|
|
|
}
|