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-30 16:11:22 -05:00
|
|
|
//! This crate implements a double-ended queue with `O(1)` amortized inserts and removals from both
|
|
|
|
//! ends of the container. It also has `O(1)` indexing like a vector. The contained elements are
|
|
|
|
//! not required to be copyable, and the queue will be sendable if the contained type is sendable.
|
2013-05-17 17:28:44 -05:00
|
|
|
|
2015-01-04 18:35:20 -06:00
|
|
|
#![stable]
|
|
|
|
|
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::*;
|
|
|
|
|
2014-12-22 11:04:23 -06:00
|
|
|
use core::cmp::Ordering;
|
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;
|
2015-01-05 08:48:58 -06:00
|
|
|
use core::iter::{self, repeat, FromIterator, RandomAccessIterator};
|
2015-01-06 16:33:42 -06:00
|
|
|
use core::marker;
|
2014-10-19 15:19:07 -05:00
|
|
|
use core::mem;
|
2014-11-14 03:21:44 -06:00
|
|
|
use core::num::{Int, UnsignedInt};
|
2014-12-22 11:04:23 -06:00
|
|
|
use core::ops::{Index, IndexMut};
|
|
|
|
use core::ptr;
|
|
|
|
use core::raw::Slice as RawSlice;
|
2014-10-19 15:19:07 -05:00
|
|
|
|
std: Stabilize the std::hash module
This commit aims to prepare the `std::hash` module for alpha by formalizing its
current interface whileholding off on adding `#[stable]` to the new APIs. The
current usage with the `HashMap` and `HashSet` types is also reconciled by
separating out composable parts of the design. The primary goal of this slight
redesign is to separate the concepts of a hasher's state from a hashing
algorithm itself.
The primary change of this commit is to separate the `Hasher` trait into a
`Hasher` and a `HashState` trait. Conceptually the old `Hasher` trait was
actually just a factory for various states, but hashing had very little control
over how these states were used. Additionally the old `Hasher` trait was
actually fairly unrelated to hashing.
This commit redesigns the existing `Hasher` trait to match what the notion of a
`Hasher` normally implies with the following definition:
trait Hasher {
type Output;
fn reset(&mut self);
fn finish(&self) -> Output;
}
This `Hasher` trait emphasizes that hashing algorithms may produce outputs other
than a `u64`, so the output type is made generic. Other than that, however, very
little is assumed about a particular hasher. It is left up to implementors to
provide specific methods or trait implementations to feed data into a hasher.
The corresponding `Hash` trait becomes:
trait Hash<H: Hasher> {
fn hash(&self, &mut H);
}
The old default of `SipState` was removed from this trait as it's not something
that we're willing to stabilize until the end of time, but the type parameter is
always required to implement `Hasher`. Note that the type parameter `H` remains
on the trait to enable multidispatch for specialization of hashing for
particular hashers.
Note that `Writer` is not mentioned in either of `Hash` or `Hasher`, it is
simply used as part `derive` and the implementations for all primitive types.
With these definitions, the old `Hasher` trait is realized as a new `HashState`
trait in the `collections::hash_state` module as an unstable addition for
now. The current definition looks like:
trait HashState {
type Hasher: Hasher;
fn hasher(&self) -> Hasher;
}
The purpose of this trait is to emphasize that the one piece of functionality
for implementors is that new instances of `Hasher` can be created. This
conceptually represents the two keys from which more instances of a
`SipHasher` can be created, and a `HashState` is what's stored in a
`HashMap`, not a `Hasher`.
Implementors of custom hash algorithms should implement the `Hasher` trait, and
only hash algorithms intended for use in hash maps need to implement or worry
about the `HashState` trait.
The entire module and `HashState` infrastructure remains `#[unstable]` due to it
being recently redesigned, but some other stability decision made for the
`std::hash` module are:
* The `Writer` trait remains `#[experimental]` as it's intended to be replaced
with an `io::Writer` (more details soon).
* The top-level `hash` function is `#[unstable]` as it is intended to be generic
over the hashing algorithm instead of hardwired to `SipHasher`
* The inner `sip` module is now private as its one export, `SipHasher` is
reexported in the `hash` module.
And finally, a few changes were made to the default parameters on `HashMap`.
* The `RandomSipHasher` default type parameter was renamed to `RandomState`.
This renaming emphasizes that it is not a hasher, but rather just state to
generate hashers. It also moves away from the name "sip" as it may not always
be implemented as `SipHasher`. This type lives in the
`std::collections::hash_map` module as `#[unstable]`
* The associated `Hasher` type of `RandomState` is creatively called...
`Hasher`! This concrete structure lives next to `RandomState` as an
implemenation of the "default hashing algorithm" used for a `HashMap`. Under
the hood this is currently implemented as `SipHasher`, but it draws an
explicit interface for now and allows us to modify the implementation over
time if necessary.
There are many breaking changes outlined above, and as a result this commit is
a:
[breaking-change]
2014-12-09 14:37:23 -06:00
|
|
|
use std::hash::{Writer, Hash, Hasher};
|
2014-10-19 15:19:07 -05:00
|
|
|
use std::cmp;
|
2013-05-05 23:42:54 -05:00
|
|
|
|
2014-10-19 15:19:07 -05:00
|
|
|
use alloc::heap;
|
2013-07-10 08:27:14 -05:00
|
|
|
|
2015-01-05 08:48:58 -06:00
|
|
|
static INITIAL_CAPACITY: uint = 7u; // 2^3 - 1
|
|
|
|
static MINIMUM_CAPACITY: uint = 1u; // 2 - 1
|
2014-11-06 11:24:47 -06:00
|
|
|
|
2014-12-09 16:05:16 -06:00
|
|
|
/// `RingBuf` is a circular buffer, which can be used as a double-ended queue efficiently.
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2013-07-10 08:27:14 -05:00
|
|
|
pub struct RingBuf<T> {
|
2014-10-19 15:19:07 -05:00
|
|
|
// tail and head are pointers into the buffer. Tail always points
|
|
|
|
// to the first element that could be read, Head always points
|
|
|
|
// to where data should be written.
|
|
|
|
// If tail == head the buffer is empty. The length of the ringbuf
|
|
|
|
// is defined as the distance between the two.
|
|
|
|
|
|
|
|
tail: uint,
|
|
|
|
head: uint,
|
|
|
|
cap: uint,
|
|
|
|
ptr: *mut T
|
|
|
|
}
|
|
|
|
|
2014-12-30 03:20:24 -06:00
|
|
|
#[stable]
|
|
|
|
unsafe impl<T: Send> Send for RingBuf<T> {}
|
|
|
|
|
|
|
|
#[stable]
|
|
|
|
unsafe impl<T: Sync> Sync for RingBuf<T> {}
|
|
|
|
|
2014-12-20 02:35:06 -06:00
|
|
|
#[stable]
|
2014-10-19 15:19:07 -05:00
|
|
|
impl<T: Clone> Clone for RingBuf<T> {
|
|
|
|
fn clone(&self) -> RingBuf<T> {
|
|
|
|
self.iter().map(|t| t.clone()).collect()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[unsafe_destructor]
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-10-19 15:19:07 -05:00
|
|
|
impl<T> Drop for RingBuf<T> {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
self.clear();
|
|
|
|
unsafe {
|
|
|
|
if mem::size_of::<T>() != 0 {
|
|
|
|
heap::deallocate(self.ptr as *mut u8,
|
|
|
|
self.cap * mem::size_of::<T>(),
|
|
|
|
mem::min_align_of::<T>())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-01-11 05:49:33 -06:00
|
|
|
}
|
2010-07-20 20:03:09 -05:00
|
|
|
|
2014-12-15 22:04:52 -06:00
|
|
|
#[stable]
|
2014-06-09 02:30:04 -05:00
|
|
|
impl<T> Default for RingBuf<T> {
|
|
|
|
#[inline]
|
|
|
|
fn default() -> RingBuf<T> { RingBuf::new() }
|
|
|
|
}
|
|
|
|
|
2014-10-19 15:19:07 -05:00
|
|
|
impl<T> RingBuf<T> {
|
|
|
|
/// Turn ptr into a slice
|
|
|
|
#[inline]
|
2014-12-30 18:07:53 -06:00
|
|
|
unsafe fn buffer_as_slice(&self) -> &[T] {
|
2015-01-16 22:34:10 -06:00
|
|
|
mem::transmute(RawSlice { data: self.ptr, len: self.cap })
|
2014-12-15 22:01:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Turn ptr into a mut slice
|
|
|
|
#[inline]
|
2014-12-30 18:07:53 -06:00
|
|
|
unsafe fn buffer_as_mut_slice(&mut self) -> &mut [T] {
|
2015-01-16 22:34:10 -06:00
|
|
|
mem::transmute(RawSlice { data: self.ptr, len: self.cap })
|
2014-10-19 15:19:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Moves an element out of the buffer
|
|
|
|
#[inline]
|
|
|
|
unsafe fn buffer_read(&mut self, off: uint) -> T {
|
2015-01-16 22:34:10 -06:00
|
|
|
ptr::read(self.ptr.offset(off as int))
|
2014-10-19 15:19:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Writes an element into the buffer, moving it.
|
|
|
|
#[inline]
|
|
|
|
unsafe fn buffer_write(&mut self, off: uint, t: T) {
|
|
|
|
ptr::write(self.ptr.offset(off as int), t);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true iff the buffer is at capacity
|
|
|
|
#[inline]
|
|
|
|
fn is_full(&self) -> bool { self.cap - self.len() == 1 }
|
2014-11-11 19:22:07 -06:00
|
|
|
|
|
|
|
/// Returns the index in the underlying buffer for a given logical element index.
|
|
|
|
#[inline]
|
|
|
|
fn wrap_index(&self, idx: uint) -> uint { wrap_index(idx, self.cap) }
|
2014-12-03 11:12:30 -06:00
|
|
|
|
|
|
|
/// Copies a contiguous block of memory len long from src to dst
|
|
|
|
#[inline]
|
2014-12-16 17:37:55 -06:00
|
|
|
unsafe fn copy(&self, dst: uint, src: uint, len: uint) {
|
|
|
|
debug_assert!(dst + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
|
|
|
|
self.cap);
|
|
|
|
debug_assert!(src + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
|
|
|
|
self.cap);
|
|
|
|
ptr::copy_memory(
|
|
|
|
self.ptr.offset(dst as int),
|
2015-01-05 08:48:58 -06:00
|
|
|
self.ptr.offset(src as int),
|
|
|
|
len);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Copies a contiguous block of memory len long from src to dst
|
|
|
|
#[inline]
|
|
|
|
unsafe fn copy_nonoverlapping(&self, dst: uint, src: uint, len: uint) {
|
|
|
|
debug_assert!(dst + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
|
|
|
|
self.cap);
|
|
|
|
debug_assert!(src + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
|
|
|
|
self.cap);
|
|
|
|
ptr::copy_nonoverlapping_memory(
|
|
|
|
self.ptr.offset(dst as int),
|
|
|
|
self.ptr.offset(src as int),
|
2014-12-16 17:37:55 -06:00
|
|
|
len);
|
2014-12-03 11:12:30 -06:00
|
|
|
}
|
2014-10-19 15:19:07 -05:00
|
|
|
}
|
|
|
|
|
2013-07-10 08:27:14 -05:00
|
|
|
impl<T> RingBuf<T> {
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Creates an empty `RingBuf`.
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
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.
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2013-07-10 08:27:14 -05:00
|
|
|
pub fn with_capacity(n: uint) -> RingBuf<T> {
|
2014-10-19 15:19:07 -05:00
|
|
|
// +1 since the ringbuffer always leaves one space empty
|
2015-01-05 08:48:58 -06:00
|
|
|
let cap = cmp::max(n + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
|
|
|
|
assert!(cap > n, "capacity overflow");
|
2014-11-14 03:21:44 -06:00
|
|
|
let size = cap.checked_mul(mem::size_of::<T>())
|
2014-10-19 15:19:07 -05:00
|
|
|
.expect("capacity overflow");
|
|
|
|
|
2014-11-09 21:34:53 -06:00
|
|
|
let ptr = if mem::size_of::<T>() != 0 {
|
|
|
|
unsafe {
|
|
|
|
let ptr = heap::allocate(size, mem::min_align_of::<T>()) as *mut T;;
|
|
|
|
if ptr.is_null() { ::alloc::oom() }
|
|
|
|
ptr
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
heap::EMPTY as *mut T
|
|
|
|
};
|
|
|
|
|
2014-10-19 15:19:07 -05:00
|
|
|
RingBuf {
|
|
|
|
tail: 0,
|
|
|
|
head: 0,
|
|
|
|
cap: cap,
|
2014-11-09 21:34:53 -06:00
|
|
|
ptr: ptr
|
2014-10-19 15:19:07 -05:00
|
|
|
}
|
2013-07-10 08:27:14 -05:00
|
|
|
}
|
|
|
|
|
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-12-08 23:28:07 -06:00
|
|
|
/// # Examples
|
2014-11-06 11:24:47 -06:00
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf = RingBuf::new();
|
2015-01-05 21:08:37 -06:00
|
|
|
/// buf.push_back(3i);
|
2014-11-06 11:24:47 -06:00
|
|
|
/// buf.push_back(4);
|
|
|
|
/// buf.push_back(5);
|
|
|
|
/// assert_eq!(buf.get(1).unwrap(), &4);
|
|
|
|
/// ```
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-11-06 11:24:47 -06:00
|
|
|
pub fn get(&self, i: uint) -> Option<&T> {
|
2014-10-19 15:19:07 -05:00
|
|
|
if i < self.len() {
|
2014-11-11 19:22:07 -06:00
|
|
|
let idx = self.wrap_index(self.tail + i);
|
2014-10-19 15:19:07 -05:00
|
|
|
unsafe { Some(&*self.ptr.offset(idx as int)) }
|
|
|
|
} else {
|
|
|
|
None
|
2014-11-06 11:24:47 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Retrieves an element in the `RingBuf` mutably by index.
|
2014-07-17 18:19:51 -05:00
|
|
|
///
|
2014-12-08 23:28:07 -06:00
|
|
|
/// # Examples
|
2014-07-17 18:19:51 -05:00
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf = RingBuf::new();
|
2015-01-05 21:08:37 -06:00
|
|
|
/// buf.push_back(3i);
|
2014-11-06 11:24:47 -06:00
|
|
|
/// buf.push_back(4);
|
|
|
|
/// buf.push_back(5);
|
|
|
|
/// match buf.get_mut(1) {
|
|
|
|
/// None => {}
|
|
|
|
/// Some(elem) => {
|
|
|
|
/// *elem = 7;
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
2014-08-02 01:39:39 -05:00
|
|
|
/// assert_eq!(buf[1], 7);
|
2014-07-17 18:19:51 -05:00
|
|
|
/// ```
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-11-06 11:24:47 -06:00
|
|
|
pub fn get_mut(&mut self, i: uint) -> Option<&mut T> {
|
2014-10-19 15:19:07 -05:00
|
|
|
if i < self.len() {
|
2014-11-11 19:22:07 -06:00
|
|
|
let idx = self.wrap_index(self.tail + i);
|
2014-10-19 15:19:07 -05:00
|
|
|
unsafe { Some(&mut *self.ptr.offset(idx as int)) }
|
|
|
|
} else {
|
|
|
|
None
|
2014-11-06 11:24:47 -06:00
|
|
|
}
|
2013-07-10 08:27:14 -05:00
|
|
|
}
|
|
|
|
|
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
|
|
|
///
|
2014-12-08 23:28:07 -06:00
|
|
|
/// # Examples
|
2014-07-17 18:19:51 -05:00
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf = RingBuf::new();
|
2015-01-05 21:08:37 -06:00
|
|
|
/// buf.push_back(3i);
|
2014-11-06 11:24:47 -06:00
|
|
|
/// buf.push_back(4);
|
|
|
|
/// buf.push_back(5);
|
2014-07-17 18:19:51 -05:00
|
|
|
/// 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
|
|
|
/// ```
|
2014-12-19 17:53:40 -06:00
|
|
|
#[stable]
|
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());
|
2014-11-11 19:22:07 -06:00
|
|
|
let ri = self.wrap_index(self.tail + i);
|
|
|
|
let rj = self.wrap_index(self.tail + j);
|
2014-10-19 15:19:07 -05:00
|
|
|
unsafe {
|
|
|
|
ptr::swap(self.ptr.offset(ri as int), self.ptr.offset(rj as int))
|
|
|
|
}
|
2013-07-10 08:27:14 -05:00
|
|
|
}
|
|
|
|
|
2014-11-06 11:24:47 -06:00
|
|
|
/// Returns the number of elements the `RingBuf` can hold without
|
|
|
|
/// reallocating.
|
|
|
|
///
|
2014-12-08 23:28:07 -06:00
|
|
|
/// # Examples
|
2014-11-06 11:24:47 -06:00
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let buf: RingBuf<int> = RingBuf::with_capacity(10);
|
2014-10-19 15:19:07 -05:00
|
|
|
/// assert!(buf.capacity() >= 10);
|
2014-11-06 11:24:47 -06:00
|
|
|
/// ```
|
|
|
|
#[inline]
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-10-19 15:19:07 -05:00
|
|
|
pub fn capacity(&self) -> uint { self.cap - 1 }
|
2013-05-27 13:47:38 -05:00
|
|
|
|
2014-11-06 11:24:47 -06:00
|
|
|
/// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the
|
|
|
|
/// given `RingBuf`. Does nothing if the capacity is already sufficient.
|
|
|
|
///
|
|
|
|
/// Note that the allocator may give the collection more space than it requests. Therefore
|
|
|
|
/// capacity can not be relied upon to be precisely minimal. Prefer `reserve` if future
|
|
|
|
/// insertions are expected.
|
|
|
|
///
|
|
|
|
/// # Panics
|
|
|
|
///
|
|
|
|
/// Panics if the new capacity overflows `uint`.
|
2013-05-27 13:47:38 -05:00
|
|
|
///
|
2014-12-08 23:28:07 -06:00
|
|
|
/// # Examples
|
2014-11-06 11:24:47 -06:00
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf: RingBuf<int> = vec![1].into_iter().collect();
|
|
|
|
/// buf.reserve_exact(10);
|
|
|
|
/// assert!(buf.capacity() >= 11);
|
|
|
|
/// ```
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-11-06 11:24:47 -06:00
|
|
|
pub fn reserve_exact(&mut self, additional: uint) {
|
2014-10-19 15:19:07 -05:00
|
|
|
self.reserve(additional);
|
2014-11-06 11:24:47 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Reserves capacity for at least `additional` more elements to be inserted in the given
|
|
|
|
/// `Ringbuf`. The collection may reserve more space to avoid frequent reallocations.
|
|
|
|
///
|
|
|
|
/// # Panics
|
|
|
|
///
|
|
|
|
/// Panics if the new capacity overflows `uint`.
|
|
|
|
///
|
2014-12-08 23:28:07 -06:00
|
|
|
/// # Examples
|
2014-11-06 11:24:47 -06:00
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf: RingBuf<int> = vec![1].into_iter().collect();
|
|
|
|
/// buf.reserve(10);
|
|
|
|
/// assert!(buf.capacity() >= 11);
|
|
|
|
/// ```
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-11-06 11:24:47 -06:00
|
|
|
pub fn reserve(&mut self, additional: uint) {
|
2014-10-19 15:19:07 -05:00
|
|
|
let new_len = self.len() + additional;
|
|
|
|
assert!(new_len + 1 > self.len(), "capacity overflow");
|
|
|
|
if new_len > self.capacity() {
|
2014-11-14 03:21:44 -06:00
|
|
|
let count = (new_len + 1).next_power_of_two();
|
2014-10-19 15:19:07 -05:00
|
|
|
assert!(count >= new_len + 1);
|
|
|
|
|
|
|
|
if mem::size_of::<T>() != 0 {
|
|
|
|
let old = self.cap * mem::size_of::<T>();
|
2014-11-14 03:21:44 -06:00
|
|
|
let new = count.checked_mul(mem::size_of::<T>())
|
2014-10-19 15:19:07 -05:00
|
|
|
.expect("capacity overflow");
|
|
|
|
unsafe {
|
|
|
|
self.ptr = heap::reallocate(self.ptr as *mut u8,
|
|
|
|
old,
|
|
|
|
new,
|
|
|
|
mem::min_align_of::<T>()) as *mut T;
|
2014-11-09 21:34:53 -06:00
|
|
|
if self.ptr.is_null() { ::alloc::oom() }
|
2014-10-19 15:19:07 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move the shortest contiguous section of the ring buffer
|
|
|
|
// T H
|
|
|
|
// [o o o o o o o . ]
|
|
|
|
// T H
|
|
|
|
// A [o o o o o o o . . . . . . . . . ]
|
|
|
|
// H T
|
|
|
|
// [o o . o o o o o ]
|
|
|
|
// T H
|
|
|
|
// B [. . . o o o o o o o . . . . . . ]
|
|
|
|
// H T
|
|
|
|
// [o o o o o . o o ]
|
|
|
|
// H T
|
|
|
|
// C [o o o o o . . . . . . . . . o o ]
|
|
|
|
|
|
|
|
let oldcap = self.cap;
|
|
|
|
self.cap = count;
|
|
|
|
|
|
|
|
if self.tail <= self.head { // A
|
|
|
|
// Nop
|
|
|
|
} else if self.head < oldcap - self.tail { // B
|
|
|
|
unsafe {
|
2015-01-05 08:48:58 -06:00
|
|
|
self.copy_nonoverlapping(oldcap, 0, self.head);
|
2014-10-19 15:19:07 -05:00
|
|
|
}
|
|
|
|
self.head += oldcap;
|
2014-11-10 20:16:29 -06:00
|
|
|
debug_assert!(self.head > self.tail);
|
2014-10-19 15:19:07 -05:00
|
|
|
} else { // C
|
2015-01-05 08:48:58 -06:00
|
|
|
let new_tail = count - (oldcap - self.tail);
|
2014-10-19 15:19:07 -05:00
|
|
|
unsafe {
|
2015-01-05 08:48:58 -06:00
|
|
|
self.copy_nonoverlapping(new_tail, self.tail, oldcap - self.tail);
|
2014-10-19 15:19:07 -05:00
|
|
|
}
|
2015-01-05 08:48:58 -06:00
|
|
|
self.tail = new_tail;
|
|
|
|
debug_assert!(self.head < self.tail);
|
|
|
|
}
|
|
|
|
debug_assert!(self.head < self.cap);
|
|
|
|
debug_assert!(self.tail < self.cap);
|
|
|
|
debug_assert!(self.cap.count_ones() == 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Shrinks the capacity of the ringbuf as much as possible.
|
|
|
|
///
|
|
|
|
/// It will drop down as close as possible to the length but the allocator may still inform the
|
|
|
|
/// ringbuf that there is space for a few more elements.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf = RingBuf::with_capacity(15);
|
|
|
|
/// buf.extend(range(0u, 4));
|
|
|
|
/// assert_eq!(buf.capacity(), 15);
|
|
|
|
/// buf.shrink_to_fit();
|
|
|
|
/// assert!(buf.capacity() >= 4);
|
|
|
|
/// ```
|
|
|
|
pub fn shrink_to_fit(&mut self) {
|
|
|
|
// +1 since the ringbuffer always leaves one space empty
|
|
|
|
// len + 1 can't overflow for an existing, well-formed ringbuf.
|
|
|
|
let target_cap = cmp::max(self.len() + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
|
|
|
|
if target_cap < self.cap {
|
|
|
|
// There are three cases of interest:
|
|
|
|
// All elements are out of desired bounds
|
|
|
|
// Elements are contiguous, and head is out of desired bounds
|
|
|
|
// Elements are discontiguous, and tail is out of desired bounds
|
|
|
|
//
|
|
|
|
// At all other times, element positions are unaffected.
|
|
|
|
//
|
|
|
|
// Indicates that elements at the head should be moved.
|
|
|
|
let head_outside = self.head == 0 || self.head >= target_cap;
|
|
|
|
// Move elements from out of desired bounds (positions after target_cap)
|
|
|
|
if self.tail >= target_cap && head_outside {
|
|
|
|
// T H
|
|
|
|
// [. . . . . . . . o o o o o o o . ]
|
|
|
|
// T H
|
|
|
|
// [o o o o o o o . ]
|
|
|
|
unsafe {
|
|
|
|
self.copy_nonoverlapping(0, self.tail, self.len());
|
|
|
|
}
|
|
|
|
self.head = self.len();
|
|
|
|
self.tail = 0;
|
|
|
|
} else if self.tail != 0 && self.tail < target_cap && head_outside {
|
|
|
|
// T H
|
|
|
|
// [. . . o o o o o o o . . . . . . ]
|
|
|
|
// H T
|
|
|
|
// [o o . o o o o o ]
|
|
|
|
let len = self.wrap_index(self.head - target_cap);
|
|
|
|
unsafe {
|
|
|
|
self.copy_nonoverlapping(0, target_cap, len);
|
|
|
|
}
|
|
|
|
self.head = len;
|
|
|
|
debug_assert!(self.head < self.tail);
|
|
|
|
} else if self.tail >= target_cap {
|
|
|
|
// H T
|
|
|
|
// [o o o o o . . . . . . . . . o o ]
|
|
|
|
// H T
|
|
|
|
// [o o o o o . o o ]
|
|
|
|
debug_assert!(self.wrap_index(self.head - 1) < target_cap);
|
|
|
|
let len = self.cap - self.tail;
|
|
|
|
let new_tail = target_cap - len;
|
|
|
|
unsafe {
|
|
|
|
self.copy_nonoverlapping(new_tail, self.tail, len);
|
|
|
|
}
|
|
|
|
self.tail = new_tail;
|
2014-11-10 20:16:29 -06:00
|
|
|
debug_assert!(self.head < self.tail);
|
2014-10-19 15:19:07 -05:00
|
|
|
}
|
2015-01-05 08:48:58 -06:00
|
|
|
|
|
|
|
if mem::size_of::<T>() != 0 {
|
|
|
|
let old = self.cap * mem::size_of::<T>();
|
|
|
|
let new_size = target_cap * mem::size_of::<T>();
|
|
|
|
unsafe {
|
|
|
|
self.ptr = heap::reallocate(self.ptr as *mut u8,
|
|
|
|
old,
|
|
|
|
new_size,
|
|
|
|
mem::min_align_of::<T>()) as *mut T;
|
|
|
|
if self.ptr.is_null() { ::alloc::oom() }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.cap = target_cap;
|
2014-11-10 20:16:29 -06:00
|
|
|
debug_assert!(self.head < self.cap);
|
|
|
|
debug_assert!(self.tail < self.cap);
|
2014-11-11 19:22:07 -06:00
|
|
|
debug_assert!(self.cap.count_ones() == 1);
|
2014-10-19 15:19:07 -05:00
|
|
|
}
|
2013-05-27 13:47:38 -05:00
|
|
|
}
|
2013-06-25 14:08:47 -05:00
|
|
|
|
2015-01-05 08:48:58 -06:00
|
|
|
/// Shorten a ringbuf, dropping excess elements from the back.
|
|
|
|
///
|
|
|
|
/// If `len` is greater than the ringbuf's current length, this has no
|
|
|
|
/// effect.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf = RingBuf::new();
|
|
|
|
/// buf.push_back(5i);
|
|
|
|
/// buf.push_back(10i);
|
|
|
|
/// buf.push_back(15);
|
|
|
|
/// buf.truncate(1);
|
|
|
|
/// assert_eq!(buf.len(), 1);
|
|
|
|
/// assert_eq!(Some(&5), buf.get(0));
|
|
|
|
/// ```
|
|
|
|
#[unstable = "matches collection reform specification; waiting on panic semantics"]
|
|
|
|
pub fn truncate(&mut self, len: uint) {
|
|
|
|
for _ in range(len, self.len()) {
|
|
|
|
self.pop_back();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Returns a front-to-back iterator.
|
2014-07-17 18:19:51 -05:00
|
|
|
///
|
2014-12-08 23:28:07 -06:00
|
|
|
/// # Examples
|
2014-07-17 18:19:51 -05:00
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf = RingBuf::new();
|
2015-01-05 21:08:37 -06:00
|
|
|
/// buf.push_back(5i);
|
2014-11-06 11:24:47 -06:00
|
|
|
/// buf.push_back(3);
|
|
|
|
/// buf.push_back(4);
|
2014-08-06 04:59:40 -05:00
|
|
|
/// let b: &[_] = &[&5, &3, &4];
|
|
|
|
/// assert_eq!(buf.iter().collect::<Vec<&int>>().as_slice(), b);
|
2014-07-17 18:19:51 -05:00
|
|
|
/// ```
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-12-19 14:52:10 -06:00
|
|
|
pub fn iter(&self) -> Iter<T> {
|
|
|
|
Iter {
|
2014-10-19 15:19:07 -05:00
|
|
|
tail: self.tail,
|
|
|
|
head: self.head,
|
|
|
|
ring: unsafe { self.buffer_as_slice() }
|
|
|
|
}
|
2013-06-25 14:08:47 -05:00
|
|
|
}
|
2013-06-26 17:14:35 -05:00
|
|
|
|
2014-12-15 03:22:49 -06:00
|
|
|
/// Returns a front-to-back iterator that returns mutable references.
|
2014-07-17 18:19:51 -05:00
|
|
|
///
|
2014-12-08 23:28:07 -06:00
|
|
|
/// # Examples
|
2014-07-17 18:19:51 -05:00
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf = RingBuf::new();
|
2015-01-05 21:08:37 -06:00
|
|
|
/// buf.push_back(5i);
|
2014-11-06 11:24:47 -06:00
|
|
|
/// buf.push_back(3);
|
|
|
|
/// buf.push_back(4);
|
2014-09-14 22:27:36 -05:00
|
|
|
/// for num in buf.iter_mut() {
|
2014-07-17 18:19:51 -05:00
|
|
|
/// *num = *num - 2;
|
|
|
|
/// }
|
2014-08-06 04:59:40 -05:00
|
|
|
/// let b: &[_] = &[&mut 3, &mut 1, &mut 2];
|
2015-01-03 22:43:24 -06:00
|
|
|
/// assert_eq!(&buf.iter_mut().collect::<Vec<&mut int>>()[], b);
|
2014-07-17 18:19:51 -05:00
|
|
|
/// ```
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-12-19 14:52:10 -06:00
|
|
|
pub fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T> {
|
|
|
|
IterMut {
|
2014-10-19 15:19:07 -05:00
|
|
|
tail: self.tail,
|
|
|
|
head: self.head,
|
|
|
|
cap: self.cap,
|
|
|
|
ptr: self.ptr,
|
|
|
|
marker: marker::ContravariantLifetime::<'a>,
|
2013-11-16 16:29:39 -06:00
|
|
|
}
|
2013-06-25 14:08:47 -05:00
|
|
|
}
|
2014-10-30 15:43:24 -05:00
|
|
|
|
2014-11-22 20:34:11 -06:00
|
|
|
/// Consumes the list into an iterator yielding elements by value.
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-12-19 14:52:10 -06:00
|
|
|
pub fn into_iter(self) -> IntoIter<T> {
|
|
|
|
IntoIter {
|
2014-11-22 20:34:11 -06:00
|
|
|
inner: self,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-15 22:01:58 -06:00
|
|
|
/// Returns a pair of slices which contain, in order, the contents of the
|
|
|
|
/// `RingBuf`.
|
|
|
|
#[inline]
|
|
|
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
|
|
|
pub fn as_slices<'a>(&'a self) -> (&'a [T], &'a [T]) {
|
|
|
|
unsafe {
|
|
|
|
let contiguous = self.is_contiguous();
|
|
|
|
let buf = self.buffer_as_slice();
|
|
|
|
if contiguous {
|
|
|
|
let (empty, buf) = buf.split_at(0);
|
2015-01-07 10:58:31 -06:00
|
|
|
(&buf[self.tail..self.head], empty)
|
2014-12-15 22:01:58 -06:00
|
|
|
} else {
|
|
|
|
let (mid, right) = buf.split_at(self.tail);
|
|
|
|
let (left, _) = mid.split_at(self.head);
|
|
|
|
(right, left)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns a pair of slices which contain, in order, the contents of the
|
|
|
|
/// `RingBuf`.
|
|
|
|
#[inline]
|
|
|
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
|
|
|
pub fn as_mut_slices<'a>(&'a mut self) -> (&'a mut [T], &'a mut [T]) {
|
|
|
|
unsafe {
|
|
|
|
let contiguous = self.is_contiguous();
|
|
|
|
let head = self.head;
|
|
|
|
let tail = self.tail;
|
|
|
|
let buf = self.buffer_as_mut_slice();
|
|
|
|
|
|
|
|
if contiguous {
|
|
|
|
let (empty, buf) = buf.split_at_mut(0);
|
2014-12-22 21:23:11 -06:00
|
|
|
(buf.slice_mut(tail, head), empty)
|
2014-12-15 22:01:58 -06:00
|
|
|
} else {
|
|
|
|
let (mid, right) = buf.split_at_mut(tail);
|
|
|
|
let (left, _) = mid.split_at_mut(head);
|
|
|
|
|
|
|
|
(right, left)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-30 15:43:24 -05:00
|
|
|
/// Returns the number of elements in the `RingBuf`.
|
|
|
|
///
|
2014-12-08 23:28:07 -06:00
|
|
|
/// # Examples
|
2014-10-30 15:43:24 -05:00
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut v = RingBuf::new();
|
|
|
|
/// assert_eq!(v.len(), 0);
|
2015-01-05 21:08:37 -06:00
|
|
|
/// v.push_back(1i);
|
2014-10-30 15:43:24 -05:00
|
|
|
/// assert_eq!(v.len(), 1);
|
|
|
|
/// ```
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-10-19 15:19:07 -05:00
|
|
|
pub fn len(&self) -> uint { count(self.tail, self.head, self.cap) }
|
2014-10-30 15:43:24 -05:00
|
|
|
|
|
|
|
/// Returns true if the buffer contains no elements
|
|
|
|
///
|
2014-12-08 23:28:07 -06:00
|
|
|
/// # Examples
|
2014-10-30 15:43:24 -05:00
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut v = RingBuf::new();
|
|
|
|
/// assert!(v.is_empty());
|
2015-01-05 21:08:37 -06:00
|
|
|
/// v.push_front(1i);
|
2014-10-30 15:43:24 -05:00
|
|
|
/// assert!(!v.is_empty());
|
|
|
|
/// ```
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-10-30 15:43:24 -05:00
|
|
|
pub fn is_empty(&self) -> bool { self.len() == 0 }
|
|
|
|
|
2014-12-16 16:45:03 -06:00
|
|
|
/// Creates a draining iterator that clears the `RingBuf` and iterates over
|
|
|
|
/// the removed items from start to end.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut v = RingBuf::new();
|
2015-01-05 21:08:37 -06:00
|
|
|
/// v.push_back(1i);
|
2014-12-16 16:45:03 -06:00
|
|
|
/// assert_eq!(v.drain().next(), Some(1));
|
|
|
|
/// assert!(v.is_empty());
|
|
|
|
/// ```
|
|
|
|
#[inline]
|
|
|
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
2014-12-30 18:07:53 -06:00
|
|
|
pub fn drain(&mut self) -> Drain<T> {
|
2014-12-16 16:45:03 -06:00
|
|
|
Drain {
|
|
|
|
inner: self,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-30 15:43:24 -05:00
|
|
|
/// Clears the buffer, removing all values.
|
|
|
|
///
|
2014-12-08 23:28:07 -06:00
|
|
|
/// # Examples
|
2014-10-30 15:43:24 -05:00
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut v = RingBuf::new();
|
2015-01-05 21:08:37 -06:00
|
|
|
/// v.push_back(1i);
|
2014-10-30 15:43:24 -05:00
|
|
|
/// v.clear();
|
|
|
|
/// assert!(v.is_empty());
|
|
|
|
/// ```
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-12-16 16:45:03 -06:00
|
|
|
#[inline]
|
2014-10-30 15:43:24 -05:00
|
|
|
pub fn clear(&mut self) {
|
2014-12-16 16:45:03 -06:00
|
|
|
self.drain();
|
2014-10-30 15:43:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Provides a reference to the front element, or `None` if the sequence is
|
|
|
|
/// empty.
|
|
|
|
///
|
2014-12-08 23:28:07 -06:00
|
|
|
/// # Examples
|
2014-10-30 15:43:24 -05:00
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut d = RingBuf::new();
|
|
|
|
/// assert_eq!(d.front(), None);
|
|
|
|
///
|
2015-01-05 21:08:37 -06:00
|
|
|
/// d.push_back(1i);
|
|
|
|
/// d.push_back(2i);
|
|
|
|
/// assert_eq!(d.front(), Some(&1i));
|
2014-10-30 15:43:24 -05:00
|
|
|
/// ```
|
2014-12-19 17:53:40 -06:00
|
|
|
#[stable]
|
2014-10-30 15:43:24 -05:00
|
|
|
pub fn front(&self) -> Option<&T> {
|
2014-10-19 15:19:07 -05:00
|
|
|
if !self.is_empty() { Some(&self[0]) } else { None }
|
2014-10-30 15:43:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Provides a mutable reference to the front element, or `None` if the
|
|
|
|
/// sequence is empty.
|
|
|
|
///
|
2014-12-08 23:28:07 -06:00
|
|
|
/// # Examples
|
2014-10-30 15:43:24 -05:00
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut d = RingBuf::new();
|
|
|
|
/// assert_eq!(d.front_mut(), None);
|
|
|
|
///
|
2015-01-05 21:08:37 -06:00
|
|
|
/// d.push_back(1i);
|
|
|
|
/// d.push_back(2i);
|
2014-10-30 15:43:24 -05:00
|
|
|
/// match d.front_mut() {
|
2015-01-05 21:08:37 -06:00
|
|
|
/// Some(x) => *x = 9i,
|
2014-10-30 15:43:24 -05:00
|
|
|
/// None => (),
|
|
|
|
/// }
|
2015-01-05 21:08:37 -06:00
|
|
|
/// assert_eq!(d.front(), Some(&9i));
|
2014-10-30 15:43:24 -05:00
|
|
|
/// ```
|
2014-12-19 17:53:40 -06:00
|
|
|
#[stable]
|
2014-10-30 15:43:24 -05:00
|
|
|
pub fn front_mut(&mut self) -> Option<&mut T> {
|
2014-10-19 15:19:07 -05:00
|
|
|
if !self.is_empty() { Some(&mut self[0]) } else { None }
|
2014-10-30 15:43:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Provides a reference to the back element, or `None` if the sequence is
|
|
|
|
/// empty.
|
|
|
|
///
|
2014-12-08 23:28:07 -06:00
|
|
|
/// # Examples
|
2014-10-30 15:43:24 -05:00
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut d = RingBuf::new();
|
|
|
|
/// assert_eq!(d.back(), None);
|
|
|
|
///
|
2015-01-05 21:08:37 -06:00
|
|
|
/// d.push_back(1i);
|
|
|
|
/// d.push_back(2i);
|
|
|
|
/// assert_eq!(d.back(), Some(&2i));
|
2014-10-30 15:43:24 -05:00
|
|
|
/// ```
|
2014-12-19 17:53:40 -06:00
|
|
|
#[stable]
|
2014-10-30 15:43:24 -05:00
|
|
|
pub fn back(&self) -> Option<&T> {
|
2014-10-19 15:19:07 -05:00
|
|
|
if !self.is_empty() { Some(&self[self.len() - 1]) } else { None }
|
2014-10-30 15:43:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Provides a mutable reference to the back element, or `None` if the
|
|
|
|
/// sequence is empty.
|
|
|
|
///
|
2014-12-08 23:28:07 -06:00
|
|
|
/// # Examples
|
2014-10-30 15:43:24 -05:00
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut d = RingBuf::new();
|
|
|
|
/// assert_eq!(d.back(), None);
|
|
|
|
///
|
2015-01-05 21:08:37 -06:00
|
|
|
/// d.push_back(1i);
|
|
|
|
/// d.push_back(2i);
|
2014-10-30 15:43:24 -05:00
|
|
|
/// match d.back_mut() {
|
2015-01-05 21:08:37 -06:00
|
|
|
/// Some(x) => *x = 9i,
|
2014-10-30 15:43:24 -05:00
|
|
|
/// None => (),
|
|
|
|
/// }
|
2015-01-05 21:08:37 -06:00
|
|
|
/// assert_eq!(d.back(), Some(&9i));
|
2014-10-30 15:43:24 -05:00
|
|
|
/// ```
|
2014-12-19 17:53:40 -06:00
|
|
|
#[stable]
|
2014-10-30 15:43:24 -05:00
|
|
|
pub fn back_mut(&mut self) -> Option<&mut T> {
|
2014-10-19 15:19:07 -05:00
|
|
|
let len = self.len();
|
|
|
|
if !self.is_empty() { Some(&mut self[len - 1]) } else { None }
|
2014-10-30 15:43:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Removes the first element and returns it, or `None` if the sequence is
|
|
|
|
/// empty.
|
|
|
|
///
|
2014-12-08 23:28:07 -06:00
|
|
|
/// # Examples
|
2014-10-30 15:43:24 -05:00
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut d = RingBuf::new();
|
2015-01-05 21:08:37 -06:00
|
|
|
/// d.push_back(1i);
|
|
|
|
/// d.push_back(2i);
|
2014-10-30 15:43:24 -05:00
|
|
|
///
|
2015-01-05 21:08:37 -06:00
|
|
|
/// assert_eq!(d.pop_front(), Some(1i));
|
|
|
|
/// assert_eq!(d.pop_front(), Some(2i));
|
2014-10-30 15:43:24 -05:00
|
|
|
/// assert_eq!(d.pop_front(), None);
|
|
|
|
/// ```
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-10-30 15:43:24 -05:00
|
|
|
pub fn pop_front(&mut self) -> Option<T> {
|
2014-10-19 15:19:07 -05:00
|
|
|
if self.is_empty() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
let tail = self.tail;
|
2014-11-11 19:22:07 -06:00
|
|
|
self.tail = self.wrap_index(self.tail + 1);
|
2014-10-19 15:19:07 -05:00
|
|
|
unsafe { Some(self.buffer_read(tail)) }
|
2014-10-30 15:43:24 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Inserts an element first in the sequence.
|
|
|
|
///
|
2014-12-08 23:28:07 -06:00
|
|
|
/// # Examples
|
2014-10-30 15:43:24 -05:00
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut d = RingBuf::new();
|
2015-01-05 21:08:37 -06:00
|
|
|
/// d.push_front(1i);
|
|
|
|
/// d.push_front(2i);
|
|
|
|
/// assert_eq!(d.front(), Some(&2i));
|
2014-10-30 15:43:24 -05:00
|
|
|
/// ```
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-10-30 15:43:24 -05:00
|
|
|
pub fn push_front(&mut self, t: T) {
|
2014-11-10 20:16:29 -06:00
|
|
|
if self.is_full() {
|
|
|
|
self.reserve(1);
|
|
|
|
debug_assert!(!self.is_full());
|
|
|
|
}
|
2014-10-19 15:19:07 -05:00
|
|
|
|
2014-11-11 19:22:07 -06:00
|
|
|
self.tail = self.wrap_index(self.tail - 1);
|
2014-10-19 15:19:07 -05:00
|
|
|
let tail = self.tail;
|
|
|
|
unsafe { self.buffer_write(tail, t); }
|
2014-10-30 15:43:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Appends an element to the back of a buffer
|
|
|
|
///
|
2014-12-08 23:28:07 -06:00
|
|
|
/// # Examples
|
2014-10-30 15:43:24 -05:00
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf = RingBuf::new();
|
2015-01-05 21:08:37 -06:00
|
|
|
/// buf.push_back(1i);
|
2014-11-06 11:24:47 -06:00
|
|
|
/// buf.push_back(3);
|
2014-10-30 15:43:24 -05:00
|
|
|
/// assert_eq!(3, *buf.back().unwrap());
|
|
|
|
/// ```
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-11-06 11:24:47 -06:00
|
|
|
pub fn push_back(&mut self, t: T) {
|
2014-11-10 20:16:29 -06:00
|
|
|
if self.is_full() {
|
|
|
|
self.reserve(1);
|
|
|
|
debug_assert!(!self.is_full());
|
|
|
|
}
|
2014-10-19 15:19:07 -05:00
|
|
|
|
|
|
|
let head = self.head;
|
2014-11-11 19:22:07 -06:00
|
|
|
self.head = self.wrap_index(self.head + 1);
|
2014-10-19 15:19:07 -05:00
|
|
|
unsafe { self.buffer_write(head, t) }
|
2014-10-30 15:43:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Removes the last element from a buffer and returns it, or `None` if
|
|
|
|
/// it is empty.
|
|
|
|
///
|
2014-12-08 23:28:07 -06:00
|
|
|
/// # Examples
|
2014-10-30 15:43:24 -05:00
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf = RingBuf::new();
|
2014-11-06 11:24:47 -06:00
|
|
|
/// assert_eq!(buf.pop_back(), None);
|
2015-01-05 21:08:37 -06:00
|
|
|
/// buf.push_back(1i);
|
2014-11-06 11:24:47 -06:00
|
|
|
/// buf.push_back(3);
|
|
|
|
/// assert_eq!(buf.pop_back(), Some(3));
|
2014-10-30 15:43:24 -05:00
|
|
|
/// ```
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-11-06 11:24:47 -06:00
|
|
|
pub fn pop_back(&mut self) -> Option<T> {
|
2014-10-19 15:19:07 -05:00
|
|
|
if self.is_empty() {
|
2014-10-30 15:43:24 -05:00
|
|
|
None
|
2014-10-19 15:19:07 -05:00
|
|
|
} else {
|
2014-11-11 19:22:07 -06:00
|
|
|
self.head = self.wrap_index(self.head - 1);
|
2014-10-19 15:19:07 -05:00
|
|
|
let head = self.head;
|
|
|
|
unsafe { Some(self.buffer_read(head)) }
|
2014-10-30 15:43:24 -05:00
|
|
|
}
|
|
|
|
}
|
2014-12-03 11:12:30 -06:00
|
|
|
|
2014-12-15 22:01:58 -06:00
|
|
|
#[inline]
|
|
|
|
fn is_contiguous(&self) -> bool {
|
|
|
|
self.tail <= self.head
|
|
|
|
}
|
|
|
|
|
2015-01-05 08:48:58 -06:00
|
|
|
/// Removes an element from anywhere in the ringbuf and returns it, replacing it with the last
|
|
|
|
/// element.
|
|
|
|
///
|
|
|
|
/// This does not preserve ordering, but is O(1).
|
|
|
|
///
|
|
|
|
/// Returns `None` if `index` is out of bounds.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf = RingBuf::new();
|
|
|
|
/// assert_eq!(buf.swap_back_remove(0), None);
|
|
|
|
/// buf.push_back(5i);
|
|
|
|
/// buf.push_back(99);
|
|
|
|
/// buf.push_back(15);
|
|
|
|
/// buf.push_back(20);
|
|
|
|
/// buf.push_back(10);
|
|
|
|
/// assert_eq!(buf.swap_back_remove(1), Some(99));
|
|
|
|
/// ```
|
|
|
|
#[unstable = "the naming of this function may be altered"]
|
|
|
|
pub fn swap_back_remove(&mut self, index: uint) -> Option<T> {
|
|
|
|
let length = self.len();
|
|
|
|
if length > 0 && index < length - 1 {
|
|
|
|
self.swap(index, length - 1);
|
|
|
|
} else if index >= length {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
self.pop_back()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Removes an element from anywhere in the ringbuf and returns it, replacing it with the first
|
|
|
|
/// element.
|
|
|
|
///
|
|
|
|
/// This does not preserve ordering, but is O(1).
|
|
|
|
///
|
|
|
|
/// Returns `None` if `index` is out of bounds.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf = RingBuf::new();
|
|
|
|
/// assert_eq!(buf.swap_front_remove(0), None);
|
|
|
|
/// buf.push_back(15i);
|
|
|
|
/// buf.push_back(5);
|
|
|
|
/// buf.push_back(10);
|
|
|
|
/// buf.push_back(99);
|
|
|
|
/// buf.push_back(20i);
|
|
|
|
/// assert_eq!(buf.swap_front_remove(3), Some(99));
|
|
|
|
/// ```
|
|
|
|
#[unstable = "the naming of this function may be altered"]
|
|
|
|
pub fn swap_front_remove(&mut self, index: uint) -> Option<T> {
|
|
|
|
let length = self.len();
|
|
|
|
if length > 0 && index < length && index != 0 {
|
|
|
|
self.swap(index, 0);
|
|
|
|
} else if index >= length {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
self.pop_front()
|
|
|
|
}
|
|
|
|
|
2014-12-03 11:12:30 -06:00
|
|
|
/// Inserts an element at position `i` within the ringbuf. Whichever
|
|
|
|
/// end is closer to the insertion point will be moved to make room,
|
|
|
|
/// and all the affected elements will be moved to new positions.
|
|
|
|
///
|
|
|
|
/// # Panics
|
|
|
|
///
|
|
|
|
/// Panics if `i` is greater than ringbuf's length
|
|
|
|
///
|
2015-01-05 08:48:58 -06:00
|
|
|
/// # Examples
|
2014-12-03 11:12:30 -06:00
|
|
|
/// ```rust
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf = RingBuf::new();
|
2015-01-05 21:08:37 -06:00
|
|
|
/// buf.push_back(10i);
|
2014-12-03 11:12:30 -06:00
|
|
|
/// buf.push_back(12);
|
|
|
|
/// buf.insert(1,11);
|
|
|
|
/// assert_eq!(Some(&11), buf.get(1));
|
|
|
|
/// ```
|
|
|
|
pub fn insert(&mut self, i: uint, t: T) {
|
|
|
|
assert!(i <= self.len(), "index out of bounds");
|
|
|
|
if self.is_full() {
|
|
|
|
self.reserve(1);
|
|
|
|
debug_assert!(!self.is_full());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move the least number of elements in the ring buffer and insert
|
|
|
|
// the given object
|
|
|
|
//
|
|
|
|
// At most len/2 - 1 elements will be moved. O(min(n, n-i))
|
|
|
|
//
|
|
|
|
// There are three main cases:
|
|
|
|
// Elements are contiguous
|
|
|
|
// - special case when tail is 0
|
|
|
|
// Elements are discontiguous and the insert is in the tail section
|
|
|
|
// Elements are discontiguous and the insert is in the head section
|
|
|
|
//
|
|
|
|
// For each of those there are two more cases:
|
|
|
|
// Insert is closer to tail
|
|
|
|
// Insert is closer to head
|
|
|
|
//
|
|
|
|
// Key: H - self.head
|
|
|
|
// T - self.tail
|
|
|
|
// o - Valid element
|
|
|
|
// I - Insertion element
|
|
|
|
// A - The element that should be after the insertion point
|
|
|
|
// M - Indicates element was moved
|
|
|
|
|
|
|
|
let idx = self.wrap_index(self.tail + i);
|
|
|
|
|
|
|
|
let distance_to_tail = i;
|
|
|
|
let distance_to_head = self.len() - i;
|
|
|
|
|
2014-12-15 22:01:58 -06:00
|
|
|
let contiguous = self.is_contiguous();
|
2014-12-03 11:12:30 -06:00
|
|
|
|
|
|
|
match (contiguous, distance_to_tail <= distance_to_head, idx >= self.tail) {
|
|
|
|
(true, true, _) if i == 0 => {
|
|
|
|
// push_front
|
|
|
|
//
|
|
|
|
// T
|
|
|
|
// I H
|
|
|
|
// [A o o o o o o . . . . . . . . .]
|
|
|
|
//
|
|
|
|
// H T
|
|
|
|
// [A o o o o o o o . . . . . I]
|
|
|
|
//
|
|
|
|
|
|
|
|
self.tail = self.wrap_index(self.tail - 1);
|
|
|
|
},
|
2014-12-16 17:37:55 -06:00
|
|
|
(true, true, _) => unsafe {
|
2014-12-03 11:12:30 -06:00
|
|
|
// contiguous, insert closer to tail:
|
|
|
|
//
|
|
|
|
// T I H
|
|
|
|
// [. . . o o A o o o o . . . . . .]
|
|
|
|
//
|
|
|
|
// T H
|
|
|
|
// [. . o o I A o o o o . . . . . .]
|
|
|
|
// M M
|
|
|
|
//
|
|
|
|
// contiguous, insert closer to tail and tail is 0:
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// T I H
|
|
|
|
// [o o A o o o o . . . . . . . . .]
|
|
|
|
//
|
|
|
|
// H T
|
|
|
|
// [o I A o o o o o . . . . . . . o]
|
|
|
|
// M M
|
|
|
|
|
2014-12-16 17:37:55 -06:00
|
|
|
let new_tail = self.wrap_index(self.tail - 1);
|
|
|
|
|
|
|
|
self.copy(new_tail, self.tail, 1);
|
|
|
|
// Already moved the tail, so we only copy `i - 1` elements.
|
|
|
|
self.copy(self.tail, self.tail + 1, i - 1);
|
2014-12-03 11:12:30 -06:00
|
|
|
|
2014-12-16 17:37:55 -06:00
|
|
|
self.tail = new_tail;
|
2014-12-03 11:12:30 -06:00
|
|
|
},
|
2014-12-16 17:37:55 -06:00
|
|
|
(true, false, _) => unsafe {
|
2014-12-03 11:12:30 -06:00
|
|
|
// contiguous, insert closer to head:
|
|
|
|
//
|
|
|
|
// T I H
|
|
|
|
// [. . . o o o o A o o . . . . . .]
|
|
|
|
//
|
|
|
|
// T H
|
|
|
|
// [. . . o o o o I A o o . . . . .]
|
|
|
|
// M M M
|
|
|
|
|
2014-12-16 17:37:55 -06:00
|
|
|
self.copy(idx + 1, idx, self.head - idx);
|
2014-12-03 11:12:30 -06:00
|
|
|
self.head = self.wrap_index(self.head + 1);
|
|
|
|
},
|
2014-12-16 17:37:55 -06:00
|
|
|
(false, true, true) => unsafe {
|
|
|
|
// discontiguous, insert closer to tail, tail section:
|
2014-12-03 11:12:30 -06:00
|
|
|
//
|
|
|
|
// H T I
|
|
|
|
// [o o o o o o . . . . . o o A o o]
|
|
|
|
//
|
|
|
|
// H T
|
|
|
|
// [o o o o o o . . . . o o I A o o]
|
|
|
|
// M M
|
|
|
|
|
2014-12-16 17:37:55 -06:00
|
|
|
self.copy(self.tail - 1, self.tail, i);
|
|
|
|
self.tail -= 1;
|
2014-12-03 11:12:30 -06:00
|
|
|
},
|
2014-12-16 17:37:55 -06:00
|
|
|
(false, false, true) => unsafe {
|
|
|
|
// discontiguous, insert closer to head, tail section:
|
2014-12-03 11:12:30 -06:00
|
|
|
//
|
|
|
|
// H T I
|
|
|
|
// [o o . . . . . . . o o o o o A o]
|
|
|
|
//
|
|
|
|
// H T
|
|
|
|
// [o o o . . . . . . o o o o o I A]
|
|
|
|
// M M M M
|
|
|
|
|
|
|
|
// copy elements up to new head
|
2014-12-16 17:37:55 -06:00
|
|
|
self.copy(1, 0, self.head);
|
2014-12-03 11:12:30 -06:00
|
|
|
|
|
|
|
// copy last element into empty spot at bottom of buffer
|
|
|
|
self.copy(0, self.cap - 1, 1);
|
|
|
|
|
|
|
|
// move elements from idx to end forward not including ^ element
|
|
|
|
self.copy(idx + 1, idx, self.cap - 1 - idx);
|
2014-12-16 17:37:55 -06:00
|
|
|
|
|
|
|
self.head += 1;
|
2014-12-03 11:12:30 -06:00
|
|
|
},
|
2014-12-16 17:37:55 -06:00
|
|
|
(false, true, false) if idx == 0 => unsafe {
|
|
|
|
// discontiguous, insert is closer to tail, head section,
|
2014-12-03 11:12:30 -06:00
|
|
|
// and is at index zero in the internal buffer:
|
|
|
|
//
|
|
|
|
// I H T
|
|
|
|
// [A o o o o o o o o o . . . o o o]
|
|
|
|
//
|
|
|
|
// H T
|
|
|
|
// [A o o o o o o o o o . . o o o I]
|
|
|
|
// M M M
|
|
|
|
|
|
|
|
// copy elements up to new tail
|
2014-12-16 17:37:55 -06:00
|
|
|
self.copy(self.tail - 1, self.tail, self.cap - self.tail);
|
2014-12-03 11:12:30 -06:00
|
|
|
|
|
|
|
// copy last element into empty spot at bottom of buffer
|
|
|
|
self.copy(self.cap - 1, 0, 1);
|
2014-12-16 17:37:55 -06:00
|
|
|
|
|
|
|
self.tail -= 1;
|
2014-12-03 11:12:30 -06:00
|
|
|
},
|
2014-12-16 17:37:55 -06:00
|
|
|
(false, true, false) => unsafe {
|
|
|
|
// discontiguous, insert closer to tail, head section:
|
2014-12-03 11:12:30 -06:00
|
|
|
//
|
|
|
|
// I H T
|
|
|
|
// [o o o A o o o o o o . . . o o o]
|
|
|
|
//
|
|
|
|
// H T
|
|
|
|
// [o o I A o o o o o o . . o o o o]
|
|
|
|
// M M M M M M
|
|
|
|
|
|
|
|
// copy elements up to new tail
|
2014-12-16 17:37:55 -06:00
|
|
|
self.copy(self.tail - 1, self.tail, self.cap - self.tail);
|
2014-12-03 11:12:30 -06:00
|
|
|
|
|
|
|
// copy last element into empty spot at bottom of buffer
|
|
|
|
self.copy(self.cap - 1, 0, 1);
|
|
|
|
|
|
|
|
// move elements from idx-1 to end forward not including ^ element
|
|
|
|
self.copy(0, 1, idx - 1);
|
2014-12-16 17:37:55 -06:00
|
|
|
|
|
|
|
self.tail -= 1;
|
|
|
|
},
|
|
|
|
(false, false, false) => unsafe {
|
|
|
|
// discontiguous, insert closer to head, head section:
|
2014-12-03 11:12:30 -06:00
|
|
|
//
|
|
|
|
// I H T
|
|
|
|
// [o o o o A o o . . . . . . o o o]
|
|
|
|
//
|
|
|
|
// H T
|
|
|
|
// [o o o o I A o o . . . . . o o o]
|
|
|
|
// M M M
|
|
|
|
|
2014-12-16 17:37:55 -06:00
|
|
|
self.copy(idx + 1, idx, self.head - idx);
|
|
|
|
self.head += 1;
|
2014-12-03 11:12:30 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// tail might've been changed so we need to recalculate
|
|
|
|
let new_idx = self.wrap_index(self.tail + i);
|
|
|
|
unsafe {
|
|
|
|
self.buffer_write(new_idx, t);
|
|
|
|
}
|
|
|
|
}
|
2014-12-16 17:37:55 -06:00
|
|
|
|
|
|
|
/// Removes and returns the element at position `i` from the ringbuf.
|
|
|
|
/// Whichever end is closer to the removal point will be moved to make
|
|
|
|
/// room, and all the affected elements will be moved to new positions.
|
|
|
|
/// Returns `None` if `i` is out of bounds.
|
|
|
|
///
|
2015-01-05 08:48:58 -06:00
|
|
|
/// # Examples
|
2014-12-16 17:37:55 -06:00
|
|
|
/// ```rust
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf = RingBuf::new();
|
2015-01-05 21:08:37 -06:00
|
|
|
/// buf.push_back(5i);
|
|
|
|
/// buf.push_back(10i);
|
|
|
|
/// buf.push_back(12i);
|
2014-12-16 17:37:55 -06:00
|
|
|
/// buf.push_back(15);
|
|
|
|
/// buf.remove(2);
|
|
|
|
/// assert_eq!(Some(&15), buf.get(2));
|
|
|
|
/// ```
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-12-16 17:37:55 -06:00
|
|
|
pub fn remove(&mut self, i: uint) -> Option<T> {
|
|
|
|
if self.is_empty() || self.len() <= i {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
|
|
|
// There are three main cases:
|
|
|
|
// Elements are contiguous
|
|
|
|
// Elements are discontiguous and the removal is in the tail section
|
|
|
|
// Elements are discontiguous and the removal is in the head section
|
|
|
|
// - special case when elements are technically contiguous,
|
|
|
|
// but self.head = 0
|
|
|
|
//
|
|
|
|
// For each of those there are two more cases:
|
|
|
|
// Insert is closer to tail
|
|
|
|
// Insert is closer to head
|
|
|
|
//
|
|
|
|
// Key: H - self.head
|
|
|
|
// T - self.tail
|
|
|
|
// o - Valid element
|
|
|
|
// x - Element marked for removal
|
|
|
|
// R - Indicates element that is being removed
|
|
|
|
// M - Indicates element was moved
|
|
|
|
|
|
|
|
let idx = self.wrap_index(self.tail + i);
|
|
|
|
|
|
|
|
let elem = unsafe {
|
|
|
|
Some(self.buffer_read(idx))
|
|
|
|
};
|
|
|
|
|
|
|
|
let distance_to_tail = i;
|
|
|
|
let distance_to_head = self.len() - i;
|
|
|
|
|
2015-01-05 08:48:58 -06:00
|
|
|
let contiguous = self.is_contiguous();
|
2014-12-16 17:37:55 -06:00
|
|
|
|
|
|
|
match (contiguous, distance_to_tail <= distance_to_head, idx >= self.tail) {
|
|
|
|
(true, true, _) => unsafe {
|
|
|
|
// contiguous, remove closer to tail:
|
|
|
|
//
|
|
|
|
// T R H
|
|
|
|
// [. . . o o x o o o o . . . . . .]
|
|
|
|
//
|
|
|
|
// T H
|
|
|
|
// [. . . . o o o o o o . . . . . .]
|
|
|
|
// M M
|
|
|
|
|
|
|
|
self.copy(self.tail + 1, self.tail, i);
|
|
|
|
self.tail += 1;
|
|
|
|
},
|
|
|
|
(true, false, _) => unsafe {
|
|
|
|
// contiguous, remove closer to head:
|
|
|
|
//
|
|
|
|
// T R H
|
|
|
|
// [. . . o o o o x o o . . . . . .]
|
|
|
|
//
|
|
|
|
// T H
|
|
|
|
// [. . . o o o o o o . . . . . . .]
|
|
|
|
// M M
|
|
|
|
|
|
|
|
self.copy(idx, idx + 1, self.head - idx - 1);
|
|
|
|
self.head -= 1;
|
|
|
|
},
|
|
|
|
(false, true, true) => unsafe {
|
|
|
|
// discontiguous, remove closer to tail, tail section:
|
|
|
|
//
|
|
|
|
// H T R
|
|
|
|
// [o o o o o o . . . . . o o x o o]
|
|
|
|
//
|
|
|
|
// H T
|
|
|
|
// [o o o o o o . . . . . . o o o o]
|
|
|
|
// M M
|
|
|
|
|
|
|
|
self.copy(self.tail + 1, self.tail, i);
|
|
|
|
self.tail = self.wrap_index(self.tail + 1);
|
|
|
|
},
|
|
|
|
(false, false, false) => unsafe {
|
|
|
|
// discontiguous, remove closer to head, head section:
|
|
|
|
//
|
|
|
|
// R H T
|
|
|
|
// [o o o o x o o . . . . . . o o o]
|
|
|
|
//
|
|
|
|
// H T
|
|
|
|
// [o o o o o o . . . . . . . o o o]
|
|
|
|
// M M
|
|
|
|
|
|
|
|
self.copy(idx, idx + 1, self.head - idx - 1);
|
|
|
|
self.head -= 1;
|
|
|
|
},
|
|
|
|
(false, false, true) => unsafe {
|
|
|
|
// discontiguous, remove closer to head, tail section:
|
|
|
|
//
|
|
|
|
// H T R
|
|
|
|
// [o o o . . . . . . o o o o o x o]
|
|
|
|
//
|
|
|
|
// H T
|
|
|
|
// [o o . . . . . . . o o o o o o o]
|
|
|
|
// M M M M
|
|
|
|
//
|
|
|
|
// or quasi-discontiguous, remove next to head, tail section:
|
|
|
|
//
|
|
|
|
// H T R
|
|
|
|
// [. . . . . . . . . o o o o o x o]
|
|
|
|
//
|
|
|
|
// T H
|
|
|
|
// [. . . . . . . . . o o o o o o .]
|
|
|
|
// M
|
|
|
|
|
|
|
|
// draw in elements in the tail section
|
|
|
|
self.copy(idx, idx + 1, self.cap - idx - 1);
|
|
|
|
|
|
|
|
// Prevents underflow.
|
|
|
|
if self.head != 0 {
|
|
|
|
// copy first element into empty spot
|
|
|
|
self.copy(self.cap - 1, 0, 1);
|
|
|
|
|
|
|
|
// move elements in the head section backwards
|
|
|
|
self.copy(0, 1, self.head - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
self.head = self.wrap_index(self.head - 1);
|
|
|
|
},
|
|
|
|
(false, true, false) => unsafe {
|
|
|
|
// discontiguous, remove closer to tail, head section:
|
|
|
|
//
|
|
|
|
// R H T
|
|
|
|
// [o o x o o o o o o o . . . o o o]
|
|
|
|
//
|
|
|
|
// H T
|
|
|
|
// [o o o o o o o o o o . . . . o o]
|
|
|
|
// M M M M M
|
|
|
|
|
|
|
|
// draw in elements up to idx
|
|
|
|
self.copy(1, 0, idx);
|
|
|
|
|
|
|
|
// copy last element into empty spot
|
|
|
|
self.copy(0, self.cap - 1, 1);
|
|
|
|
|
|
|
|
// move elements from tail to end forward, excluding the last one
|
|
|
|
self.copy(self.tail + 1, self.tail, self.cap - self.tail - 1);
|
|
|
|
|
|
|
|
self.tail = self.wrap_index(self.tail + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return elem;
|
|
|
|
}
|
2013-06-25 14:08:47 -05:00
|
|
|
}
|
|
|
|
|
2015-01-05 08:48:58 -06:00
|
|
|
impl<T: Clone> RingBuf<T> {
|
|
|
|
/// Modifies the ringbuf in-place so that `len()` is equal to new_len,
|
|
|
|
/// either by removing excess elements or by appending copies of a value to the back.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::collections::RingBuf;
|
|
|
|
///
|
|
|
|
/// let mut buf = RingBuf::new();
|
|
|
|
/// buf.push_back(5i);
|
|
|
|
/// buf.push_back(10i);
|
|
|
|
/// buf.push_back(15);
|
|
|
|
/// buf.resize(2, 0);
|
|
|
|
/// buf.resize(6, 20);
|
|
|
|
/// for (a, b) in [5, 10, 20, 20, 20, 20].iter().zip(buf.iter()) {
|
|
|
|
/// assert_eq!(a, b);
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
#[unstable = "matches collection reform specification; waiting on panic semantics"]
|
|
|
|
pub fn resize(&mut self, new_len: uint, value: T) {
|
|
|
|
let len = self.len();
|
|
|
|
|
|
|
|
if new_len > len {
|
|
|
|
self.extend(repeat(value).take(new_len - len))
|
|
|
|
} else {
|
|
|
|
self.truncate(new_len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-19 15:19:07 -05:00
|
|
|
/// Returns the index in the underlying buffer for a given logical element index.
|
|
|
|
#[inline]
|
|
|
|
fn wrap_index(index: uint, size: uint) -> uint {
|
|
|
|
// size is always a power of 2
|
2014-11-11 19:22:07 -06:00
|
|
|
index & (size - 1)
|
2014-10-19 15:19:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Calculate the number of elements left to be read in the buffer
|
|
|
|
#[inline]
|
|
|
|
fn count(tail: uint, head: uint, size: uint) -> uint {
|
|
|
|
// size is always a power of 2
|
|
|
|
(head - tail) & (size - 1)
|
|
|
|
}
|
|
|
|
|
2014-08-27 20:46:52 -05:00
|
|
|
/// `RingBuf` iterator.
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-12-19 14:52:10 -06:00
|
|
|
pub struct Iter<'a, T:'a> {
|
2014-10-19 15:19:07 -05:00
|
|
|
ring: &'a [T],
|
|
|
|
tail: uint,
|
|
|
|
head: uint
|
2014-08-27 20:46:52 -05:00
|
|
|
}
|
|
|
|
|
2015-01-03 21:54:18 -06:00
|
|
|
// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
|
2014-12-30 04:01:36 -06:00
|
|
|
impl<'a, T> Clone for Iter<'a, T> {
|
|
|
|
fn clone(&self) -> Iter<'a, T> {
|
|
|
|
Iter {
|
|
|
|
ring: self.ring,
|
|
|
|
tail: self.tail,
|
|
|
|
head: self.head
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2015-01-01 22:15:35 -06:00
|
|
|
impl<'a, T> Iterator for Iter<'a, T> {
|
|
|
|
type Item = &'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> {
|
2014-10-19 15:19:07 -05:00
|
|
|
if self.tail == self.head {
|
2013-11-16 16:29:39 -06:00
|
|
|
return None;
|
2013-06-26 10:38:29 -05:00
|
|
|
}
|
2014-10-19 15:19:07 -05:00
|
|
|
let tail = self.tail;
|
|
|
|
self.tail = wrap_index(self.tail + 1, self.ring.len());
|
2014-12-30 12:51:18 -06:00
|
|
|
unsafe { Some(self.ring.get_unchecked(tail)) }
|
2013-06-26 10:38:29 -05:00
|
|
|
}
|
|
|
|
|
2013-11-16 16:29:39 -06:00
|
|
|
#[inline]
|
|
|
|
fn size_hint(&self) -> (uint, Option<uint>) {
|
2014-10-19 15:19:07 -05:00
|
|
|
let len = count(self.tail, self.head, self.ring.len());
|
2013-11-16 16:29:39 -06:00
|
|
|
(len, Some(len))
|
2013-07-15 18:13:26 -05:00
|
|
|
}
|
2013-06-25 14:08:47 -05:00
|
|
|
}
|
|
|
|
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2015-01-01 22:15:35 -06:00
|
|
|
impl<'a, T> DoubleEndedIterator for Iter<'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> {
|
2014-10-19 15:19:07 -05:00
|
|
|
if self.tail == self.head {
|
2013-11-16 16:29:39 -06:00
|
|
|
return None;
|
|
|
|
}
|
2014-10-19 15:19:07 -05:00
|
|
|
self.head = wrap_index(self.head - 1, self.ring.len());
|
2014-12-30 12:51:18 -06:00
|
|
|
unsafe { Some(self.ring.get_unchecked(self.head)) }
|
2013-11-16 16:29:39 -06:00
|
|
|
}
|
2013-06-25 14:08:47 -05:00
|
|
|
}
|
2013-06-26 10:38:29 -05:00
|
|
|
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2015-01-01 22:15:35 -06:00
|
|
|
impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
|
2013-09-01 11:20:24 -05:00
|
|
|
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2015-01-01 22:15:35 -06:00
|
|
|
impl<'a, T> RandomAccessIterator for Iter<'a, T> {
|
2013-07-29 13:16:26 -05:00
|
|
|
#[inline]
|
2014-10-19 15:19:07 -05:00
|
|
|
fn indexable(&self) -> uint {
|
|
|
|
let (len, _) = self.size_hint();
|
|
|
|
len
|
|
|
|
}
|
2013-07-29 13:16:26 -05:00
|
|
|
|
|
|
|
#[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 {
|
2014-10-19 15:19:07 -05:00
|
|
|
let idx = wrap_index(self.tail + j, self.ring.len());
|
2014-12-30 12:51:18 -06:00
|
|
|
unsafe { Some(self.ring.get_unchecked(idx)) }
|
2013-07-29 13:16:26 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-19 14:52:10 -06:00
|
|
|
// FIXME This was implemented differently from Iter because of a problem
|
2014-10-19 15:19:07 -05:00
|
|
|
// with returning the mutable reference. I couldn't find a way to
|
|
|
|
// make the lifetime checker happy so, but there should be a way.
|
2014-08-27 20:46:52 -05:00
|
|
|
/// `RingBuf` mutable iterator.
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-12-19 14:52:10 -06:00
|
|
|
pub struct IterMut<'a, T:'a> {
|
2014-10-19 15:19:07 -05:00
|
|
|
ptr: *mut T,
|
|
|
|
tail: uint,
|
|
|
|
head: uint,
|
|
|
|
cap: uint,
|
|
|
|
marker: marker::ContravariantLifetime<'a>,
|
2014-08-27 20:46:52 -05:00
|
|
|
}
|
|
|
|
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2015-01-01 22:15:35 -06:00
|
|
|
impl<'a, T> Iterator for IterMut<'a, T> {
|
|
|
|
type Item = &'a mut T;
|
|
|
|
|
2013-11-16 16:29:39 -06:00
|
|
|
#[inline]
|
2013-12-10 01:16:18 -06:00
|
|
|
fn next(&mut self) -> Option<&'a mut T> {
|
2014-10-19 15:19:07 -05:00
|
|
|
if self.tail == self.head {
|
2013-11-16 16:29:39 -06:00
|
|
|
return None;
|
|
|
|
}
|
2014-10-19 15:19:07 -05:00
|
|
|
let tail = self.tail;
|
|
|
|
self.tail = wrap_index(self.tail + 1, self.cap);
|
2014-11-22 20:34:11 -06:00
|
|
|
|
|
|
|
unsafe {
|
|
|
|
Some(&mut *self.ptr.offset(tail as int))
|
2014-10-15 01:05:01 -05:00
|
|
|
}
|
2013-11-16 16:29:39 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn size_hint(&self) -> (uint, Option<uint>) {
|
2014-10-19 15:19:07 -05:00
|
|
|
let len = count(self.tail, self.head, self.cap);
|
|
|
|
(len, Some(len))
|
2013-11-16 16:29:39 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2015-01-01 22:15:35 -06:00
|
|
|
impl<'a, T> DoubleEndedIterator for IterMut<'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 mut T> {
|
2014-10-19 15:19:07 -05:00
|
|
|
if self.tail == self.head {
|
2013-11-16 16:29:39 -06:00
|
|
|
return None;
|
|
|
|
}
|
2014-10-19 15:19:07 -05:00
|
|
|
self.head = wrap_index(self.head - 1, self.cap);
|
2014-11-22 20:34:11 -06:00
|
|
|
|
|
|
|
unsafe {
|
|
|
|
Some(&mut *self.ptr.offset(self.head as int))
|
|
|
|
}
|
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-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2015-01-01 22:15:35 -06:00
|
|
|
impl<'a, T> ExactSizeIterator for IterMut<'a, T> {}
|
2013-09-01 11:20:24 -05:00
|
|
|
|
2014-12-30 18:07:53 -06:00
|
|
|
/// A by-value RingBuf iterator
|
|
|
|
#[stable]
|
2014-12-19 14:52:10 -06:00
|
|
|
pub struct IntoIter<T> {
|
2014-11-22 20:34:11 -06:00
|
|
|
inner: RingBuf<T>,
|
|
|
|
}
|
|
|
|
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2015-01-01 22:15:35 -06:00
|
|
|
impl<T> Iterator for IntoIter<T> {
|
|
|
|
type Item = T;
|
|
|
|
|
2014-11-22 20:34:11 -06:00
|
|
|
#[inline]
|
|
|
|
fn next(&mut self) -> Option<T> {
|
|
|
|
self.inner.pop_front()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn size_hint(&self) -> (uint, Option<uint>) {
|
|
|
|
let len = self.inner.len();
|
|
|
|
(len, Some(len))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2015-01-01 22:15:35 -06:00
|
|
|
impl<T> DoubleEndedIterator for IntoIter<T> {
|
2014-11-22 20:34:11 -06:00
|
|
|
#[inline]
|
|
|
|
fn next_back(&mut self) -> Option<T> {
|
|
|
|
self.inner.pop_back()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2015-01-01 22:15:35 -06:00
|
|
|
impl<T> ExactSizeIterator for IntoIter<T> {}
|
2014-11-22 20:34:11 -06:00
|
|
|
|
2014-12-16 16:45:03 -06:00
|
|
|
/// A draining RingBuf iterator
|
2014-12-30 18:07:53 -06:00
|
|
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
2014-12-16 16:45:03 -06:00
|
|
|
pub struct Drain<'a, T: 'a> {
|
|
|
|
inner: &'a mut RingBuf<T>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[unsafe_destructor]
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-12-16 16:45:03 -06:00
|
|
|
impl<'a, T: 'a> Drop for Drain<'a, T> {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
for _ in *self {}
|
|
|
|
self.inner.head = 0;
|
|
|
|
self.inner.tail = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2015-01-01 22:15:35 -06:00
|
|
|
impl<'a, T: 'a> Iterator for Drain<'a, T> {
|
|
|
|
type Item = T;
|
|
|
|
|
2014-12-16 16:45:03 -06:00
|
|
|
#[inline]
|
|
|
|
fn next(&mut self) -> Option<T> {
|
|
|
|
self.inner.pop_front()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn size_hint(&self) -> (uint, Option<uint>) {
|
|
|
|
let len = self.inner.len();
|
|
|
|
(len, Some(len))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2015-01-01 22:15:35 -06:00
|
|
|
impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
|
2014-12-16 16:45:03 -06:00
|
|
|
#[inline]
|
|
|
|
fn next_back(&mut self) -> Option<T> {
|
|
|
|
self.inner.pop_back()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2015-01-01 22:15:35 -06:00
|
|
|
impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {}
|
2014-12-16 16:45:03 -06:00
|
|
|
|
2014-12-30 16:44:26 -06:00
|
|
|
#[stable]
|
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 {
|
2014-10-19 15:19:07 -05:00
|
|
|
self.len() == other.len() &&
|
2013-07-06 08:27:32 -05:00
|
|
|
self.iter().zip(other.iter()).all(|(a, b)| a.eq(b))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-30 16:44:26 -06:00
|
|
|
#[stable]
|
2014-08-01 15:05:03 -05:00
|
|
|
impl<A: Eq> Eq for RingBuf<A> {}
|
|
|
|
|
2014-12-30 16:44:26 -06:00
|
|
|
#[stable]
|
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-12-30 16:44:26 -06:00
|
|
|
#[stable]
|
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-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
std: Stabilize the std::hash module
This commit aims to prepare the `std::hash` module for alpha by formalizing its
current interface whileholding off on adding `#[stable]` to the new APIs. The
current usage with the `HashMap` and `HashSet` types is also reconciled by
separating out composable parts of the design. The primary goal of this slight
redesign is to separate the concepts of a hasher's state from a hashing
algorithm itself.
The primary change of this commit is to separate the `Hasher` trait into a
`Hasher` and a `HashState` trait. Conceptually the old `Hasher` trait was
actually just a factory for various states, but hashing had very little control
over how these states were used. Additionally the old `Hasher` trait was
actually fairly unrelated to hashing.
This commit redesigns the existing `Hasher` trait to match what the notion of a
`Hasher` normally implies with the following definition:
trait Hasher {
type Output;
fn reset(&mut self);
fn finish(&self) -> Output;
}
This `Hasher` trait emphasizes that hashing algorithms may produce outputs other
than a `u64`, so the output type is made generic. Other than that, however, very
little is assumed about a particular hasher. It is left up to implementors to
provide specific methods or trait implementations to feed data into a hasher.
The corresponding `Hash` trait becomes:
trait Hash<H: Hasher> {
fn hash(&self, &mut H);
}
The old default of `SipState` was removed from this trait as it's not something
that we're willing to stabilize until the end of time, but the type parameter is
always required to implement `Hasher`. Note that the type parameter `H` remains
on the trait to enable multidispatch for specialization of hashing for
particular hashers.
Note that `Writer` is not mentioned in either of `Hash` or `Hasher`, it is
simply used as part `derive` and the implementations for all primitive types.
With these definitions, the old `Hasher` trait is realized as a new `HashState`
trait in the `collections::hash_state` module as an unstable addition for
now. The current definition looks like:
trait HashState {
type Hasher: Hasher;
fn hasher(&self) -> Hasher;
}
The purpose of this trait is to emphasize that the one piece of functionality
for implementors is that new instances of `Hasher` can be created. This
conceptually represents the two keys from which more instances of a
`SipHasher` can be created, and a `HashState` is what's stored in a
`HashMap`, not a `Hasher`.
Implementors of custom hash algorithms should implement the `Hasher` trait, and
only hash algorithms intended for use in hash maps need to implement or worry
about the `HashState` trait.
The entire module and `HashState` infrastructure remains `#[unstable]` due to it
being recently redesigned, but some other stability decision made for the
`std::hash` module are:
* The `Writer` trait remains `#[experimental]` as it's intended to be replaced
with an `io::Writer` (more details soon).
* The top-level `hash` function is `#[unstable]` as it is intended to be generic
over the hashing algorithm instead of hardwired to `SipHasher`
* The inner `sip` module is now private as its one export, `SipHasher` is
reexported in the `hash` module.
And finally, a few changes were made to the default parameters on `HashMap`.
* The `RandomSipHasher` default type parameter was renamed to `RandomState`.
This renaming emphasizes that it is not a hasher, but rather just state to
generate hashers. It also moves away from the name "sip" as it may not always
be implemented as `SipHasher`. This type lives in the
`std::collections::hash_map` module as `#[unstable]`
* The associated `Hasher` type of `RandomState` is creatively called...
`Hasher`! This concrete structure lives next to `RandomState` as an
implemenation of the "default hashing algorithm" used for a `HashMap`. Under
the hood this is currently implemented as `SipHasher`, but it draws an
explicit interface for now and allows us to modify the implementation over
time if necessary.
There are many breaking changes outlined above, and as a result this commit is
a:
[breaking-change]
2014-12-09 14:37:23 -06:00
|
|
|
impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for RingBuf<A> {
|
2014-07-26 21:33:47 -05:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-03 09:40:10 -06:00
|
|
|
#[stable]
|
|
|
|
impl<A> Index<uint> for RingBuf<A> {
|
|
|
|
type Output = A;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn index<'a>(&'a self, i: &uint) -> &'a A {
|
|
|
|
self.get(*i).expect("Out of bounds access")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[stable]
|
|
|
|
impl<A> IndexMut<uint> for RingBuf<A> {
|
|
|
|
type Output = A;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut A {
|
|
|
|
self.get_mut(*i).expect("Out of bounds access")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
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> {
|
2015-01-01 22:15:35 -06:00
|
|
|
fn from_iter<T: Iterator<Item=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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
2014-11-07 18:39:39 -06:00
|
|
|
impl<A> Extend<A> for RingBuf<A> {
|
2015-01-01 22:15:35 -06:00
|
|
|
fn extend<T: Iterator<Item=A>>(&mut self, mut iterator: T) {
|
2014-03-20 08:12:56 -05:00
|
|
|
for elt in iterator {
|
2014-11-06 11:24:47 -06:00
|
|
|
self.push_back(elt);
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-30 18:07:53 -06:00
|
|
|
#[stable]
|
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 {
|
2014-12-20 02:09:35 -06:00
|
|
|
try!(write!(f, "RingBuf ["));
|
2014-06-04 09:15:04 -05:00
|
|
|
|
|
|
|
for (i, e) in self.iter().enumerate() {
|
|
|
|
if i != 0 { try!(write!(f, ", ")); }
|
2014-12-20 02:09:35 -06:00
|
|
|
try!(write!(f, "{:?}", *e));
|
2014-06-04 09:15:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, "]")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-17 21:05:07 -06:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2014-11-06 02:05:53 -06:00
|
|
|
use self::Taggy::*;
|
|
|
|
use self::Taggypar::*;
|
2014-12-19 06:02:22 -06:00
|
|
|
use prelude::*;
|
|
|
|
use core::iter;
|
2014-02-28 03:23:06 -06:00
|
|
|
use std::fmt::Show;
|
std: Stabilize the std::hash module
This commit aims to prepare the `std::hash` module for alpha by formalizing its
current interface whileholding off on adding `#[stable]` to the new APIs. The
current usage with the `HashMap` and `HashSet` types is also reconciled by
separating out composable parts of the design. The primary goal of this slight
redesign is to separate the concepts of a hasher's state from a hashing
algorithm itself.
The primary change of this commit is to separate the `Hasher` trait into a
`Hasher` and a `HashState` trait. Conceptually the old `Hasher` trait was
actually just a factory for various states, but hashing had very little control
over how these states were used. Additionally the old `Hasher` trait was
actually fairly unrelated to hashing.
This commit redesigns the existing `Hasher` trait to match what the notion of a
`Hasher` normally implies with the following definition:
trait Hasher {
type Output;
fn reset(&mut self);
fn finish(&self) -> Output;
}
This `Hasher` trait emphasizes that hashing algorithms may produce outputs other
than a `u64`, so the output type is made generic. Other than that, however, very
little is assumed about a particular hasher. It is left up to implementors to
provide specific methods or trait implementations to feed data into a hasher.
The corresponding `Hash` trait becomes:
trait Hash<H: Hasher> {
fn hash(&self, &mut H);
}
The old default of `SipState` was removed from this trait as it's not something
that we're willing to stabilize until the end of time, but the type parameter is
always required to implement `Hasher`. Note that the type parameter `H` remains
on the trait to enable multidispatch for specialization of hashing for
particular hashers.
Note that `Writer` is not mentioned in either of `Hash` or `Hasher`, it is
simply used as part `derive` and the implementations for all primitive types.
With these definitions, the old `Hasher` trait is realized as a new `HashState`
trait in the `collections::hash_state` module as an unstable addition for
now. The current definition looks like:
trait HashState {
type Hasher: Hasher;
fn hasher(&self) -> Hasher;
}
The purpose of this trait is to emphasize that the one piece of functionality
for implementors is that new instances of `Hasher` can be created. This
conceptually represents the two keys from which more instances of a
`SipHasher` can be created, and a `HashState` is what's stored in a
`HashMap`, not a `Hasher`.
Implementors of custom hash algorithms should implement the `Hasher` trait, and
only hash algorithms intended for use in hash maps need to implement or worry
about the `HashState` trait.
The entire module and `HashState` infrastructure remains `#[unstable]` due to it
being recently redesigned, but some other stability decision made for the
`std::hash` module are:
* The `Writer` trait remains `#[experimental]` as it's intended to be replaced
with an `io::Writer` (more details soon).
* The top-level `hash` function is `#[unstable]` as it is intended to be generic
over the hashing algorithm instead of hardwired to `SipHasher`
* The inner `sip` module is now private as its one export, `SipHasher` is
reexported in the `hash` module.
And finally, a few changes were made to the default parameters on `HashMap`.
* The `RandomSipHasher` default type parameter was renamed to `RandomState`.
This renaming emphasizes that it is not a hasher, but rather just state to
generate hashers. It also moves away from the name "sip" as it may not always
be implemented as `SipHasher`. This type lives in the
`std::collections::hash_map` module as `#[unstable]`
* The associated `Hasher` type of `RandomState` is creatively called...
`Hasher`! This concrete structure lives next to `RandomState` as an
implemenation of the "default hashing algorithm" used for a `HashMap`. Under
the hood this is currently implemented as `SipHasher`, but it draws an
explicit interface for now and allows us to modify the implementation over
time if necessary.
There are many breaking changes outlined above, and as a result this commit is
a:
[breaking-change]
2014-12-09 14:37:23 -06:00
|
|
|
use std::hash::{self, SipHasher};
|
2014-05-29 21:03:06 -05:00
|
|
|
use test::Bencher;
|
|
|
|
use test;
|
|
|
|
|
2014-01-07 00:33:50 -06:00
|
|
|
use super::RingBuf;
|
2012-12-27 20:24:18 -06:00
|
|
|
|
2012-01-17 21:05:07 -06:00
|
|
|
#[test]
|
2014-09-22 12:30:06 -05:00
|
|
|
#[allow(deprecated)]
|
2012-01-17 21:05:07 -06:00
|
|
|
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);
|
2014-11-06 11:24:47 -06:00
|
|
|
d.push_back(137);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(d.len(), 3u);
|
2014-11-06 11:24:47 -06:00
|
|
|
d.push_back(137);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(d.len(), 4u);
|
2013-07-10 08:27:14 -05:00
|
|
|
assert_eq!(*d.front().unwrap(), 42);
|
|
|
|
assert_eq!(*d.back().unwrap(), 137);
|
|
|
|
let mut i = d.pop_front();
|
|
|
|
assert_eq!(i, Some(42));
|
2014-11-06 11:24:47 -06:00
|
|
|
i = d.pop_back();
|
2013-07-10 08:27:14 -05:00
|
|
|
assert_eq!(i, Some(137));
|
2014-11-06 11:24:47 -06:00
|
|
|
i = d.pop_back();
|
2013-07-10 08:27:14 -05:00
|
|
|
assert_eq!(i, Some(137));
|
2014-11-06 11:24:47 -06:00
|
|
|
i = d.pop_back();
|
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);
|
2014-11-06 11:24:47 -06: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);
|
2014-11-06 11:24:47 -06: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);
|
2014-10-15 01:05:01 -05:00
|
|
|
debug!("{}", d[0]);
|
|
|
|
debug!("{}", d[1]);
|
|
|
|
debug!("{}", d[2]);
|
|
|
|
debug!("{}", d[3]);
|
|
|
|
assert_eq!(d[0], 1);
|
|
|
|
assert_eq!(d[1], 2);
|
|
|
|
assert_eq!(d[2], 3);
|
|
|
|
assert_eq!(d[3], 4);
|
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());
|
2014-11-06 11:24:47 -06:00
|
|
|
deq.push_back(c.clone());
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(deq.len(), 3);
|
2014-11-06 11:24:47 -06: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());
|
2014-11-06 11:24:47 -06:00
|
|
|
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);
|
2014-11-06 11:24:47 -06: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);
|
2014-11-06 11:24:47 -06: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);
|
2014-10-05 05:11:17 -05:00
|
|
|
assert_eq!(deq[0].clone(), a.clone());
|
|
|
|
assert_eq!(deq[1].clone(), b.clone());
|
|
|
|
assert_eq!(deq[2].clone(), c.clone());
|
|
|
|
assert_eq!(deq[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) {
|
2014-10-05 05:11:17 -05:00
|
|
|
assert_eq!(deq[i], 65 - i);
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
|
|
|
|
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) {
|
2014-11-06 11:24:47 -06: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) {
|
2014-10-05 05:11:17 -05:00
|
|
|
assert_eq!(deq[i], i);
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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(|| {
|
2014-11-10 20:57:52 -06:00
|
|
|
let ring: RingBuf<u64> = RingBuf::new();
|
|
|
|
test::black_box(ring);
|
2013-11-21 21:20:48 -06:00
|
|
|
})
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-10-19 15:19:07 -05:00
|
|
|
fn bench_push_back_100(b: &mut test::Bencher) {
|
2014-11-10 20:57:52 -06:00
|
|
|
let mut deq = RingBuf::with_capacity(101);
|
2013-11-21 21:20:48 -06:00
|
|
|
b.iter(|| {
|
2014-10-19 15:19:07 -05:00
|
|
|
for i in range(0i, 100) {
|
|
|
|
deq.push_back(i);
|
|
|
|
}
|
2014-11-10 20:57:52 -06:00
|
|
|
deq.head = 0;
|
|
|
|
deq.tail = 0;
|
2013-11-21 21:20:48 -06:00
|
|
|
})
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-10-19 15:19:07 -05:00
|
|
|
fn bench_push_front_100(b: &mut test::Bencher) {
|
2014-11-10 20:57:52 -06:00
|
|
|
let mut deq = RingBuf::with_capacity(101);
|
2013-11-21 21:20:48 -06:00
|
|
|
b.iter(|| {
|
2014-10-19 15:19:07 -05:00
|
|
|
for i in range(0i, 100) {
|
|
|
|
deq.push_front(i);
|
|
|
|
}
|
2014-11-10 20:57:52 -06:00
|
|
|
deq.head = 0;
|
|
|
|
deq.tail = 0;
|
2013-11-21 21:20:48 -06:00
|
|
|
})
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-11-10 20:57:52 -06:00
|
|
|
fn bench_pop_back_100(b: &mut test::Bencher) {
|
|
|
|
let mut deq: RingBuf<int> = RingBuf::with_capacity(101);
|
2014-10-19 15:19:07 -05:00
|
|
|
|
|
|
|
b.iter(|| {
|
2014-11-10 20:57:52 -06:00
|
|
|
deq.head = 100;
|
|
|
|
deq.tail = 0;
|
|
|
|
while !deq.is_empty() {
|
|
|
|
test::black_box(deq.pop_back());
|
2014-10-19 15:19:07 -05:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_pop_front_100(b: &mut test::Bencher) {
|
2014-11-10 20:57:52 -06:00
|
|
|
let mut deq: RingBuf<int> = RingBuf::with_capacity(101);
|
2014-10-19 15:19:07 -05:00
|
|
|
|
|
|
|
b.iter(|| {
|
2014-11-10 20:57:52 -06:00
|
|
|
deq.head = 100;
|
|
|
|
deq.tail = 0;
|
|
|
|
while !deq.is_empty() {
|
|
|
|
test::black_box(deq.pop_front());
|
2014-10-19 15:19:07 -05:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_grow_1025(b: &mut test::Bencher) {
|
|
|
|
b.iter(|| {
|
|
|
|
let mut deq = RingBuf::new();
|
|
|
|
for i in range(0i, 1025) {
|
|
|
|
deq.push_front(i);
|
|
|
|
}
|
2014-11-10 20:57:52 -06:00
|
|
|
test::black_box(deq);
|
2014-10-19 15:19:07 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_iter_1000(b: &mut test::Bencher) {
|
|
|
|
let ring: RingBuf<int> = range(0i, 1000).collect();
|
|
|
|
|
2013-11-21 21:20:48 -06:00
|
|
|
b.iter(|| {
|
2014-10-19 15:19:07 -05:00
|
|
|
let mut sum = 0;
|
|
|
|
for &i in ring.iter() {
|
|
|
|
sum += i;
|
2014-01-29 18:20:34 -06:00
|
|
|
}
|
2014-11-10 20:57:52 -06:00
|
|
|
test::black_box(sum);
|
2013-11-21 21:20:48 -06:00
|
|
|
})
|
2013-07-05 22:42:45 -05:00
|
|
|
}
|
|
|
|
|
2014-10-19 15:19:07 -05:00
|
|
|
#[bench]
|
|
|
|
fn bench_mut_iter_1000(b: &mut test::Bencher) {
|
|
|
|
let mut ring: RingBuf<int> = range(0i, 1000).collect();
|
|
|
|
|
|
|
|
b.iter(|| {
|
2014-11-10 20:57:52 -06:00
|
|
|
let mut sum = 0;
|
2014-10-19 15:19:07 -05:00
|
|
|
for i in ring.iter_mut() {
|
2014-11-10 20:57:52 -06:00
|
|
|
sum += *i;
|
2014-10-19 15:19:07 -05:00
|
|
|
}
|
2014-11-10 20:57:52 -06:00
|
|
|
test::black_box(sum);
|
2014-10-19 15:19:07 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-01-03 21:54:18 -06:00
|
|
|
#[derive(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
|
|
|
|
2015-01-03 21:54:18 -06:00
|
|
|
#[derive(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
|
|
|
}
|
|
|
|
|
2015-01-03 21:54:18 -06:00
|
|
|
#[derive(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_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-11-06 11:24:47 -06: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-11-06 11:24:47 -06: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);
|
2014-11-06 11:24:47 -06:00
|
|
|
d3.push_back(1i);
|
2014-08-06 20:11:13 -05:00
|
|
|
|
|
|
|
// X = None, | = lo
|
|
|
|
// [|1, X, X]
|
|
|
|
assert_eq!(d3.pop_front(), Some(1));
|
|
|
|
// [X, |X, X]
|
|
|
|
assert_eq!(d3.front(), None);
|
|
|
|
|
|
|
|
// [X, |3, X]
|
2014-11-06 11:24:47 -06:00
|
|
|
d3.push_back(3);
|
2014-08-06 20:11:13 -05:00
|
|
|
// [X, |3, 6]
|
2014-11-06 11:24:47 -06:00
|
|
|
d3.push_back(6);
|
2014-08-06 20:11:13 -05:00
|
|
|
// [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]
|
2014-11-06 11:24:47 -06:00
|
|
|
d3.push_back(9);
|
2014-08-06 20:11:13 -05:00
|
|
|
// [9, 12, |6]
|
2014-11-06 11:24:47 -06:00
|
|
|
d3.push_back(12);
|
2014-08-06 20:11:13 -05:00
|
|
|
|
2014-11-06 11:24:47 -06:00
|
|
|
d3.push_back(15);
|
2014-08-06 20:11:13 -05:00
|
|
|
// 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();
|
2014-11-06 11:24:47 -06:00
|
|
|
d.push_back(0u64);
|
2014-01-31 07:03:20 -06:00
|
|
|
d.reserve_exact(50);
|
2014-11-06 11:24:47 -06:00
|
|
|
assert!(d.capacity() >= 51);
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut d = RingBuf::new();
|
2014-11-06 11:24:47 -06:00
|
|
|
d.push_back(0u32);
|
2014-01-31 07:03:20 -06:00
|
|
|
d.reserve_exact(50);
|
2014-11-06 11:24:47 -06:00
|
|
|
assert!(d.capacity() >= 51);
|
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();
|
2014-11-06 11:24:47 -06:00
|
|
|
d.push_back(0u64);
|
2014-01-31 07:03:20 -06:00
|
|
|
d.reserve(50);
|
2014-10-19 15:19:07 -05:00
|
|
|
assert!(d.capacity() >= 51);
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut d = RingBuf::new();
|
2014-11-06 11:24:47 -06:00
|
|
|
d.push_back(0u32);
|
2014-01-31 07:03:20 -06:00
|
|
|
d.reserve(50);
|
2014-10-19 15:19:07 -05:00
|
|
|
assert!(d.capacity() >= 51);
|
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) {
|
2014-11-06 11:24:47 -06: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];
|
2014-11-27 10:45:50 -06:00
|
|
|
assert_eq!(d.iter().collect::<Vec<&int>>(), b);
|
2014-08-04 07:19:02 -05:00
|
|
|
}
|
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];
|
2014-11-27 10:45:50 -06:00
|
|
|
assert_eq!(d.iter().collect::<Vec<&int>>(), b);
|
2014-08-04 07:19:02 -05:00
|
|
|
}
|
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) {
|
2014-11-06 11:24:47 -06: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];
|
2014-11-27 10:45:50 -06:00
|
|
|
assert_eq!(d.iter().rev().collect::<Vec<&int>>(), b);
|
2014-08-04 07:19:02 -05:00
|
|
|
}
|
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];
|
2014-11-27 10:45:50 -06:00
|
|
|
assert_eq!(d.iter().rev().collect::<Vec<&int>>(), 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);
|
2014-09-14 22:27:36 -05:00
|
|
|
assert!(d.iter_mut().rev().next().is_none());
|
2013-11-16 16:29:39 -06:00
|
|
|
|
2014-11-06 11:24:47 -06:00
|
|
|
d.push_back(1i);
|
|
|
|
d.push_back(2);
|
|
|
|
d.push_back(3);
|
2013-11-16 16:29:39 -06:00
|
|
|
assert_eq!(d.pop_front(), Some(1));
|
2014-11-06 11:24:47 -06:00
|
|
|
d.push_back(4);
|
2013-11-16 16:29:39 -06:00
|
|
|
|
2014-09-14 22:27:36 -05:00
|
|
|
assert_eq!(d.iter_mut().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();
|
2014-09-14 22:27:36 -05:00
|
|
|
assert!(d.iter_mut().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
|
|
|
}
|
|
|
|
|
2014-09-14 22:27:36 -05:00
|
|
|
for (i, elt) in d.iter_mut().enumerate() {
|
2013-07-05 22:42:45 -05:00
|
|
|
assert_eq!(*elt, 2 - i);
|
|
|
|
*elt = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2014-09-14 22:27:36 -05:00
|
|
|
let mut it = d.iter_mut();
|
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());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_mut_rev_iter() {
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut d = RingBuf::new();
|
2014-09-14 22:27:36 -05:00
|
|
|
assert!(d.iter_mut().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
|
|
|
}
|
|
|
|
|
2014-09-14 22:27:36 -05:00
|
|
|
for (i, elt) in d.iter_mut().rev().enumerate() {
|
2013-07-05 22:42:45 -05:00
|
|
|
assert_eq!(*elt, i);
|
|
|
|
*elt = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2014-09-14 22:27:36 -05:00
|
|
|
let mut it = d.iter_mut().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());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-22 20:34:11 -06:00
|
|
|
#[test]
|
|
|
|
fn test_into_iter() {
|
|
|
|
|
|
|
|
// Empty iter
|
|
|
|
{
|
|
|
|
let d: RingBuf<int> = RingBuf::new();
|
|
|
|
let mut iter = d.into_iter();
|
|
|
|
|
|
|
|
assert_eq!(iter.size_hint(), (0, Some(0)));
|
|
|
|
assert_eq!(iter.next(), None);
|
|
|
|
assert_eq!(iter.size_hint(), (0, Some(0)));
|
|
|
|
}
|
|
|
|
|
|
|
|
// simple iter
|
|
|
|
{
|
|
|
|
let mut d = RingBuf::new();
|
|
|
|
for i in range(0i, 5) {
|
|
|
|
d.push_back(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
let b = vec![0,1,2,3,4];
|
|
|
|
assert_eq!(d.into_iter().collect::<Vec<int>>(), b);
|
|
|
|
}
|
|
|
|
|
|
|
|
// wrapped iter
|
|
|
|
{
|
|
|
|
let mut d = RingBuf::new();
|
|
|
|
for i in range(0i, 5) {
|
|
|
|
d.push_back(i);
|
|
|
|
}
|
|
|
|
for i in range(6, 9) {
|
|
|
|
d.push_front(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
let b = vec![8,7,6,0,1,2,3,4];
|
|
|
|
assert_eq!(d.into_iter().collect::<Vec<int>>(), b);
|
|
|
|
}
|
|
|
|
|
|
|
|
// partially used
|
|
|
|
{
|
|
|
|
let mut d = RingBuf::new();
|
|
|
|
for i in range(0i, 5) {
|
|
|
|
d.push_back(i);
|
|
|
|
}
|
|
|
|
for i in range(6, 9) {
|
|
|
|
d.push_front(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut it = d.into_iter();
|
|
|
|
assert_eq!(it.size_hint(), (8, Some(8)));
|
|
|
|
assert_eq!(it.next(), Some(8));
|
|
|
|
assert_eq!(it.size_hint(), (7, Some(7)));
|
|
|
|
assert_eq!(it.next_back(), Some(4));
|
|
|
|
assert_eq!(it.size_hint(), (6, Some(6)));
|
|
|
|
assert_eq!(it.next(), Some(7));
|
|
|
|
assert_eq!(it.size_hint(), (5, Some(5)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-16 16:45:03 -06:00
|
|
|
#[test]
|
|
|
|
fn test_drain() {
|
|
|
|
|
|
|
|
// Empty iter
|
|
|
|
{
|
|
|
|
let mut d: RingBuf<int> = RingBuf::new();
|
|
|
|
|
|
|
|
{
|
|
|
|
let mut iter = d.drain();
|
|
|
|
|
|
|
|
assert_eq!(iter.size_hint(), (0, Some(0)));
|
|
|
|
assert_eq!(iter.next(), None);
|
|
|
|
assert_eq!(iter.size_hint(), (0, Some(0)));
|
|
|
|
}
|
|
|
|
|
|
|
|
assert!(d.is_empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
// simple iter
|
|
|
|
{
|
|
|
|
let mut d = RingBuf::new();
|
|
|
|
for i in range(0i, 5) {
|
|
|
|
d.push_back(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert_eq!(d.drain().collect::<Vec<int>>(), [0, 1, 2, 3, 4]);
|
|
|
|
assert!(d.is_empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
// wrapped iter
|
|
|
|
{
|
|
|
|
let mut d = RingBuf::new();
|
|
|
|
for i in range(0i, 5) {
|
|
|
|
d.push_back(i);
|
|
|
|
}
|
|
|
|
for i in range(6, 9) {
|
|
|
|
d.push_front(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert_eq!(d.drain().collect::<Vec<int>>(), [8,7,6,0,1,2,3,4]);
|
|
|
|
assert!(d.is_empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
// partially used
|
|
|
|
{
|
|
|
|
let mut d = RingBuf::new();
|
|
|
|
for i in range(0i, 5) {
|
|
|
|
d.push_back(i);
|
|
|
|
}
|
|
|
|
for i in range(6, 9) {
|
|
|
|
d.push_front(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
let mut it = d.drain();
|
|
|
|
assert_eq!(it.size_hint(), (8, Some(8)));
|
|
|
|
assert_eq!(it.next(), Some(8));
|
|
|
|
assert_eq!(it.size_hint(), (7, Some(7)));
|
|
|
|
assert_eq!(it.next_back(), Some(4));
|
|
|
|
assert_eq!(it.size_hint(), (6, Some(6)));
|
|
|
|
assert_eq!(it.next(), Some(7));
|
|
|
|
assert_eq!(it.size_hint(), (5, Some(5)));
|
|
|
|
}
|
|
|
|
assert!(d.is_empty());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-05 22:42:45 -05:00
|
|
|
#[test]
|
2014-03-30 23:45:55 -05:00
|
|
|
fn test_from_iter() {
|
2014-12-19 06:02:22 -06:00
|
|
|
use core::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);
|
|
|
|
|
2014-11-06 11:32:37 -06:00
|
|
|
let 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);
|
2014-11-06 11:24:47 -06:00
|
|
|
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() {
|
2014-11-06 11:24:47 -06:00
|
|
|
assert_eq!(d.pop_back(), e.pop_back());
|
2013-07-06 08:27:32 -05:00
|
|
|
}
|
|
|
|
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);
|
2014-11-06 11:24:47 -06:00
|
|
|
d.push_back(137);
|
2013-07-10 08:27:14 -05:00
|
|
|
let mut e = RingBuf::with_capacity(0);
|
2014-11-06 11:24:47 -06:00
|
|
|
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);
|
2014-11-06 11:24:47 -06:00
|
|
|
e.pop_back();
|
|
|
|
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();
|
|
|
|
|
2014-11-06 11:24:47 -06:00
|
|
|
x.push_back(1i);
|
|
|
|
x.push_back(2);
|
|
|
|
x.push_back(3);
|
2014-07-26 21:33:47 -05:00
|
|
|
|
2014-11-06 11:24:47 -06:00
|
|
|
y.push_back(0i);
|
|
|
|
y.push_back(1i);
|
2014-07-26 21:33:47 -05:00
|
|
|
y.pop_front();
|
2014-11-06 11:24:47 -06:00
|
|
|
y.push_back(2);
|
|
|
|
y.push_back(3);
|
2014-07-26 21:33:47 -05:00
|
|
|
|
std: Stabilize the std::hash module
This commit aims to prepare the `std::hash` module for alpha by formalizing its
current interface whileholding off on adding `#[stable]` to the new APIs. The
current usage with the `HashMap` and `HashSet` types is also reconciled by
separating out composable parts of the design. The primary goal of this slight
redesign is to separate the concepts of a hasher's state from a hashing
algorithm itself.
The primary change of this commit is to separate the `Hasher` trait into a
`Hasher` and a `HashState` trait. Conceptually the old `Hasher` trait was
actually just a factory for various states, but hashing had very little control
over how these states were used. Additionally the old `Hasher` trait was
actually fairly unrelated to hashing.
This commit redesigns the existing `Hasher` trait to match what the notion of a
`Hasher` normally implies with the following definition:
trait Hasher {
type Output;
fn reset(&mut self);
fn finish(&self) -> Output;
}
This `Hasher` trait emphasizes that hashing algorithms may produce outputs other
than a `u64`, so the output type is made generic. Other than that, however, very
little is assumed about a particular hasher. It is left up to implementors to
provide specific methods or trait implementations to feed data into a hasher.
The corresponding `Hash` trait becomes:
trait Hash<H: Hasher> {
fn hash(&self, &mut H);
}
The old default of `SipState` was removed from this trait as it's not something
that we're willing to stabilize until the end of time, but the type parameter is
always required to implement `Hasher`. Note that the type parameter `H` remains
on the trait to enable multidispatch for specialization of hashing for
particular hashers.
Note that `Writer` is not mentioned in either of `Hash` or `Hasher`, it is
simply used as part `derive` and the implementations for all primitive types.
With these definitions, the old `Hasher` trait is realized as a new `HashState`
trait in the `collections::hash_state` module as an unstable addition for
now. The current definition looks like:
trait HashState {
type Hasher: Hasher;
fn hasher(&self) -> Hasher;
}
The purpose of this trait is to emphasize that the one piece of functionality
for implementors is that new instances of `Hasher` can be created. This
conceptually represents the two keys from which more instances of a
`SipHasher` can be created, and a `HashState` is what's stored in a
`HashMap`, not a `Hasher`.
Implementors of custom hash algorithms should implement the `Hasher` trait, and
only hash algorithms intended for use in hash maps need to implement or worry
about the `HashState` trait.
The entire module and `HashState` infrastructure remains `#[unstable]` due to it
being recently redesigned, but some other stability decision made for the
`std::hash` module are:
* The `Writer` trait remains `#[experimental]` as it's intended to be replaced
with an `io::Writer` (more details soon).
* The top-level `hash` function is `#[unstable]` as it is intended to be generic
over the hashing algorithm instead of hardwired to `SipHasher`
* The inner `sip` module is now private as its one export, `SipHasher` is
reexported in the `hash` module.
And finally, a few changes were made to the default parameters on `HashMap`.
* The `RandomSipHasher` default type parameter was renamed to `RandomState`.
This renaming emphasizes that it is not a hasher, but rather just state to
generate hashers. It also moves away from the name "sip" as it may not always
be implemented as `SipHasher`. This type lives in the
`std::collections::hash_map` module as `#[unstable]`
* The associated `Hasher` type of `RandomState` is creatively called...
`Hasher`! This concrete structure lives next to `RandomState` as an
implemenation of the "default hashing algorithm" used for a `HashMap`. Under
the hood this is currently implemented as `SipHasher`, but it draws an
explicit interface for now and allows us to modify the implementation over
time if necessary.
There are many breaking changes outlined above, and as a result this commit is
a:
[breaking-change]
2014-12-09 14:37:23 -06:00
|
|
|
assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y));
|
2014-07-26 21:33:47 -05:00
|
|
|
}
|
|
|
|
|
2014-07-26 22:18:56 -05:00
|
|
|
#[test]
|
|
|
|
fn test_ord() {
|
|
|
|
let x = RingBuf::new();
|
|
|
|
let mut y = RingBuf::new();
|
2014-11-06 11:24:47 -06:00
|
|
|
y.push_back(1i);
|
|
|
|
y.push_back(2);
|
|
|
|
y.push_back(3);
|
2014-07-26 22:18:56 -05:00
|
|
|
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();
|
2015-01-06 18:16:35 -06:00
|
|
|
assert_eq!(format!("{:?}", ringbuf), "RingBuf [0i, 1i, 2i, 3i, 4i, 5i, 6i, 7i, 8i, 9i]");
|
2014-06-04 09:15:04 -05:00
|
|
|
|
|
|
|
let ringbuf: RingBuf<&str> = vec!["just", "one", "test", "more"].iter()
|
|
|
|
.map(|&s| s)
|
|
|
|
.collect();
|
2015-01-06 18:16:35 -06:00
|
|
|
assert_eq!(format!("{:?}", ringbuf), "RingBuf [\"just\", \"one\", \"test\", \"more\"]");
|
2014-06-04 09:15:04 -05:00
|
|
|
}
|
2014-10-19 15:19:07 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_drop() {
|
|
|
|
static mut drops: uint = 0;
|
|
|
|
struct Elem;
|
|
|
|
impl Drop for Elem {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe { drops += 1; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut ring = RingBuf::new();
|
|
|
|
ring.push_back(Elem);
|
|
|
|
ring.push_front(Elem);
|
|
|
|
ring.push_back(Elem);
|
|
|
|
ring.push_front(Elem);
|
|
|
|
drop(ring);
|
|
|
|
|
|
|
|
assert_eq!(unsafe {drops}, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_drop_with_pop() {
|
|
|
|
static mut drops: uint = 0;
|
|
|
|
struct Elem;
|
|
|
|
impl Drop for Elem {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe { drops += 1; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut ring = RingBuf::new();
|
|
|
|
ring.push_back(Elem);
|
|
|
|
ring.push_front(Elem);
|
|
|
|
ring.push_back(Elem);
|
|
|
|
ring.push_front(Elem);
|
|
|
|
|
|
|
|
drop(ring.pop_back());
|
|
|
|
drop(ring.pop_front());
|
|
|
|
assert_eq!(unsafe {drops}, 2);
|
|
|
|
|
|
|
|
drop(ring);
|
|
|
|
assert_eq!(unsafe {drops}, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_drop_clear() {
|
|
|
|
static mut drops: uint = 0;
|
|
|
|
struct Elem;
|
|
|
|
impl Drop for Elem {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe { drops += 1; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut ring = RingBuf::new();
|
|
|
|
ring.push_back(Elem);
|
|
|
|
ring.push_front(Elem);
|
|
|
|
ring.push_back(Elem);
|
|
|
|
ring.push_front(Elem);
|
|
|
|
ring.clear();
|
|
|
|
assert_eq!(unsafe {drops}, 4);
|
|
|
|
|
|
|
|
drop(ring);
|
|
|
|
assert_eq!(unsafe {drops}, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_reserve_grow() {
|
|
|
|
// test growth path A
|
|
|
|
// [T o o H] -> [T o o H . . . . ]
|
|
|
|
let mut ring = RingBuf::with_capacity(4);
|
|
|
|
for i in range(0i, 3) {
|
|
|
|
ring.push_back(i);
|
|
|
|
}
|
|
|
|
ring.reserve(7);
|
|
|
|
for i in range(0i, 3) {
|
|
|
|
assert_eq!(ring.pop_front(), Some(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
// test growth path B
|
|
|
|
// [H T o o] -> [. T o o H . . . ]
|
|
|
|
let mut ring = RingBuf::with_capacity(4);
|
|
|
|
for i in range(0i, 1) {
|
|
|
|
ring.push_back(i);
|
|
|
|
assert_eq!(ring.pop_front(), Some(i));
|
|
|
|
}
|
|
|
|
for i in range(0i, 3) {
|
|
|
|
ring.push_back(i);
|
|
|
|
}
|
|
|
|
ring.reserve(7);
|
|
|
|
for i in range(0i, 3) {
|
|
|
|
assert_eq!(ring.pop_front(), Some(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
// test growth path C
|
|
|
|
// [o o H T] -> [o o H . . . . T ]
|
|
|
|
let mut ring = RingBuf::with_capacity(4);
|
|
|
|
for i in range(0i, 3) {
|
|
|
|
ring.push_back(i);
|
|
|
|
assert_eq!(ring.pop_front(), Some(i));
|
|
|
|
}
|
|
|
|
for i in range(0i, 3) {
|
|
|
|
ring.push_back(i);
|
|
|
|
}
|
|
|
|
ring.reserve(7);
|
|
|
|
for i in range(0i, 3) {
|
|
|
|
assert_eq!(ring.pop_front(), Some(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_get() {
|
|
|
|
let mut ring = RingBuf::new();
|
|
|
|
ring.push_back(0i);
|
|
|
|
assert_eq!(ring.get(0), Some(&0));
|
|
|
|
assert_eq!(ring.get(1), None);
|
|
|
|
|
|
|
|
ring.push_back(1);
|
|
|
|
assert_eq!(ring.get(0), Some(&0));
|
|
|
|
assert_eq!(ring.get(1), Some(&1));
|
|
|
|
assert_eq!(ring.get(2), None);
|
|
|
|
|
|
|
|
ring.push_back(2);
|
|
|
|
assert_eq!(ring.get(0), Some(&0));
|
|
|
|
assert_eq!(ring.get(1), Some(&1));
|
|
|
|
assert_eq!(ring.get(2), Some(&2));
|
|
|
|
assert_eq!(ring.get(3), None);
|
|
|
|
|
|
|
|
assert_eq!(ring.pop_front(), Some(0));
|
|
|
|
assert_eq!(ring.get(0), Some(&1));
|
|
|
|
assert_eq!(ring.get(1), Some(&2));
|
|
|
|
assert_eq!(ring.get(2), None);
|
|
|
|
|
|
|
|
assert_eq!(ring.pop_front(), Some(1));
|
|
|
|
assert_eq!(ring.get(0), Some(&2));
|
|
|
|
assert_eq!(ring.get(1), None);
|
|
|
|
|
|
|
|
assert_eq!(ring.pop_front(), Some(2));
|
|
|
|
assert_eq!(ring.get(0), None);
|
|
|
|
assert_eq!(ring.get(1), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_get_mut() {
|
|
|
|
let mut ring = RingBuf::new();
|
|
|
|
for i in range(0i, 3) {
|
|
|
|
ring.push_back(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
match ring.get_mut(1) {
|
|
|
|
Some(x) => *x = -1,
|
|
|
|
None => ()
|
|
|
|
};
|
|
|
|
|
|
|
|
assert_eq!(ring.get_mut(0), Some(&mut 0));
|
|
|
|
assert_eq!(ring.get_mut(1), Some(&mut -1));
|
|
|
|
assert_eq!(ring.get_mut(2), Some(&mut 2));
|
|
|
|
assert_eq!(ring.get_mut(3), None);
|
|
|
|
|
|
|
|
assert_eq!(ring.pop_front(), Some(0));
|
|
|
|
assert_eq!(ring.get_mut(0), Some(&mut -1));
|
|
|
|
assert_eq!(ring.get_mut(1), Some(&mut 2));
|
|
|
|
assert_eq!(ring.get_mut(2), None);
|
|
|
|
}
|
2014-12-03 11:12:30 -06:00
|
|
|
|
2015-01-05 08:48:58 -06:00
|
|
|
#[test]
|
|
|
|
fn test_swap_front_back_remove() {
|
|
|
|
fn test(back: bool) {
|
|
|
|
// This test checks that every single combination of tail position and length is tested.
|
|
|
|
// Capacity 15 should be large enough to cover every case.
|
|
|
|
let mut tester = RingBuf::with_capacity(15);
|
|
|
|
let usable_cap = tester.capacity();
|
|
|
|
let final_len = usable_cap / 2;
|
|
|
|
|
|
|
|
for len in range(0, final_len) {
|
|
|
|
let expected = if back {
|
|
|
|
range(0, len).collect()
|
|
|
|
} else {
|
|
|
|
range(0, len).rev().collect()
|
|
|
|
};
|
|
|
|
for tail_pos in range(0, usable_cap) {
|
|
|
|
tester.tail = tail_pos;
|
|
|
|
tester.head = tail_pos;
|
|
|
|
if back {
|
|
|
|
for i in range(0, len * 2) {
|
|
|
|
tester.push_front(i);
|
|
|
|
}
|
|
|
|
for i in range(0, len) {
|
|
|
|
assert_eq!(tester.swap_back_remove(i), Some(len * 2 - 1 - i));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for i in range(0, len * 2) {
|
|
|
|
tester.push_back(i);
|
|
|
|
}
|
|
|
|
for i in range(0, len) {
|
|
|
|
let idx = tester.len() - 1 - i;
|
|
|
|
assert_eq!(tester.swap_front_remove(idx), Some(len * 2 - 1 - i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert!(tester.tail < tester.cap);
|
|
|
|
assert!(tester.head < tester.cap);
|
|
|
|
assert_eq!(tester, expected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
test(true);
|
|
|
|
test(false);
|
|
|
|
}
|
|
|
|
|
2014-12-03 11:12:30 -06:00
|
|
|
#[test]
|
|
|
|
fn test_insert() {
|
|
|
|
// This test checks that every single combination of tail position, length, and
|
2014-12-16 17:37:55 -06:00
|
|
|
// insertion position is tested. Capacity 15 should be large enough to cover every case.
|
2014-12-03 11:12:30 -06:00
|
|
|
|
2014-12-16 17:37:55 -06:00
|
|
|
let mut tester = RingBuf::with_capacity(15);
|
|
|
|
// can't guarantee we got 15, so have to get what we got.
|
|
|
|
// 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else
|
2014-12-03 11:12:30 -06:00
|
|
|
// this test isn't covering what it wants to
|
|
|
|
let cap = tester.capacity();
|
|
|
|
|
|
|
|
|
|
|
|
// len is the length *after* insertion
|
|
|
|
for len in range(1, cap) {
|
|
|
|
// 0, 1, 2, .., len - 1
|
|
|
|
let expected = iter::count(0, 1).take(len).collect();
|
|
|
|
for tail_pos in range(0, cap) {
|
|
|
|
for to_insert in range(0, len) {
|
|
|
|
tester.tail = tail_pos;
|
|
|
|
tester.head = tail_pos;
|
|
|
|
for i in range(0, len) {
|
|
|
|
if i != to_insert {
|
|
|
|
tester.push_back(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tester.insert(to_insert, to_insert);
|
2014-12-16 17:37:55 -06:00
|
|
|
assert!(tester.tail < tester.cap);
|
|
|
|
assert!(tester.head < tester.cap);
|
|
|
|
assert_eq!(tester, expected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_remove() {
|
|
|
|
// This test checks that every single combination of tail position, length, and
|
|
|
|
// removal position is tested. Capacity 15 should be large enough to cover every case.
|
|
|
|
|
|
|
|
let mut tester = RingBuf::with_capacity(15);
|
|
|
|
// can't guarantee we got 15, so have to get what we got.
|
|
|
|
// 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else
|
|
|
|
// this test isn't covering what it wants to
|
|
|
|
let cap = tester.capacity();
|
|
|
|
|
|
|
|
// len is the length *after* removal
|
|
|
|
for len in range(0, cap - 1) {
|
|
|
|
// 0, 1, 2, .., len - 1
|
|
|
|
let expected = iter::count(0, 1).take(len).collect();
|
|
|
|
for tail_pos in range(0, cap) {
|
|
|
|
for to_remove in range(0, len + 1) {
|
|
|
|
tester.tail = tail_pos;
|
|
|
|
tester.head = tail_pos;
|
|
|
|
for i in range(0, len) {
|
|
|
|
if i == to_remove {
|
|
|
|
tester.push_back(1234);
|
|
|
|
}
|
|
|
|
tester.push_back(i);
|
|
|
|
}
|
|
|
|
if to_remove == len {
|
|
|
|
tester.push_back(1234);
|
|
|
|
}
|
|
|
|
tester.remove(to_remove);
|
|
|
|
assert!(tester.tail < tester.cap);
|
|
|
|
assert!(tester.head < tester.cap);
|
2014-12-03 11:12:30 -06:00
|
|
|
assert_eq!(tester, expected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-05 08:48:58 -06:00
|
|
|
#[test]
|
|
|
|
fn test_shrink_to_fit() {
|
|
|
|
// This test checks that every single combination of head and tail position,
|
|
|
|
// is tested. Capacity 15 should be large enough to cover every case.
|
|
|
|
|
|
|
|
let mut tester = RingBuf::with_capacity(15);
|
|
|
|
// can't guarantee we got 15, so have to get what we got.
|
|
|
|
// 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else
|
|
|
|
// this test isn't covering what it wants to
|
|
|
|
let cap = tester.capacity();
|
|
|
|
tester.reserve(63);
|
|
|
|
let max_cap = tester.capacity();
|
|
|
|
|
|
|
|
for len in range(0, cap + 1) {
|
|
|
|
// 0, 1, 2, .., len - 1
|
|
|
|
let expected = iter::count(0, 1).take(len).collect();
|
|
|
|
for tail_pos in range(0, max_cap + 1) {
|
|
|
|
tester.tail = tail_pos;
|
|
|
|
tester.head = tail_pos;
|
|
|
|
tester.reserve(63);
|
|
|
|
for i in range(0, len) {
|
|
|
|
tester.push_back(i);
|
|
|
|
}
|
|
|
|
tester.shrink_to_fit();
|
|
|
|
assert!(tester.capacity() <= cap);
|
|
|
|
assert!(tester.tail < tester.cap);
|
|
|
|
assert!(tester.head < tester.cap);
|
|
|
|
assert_eq!(tester, expected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-03 11:12:30 -06:00
|
|
|
#[test]
|
|
|
|
fn test_front() {
|
|
|
|
let mut ring = RingBuf::new();
|
|
|
|
ring.push_back(10i);
|
|
|
|
ring.push_back(20i);
|
|
|
|
assert_eq!(ring.front(), Some(&10));
|
|
|
|
ring.pop_front();
|
|
|
|
assert_eq!(ring.front(), Some(&20));
|
|
|
|
ring.pop_front();
|
|
|
|
assert_eq!(ring.front(), None);
|
|
|
|
}
|
2014-12-15 22:01:58 -06:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_as_slices() {
|
|
|
|
let mut ring: RingBuf<int> = RingBuf::with_capacity(127);
|
|
|
|
let cap = ring.capacity() as int;
|
|
|
|
let first = cap/2;
|
|
|
|
let last = cap - first;
|
|
|
|
for i in range(0, first) {
|
|
|
|
ring.push_back(i);
|
|
|
|
|
|
|
|
let (left, right) = ring.as_slices();
|
|
|
|
let expected: Vec<_> = range(0, i+1).collect();
|
|
|
|
assert_eq!(left, expected);
|
|
|
|
assert_eq!(right, []);
|
|
|
|
}
|
|
|
|
|
|
|
|
for j in range(-last, 0) {
|
|
|
|
ring.push_front(j);
|
|
|
|
let (left, right) = ring.as_slices();
|
|
|
|
let expected_left: Vec<_> = range(-last, j+1).rev().collect();
|
|
|
|
let expected_right: Vec<_> = range(0, first).collect();
|
|
|
|
assert_eq!(left, expected_left);
|
|
|
|
assert_eq!(right, expected_right);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert_eq!(ring.len() as int, cap);
|
|
|
|
assert_eq!(ring.capacity() as int, cap);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_as_mut_slices() {
|
|
|
|
let mut ring: RingBuf<int> = RingBuf::with_capacity(127);
|
|
|
|
let cap = ring.capacity() as int;
|
|
|
|
let first = cap/2;
|
|
|
|
let last = cap - first;
|
|
|
|
for i in range(0, first) {
|
|
|
|
ring.push_back(i);
|
|
|
|
|
|
|
|
let (left, right) = ring.as_mut_slices();
|
|
|
|
let expected: Vec<_> = range(0, i+1).collect();
|
|
|
|
assert_eq!(left, expected);
|
|
|
|
assert_eq!(right, []);
|
|
|
|
}
|
|
|
|
|
|
|
|
for j in range(-last, 0) {
|
|
|
|
ring.push_front(j);
|
|
|
|
let (left, right) = ring.as_mut_slices();
|
|
|
|
let expected_left: Vec<_> = range(-last, j+1).rev().collect();
|
|
|
|
let expected_right: Vec<_> = range(0, first).collect();
|
|
|
|
assert_eq!(left, expected_left);
|
|
|
|
assert_eq!(right, expected_right);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert_eq!(ring.len() as int, cap);
|
|
|
|
assert_eq!(ring.capacity() as int, cap);
|
|
|
|
}
|
2012-07-03 12:52:32 -05:00
|
|
|
}
|