2014-01-21 08:35:11 -06:00
|
|
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
2014-04-02 18:54:22 -05:00
|
|
|
|
2014-08-30 16:11:22 -05:00
|
|
|
//! A growable list type, written `Vec<T>` but pronounced 'vector.'
|
|
|
|
//!
|
|
|
|
//! Vectors have `O(1)` indexing, push (to the end) and pop (from the end).
|
2014-01-21 08:35:11 -06:00
|
|
|
|
std: Recreate a `collections` module
As with the previous commit with `librand`, this commit shuffles around some
`collections` code. The new state of the world is similar to that of librand:
* The libcollections crate now only depends on libcore and liballoc.
* The standard library has a new module, `std::collections`. All functionality
of libcollections is reexported through this module.
I would like to stress that this change is purely cosmetic. There are very few
alterations to these primitives.
There are a number of notable points about the new organization:
* std::{str, slice, string, vec} all moved to libcollections. There is no reason
that these primitives shouldn't be necessarily usable in a freestanding
context that has allocation. These are all reexported in their usual places in
the standard library.
* The `hashmap`, and transitively the `lru_cache`, modules no longer reside in
`libcollections`, but rather in libstd. The reason for this is because the
`HashMap::new` contructor requires access to the OSRng for initially seeding
the hash map. Beyond this requirement, there is no reason that the hashmap
could not move to libcollections.
I do, however, have a plan to move the hash map to the collections module. The
`HashMap::new` function could be altered to require that the `H` hasher
parameter ascribe to the `Default` trait, allowing the entire `hashmap` module
to live in libcollections. The key idea would be that the default hasher would
be different in libstd. Something along the lines of:
// src/libstd/collections/mod.rs
pub type HashMap<K, V, H = RandomizedSipHasher> =
core_collections::HashMap<K, V, H>;
This is not possible today because you cannot invoke static methods through
type aliases. If we modified the compiler, however, to allow invocation of
static methods through type aliases, then this type definition would
essentially be switching the default hasher from `SipHasher` in libcollections
to a libstd-defined `RandomizedSipHasher` type. This type's `Default`
implementation would randomly seed the `SipHasher` instance, and otherwise
perform the same as `SipHasher`.
This future state doesn't seem incredibly far off, but until that time comes,
the hashmap module will live in libstd to not compromise on functionality.
* In preparation for the hashmap moving to libcollections, the `hash` module has
moved from libstd to libcollections. A previously snapshotted commit enables a
distinct `Writer` trait to live in the `hash` module which `Hash`
implementations are now parameterized over.
Due to using a custom trait, the `SipHasher` implementation has lost its
specialized methods for writing integers. These can be re-added
backwards-compatibly in the future via default methods if necessary, but the
FNV hashing should satisfy much of the need for speedier hashing.
A list of breaking changes:
* HashMap::{get, get_mut} no longer fails with the key formatted into the error
message with `{:?}`, instead, a generic message is printed. With backtraces,
it should still be not-too-hard to track down errors.
* The HashMap, HashSet, and LruCache types are now available through
std::collections instead of the collections crate.
* Manual implementations of hash should be parameterized over `hash::Writer`
instead of just `Writer`.
[breaking-change]
2014-05-29 20:50:12 -05:00
|
|
|
use core::prelude::*;
|
|
|
|
|
2014-10-10 04:18:42 -05:00
|
|
|
use alloc::boxed::Box;
|
2014-09-15 14:37:01 -05:00
|
|
|
use alloc::heap::{EMPTY, allocate, reallocate, deallocate};
|
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::cmp::max;
|
|
|
|
use core::default::Default;
|
|
|
|
use core::fmt;
|
2014-08-23 19:26:53 -05:00
|
|
|
use core::kinds::marker::{ContravariantLifetime, InvariantType};
|
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::mem;
|
2014-11-09 23:26:10 -06:00
|
|
|
use core::num::{Int, UnsignedInt};
|
2014-09-15 03:48:58 -05:00
|
|
|
use core::ops;
|
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::ptr;
|
2014-08-18 10:29:44 -05:00
|
|
|
use core::raw::Slice as RawSlice;
|
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::uint;
|
|
|
|
|
2014-11-02 19:04:32 -06:00
|
|
|
use slice::{CloneSliceAllocPrelude};
|
2014-03-16 18:04:29 -05:00
|
|
|
|
2014-03-20 01:01:08 -05:00
|
|
|
/// An owned, growable vector.
|
2014-03-16 18:04:29 -05:00
|
|
|
///
|
2014-03-20 01:01:08 -05:00
|
|
|
/// # Examples
|
2014-03-16 18:04:29 -05:00
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-03-20 01:01:08 -05:00
|
|
|
/// let mut vec = Vec::new();
|
2014-04-21 16:58:52 -05:00
|
|
|
/// vec.push(1i);
|
|
|
|
/// vec.push(2i);
|
2014-03-20 01:01:08 -05:00
|
|
|
///
|
|
|
|
/// assert_eq!(vec.len(), 2);
|
2014-07-14 18:37:25 -05:00
|
|
|
/// assert_eq!(vec[0], 1);
|
2014-03-20 01:01:08 -05:00
|
|
|
///
|
|
|
|
/// assert_eq!(vec.pop(), Some(2));
|
|
|
|
/// assert_eq!(vec.len(), 1);
|
2014-07-22 04:07:49 -05:00
|
|
|
///
|
2014-10-23 10:42:21 -05:00
|
|
|
/// vec[0] = 7i;
|
2014-07-22 04:07:49 -05:00
|
|
|
/// assert_eq!(vec[0], 7);
|
|
|
|
///
|
|
|
|
/// vec.push_all([1, 2, 3]);
|
|
|
|
///
|
|
|
|
/// for x in vec.iter() {
|
|
|
|
/// println!("{}", x);
|
|
|
|
/// }
|
|
|
|
/// assert_eq!(vec, vec![7i, 1, 2, 3]);
|
2014-03-20 01:01:08 -05:00
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// The `vec!` macro is provided to make initialization more convenient:
|
2014-03-16 18:04:29 -05:00
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-07-21 03:33:20 -05:00
|
|
|
/// let mut vec = vec![1i, 2i, 3i];
|
2014-03-16 18:04:29 -05:00
|
|
|
/// vec.push(4);
|
2014-07-21 03:33:20 -05:00
|
|
|
/// assert_eq!(vec, vec![1, 2, 3, 4]);
|
2014-03-16 18:04:29 -05:00
|
|
|
/// ```
|
2014-07-21 03:33:20 -05:00
|
|
|
///
|
2014-07-22 04:07:49 -05:00
|
|
|
/// Use a `Vec` as an efficient stack:
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// let mut stack = Vec::new();
|
|
|
|
///
|
|
|
|
/// stack.push(1i);
|
|
|
|
/// stack.push(2i);
|
|
|
|
/// stack.push(3i);
|
|
|
|
///
|
|
|
|
/// loop {
|
|
|
|
/// let top = match stack.pop() {
|
|
|
|
/// None => break, // empty
|
|
|
|
/// Some(x) => x,
|
|
|
|
/// };
|
|
|
|
/// // Prints 3, 2, 1
|
|
|
|
/// println!("{}", top);
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
2014-07-21 03:33:20 -05:00
|
|
|
/// # Capacity and reallocation
|
|
|
|
///
|
|
|
|
/// The capacity of a vector is the amount of space allocated for any future
|
|
|
|
/// elements that will be added onto the vector. This is not to be confused
|
|
|
|
/// with the *length* of a vector, which specifies the number of actual
|
|
|
|
/// elements within the vector. If a vector's length exceeds its capacity,
|
|
|
|
/// its capacity will automatically be increased, but its elements will
|
|
|
|
/// have to be reallocated.
|
|
|
|
///
|
|
|
|
/// For example, a vector with capacity 10 and length 0 would be an empty
|
|
|
|
/// vector with space for 10 more elements. Pushing 10 or fewer elements onto
|
|
|
|
/// the vector will not change its capacity or cause reallocation to occur.
|
|
|
|
/// However, if the vector's length is increased to 11, it will have to
|
|
|
|
/// reallocate, which can be slow. For this reason, it is recommended
|
|
|
|
/// to use `Vec::with_capacity` whenever possible to specify how big the vector
|
|
|
|
/// is expected to get.
|
2014-03-12 15:01:33 -05:00
|
|
|
#[unsafe_no_drop_flag]
|
2014-08-29 15:20:58 -05:00
|
|
|
#[stable]
|
2014-01-21 08:35:11 -06:00
|
|
|
pub struct Vec<T> {
|
2014-10-24 21:31:17 -05:00
|
|
|
ptr: *mut T,
|
2014-03-27 17:09:47 -05:00
|
|
|
len: uint,
|
|
|
|
cap: uint,
|
2014-01-21 08:35:11 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Vec<T> {
|
2014-03-16 18:04:29 -05:00
|
|
|
/// Constructs a new, empty `Vec`.
|
|
|
|
///
|
|
|
|
/// The vector will not allocate until elements are pushed onto it.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-03-16 18:04:29 -05:00
|
|
|
/// let mut vec: Vec<int> = Vec::new();
|
|
|
|
/// ```
|
2014-01-21 08:35:11 -06:00
|
|
|
#[inline]
|
2014-08-29 15:20:58 -05:00
|
|
|
#[stable]
|
2014-01-21 08:35:11 -06:00
|
|
|
pub fn new() -> Vec<T> {
|
2014-07-04 17:29:47 -05:00
|
|
|
// We want ptr to never be NULL so instead we set it to some arbitrary
|
|
|
|
// non-null value which is fine since we never call deallocate on the ptr
|
|
|
|
// if cap is 0. The reason for this is because the pointer of a slice
|
|
|
|
// being NULL would break the null pointer optimization for enums.
|
2014-10-24 21:31:17 -05:00
|
|
|
Vec { ptr: EMPTY as *mut T, len: 0, cap: 0 }
|
2014-01-21 08:35:11 -06:00
|
|
|
}
|
|
|
|
|
2014-03-16 18:04:29 -05:00
|
|
|
/// Constructs a new, empty `Vec` with the specified capacity.
|
|
|
|
///
|
|
|
|
/// The vector will be able to hold exactly `capacity` elements without
|
|
|
|
/// reallocating. If `capacity` is 0, the vector will not allocate.
|
|
|
|
///
|
2014-07-21 03:33:20 -05:00
|
|
|
/// It is important to note that this function does not specify the
|
|
|
|
/// *length* of the returned vector, but only the *capacity*. (For an
|
|
|
|
/// explanation of the difference between length and capacity, see
|
|
|
|
/// the main `Vec` docs above, 'Capacity and reallocation'.) To create
|
|
|
|
/// a vector of a given length, use `Vec::from_elem` or `Vec::from_fn`.
|
|
|
|
///
|
2014-03-16 18:04:29 -05:00
|
|
|
/// # Example
|
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-07-21 03:33:20 -05:00
|
|
|
/// let mut vec: Vec<int> = Vec::with_capacity(10);
|
|
|
|
///
|
|
|
|
/// // The vector contains no items, even though it has capacity for more
|
|
|
|
/// assert_eq!(vec.len(), 0);
|
|
|
|
///
|
|
|
|
/// // These are all done without reallocating...
|
2014-07-21 12:18:17 -05:00
|
|
|
/// for i in range(0i, 10) {
|
2014-07-21 03:33:20 -05:00
|
|
|
/// vec.push(i);
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// // ...but this may make the vector reallocate
|
|
|
|
/// vec.push(11);
|
2014-03-16 18:04:29 -05:00
|
|
|
/// ```
|
2014-06-02 23:56:29 -05:00
|
|
|
#[inline]
|
2014-08-29 15:20:58 -05:00
|
|
|
#[stable]
|
2014-01-21 08:35:11 -06:00
|
|
|
pub fn with_capacity(capacity: uint) -> Vec<T> {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
if mem::size_of::<T>() == 0 {
|
2014-10-24 21:31:17 -05:00
|
|
|
Vec { ptr: EMPTY as *mut T, len: 0, cap: uint::MAX }
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
} else if capacity == 0 {
|
2014-01-21 08:35:11 -06:00
|
|
|
Vec::new()
|
|
|
|
} else {
|
2014-11-09 07:11:28 -06:00
|
|
|
let size = capacity.checked_mul(mem::size_of::<T>())
|
2014-06-06 18:33:44 -05:00
|
|
|
.expect("capacity overflow");
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
let ptr = unsafe { allocate(size, mem::min_align_of::<T>()) };
|
2014-10-24 21:31:17 -05:00
|
|
|
Vec { ptr: ptr as *mut T, len: 0, cap: capacity }
|
2014-01-21 08:35:11 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-16 18:04:29 -05:00
|
|
|
/// Creates and initializes a `Vec`.
|
|
|
|
///
|
|
|
|
/// Creates a `Vec` of size `length` and initializes the elements to the
|
|
|
|
/// value returned by the closure `op`.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-03-16 18:04:29 -05:00
|
|
|
/// let vec = Vec::from_fn(3, |idx| idx * 2);
|
2014-07-22 03:33:26 -05:00
|
|
|
/// assert_eq!(vec, vec![0, 2, 4]);
|
2014-03-16 18:04:29 -05:00
|
|
|
/// ```
|
2014-06-02 23:56:29 -05:00
|
|
|
#[inline]
|
2014-08-29 15:20:58 -05:00
|
|
|
#[unstable = "the naming is uncertain as well as this migrating to unboxed \
|
|
|
|
closures in the future"]
|
2014-01-21 08:35:11 -06:00
|
|
|
pub fn from_fn(length: uint, op: |uint| -> T) -> Vec<T> {
|
|
|
|
unsafe {
|
|
|
|
let mut xs = Vec::with_capacity(length);
|
|
|
|
while xs.len < length {
|
2014-06-13 22:48:09 -05:00
|
|
|
let len = xs.len;
|
2014-09-14 22:27:36 -05:00
|
|
|
ptr::write(xs.as_mut_slice().unsafe_mut(len), op(len));
|
2014-01-21 08:35:11 -06:00
|
|
|
xs.len += 1;
|
|
|
|
}
|
|
|
|
xs
|
|
|
|
}
|
|
|
|
}
|
2014-03-06 16:33:46 -06:00
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Creates a `Vec<T>` directly from the raw constituents.
|
2014-03-19 09:52:37 -05:00
|
|
|
///
|
|
|
|
/// This is highly unsafe:
|
|
|
|
///
|
|
|
|
/// - if `ptr` is null, then `length` and `capacity` should be 0
|
|
|
|
/// - `ptr` must point to an allocation of size `capacity`
|
|
|
|
/// - there must be `length` valid instances of type `T` at the
|
|
|
|
/// beginning of that allocation
|
|
|
|
/// - `ptr` must be allocated by the default `Vec` allocator
|
2014-07-22 06:40:38 -05:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::ptr;
|
|
|
|
/// use std::mem;
|
|
|
|
///
|
|
|
|
/// fn main() {
|
|
|
|
/// let mut v = vec![1i, 2, 3];
|
|
|
|
///
|
|
|
|
/// // Pull out the various important pieces of information about `v`
|
|
|
|
/// let p = v.as_mut_ptr();
|
|
|
|
/// let len = v.len();
|
|
|
|
/// let cap = v.capacity();
|
|
|
|
///
|
|
|
|
/// unsafe {
|
|
|
|
/// // Cast `v` into the void: no destructor run, so we are in
|
|
|
|
/// // complete control of the allocation to which `p` points.
|
|
|
|
/// mem::forget(v);
|
|
|
|
///
|
|
|
|
/// // Overwrite memory with 4, 5, 6
|
|
|
|
/// for i in range(0, len as int) {
|
|
|
|
/// ptr::write(p.offset(i), 4 + i);
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// // Put everything back together into a Vec
|
2014-10-27 11:11:07 -05:00
|
|
|
/// let rebuilt = Vec::from_raw_parts(p, len, cap);
|
2014-07-22 06:40:38 -05:00
|
|
|
/// assert_eq!(rebuilt, vec![4i, 5i, 6i]);
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// ```
|
2014-08-29 15:20:58 -05:00
|
|
|
#[experimental]
|
2014-10-24 21:31:17 -05:00
|
|
|
pub unsafe fn from_raw_parts(ptr: *mut T, length: uint,
|
|
|
|
capacity: uint) -> Vec<T> {
|
|
|
|
Vec { ptr: ptr, len: length, cap: capacity }
|
2014-03-19 09:52:37 -05:00
|
|
|
}
|
|
|
|
|
2014-04-20 23:49:39 -05:00
|
|
|
/// Consumes the `Vec`, partitioning it based on a predicate.
|
2014-03-16 18:04:29 -05:00
|
|
|
///
|
|
|
|
/// Partitions the `Vec` into two `Vec`s `(A,B)`, where all elements of `A`
|
|
|
|
/// satisfy `f` and all elements of `B` do not. The order of elements is
|
|
|
|
/// preserved.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-07-22 03:33:26 -05:00
|
|
|
/// let vec = vec![1i, 2i, 3i, 4i];
|
2014-03-16 18:04:29 -05:00
|
|
|
/// let (even, odd) = vec.partition(|&n| n % 2 == 0);
|
2014-07-22 03:33:26 -05:00
|
|
|
/// assert_eq!(even, vec![2, 4]);
|
|
|
|
/// assert_eq!(odd, vec![1, 3]);
|
2014-03-16 18:04:29 -05:00
|
|
|
/// ```
|
2014-03-06 16:33:46 -06:00
|
|
|
#[inline]
|
2014-08-29 15:20:58 -05:00
|
|
|
#[experimental]
|
2014-03-06 16:33:46 -06:00
|
|
|
pub fn partition(self, f: |&T| -> bool) -> (Vec<T>, Vec<T>) {
|
|
|
|
let mut lefts = Vec::new();
|
|
|
|
let mut rights = Vec::new();
|
|
|
|
|
2014-09-14 22:27:36 -05:00
|
|
|
for elt in self.into_iter() {
|
2014-03-06 16:33:46 -06:00
|
|
|
if f(&elt) {
|
|
|
|
lefts.push(elt);
|
|
|
|
} else {
|
|
|
|
rights.push(elt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
(lefts, rights)
|
|
|
|
}
|
2014-01-21 08:35:11 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Clone> Vec<T> {
|
2014-03-16 18:04:29 -05:00
|
|
|
/// Constructs a `Vec` with copies of a value.
|
|
|
|
///
|
|
|
|
/// Creates a `Vec` with `length` copies of `value`.
|
|
|
|
///
|
|
|
|
/// # Example
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-03-16 18:04:29 -05:00
|
|
|
/// let vec = Vec::from_elem(3, "hi");
|
|
|
|
/// println!("{}", vec); // prints [hi, hi, hi]
|
|
|
|
/// ```
|
2014-06-02 23:56:29 -05:00
|
|
|
#[inline]
|
2014-08-29 15:20:58 -05:00
|
|
|
#[unstable = "this functionality may become more generic over all collections"]
|
2014-01-21 08:35:11 -06:00
|
|
|
pub fn from_elem(length: uint, value: T) -> Vec<T> {
|
|
|
|
unsafe {
|
|
|
|
let mut xs = Vec::with_capacity(length);
|
|
|
|
while xs.len < length {
|
2014-06-13 22:48:09 -05:00
|
|
|
let len = xs.len;
|
2014-09-14 22:27:36 -05:00
|
|
|
ptr::write(xs.as_mut_slice().unsafe_mut(len),
|
2014-05-29 21:03:06 -05:00
|
|
|
value.clone());
|
2014-01-21 08:35:11 -06:00
|
|
|
xs.len += 1;
|
|
|
|
}
|
|
|
|
xs
|
|
|
|
}
|
|
|
|
}
|
2014-02-18 23:36:51 -06:00
|
|
|
|
2014-03-16 18:04:29 -05:00
|
|
|
/// Appends all elements in a slice to the `Vec`.
|
|
|
|
///
|
|
|
|
/// Iterates over the slice `other`, clones each element, and then appends
|
|
|
|
/// it to this `Vec`. The `other` vector is traversed in-order.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-07-22 03:33:26 -05:00
|
|
|
/// let mut vec = vec![1i];
|
2014-04-21 16:58:52 -05:00
|
|
|
/// vec.push_all([2i, 3, 4]);
|
2014-07-22 03:33:26 -05:00
|
|
|
/// assert_eq!(vec, vec![1, 2, 3, 4]);
|
2014-03-16 18:04:29 -05:00
|
|
|
/// ```
|
2014-02-18 23:36:51 -06:00
|
|
|
#[inline]
|
2014-08-29 15:20:58 -05:00
|
|
|
#[experimental]
|
2014-02-18 23:36:51 -06:00
|
|
|
pub fn push_all(&mut self, other: &[T]) {
|
2014-11-06 11:24:47 -06:00
|
|
|
self.reserve(other.len());
|
2014-07-07 11:11:03 -05:00
|
|
|
|
2014-07-07 11:45:00 -05:00
|
|
|
for i in range(0, other.len()) {
|
|
|
|
let len = self.len();
|
|
|
|
|
|
|
|
// Unsafe code so this can be optimised to a memcpy (or something similarly
|
|
|
|
// fast) when T is Copy. LLVM is easily confused, so any extra operations
|
|
|
|
// during the loop can prevent this optimisation.
|
|
|
|
unsafe {
|
|
|
|
ptr::write(
|
2014-09-14 22:27:36 -05:00
|
|
|
self.as_mut_slice().unsafe_mut(len),
|
2014-08-06 22:08:16 -05:00
|
|
|
other.unsafe_get(i).clone());
|
2014-07-07 11:45:00 -05:00
|
|
|
self.set_len(len + 1);
|
|
|
|
}
|
2014-07-06 01:11:18 -05:00
|
|
|
}
|
2014-02-18 23:36:51 -06:00
|
|
|
}
|
2014-02-28 14:54:01 -06:00
|
|
|
|
2014-03-16 18:04:29 -05:00
|
|
|
/// Grows the `Vec` in-place.
|
|
|
|
///
|
|
|
|
/// Adds `n` copies of `value` to the `Vec`.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-07-22 03:33:26 -05:00
|
|
|
/// let mut vec = vec!["hello"];
|
2014-08-29 15:20:58 -05:00
|
|
|
/// vec.grow(2, "world");
|
2014-07-22 03:33:26 -05:00
|
|
|
/// assert_eq!(vec, vec!["hello", "world", "world"]);
|
2014-03-16 18:04:29 -05:00
|
|
|
/// ```
|
2014-08-29 15:20:58 -05:00
|
|
|
#[stable]
|
|
|
|
pub fn grow(&mut self, n: uint, value: T) {
|
2014-11-06 11:24:47 -06:00
|
|
|
self.reserve(n);
|
2014-02-28 14:54:01 -06:00
|
|
|
let mut i: uint = 0u;
|
|
|
|
|
|
|
|
while i < n {
|
2014-08-29 15:20:58 -05:00
|
|
|
self.push(value.clone());
|
2014-02-28 14:54:01 -06:00
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-20 23:49:39 -05:00
|
|
|
/// Partitions a vector based on a predicate.
|
2014-03-16 18:04:29 -05:00
|
|
|
///
|
|
|
|
/// Clones the elements of the vector, partitioning them into two `Vec`s
|
2014-08-04 05:48:39 -05:00
|
|
|
/// `(a, b)`, where all elements of `a` satisfy `f` and all elements of `b`
|
2014-03-16 18:04:29 -05:00
|
|
|
/// do not. The order of elements is preserved.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-07-22 03:33:26 -05:00
|
|
|
/// let vec = vec![1i, 2, 3, 4];
|
2014-03-16 18:04:29 -05:00
|
|
|
/// let (even, odd) = vec.partitioned(|&n| n % 2 == 0);
|
2014-07-22 03:33:26 -05:00
|
|
|
/// assert_eq!(even, vec![2i, 4]);
|
|
|
|
/// assert_eq!(odd, vec![1i, 3]);
|
2014-03-16 18:04:29 -05:00
|
|
|
/// ```
|
2014-08-29 15:20:58 -05:00
|
|
|
#[experimental]
|
2014-02-28 01:49:25 -06:00
|
|
|
pub fn partitioned(&self, f: |&T| -> bool) -> (Vec<T>, Vec<T>) {
|
|
|
|
let mut lefts = Vec::new();
|
|
|
|
let mut rights = Vec::new();
|
|
|
|
|
|
|
|
for elt in self.iter() {
|
|
|
|
if f(elt) {
|
|
|
|
lefts.push(elt.clone());
|
|
|
|
} else {
|
|
|
|
rights.push(elt.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
(lefts, rights)
|
|
|
|
}
|
2014-02-18 23:36:51 -06:00
|
|
|
}
|
|
|
|
|
2014-06-23 18:34:29 -05:00
|
|
|
#[unstable]
|
2014-02-18 23:36:51 -06:00
|
|
|
impl<T:Clone> Clone for Vec<T> {
|
2014-09-17 14:56:31 -05:00
|
|
|
fn clone(&self) -> Vec<T> { self.as_slice().to_vec() }
|
2014-04-03 06:28:45 -05:00
|
|
|
|
|
|
|
fn clone_from(&mut self, other: &Vec<T>) {
|
|
|
|
// drop anything in self that will not be overwritten
|
|
|
|
if self.len() > other.len() {
|
|
|
|
self.truncate(other.len())
|
2014-02-18 23:36:51 -06:00
|
|
|
}
|
2014-04-03 06:28:45 -05:00
|
|
|
|
|
|
|
// reuse the contained values' allocations/resources.
|
2014-09-14 22:27:36 -05:00
|
|
|
for (place, thing) in self.iter_mut().zip(other.iter()) {
|
2014-04-03 06:28:45 -05:00
|
|
|
place.clone_from(thing)
|
|
|
|
}
|
|
|
|
|
|
|
|
// self.len <= other.len due to the truncate above, so the
|
|
|
|
// slice here is always in-bounds.
|
2014-09-24 06:41:09 -05:00
|
|
|
let slice = other[self.len()..];
|
2014-07-07 11:11:03 -05:00
|
|
|
self.push_all(slice);
|
2014-02-18 23:36:51 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-29 15:20:58 -05:00
|
|
|
#[experimental = "waiting on Index stability"]
|
2014-07-13 18:03:23 -05:00
|
|
|
impl<T> Index<uint,T> for Vec<T> {
|
|
|
|
#[inline]
|
|
|
|
fn index<'a>(&'a self, index: &uint) -> &'a T {
|
2014-10-15 01:05:01 -05:00
|
|
|
&self.as_slice()[*index]
|
2014-07-13 18:03:23 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-10 17:17:59 -05:00
|
|
|
impl<T> IndexMut<uint,T> for Vec<T> {
|
2014-07-13 18:03:23 -05:00
|
|
|
#[inline]
|
|
|
|
fn index_mut<'a>(&'a mut self, index: &uint) -> &'a mut T {
|
2014-10-23 10:42:21 -05:00
|
|
|
&mut self.as_mut_slice()[*index]
|
2014-07-13 18:03:23 -05:00
|
|
|
}
|
2014-10-10 17:17:59 -05:00
|
|
|
}
|
2014-07-13 18:03:23 -05:00
|
|
|
|
2014-10-04 17:59:10 -05:00
|
|
|
impl<T> ops::Slice<uint, [T]> for Vec<T> {
|
|
|
|
#[inline]
|
|
|
|
fn as_slice_<'a>(&'a self) -> &'a [T] {
|
|
|
|
self.as_slice()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn slice_from_or_fail<'a>(&'a self, start: &uint) -> &'a [T] {
|
|
|
|
self.as_slice().slice_from_or_fail(start)
|
|
|
|
}
|
2014-09-15 03:48:58 -05:00
|
|
|
|
2014-10-04 17:59:10 -05:00
|
|
|
#[inline]
|
|
|
|
fn slice_to_or_fail<'a>(&'a self, end: &uint) -> &'a [T] {
|
|
|
|
self.as_slice().slice_to_or_fail(end)
|
|
|
|
}
|
|
|
|
#[inline]
|
|
|
|
fn slice_or_fail<'a>(&'a self, start: &uint, end: &uint) -> &'a [T] {
|
|
|
|
self.as_slice().slice_or_fail(start, end)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> ops::SliceMut<uint, [T]> for Vec<T> {
|
|
|
|
#[inline]
|
|
|
|
fn as_mut_slice_<'a>(&'a mut self) -> &'a mut [T] {
|
|
|
|
self.as_mut_slice()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn slice_from_or_fail_mut<'a>(&'a mut self, start: &uint) -> &'a mut [T] {
|
|
|
|
self.as_mut_slice().slice_from_or_fail_mut(start)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn slice_to_or_fail_mut<'a>(&'a mut self, end: &uint) -> &'a mut [T] {
|
|
|
|
self.as_mut_slice().slice_to_or_fail_mut(end)
|
|
|
|
}
|
|
|
|
#[inline]
|
|
|
|
fn slice_or_fail_mut<'a>(&'a mut self, start: &uint, end: &uint) -> &'a mut [T] {
|
|
|
|
self.as_mut_slice().slice_or_fail_mut(start, end)
|
|
|
|
}
|
|
|
|
}
|
2014-08-29 15:20:58 -05:00
|
|
|
|
2014-10-29 17:26:29 -05:00
|
|
|
#[experimental = "waiting on Deref stability"]
|
|
|
|
impl<T> ops::Deref<[T]> for Vec<T> {
|
|
|
|
fn deref<'a>(&'a self) -> &'a [T] { self.as_slice() }
|
|
|
|
}
|
|
|
|
|
|
|
|
#[experimental = "waiting on DerefMut stability"]
|
|
|
|
impl<T> ops::DerefMut<[T]> for Vec<T> {
|
|
|
|
fn deref_mut<'a>(&'a mut self) -> &'a mut [T] { self.as_mut_slice() }
|
|
|
|
}
|
|
|
|
|
2014-08-29 15:20:58 -05:00
|
|
|
#[experimental = "waiting on FromIterator stability"]
|
2014-02-18 23:36:51 -06:00
|
|
|
impl<T> FromIterator<T> for Vec<T> {
|
2014-06-02 23:56:29 -05:00
|
|
|
#[inline]
|
2014-03-30 23:45:55 -05:00
|
|
|
fn from_iter<I:Iterator<T>>(mut iterator: I) -> Vec<T> {
|
2014-02-18 23:36:51 -06:00
|
|
|
let (lower, _) = iterator.size_hint();
|
|
|
|
let mut vector = Vec::with_capacity(lower);
|
2014-03-20 08:12:56 -05:00
|
|
|
for element in iterator {
|
2014-02-18 23:36:51 -06:00
|
|
|
vector.push(element)
|
|
|
|
}
|
|
|
|
vector
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-07 18:39:39 -06:00
|
|
|
#[experimental = "waiting on Extend stability"]
|
|
|
|
impl<T> Extend<T> for Vec<T> {
|
2014-06-02 23:56:29 -05:00
|
|
|
#[inline]
|
2014-03-20 08:12:56 -05:00
|
|
|
fn extend<I: Iterator<T>>(&mut self, mut iterator: I) {
|
2014-03-03 14:46:24 -06:00
|
|
|
let (lower, _) = iterator.size_hint();
|
2014-11-06 11:24:47 -06:00
|
|
|
self.reserve(lower);
|
2014-03-20 08:12:56 -05:00
|
|
|
for element in iterator {
|
2014-03-03 14:46:24 -06:00
|
|
|
self.push(element)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-29 15:20:58 -05:00
|
|
|
#[unstable = "waiting on PartialEq stability"]
|
2014-05-29 19:45:07 -05:00
|
|
|
impl<T: PartialEq> PartialEq for Vec<T> {
|
2014-02-18 23:36:51 -06:00
|
|
|
#[inline]
|
|
|
|
fn eq(&self, other: &Vec<T>) -> bool {
|
|
|
|
self.as_slice() == other.as_slice()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-29 15:20:58 -05:00
|
|
|
#[unstable = "waiting on PartialOrd stability"]
|
2014-05-29 19:45:07 -05:00
|
|
|
impl<T: PartialOrd> PartialOrd for Vec<T> {
|
2014-10-29 20:21:37 -05:00
|
|
|
#[inline]
|
|
|
|
fn partial_cmp(&self, other: &Vec<T>) -> Option<Ordering> {
|
|
|
|
self.as_slice().partial_cmp(other.as_slice())
|
|
|
|
}
|
2014-02-24 07:11:00 -06:00
|
|
|
}
|
|
|
|
|
2014-08-29 15:20:58 -05:00
|
|
|
#[unstable = "waiting on Eq stability"]
|
2014-05-31 12:43:52 -05:00
|
|
|
impl<T: Eq> Eq for Vec<T> {}
|
2014-02-18 23:36:51 -06:00
|
|
|
|
2014-08-29 15:20:58 -05:00
|
|
|
#[experimental]
|
2014-10-04 18:22:42 -05:00
|
|
|
impl<T: PartialEq, V: AsSlice<T>> Equiv<V> for Vec<T> {
|
2014-06-06 12:27:49 -05:00
|
|
|
#[inline]
|
|
|
|
fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() }
|
|
|
|
}
|
|
|
|
|
2014-08-29 15:20:58 -05:00
|
|
|
#[unstable = "waiting on Ord stability"]
|
2014-05-31 12:43:52 -05:00
|
|
|
impl<T: Ord> Ord for Vec<T> {
|
2014-10-29 20:21:37 -05:00
|
|
|
#[inline]
|
|
|
|
fn cmp(&self, other: &Vec<T>) -> Ordering {
|
|
|
|
self.as_slice().cmp(other.as_slice())
|
|
|
|
}
|
2014-01-21 08:35:11 -06:00
|
|
|
}
|
|
|
|
|
2014-05-06 16:01:16 -05:00
|
|
|
// FIXME: #13996: need a way to mark the return value as `noalias`
|
|
|
|
#[inline(never)]
|
2014-10-07 23:57:29 -05:00
|
|
|
unsafe fn alloc_or_realloc<T>(ptr: *mut T, old_size: uint, size: uint) -> *mut T {
|
2014-05-06 16:01:16 -05:00
|
|
|
if old_size == 0 {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
allocate(size, mem::min_align_of::<T>()) as *mut T
|
2014-05-06 16:01:16 -05:00
|
|
|
} else {
|
2014-10-07 23:57:29 -05:00
|
|
|
reallocate(ptr as *mut u8, old_size, size, mem::min_align_of::<T>()) as *mut T
|
2014-05-06 16:01:16 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-09 23:35:56 -05:00
|
|
|
#[inline]
|
|
|
|
unsafe fn dealloc<T>(ptr: *mut T, len: uint) {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
if mem::size_of::<T>() != 0 {
|
|
|
|
deallocate(ptr as *mut u8,
|
|
|
|
len * mem::size_of::<T>(),
|
|
|
|
mem::min_align_of::<T>())
|
2014-05-09 23:35:56 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-21 08:35:11 -06:00
|
|
|
impl<T> Vec<T> {
|
2014-03-16 18:04:29 -05:00
|
|
|
/// Returns the number of elements the vector can hold without
|
|
|
|
/// reallocating.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-03-16 18:04:29 -05:00
|
|
|
/// let vec: Vec<int> = Vec::with_capacity(10);
|
|
|
|
/// assert_eq!(vec.capacity(), 10);
|
|
|
|
/// ```
|
2014-01-21 08:35:11 -06:00
|
|
|
#[inline]
|
2014-08-29 15:20:58 -05:00
|
|
|
#[stable]
|
2014-01-21 08:35:11 -06:00
|
|
|
pub fn capacity(&self) -> uint {
|
|
|
|
self.cap
|
|
|
|
}
|
|
|
|
|
2014-11-06 11:24:47 -06:00
|
|
|
/// Deprecated: Renamed to `reserve`.
|
|
|
|
#[deprecated = "Renamed to `reserve`"]
|
2014-03-03 14:46:24 -06:00
|
|
|
pub fn reserve_additional(&mut self, extra: uint) {
|
2014-11-06 11:24:47 -06:00
|
|
|
self.reserve(extra)
|
2014-03-03 14:46:24 -06:00
|
|
|
}
|
|
|
|
|
2014-11-06 11:24:47 -06:00
|
|
|
/// Reserves capacity for at least `additional` more elements to be inserted in the given
|
|
|
|
/// `Vec`. The collection may reserve more space to avoid frequent reallocations.
|
2014-03-16 18:04:29 -05:00
|
|
|
///
|
2014-11-06 11:24:47 -06:00
|
|
|
/// # Panics
|
2014-03-16 18:04:29 -05:00
|
|
|
///
|
2014-11-06 11:24:47 -06:00
|
|
|
/// Panics if the new capacity overflows `uint`.
|
2014-03-16 18:04:29 -05:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-11-06 11:24:47 -06:00
|
|
|
/// let mut vec: Vec<int> = vec![1];
|
2014-03-16 18:04:29 -05:00
|
|
|
/// vec.reserve(10);
|
2014-11-06 11:24:47 -06:00
|
|
|
/// assert!(vec.capacity() >= 11);
|
2014-03-16 18:04:29 -05:00
|
|
|
/// ```
|
2014-11-06 11:24:47 -06:00
|
|
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
|
|
|
pub fn reserve(&mut self, additional: uint) {
|
|
|
|
if self.cap - self.len < additional {
|
2014-11-09 07:11:28 -06:00
|
|
|
match self.len.checked_add(additional) {
|
2014-11-06 11:24:47 -06:00
|
|
|
None => panic!("Vec::reserve: `uint` overflow"),
|
|
|
|
// if the checked_add
|
|
|
|
Some(new_cap) => {
|
2014-11-09 00:15:45 -06:00
|
|
|
let amort_cap = new_cap.next_power_of_two();
|
2014-11-06 11:24:47 -06:00
|
|
|
// next_power_of_two will overflow to exactly 0 for really big capacities
|
|
|
|
if amort_cap == 0 {
|
|
|
|
self.grow_capacity(new_cap);
|
|
|
|
} else {
|
|
|
|
self.grow_capacity(amort_cap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-02-22 17:59:23 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-06 11:24:47 -06:00
|
|
|
/// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the
|
|
|
|
/// given `Vec`. Does nothing if the capacity is already sufficient.
|
2014-03-16 18:04:29 -05:00
|
|
|
///
|
2014-11-06 11:24:47 -06:00
|
|
|
/// 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`.
|
2014-03-16 18:04:29 -05:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-11-06 11:24:47 -06:00
|
|
|
/// let mut vec: Vec<int> = vec![1];
|
|
|
|
/// vec.reserve_exact(10);
|
|
|
|
/// assert!(vec.capacity() >= 11);
|
2014-03-16 18:04:29 -05:00
|
|
|
/// ```
|
2014-11-06 11:24:47 -06:00
|
|
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
|
|
|
pub fn reserve_exact(&mut self, additional: uint) {
|
|
|
|
if self.cap - self.len < additional {
|
2014-11-09 07:11:28 -06:00
|
|
|
match self.len.checked_add(additional) {
|
2014-11-06 11:24:47 -06:00
|
|
|
None => panic!("Vec::reserve: `uint` overflow"),
|
|
|
|
Some(new_cap) => self.grow_capacity(new_cap)
|
2014-01-21 08:35:11 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-27 16:32:53 -05:00
|
|
|
/// Shrinks the capacity of the vector as much as possible. It will drop
|
|
|
|
/// down as close as possible to the length but the allocator may still
|
|
|
|
/// inform the vector that there is space for a few more elements.
|
2014-03-16 18:04:29 -05:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-10-23 09:45:36 -05:00
|
|
|
/// let mut vec: Vec<int> = Vec::with_capacity(10);
|
|
|
|
/// vec.push_all([1, 2, 3]);
|
|
|
|
/// assert_eq!(vec.capacity(), 10);
|
2014-03-16 18:04:29 -05:00
|
|
|
/// vec.shrink_to_fit();
|
2014-10-27 16:32:53 -05:00
|
|
|
/// assert!(vec.capacity() >= 3);
|
2014-03-16 18:04:29 -05:00
|
|
|
/// ```
|
2014-08-29 15:20:58 -05:00
|
|
|
#[stable]
|
2014-01-21 08:35:11 -06:00
|
|
|
pub fn shrink_to_fit(&mut self) {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
if mem::size_of::<T>() == 0 { return }
|
|
|
|
|
2014-01-21 08:35:11 -06:00
|
|
|
if self.len == 0 {
|
2014-05-06 16:01:16 -05:00
|
|
|
if self.cap != 0 {
|
|
|
|
unsafe {
|
2014-05-09 23:35:56 -05:00
|
|
|
dealloc(self.ptr, self.cap)
|
2014-05-06 16:01:16 -05:00
|
|
|
}
|
|
|
|
self.cap = 0;
|
|
|
|
}
|
2014-01-21 08:35:11 -06:00
|
|
|
} else {
|
|
|
|
unsafe {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
// Overflow check is unnecessary as the vector is already at
|
|
|
|
// least this large.
|
|
|
|
self.ptr = reallocate(self.ptr as *mut u8,
|
2014-10-07 23:57:29 -05:00
|
|
|
self.cap * mem::size_of::<T>(),
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
self.len * mem::size_of::<T>(),
|
2014-10-07 23:57:29 -05:00
|
|
|
mem::min_align_of::<T>()) as *mut T;
|
2014-10-28 16:06:06 -05:00
|
|
|
if self.ptr.is_null() { ::alloc::oom() }
|
2014-01-21 08:35:11 -06:00
|
|
|
}
|
|
|
|
self.cap = self.len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-10 04:18:42 -05:00
|
|
|
/// Convert the vector into Box<[T]>.
|
|
|
|
///
|
|
|
|
/// Note that this will drop any excess capacity. Calling this and converting back to a vector
|
|
|
|
/// with `into_vec()` is equivalent to calling `shrink_to_fit()`.
|
|
|
|
#[experimental]
|
|
|
|
pub fn into_boxed_slice(mut self) -> Box<[T]> {
|
|
|
|
self.shrink_to_fit();
|
|
|
|
unsafe {
|
|
|
|
let xs: Box<[T]> = mem::transmute(self.as_mut_slice());
|
|
|
|
mem::forget(self);
|
|
|
|
xs
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-16 18:04:29 -05:00
|
|
|
/// Shorten a vector, dropping excess elements.
|
|
|
|
///
|
|
|
|
/// If `len` is greater than the vector's current length, this has no
|
|
|
|
/// effect.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-07-22 03:33:26 -05:00
|
|
|
/// let mut vec = vec![1i, 2, 3, 4];
|
2014-03-16 18:04:29 -05:00
|
|
|
/// vec.truncate(2);
|
2014-07-22 03:33:26 -05:00
|
|
|
/// assert_eq!(vec, vec![1, 2]);
|
2014-03-16 18:04:29 -05:00
|
|
|
/// ```
|
2014-11-06 11:24:47 -06:00
|
|
|
#[unstable = "matches collection reform specification; waiting on panic semantics"]
|
2014-01-21 08:35:11 -06:00
|
|
|
pub fn truncate(&mut self, len: uint) {
|
|
|
|
unsafe {
|
|
|
|
// drop any extra elements
|
2014-05-14 16:57:27 -05:00
|
|
|
while len < self.len {
|
2014-10-09 14:17:22 -05:00
|
|
|
// decrement len before the read(), so a panic on Drop doesn't
|
2014-05-14 16:57:27 -05:00
|
|
|
// re-drop the just-failed value.
|
|
|
|
self.len -= 1;
|
2014-08-06 22:08:16 -05:00
|
|
|
ptr::read(self.as_slice().unsafe_get(self.len));
|
2014-01-21 08:35:11 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Returns a mutable slice of the elements of `self`.
|
2014-03-16 18:04:29 -05:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-03-16 18:04:29 -05:00
|
|
|
/// fn foo(slice: &mut [int]) {}
|
|
|
|
///
|
2014-07-22 03:33:26 -05:00
|
|
|
/// let mut vec = vec![1i, 2];
|
2014-03-16 18:04:29 -05:00
|
|
|
/// foo(vec.as_mut_slice());
|
|
|
|
/// ```
|
2014-01-21 08:35:11 -06:00
|
|
|
#[inline]
|
2014-08-29 15:20:58 -05:00
|
|
|
#[stable]
|
2014-01-21 08:35:11 -06:00
|
|
|
pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
|
2014-04-17 17:28:14 -05:00
|
|
|
unsafe {
|
2014-08-06 22:03:55 -05:00
|
|
|
mem::transmute(RawSlice {
|
2014-10-29 17:26:29 -05:00
|
|
|
data: self.ptr as *const T,
|
2014-06-25 14:47:34 -05:00
|
|
|
len: self.len,
|
|
|
|
})
|
2014-04-17 17:28:14 -05:00
|
|
|
}
|
2014-01-21 08:35:11 -06:00
|
|
|
}
|
|
|
|
|
2014-03-16 18:04:29 -05:00
|
|
|
/// Creates a consuming iterator, that is, one that moves each
|
|
|
|
/// value out of the vector (from start to end). The vector cannot
|
|
|
|
/// be used after calling this.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-07-22 03:33:26 -05:00
|
|
|
/// let v = vec!["a".to_string(), "b".to_string()];
|
2014-09-14 22:27:36 -05:00
|
|
|
/// for s in v.into_iter() {
|
2014-05-22 18:57:53 -05:00
|
|
|
/// // s has type String, not &String
|
2014-03-16 18:04:29 -05:00
|
|
|
/// println!("{}", s);
|
|
|
|
/// }
|
|
|
|
/// ```
|
2014-01-21 08:35:11 -06:00
|
|
|
#[inline]
|
2014-11-06 11:24:47 -06:00
|
|
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
2014-09-14 17:57:55 -05:00
|
|
|
pub fn into_iter(self) -> MoveItems<T> {
|
2014-01-21 08:35:11 -06:00
|
|
|
unsafe {
|
2014-05-09 23:35:56 -05:00
|
|
|
let ptr = self.ptr;
|
2014-05-06 16:01:16 -05:00
|
|
|
let cap = self.cap;
|
2014-09-04 14:25:23 -05:00
|
|
|
let begin = self.ptr as *const T;
|
2014-09-04 16:59:28 -05:00
|
|
|
let end = if mem::size_of::<T>() == 0 {
|
2014-10-02 13:06:31 -05:00
|
|
|
(ptr as uint + self.len()) as *const T
|
2014-09-04 16:59:28 -05:00
|
|
|
} else {
|
2014-10-02 13:06:31 -05:00
|
|
|
ptr.offset(self.len() as int) as *const T
|
2014-09-04 16:59:28 -05:00
|
|
|
};
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
mem::forget(self);
|
2014-09-04 14:25:23 -05:00
|
|
|
MoveItems { allocation: ptr, cap: cap, ptr: begin, end: end }
|
2014-01-21 08:35:11 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-16 18:04:29 -05:00
|
|
|
/// Sets the length of a vector.
|
|
|
|
///
|
|
|
|
/// This will explicitly set the size of the vector, without actually
|
|
|
|
/// modifying its buffers, so it is up to the caller to ensure that the
|
|
|
|
/// vector is actually the specified size.
|
2014-07-22 04:07:49 -05:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// let mut v = vec![1u, 2, 3, 4];
|
|
|
|
/// unsafe {
|
|
|
|
/// v.set_len(1);
|
|
|
|
/// }
|
|
|
|
/// ```
|
2014-01-21 08:35:11 -06:00
|
|
|
#[inline]
|
2014-08-29 15:20:58 -05:00
|
|
|
#[stable]
|
2014-01-21 08:35:11 -06:00
|
|
|
pub unsafe fn set_len(&mut self, len: uint) {
|
|
|
|
self.len = len;
|
|
|
|
}
|
2014-02-18 23:36:51 -06:00
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Removes an element from anywhere in the vector and return it, replacing
|
2014-03-16 18:04:29 -05:00
|
|
|
/// it with the last element. This does not preserve ordering, but is O(1).
|
|
|
|
///
|
|
|
|
/// Returns `None` if `index` is out of bounds.
|
|
|
|
///
|
|
|
|
/// # Example
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-11-07 06:04:32 -06:00
|
|
|
/// let mut v = vec!["foo", "bar", "baz", "qux"];
|
2014-03-16 18:04:29 -05:00
|
|
|
///
|
2014-11-07 06:04:32 -06:00
|
|
|
/// assert_eq!(v.swap_remove(1), Some("bar"));
|
|
|
|
/// assert_eq!(v, vec!["foo", "qux", "baz"]);
|
2014-03-16 18:04:29 -05:00
|
|
|
///
|
2014-11-07 06:04:32 -06:00
|
|
|
/// assert_eq!(v.swap_remove(0), Some("foo"));
|
|
|
|
/// assert_eq!(v, vec!["baz", "qux"]);
|
2014-03-16 18:04:29 -05:00
|
|
|
///
|
|
|
|
/// assert_eq!(v.swap_remove(2), None);
|
|
|
|
/// ```
|
2014-02-18 23:36:51 -06:00
|
|
|
#[inline]
|
2014-08-29 15:20:58 -05:00
|
|
|
#[unstable = "the naming of this function may be altered"]
|
2014-02-22 17:56:38 -06:00
|
|
|
pub fn swap_remove(&mut self, index: uint) -> Option<T> {
|
2014-02-18 23:36:51 -06:00
|
|
|
let length = self.len();
|
2014-08-02 13:36:51 -05:00
|
|
|
if length > 0 && index < length - 1 {
|
2014-02-18 23:36:51 -06:00
|
|
|
self.as_mut_slice().swap(index, length - 1);
|
2014-02-22 17:56:38 -06:00
|
|
|
} else if index >= length {
|
|
|
|
return None
|
2014-02-18 23:36:51 -06:00
|
|
|
}
|
2014-02-22 17:56:38 -06:00
|
|
|
self.pop()
|
2014-02-18 23:36:51 -06:00
|
|
|
}
|
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Inserts an element at position `index` within the vector, shifting all
|
|
|
|
/// elements after position `i` one position to the right.
|
2014-03-16 18:04:29 -05:00
|
|
|
///
|
2014-10-09 14:17:22 -05:00
|
|
|
/// # Panics
|
2014-03-16 18:04:29 -05:00
|
|
|
///
|
2014-10-09 14:17:22 -05:00
|
|
|
/// Panics if `index` is not between `0` and the vector's length (both
|
2014-06-27 03:51:56 -05:00
|
|
|
/// bounds inclusive).
|
2014-03-16 18:04:29 -05:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-07-22 03:33:26 -05:00
|
|
|
/// let mut vec = vec![1i, 2, 3];
|
2014-03-16 18:04:29 -05:00
|
|
|
/// vec.insert(1, 4);
|
2014-07-22 03:33:26 -05:00
|
|
|
/// assert_eq!(vec, vec![1, 4, 2, 3]);
|
2014-06-27 03:51:56 -05:00
|
|
|
/// vec.insert(4, 5);
|
2014-07-22 03:33:26 -05:00
|
|
|
/// assert_eq!(vec, vec![1, 4, 2, 3, 5]);
|
2014-03-16 18:04:29 -05:00
|
|
|
/// ```
|
2014-10-09 14:17:22 -05:00
|
|
|
#[unstable = "panic semantics need settling"]
|
2014-02-18 23:36:51 -06:00
|
|
|
pub fn insert(&mut self, index: uint, element: T) {
|
|
|
|
let len = self.len();
|
|
|
|
assert!(index <= len);
|
|
|
|
// space for the new element
|
2014-11-06 11:24:47 -06:00
|
|
|
self.reserve(1);
|
2014-02-18 23:36:51 -06:00
|
|
|
|
|
|
|
unsafe { // infallible
|
|
|
|
// The spot to put the new value
|
|
|
|
{
|
2014-03-16 16:20:44 -05:00
|
|
|
let p = self.as_mut_ptr().offset(index as int);
|
2014-02-18 23:36:51 -06:00
|
|
|
// Shift everything over to make space. (Duplicating the
|
|
|
|
// `index`th element into two consecutive places.)
|
|
|
|
ptr::copy_memory(p.offset(1), &*p, len - index);
|
|
|
|
// Write it in, overwriting the first copy of the `index`th
|
|
|
|
// element.
|
2014-05-29 21:03:06 -05:00
|
|
|
ptr::write(&mut *p, element);
|
2014-02-18 23:36:51 -06:00
|
|
|
}
|
|
|
|
self.set_len(len + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Removes and returns the element at position `index` within the vector,
|
2014-03-16 18:04:29 -05:00
|
|
|
/// shifting all elements after position `index` one position to the left.
|
|
|
|
/// Returns `None` if `i` is out of bounds.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-07-22 03:33:26 -05:00
|
|
|
/// let mut v = vec![1i, 2, 3];
|
2014-03-16 18:04:29 -05:00
|
|
|
/// assert_eq!(v.remove(1), Some(2));
|
2014-07-22 03:33:26 -05:00
|
|
|
/// assert_eq!(v, vec![1, 3]);
|
2014-03-16 18:04:29 -05:00
|
|
|
///
|
|
|
|
/// assert_eq!(v.remove(4), None);
|
|
|
|
/// // v is unchanged:
|
2014-07-22 03:33:26 -05:00
|
|
|
/// assert_eq!(v, vec![1, 3]);
|
2014-03-16 18:04:29 -05:00
|
|
|
/// ```
|
2014-10-09 14:17:22 -05:00
|
|
|
#[unstable = "panic semantics need settling"]
|
2014-03-18 11:53:32 -05:00
|
|
|
pub fn remove(&mut self, index: uint) -> Option<T> {
|
2014-03-10 23:53:23 -05:00
|
|
|
let len = self.len();
|
|
|
|
if index < len {
|
|
|
|
unsafe { // infallible
|
|
|
|
let ret;
|
|
|
|
{
|
|
|
|
// the place we are taking from.
|
2014-03-16 16:20:44 -05:00
|
|
|
let ptr = self.as_mut_ptr().offset(index as int);
|
2014-03-10 23:53:23 -05:00
|
|
|
// copy it out, unsafely having a copy of the value on
|
|
|
|
// the stack and in the vector at the same time.
|
2014-06-25 14:47:34 -05:00
|
|
|
ret = Some(ptr::read(ptr as *const T));
|
2014-03-10 23:53:23 -05:00
|
|
|
|
|
|
|
// Shift everything down to fill in that spot.
|
|
|
|
ptr::copy_memory(ptr, &*ptr.offset(1), len - index - 1);
|
|
|
|
}
|
|
|
|
self.set_len(len - 1);
|
|
|
|
ret
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-02 22:10:36 -05:00
|
|
|
/// Retains only the elements specified by the predicate.
|
|
|
|
///
|
|
|
|
/// In other words, remove all elements `e` such that `f(&e)` returns false.
|
2014-08-07 10:27:06 -05:00
|
|
|
/// This method operates in place and preserves the order of the retained elements.
|
2014-04-02 22:10:36 -05:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-07-22 03:33:26 -05:00
|
|
|
/// let mut vec = vec![1i, 2, 3, 4];
|
2014-10-31 04:40:15 -05:00
|
|
|
/// vec.retain(|&x| x%2 == 0);
|
2014-07-22 03:33:26 -05:00
|
|
|
/// assert_eq!(vec, vec![2, 4]);
|
2014-04-02 22:10:36 -05:00
|
|
|
/// ```
|
2014-08-29 15:20:58 -05:00
|
|
|
#[unstable = "the closure argument may become an unboxed closure"]
|
2014-04-02 22:10:36 -05:00
|
|
|
pub fn retain(&mut self, f: |&T| -> bool) {
|
|
|
|
let len = self.len();
|
|
|
|
let mut del = 0u;
|
|
|
|
{
|
|
|
|
let v = self.as_mut_slice();
|
|
|
|
|
|
|
|
for i in range(0u, len) {
|
|
|
|
if !f(&v[i]) {
|
|
|
|
del += 1;
|
|
|
|
} else if del > 0 {
|
|
|
|
v.swap(i-del, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if del > 0 {
|
|
|
|
self.truncate(len - del);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Expands a vector in place, initializing the new elements to the result of a function.
|
|
|
|
///
|
|
|
|
/// The vector is grown by `n` elements. The i-th new element are initialized to the value
|
|
|
|
/// returned by `f(i)` where `i` is in the range [0, n).
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-07-22 03:33:26 -05:00
|
|
|
/// let mut vec = vec![0u, 1];
|
2014-04-02 22:10:36 -05:00
|
|
|
/// vec.grow_fn(3, |i| i);
|
2014-07-22 03:33:26 -05:00
|
|
|
/// assert_eq!(vec, vec![0, 1, 0, 1, 2]);
|
2014-04-02 22:10:36 -05:00
|
|
|
/// ```
|
2014-08-29 15:20:58 -05:00
|
|
|
#[unstable = "this function may be renamed or change to unboxed closures"]
|
2014-04-02 22:10:36 -05:00
|
|
|
pub fn grow_fn(&mut self, n: uint, f: |uint| -> T) {
|
2014-11-06 11:24:47 -06:00
|
|
|
self.reserve(n);
|
2014-04-02 22:10:36 -05:00
|
|
|
for i in range(0u, n) {
|
|
|
|
self.push(f(i));
|
|
|
|
}
|
|
|
|
}
|
2014-03-04 12:39:49 -06:00
|
|
|
|
2014-10-30 15:43:24 -05:00
|
|
|
/// Appends an element to the back of a collection.
|
|
|
|
///
|
2014-11-11 12:36:09 -06:00
|
|
|
/// # Panics
|
2014-10-30 15:43:24 -05:00
|
|
|
///
|
2014-11-11 12:36:09 -06:00
|
|
|
/// Panics if the number of elements in the vector overflows a `uint`.
|
2014-10-30 15:43:24 -05:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// let mut vec = vec!(1i, 2);
|
|
|
|
/// vec.push(3);
|
|
|
|
/// assert_eq!(vec, vec!(1, 2, 3));
|
|
|
|
/// ```
|
|
|
|
#[inline]
|
|
|
|
#[stable]
|
|
|
|
pub fn push(&mut self, value: T) {
|
|
|
|
if mem::size_of::<T>() == 0 {
|
|
|
|
// zero-size types consume no memory, so we can't rely on the address space running out
|
2014-11-09 07:11:28 -06:00
|
|
|
self.len = self.len.checked_add(1).expect("length overflow");
|
2014-10-30 15:43:24 -05:00
|
|
|
unsafe { mem::forget(value); }
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if self.len == self.cap {
|
|
|
|
let old_size = self.cap * mem::size_of::<T>();
|
|
|
|
let size = max(old_size, 2 * mem::size_of::<T>()) * 2;
|
|
|
|
if old_size > size { panic!("capacity overflow") }
|
|
|
|
unsafe {
|
|
|
|
self.ptr = alloc_or_realloc(self.ptr, old_size, size);
|
2014-10-28 16:06:06 -05:00
|
|
|
if self.ptr.is_null() { ::alloc::oom() }
|
2014-10-30 15:43:24 -05:00
|
|
|
}
|
|
|
|
self.cap = max(self.cap, 2) * 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
let end = (self.ptr as *const T).offset(self.len as int) as *mut T;
|
|
|
|
ptr::write(&mut *end, value);
|
|
|
|
self.len += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Removes the last element from a vector and returns it, or `None` if
|
|
|
|
/// it is empty.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// let mut vec = vec![1i, 2, 3];
|
|
|
|
/// assert_eq!(vec.pop(), Some(3));
|
|
|
|
/// assert_eq!(vec, vec![1, 2]);
|
|
|
|
/// ```
|
2014-03-04 12:39:49 -06:00
|
|
|
#[inline]
|
2014-08-29 15:20:58 -05:00
|
|
|
#[stable]
|
2014-10-30 15:43:24 -05:00
|
|
|
pub fn pop(&mut self) -> Option<T> {
|
|
|
|
if self.len == 0 {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
unsafe {
|
|
|
|
self.len -= 1;
|
|
|
|
Some(ptr::read(self.as_slice().unsafe_get(self.len())))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Clears the vector, removing all values.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// let mut v = vec![1i, 2, 3];
|
|
|
|
/// v.clear();
|
|
|
|
/// assert!(v.is_empty());
|
|
|
|
/// ```
|
|
|
|
#[inline]
|
|
|
|
#[stable]
|
|
|
|
pub fn clear(&mut self) {
|
2014-03-04 12:39:49 -06:00
|
|
|
self.truncate(0)
|
|
|
|
}
|
2014-10-30 15:43:24 -05:00
|
|
|
|
|
|
|
/// Return the number of elements in the vector
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// let a = vec![1i, 2, 3];
|
|
|
|
/// assert_eq!(a.len(), 3);
|
|
|
|
/// ```
|
|
|
|
#[inline]
|
|
|
|
#[stable]
|
|
|
|
pub fn len(&self) -> uint { self.len }
|
|
|
|
|
|
|
|
/// Returns true if the vector contains no elements
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// let mut v = Vec::new();
|
|
|
|
/// assert!(v.is_empty());
|
|
|
|
/// v.push(1i);
|
|
|
|
/// assert!(!v.is_empty());
|
|
|
|
/// ```
|
2014-11-06 11:24:47 -06:00
|
|
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
2014-10-30 15:43:24 -05:00
|
|
|
pub fn is_empty(&self) -> bool { self.len() == 0 }
|
2014-11-06 11:24:47 -06:00
|
|
|
|
|
|
|
/// Reserves capacity for exactly `capacity` elements in the given vector.
|
|
|
|
///
|
|
|
|
/// If the capacity for `self` is already equal to or greater than the
|
|
|
|
/// requested capacity, then no action is taken.
|
|
|
|
fn grow_capacity(&mut self, capacity: uint) {
|
|
|
|
if mem::size_of::<T>() == 0 { return }
|
|
|
|
|
|
|
|
if capacity > self.cap {
|
2014-11-09 07:11:28 -06:00
|
|
|
let size = capacity.checked_mul(mem::size_of::<T>())
|
2014-11-06 11:24:47 -06:00
|
|
|
.expect("capacity overflow");
|
|
|
|
unsafe {
|
|
|
|
self.ptr = alloc_or_realloc(self.ptr, self.cap * mem::size_of::<T>(), size);
|
|
|
|
if self.ptr.is_null() { ::alloc::oom() }
|
|
|
|
}
|
|
|
|
self.cap = capacity;
|
|
|
|
}
|
|
|
|
}
|
2014-02-28 14:55:51 -06:00
|
|
|
}
|
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
impl<T: PartialEq> Vec<T> {
|
|
|
|
/// Removes consecutive repeated elements in the vector.
|
2014-03-16 18:04:29 -05:00
|
|
|
///
|
|
|
|
/// If the vector is sorted, this removes all duplicates.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-07-22 03:33:26 -05:00
|
|
|
/// let mut vec = vec![1i, 2, 2, 3, 2];
|
2014-03-16 18:04:29 -05:00
|
|
|
/// vec.dedup();
|
2014-07-22 03:33:26 -05:00
|
|
|
/// assert_eq!(vec, vec![1i, 2, 3, 2]);
|
2014-03-16 18:04:29 -05:00
|
|
|
/// ```
|
2014-08-29 15:20:58 -05:00
|
|
|
#[unstable = "this function may be renamed"]
|
2014-03-04 12:39:49 -06:00
|
|
|
pub fn dedup(&mut self) {
|
|
|
|
unsafe {
|
|
|
|
// Although we have a mutable reference to `self`, we cannot make
|
2014-10-09 14:17:22 -05:00
|
|
|
// *arbitrary* changes. The `PartialEq` comparisons could panic, so we
|
2014-03-04 12:39:49 -06:00
|
|
|
// must ensure that the vector is in a valid state at all time.
|
|
|
|
//
|
|
|
|
// The way that we handle this is by using swaps; we iterate
|
|
|
|
// over all the elements, swapping as we go so that at the end
|
|
|
|
// the elements we wish to keep are in the front, and those we
|
|
|
|
// wish to reject are at the back. We can then truncate the
|
|
|
|
// vector. This operation is still O(n).
|
|
|
|
//
|
|
|
|
// Example: We start in this state, where `r` represents "next
|
|
|
|
// read" and `w` represents "next_write`.
|
|
|
|
//
|
|
|
|
// r
|
|
|
|
// +---+---+---+---+---+---+
|
|
|
|
// | 0 | 1 | 1 | 2 | 3 | 3 |
|
|
|
|
// +---+---+---+---+---+---+
|
|
|
|
// w
|
|
|
|
//
|
2014-04-28 08:39:11 -05:00
|
|
|
// Comparing self[r] against self[w-1], this is not a duplicate, so
|
2014-03-04 12:39:49 -06:00
|
|
|
// we swap self[r] and self[w] (no effect as r==w) and then increment both
|
|
|
|
// r and w, leaving us with:
|
|
|
|
//
|
|
|
|
// r
|
|
|
|
// +---+---+---+---+---+---+
|
|
|
|
// | 0 | 1 | 1 | 2 | 3 | 3 |
|
|
|
|
// +---+---+---+---+---+---+
|
|
|
|
// w
|
|
|
|
//
|
|
|
|
// Comparing self[r] against self[w-1], this value is a duplicate,
|
|
|
|
// so we increment `r` but leave everything else unchanged:
|
|
|
|
//
|
|
|
|
// r
|
|
|
|
// +---+---+---+---+---+---+
|
|
|
|
// | 0 | 1 | 1 | 2 | 3 | 3 |
|
|
|
|
// +---+---+---+---+---+---+
|
|
|
|
// w
|
|
|
|
//
|
|
|
|
// Comparing self[r] against self[w-1], this is not a duplicate,
|
|
|
|
// so swap self[r] and self[w] and advance r and w:
|
|
|
|
//
|
|
|
|
// r
|
|
|
|
// +---+---+---+---+---+---+
|
|
|
|
// | 0 | 1 | 2 | 1 | 3 | 3 |
|
|
|
|
// +---+---+---+---+---+---+
|
|
|
|
// w
|
|
|
|
//
|
|
|
|
// Not a duplicate, repeat:
|
|
|
|
//
|
|
|
|
// r
|
|
|
|
// +---+---+---+---+---+---+
|
|
|
|
// | 0 | 1 | 2 | 3 | 1 | 3 |
|
|
|
|
// +---+---+---+---+---+---+
|
|
|
|
// w
|
|
|
|
//
|
|
|
|
// Duplicate, advance r. End of vec. Truncate to w.
|
|
|
|
|
|
|
|
let ln = self.len();
|
|
|
|
if ln < 1 { return; }
|
|
|
|
|
|
|
|
// Avoid bounds checks by using unsafe pointers.
|
|
|
|
let p = self.as_mut_slice().as_mut_ptr();
|
|
|
|
let mut r = 1;
|
|
|
|
let mut w = 1;
|
|
|
|
|
|
|
|
while r < ln {
|
|
|
|
let p_r = p.offset(r as int);
|
|
|
|
let p_wm1 = p.offset((w - 1) as int);
|
|
|
|
if *p_r != *p_wm1 {
|
|
|
|
if r != w {
|
|
|
|
let p_w = p_wm1.offset(1);
|
|
|
|
mem::swap(&mut *p_r, &mut *p_w);
|
|
|
|
}
|
|
|
|
w += 1;
|
|
|
|
}
|
|
|
|
r += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.truncate(w);
|
|
|
|
}
|
|
|
|
}
|
2014-01-21 08:35:11 -06:00
|
|
|
}
|
|
|
|
|
2014-10-04 18:22:42 -05:00
|
|
|
impl<T> AsSlice<T> for Vec<T> {
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Returns a slice into `self`.
|
2014-03-06 12:22:21 -06:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2014-07-22 07:02:55 -05:00
|
|
|
/// ```
|
2014-03-06 12:22:21 -06:00
|
|
|
/// fn foo(slice: &[int]) {}
|
|
|
|
///
|
2014-07-22 03:33:26 -05:00
|
|
|
/// let vec = vec![1i, 2];
|
2014-03-06 12:22:21 -06:00
|
|
|
/// foo(vec.as_slice());
|
|
|
|
/// ```
|
|
|
|
#[inline]
|
2014-08-29 15:20:58 -05:00
|
|
|
#[stable]
|
2014-03-06 12:22:21 -06:00
|
|
|
fn as_slice<'a>(&'a self) -> &'a [T] {
|
2014-10-29 17:26:29 -05:00
|
|
|
unsafe {
|
|
|
|
mem::transmute(RawSlice {
|
|
|
|
data: self.ptr as *const T,
|
|
|
|
len: self.len
|
|
|
|
})
|
|
|
|
}
|
2014-03-06 12:22:21 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-04 18:22:42 -05:00
|
|
|
impl<T: Clone, V: AsSlice<T>> Add<V, Vec<T>> for Vec<T> {
|
2014-05-04 01:09:45 -05:00
|
|
|
#[inline]
|
|
|
|
fn add(&self, rhs: &V) -> Vec<T> {
|
|
|
|
let mut res = Vec::with_capacity(self.len() + rhs.as_slice().len());
|
|
|
|
res.push_all(self.as_slice());
|
|
|
|
res.push_all(rhs.as_slice());
|
|
|
|
res
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-21 08:35:11 -06:00
|
|
|
#[unsafe_destructor]
|
|
|
|
impl<T> Drop for Vec<T> {
|
|
|
|
fn drop(&mut self) {
|
2014-03-12 15:01:33 -05:00
|
|
|
// This is (and should always remain) a no-op if the fields are
|
|
|
|
// zeroed (when moving out, because of #[unsafe_no_drop_flag]).
|
2014-05-06 16:01:16 -05:00
|
|
|
if self.cap != 0 {
|
|
|
|
unsafe {
|
|
|
|
for x in self.as_mut_slice().iter() {
|
|
|
|
ptr::read(x);
|
|
|
|
}
|
2014-05-09 23:35:56 -05:00
|
|
|
dealloc(self.ptr, self.cap)
|
2014-01-21 08:35:11 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-29 15:20:58 -05:00
|
|
|
#[stable]
|
2014-02-28 14:55:51 -06:00
|
|
|
impl<T> Default for Vec<T> {
|
|
|
|
fn default() -> Vec<T> {
|
|
|
|
Vec::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-29 15:20:58 -05:00
|
|
|
#[experimental = "waiting on Show stability"]
|
2014-02-28 14:54:01 -06:00
|
|
|
impl<T:fmt::Show> fmt::Show for Vec<T> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
self.as_slice().fmt(f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-16 18:04:29 -05:00
|
|
|
/// An iterator that moves out of a vector.
|
2014-01-21 08:35:11 -06:00
|
|
|
pub struct MoveItems<T> {
|
2014-05-09 23:35:56 -05:00
|
|
|
allocation: *mut T, // the block of memory allocated for the vector
|
2014-05-06 16:01:16 -05:00
|
|
|
cap: uint, // the capacity of the vector
|
2014-09-04 14:25:23 -05:00
|
|
|
ptr: *const T,
|
|
|
|
end: *const T
|
2014-01-21 08:35:11 -06:00
|
|
|
}
|
|
|
|
|
2014-08-31 08:29:22 -05:00
|
|
|
impl<T> MoveItems<T> {
|
|
|
|
#[inline]
|
|
|
|
/// Drops all items that have not yet been moved and returns the empty vector.
|
|
|
|
pub fn unwrap(mut self) -> Vec<T> {
|
|
|
|
unsafe {
|
|
|
|
for _x in self { }
|
2014-10-02 13:06:31 -05:00
|
|
|
let MoveItems { allocation, cap, ptr: _ptr, end: _end } = self;
|
2014-08-31 08:29:22 -05:00
|
|
|
mem::forget(self);
|
|
|
|
Vec { ptr: allocation, cap: cap, len: 0 }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-21 08:35:11 -06:00
|
|
|
impl<T> Iterator<T> for MoveItems<T> {
|
|
|
|
#[inline]
|
2014-08-27 20:46:52 -05:00
|
|
|
fn next<'a>(&'a mut self) -> Option<T> {
|
2014-01-21 08:35:11 -06:00
|
|
|
unsafe {
|
2014-09-04 14:25:23 -05:00
|
|
|
if self.ptr == self.end {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
if mem::size_of::<T>() == 0 {
|
|
|
|
// purposefully don't use 'ptr.offset' because for
|
|
|
|
// vectors with 0-size elements this would return the
|
|
|
|
// same pointer.
|
|
|
|
self.ptr = mem::transmute(self.ptr as uint + 1);
|
|
|
|
|
|
|
|
// Use a non-null pointer value
|
|
|
|
Some(ptr::read(mem::transmute(1u)))
|
|
|
|
} else {
|
|
|
|
let old = self.ptr;
|
|
|
|
self.ptr = self.ptr.offset(1);
|
|
|
|
|
|
|
|
Some(ptr::read(old))
|
|
|
|
}
|
|
|
|
}
|
2014-01-21 08:35:11 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn size_hint(&self) -> (uint, Option<uint>) {
|
2014-09-04 14:25:23 -05:00
|
|
|
let diff = (self.end as uint) - (self.ptr as uint);
|
|
|
|
let size = mem::size_of::<T>();
|
|
|
|
let exact = diff / (if size == 0 {1} else {size});
|
|
|
|
(exact, Some(exact))
|
2014-01-21 08:35:11 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> DoubleEndedIterator<T> for MoveItems<T> {
|
|
|
|
#[inline]
|
2014-08-27 20:46:52 -05:00
|
|
|
fn next_back<'a>(&'a mut self) -> Option<T> {
|
2014-01-21 08:35:11 -06:00
|
|
|
unsafe {
|
2014-09-04 14:25:23 -05:00
|
|
|
if self.end == self.ptr {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
if mem::size_of::<T>() == 0 {
|
|
|
|
// See above for why 'ptr.offset' isn't used
|
|
|
|
self.end = mem::transmute(self.end as uint - 1);
|
|
|
|
|
|
|
|
// Use a non-null pointer value
|
|
|
|
Some(ptr::read(mem::transmute(1u)))
|
|
|
|
} else {
|
|
|
|
self.end = self.end.offset(-1);
|
|
|
|
|
|
|
|
Some(ptr::read(mem::transmute(self.end)))
|
|
|
|
}
|
|
|
|
}
|
2014-01-21 08:35:11 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-14 22:25:08 -05:00
|
|
|
impl<T> ExactSize<T> for MoveItems<T> {}
|
|
|
|
|
2014-01-21 08:35:11 -06:00
|
|
|
#[unsafe_destructor]
|
|
|
|
impl<T> Drop for MoveItems<T> {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
// destroy the remaining elements
|
2014-05-06 16:01:16 -05:00
|
|
|
if self.cap != 0 {
|
|
|
|
for _x in *self {}
|
|
|
|
unsafe {
|
2014-05-09 23:35:56 -05:00
|
|
|
dealloc(self.allocation, self.cap);
|
2014-05-06 16:01:16 -05:00
|
|
|
}
|
2014-01-21 08:35:11 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-03-03 14:46:24 -06:00
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Converts an iterator of pairs into a pair of vectors.
|
|
|
|
///
|
|
|
|
/// Returns a tuple containing two vectors where the i-th element of the first
|
|
|
|
/// vector contains the first element of the i-th tuple of the input iterator,
|
|
|
|
/// and the i-th element of the second vector contains the second element
|
|
|
|
/// of the i-th tuple of the input iterator.
|
2014-08-29 15:20:58 -05:00
|
|
|
#[unstable = "this functionality may become more generic over time"]
|
2014-05-03 20:10:04 -05:00
|
|
|
pub fn unzip<T, U, V: Iterator<(T, U)>>(mut iter: V) -> (Vec<T>, Vec<U>) {
|
|
|
|
let (lo, _) = iter.size_hint();
|
|
|
|
let mut ts = Vec::with_capacity(lo);
|
|
|
|
let mut us = Vec::with_capacity(lo);
|
|
|
|
for (t, u) in iter {
|
|
|
|
ts.push(t);
|
|
|
|
us.push(u);
|
|
|
|
}
|
|
|
|
(ts, us)
|
|
|
|
}
|
|
|
|
|
2014-08-23 19:26:53 -05:00
|
|
|
/// Wrapper type providing a `&Vec<T>` reference via `Deref`.
|
|
|
|
#[experimental]
|
|
|
|
pub struct DerefVec<'a, T> {
|
|
|
|
x: Vec<T>,
|
|
|
|
l: ContravariantLifetime<'a>
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, T> Deref<Vec<T>> for DerefVec<'a, T> {
|
|
|
|
fn deref<'b>(&'b self) -> &'b Vec<T> {
|
|
|
|
&self.x
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Prevent the inner `Vec<T>` from attempting to deallocate memory.
|
|
|
|
#[unsafe_destructor]
|
|
|
|
impl<'a, T> Drop for DerefVec<'a, T> {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
self.x.len = 0;
|
|
|
|
self.x.cap = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Convert a slice to a wrapper type providing a `&Vec<T>` reference.
|
|
|
|
#[experimental]
|
|
|
|
pub fn as_vec<'a, T>(x: &'a [T]) -> DerefVec<'a, T> {
|
|
|
|
unsafe {
|
|
|
|
DerefVec {
|
2014-10-24 21:31:17 -05:00
|
|
|
x: Vec::from_raw_parts(x.as_ptr() as *mut T, x.len(), x.len()),
|
2014-08-23 19:26:53 -05:00
|
|
|
l: ContravariantLifetime::<'a>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-04 05:48:39 -05:00
|
|
|
/// Unsafe vector operations.
|
2014-08-29 15:20:58 -05:00
|
|
|
#[unstable]
|
2014-05-03 20:20:35 -05:00
|
|
|
pub mod raw {
|
|
|
|
use super::Vec;
|
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::ptr;
|
2014-11-02 19:04:32 -06:00
|
|
|
use core::slice::SlicePrelude;
|
2014-05-03 20:20:35 -05:00
|
|
|
|
|
|
|
/// Constructs a vector from an unsafe pointer to a buffer.
|
|
|
|
///
|
|
|
|
/// The elements of the buffer are copied into the vector without cloning,
|
|
|
|
/// as if `ptr::read()` were called on them.
|
|
|
|
#[inline]
|
2014-08-29 15:20:58 -05:00
|
|
|
#[unstable]
|
2014-06-25 14:47:34 -05:00
|
|
|
pub unsafe fn from_buf<T>(ptr: *const T, elts: uint) -> Vec<T> {
|
2014-05-03 20:20:35 -05:00
|
|
|
let mut dst = Vec::with_capacity(elts);
|
|
|
|
dst.set_len(elts);
|
|
|
|
ptr::copy_nonoverlapping_memory(dst.as_mut_ptr(), ptr, elts);
|
|
|
|
dst
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-18 18:38:50 -05:00
|
|
|
/// An owned, partially type-converted vector of elements with non-zero size.
|
2014-07-01 08:10:22 -05:00
|
|
|
///
|
2014-09-18 18:38:50 -05:00
|
|
|
/// `T` and `U` must have the same, non-zero size. They must also have the same
|
|
|
|
/// alignment.
|
2014-08-03 07:16:10 -05:00
|
|
|
///
|
2014-09-18 18:38:50 -05:00
|
|
|
/// When the destructor of this struct runs, all `U`s from `start_u` (incl.) to
|
|
|
|
/// `end_u` (excl.) and all `T`s from `start_t` (incl.) to `end_t` (excl.) are
|
|
|
|
/// destructed. Additionally the underlying storage of `vec` will be freed.
|
|
|
|
struct PartialVecNonZeroSized<T,U> {
|
2014-07-01 08:10:22 -05:00
|
|
|
vec: Vec<T>,
|
|
|
|
|
|
|
|
start_u: *mut U,
|
|
|
|
end_u: *mut U,
|
|
|
|
start_t: *mut T,
|
|
|
|
end_t: *mut T,
|
|
|
|
}
|
|
|
|
|
2014-09-18 18:38:50 -05:00
|
|
|
/// An owned, partially type-converted vector of zero-sized elements.
|
|
|
|
///
|
|
|
|
/// When the destructor of this struct runs, all `num_t` `T`s and `num_u` `U`s
|
|
|
|
/// are destructed.
|
|
|
|
struct PartialVecZeroSized<T,U> {
|
|
|
|
num_t: uint,
|
|
|
|
num_u: uint,
|
|
|
|
marker_t: InvariantType<T>,
|
|
|
|
marker_u: InvariantType<U>,
|
2014-07-01 08:10:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[unsafe_destructor]
|
2014-09-18 18:38:50 -05:00
|
|
|
impl<T,U> Drop for PartialVecNonZeroSized<T,U> {
|
2014-07-01 08:10:22 -05:00
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe {
|
2014-09-18 18:38:50 -05:00
|
|
|
// `vec` hasn't been modified until now. As it has a length
|
|
|
|
// currently, this would run destructors of `T`s which might not be
|
|
|
|
// there. So at first, set `vec`s length to `0`. This must be done
|
|
|
|
// at first to remain memory-safe as the destructors of `U` or `T`
|
|
|
|
// might cause unwinding where `vec`s destructor would be executed.
|
2014-07-01 08:10:22 -05:00
|
|
|
self.vec.set_len(0);
|
|
|
|
|
2014-09-18 18:38:50 -05:00
|
|
|
// We have instances of `U`s and `T`s in `vec`. Destruct them.
|
|
|
|
while self.start_u != self.end_u {
|
2014-07-01 08:10:22 -05:00
|
|
|
let _ = ptr::read(self.start_u as *const U); // Run a `U` destructor.
|
|
|
|
self.start_u = self.start_u.offset(1);
|
|
|
|
}
|
2014-09-18 18:38:50 -05:00
|
|
|
while self.start_t != self.end_t {
|
2014-07-01 08:10:22 -05:00
|
|
|
let _ = ptr::read(self.start_t as *const T); // Run a `T` destructor.
|
|
|
|
self.start_t = self.start_t.offset(1);
|
|
|
|
}
|
|
|
|
// After this destructor ran, the destructor of `vec` will run,
|
|
|
|
// deallocating the underlying memory.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-18 18:38:50 -05:00
|
|
|
#[unsafe_destructor]
|
|
|
|
impl<T,U> Drop for PartialVecZeroSized<T,U> {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe {
|
|
|
|
// Destruct the instances of `T` and `U` this struct owns.
|
|
|
|
while self.num_t != 0 {
|
|
|
|
let _: T = mem::uninitialized(); // Run a `T` destructor.
|
|
|
|
self.num_t -= 1;
|
|
|
|
}
|
|
|
|
while self.num_u != 0 {
|
|
|
|
let _: U = mem::uninitialized(); // Run a `U` destructor.
|
|
|
|
self.num_u -= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-01 08:10:22 -05:00
|
|
|
impl<T> Vec<T> {
|
2014-08-03 07:16:10 -05:00
|
|
|
/// Converts a `Vec<T>` to a `Vec<U>` where `T` and `U` have the same
|
2014-09-18 18:38:50 -05:00
|
|
|
/// size and in case they are not zero-sized the same minimal alignment.
|
2014-08-03 07:16:10 -05:00
|
|
|
///
|
2014-11-11 12:36:09 -06:00
|
|
|
/// # Panics
|
2014-08-03 07:16:10 -05:00
|
|
|
///
|
2014-11-11 12:36:09 -06:00
|
|
|
/// Panics if `T` and `U` have differing sizes or are not zero-sized and
|
2014-09-18 18:38:50 -05:00
|
|
|
/// have differing minimal alignments.
|
2014-07-01 08:10:22 -05:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2014-09-10 19:04:51 -05:00
|
|
|
/// ```
|
2014-07-01 08:10:22 -05:00
|
|
|
/// let v = vec![0u, 1, 2];
|
2014-09-10 19:04:51 -05:00
|
|
|
/// let w = v.map_in_place(|i| i + 3);
|
2014-09-14 14:33:48 -05:00
|
|
|
/// assert_eq!(w.as_slice(), [3, 4, 5].as_slice());
|
2014-07-01 08:10:22 -05:00
|
|
|
///
|
2014-09-14 14:33:48 -05:00
|
|
|
/// #[deriving(PartialEq, Show)]
|
|
|
|
/// struct Newtype(u8);
|
|
|
|
/// let bytes = vec![0x11, 0x22];
|
|
|
|
/// let newtyped_bytes = bytes.map_in_place(|x| Newtype(x));
|
|
|
|
/// assert_eq!(newtyped_bytes.as_slice(), [Newtype(0x11), Newtype(0x22)].as_slice());
|
2014-07-01 08:10:22 -05:00
|
|
|
/// ```
|
2014-09-10 19:04:51 -05:00
|
|
|
pub fn map_in_place<U>(self, f: |T| -> U) -> Vec<U> {
|
2014-09-18 18:38:50 -05:00
|
|
|
// FIXME: Assert statically that the types `T` and `U` have the same
|
|
|
|
// size.
|
|
|
|
assert!(mem::size_of::<T>() == mem::size_of::<U>());
|
|
|
|
|
|
|
|
let mut vec = self;
|
|
|
|
|
|
|
|
if mem::size_of::<T>() != 0 {
|
|
|
|
// FIXME: Assert statically that the types `T` and `U` have the
|
|
|
|
// same minimal alignment in case they are not zero-sized.
|
|
|
|
|
|
|
|
// These asserts are necessary because the `min_align_of` of the
|
|
|
|
// types are passed to the allocator by `Vec`.
|
|
|
|
assert!(mem::min_align_of::<T>() == mem::min_align_of::<U>());
|
|
|
|
|
|
|
|
// This `as int` cast is safe, because the size of the elements of the
|
|
|
|
// vector is not 0, and:
|
|
|
|
//
|
|
|
|
// 1) If the size of the elements in the vector is 1, the `int` may
|
|
|
|
// overflow, but it has the correct bit pattern so that the
|
|
|
|
// `.offset()` function will work.
|
|
|
|
//
|
|
|
|
// Example:
|
|
|
|
// Address space 0x0-0xF.
|
|
|
|
// `u8` array at: 0x1.
|
|
|
|
// Size of `u8` array: 0x8.
|
|
|
|
// Calculated `offset`: -0x8.
|
|
|
|
// After `array.offset(offset)`: 0x9.
|
|
|
|
// (0x1 + 0x8 = 0x1 - 0x8)
|
|
|
|
//
|
|
|
|
// 2) If the size of the elements in the vector is >1, the `uint` ->
|
|
|
|
// `int` conversion can't overflow.
|
|
|
|
let offset = vec.len() as int;
|
|
|
|
let start = vec.as_mut_ptr();
|
|
|
|
|
|
|
|
let mut pv = PartialVecNonZeroSized {
|
|
|
|
vec: vec,
|
|
|
|
|
|
|
|
start_t: start,
|
|
|
|
// This points inside the vector, as the vector has length
|
|
|
|
// `offset`.
|
|
|
|
end_t: unsafe { start.offset(offset) },
|
|
|
|
start_u: start as *mut U,
|
|
|
|
end_u: start as *mut U,
|
|
|
|
};
|
|
|
|
// start_t
|
|
|
|
// start_u
|
|
|
|
// |
|
|
|
|
// +-+-+-+-+-+-+
|
|
|
|
// |T|T|T|...|T|
|
|
|
|
// +-+-+-+-+-+-+
|
|
|
|
// | |
|
|
|
|
// end_u end_t
|
|
|
|
|
|
|
|
while pv.end_u as *mut T != pv.end_t {
|
|
|
|
unsafe {
|
|
|
|
// start_u start_t
|
|
|
|
// | |
|
|
|
|
// +-+-+-+-+-+-+-+-+-+
|
|
|
|
// |U|...|U|T|T|...|T|
|
|
|
|
// +-+-+-+-+-+-+-+-+-+
|
|
|
|
// | |
|
|
|
|
// end_u end_t
|
|
|
|
|
|
|
|
let t = ptr::read(pv.start_t as *const T);
|
|
|
|
// start_u start_t
|
|
|
|
// | |
|
|
|
|
// +-+-+-+-+-+-+-+-+-+
|
|
|
|
// |U|...|U|X|T|...|T|
|
|
|
|
// +-+-+-+-+-+-+-+-+-+
|
|
|
|
// | |
|
|
|
|
// end_u end_t
|
2014-10-09 14:17:22 -05:00
|
|
|
// We must not panic here, one cell is marked as `T`
|
2014-09-18 18:38:50 -05:00
|
|
|
// although it is not `T`.
|
|
|
|
|
|
|
|
pv.start_t = pv.start_t.offset(1);
|
|
|
|
// start_u start_t
|
|
|
|
// | |
|
|
|
|
// +-+-+-+-+-+-+-+-+-+
|
|
|
|
// |U|...|U|X|T|...|T|
|
|
|
|
// +-+-+-+-+-+-+-+-+-+
|
|
|
|
// | |
|
|
|
|
// end_u end_t
|
2014-10-09 14:17:22 -05:00
|
|
|
// We may panic again.
|
2014-09-18 18:38:50 -05:00
|
|
|
|
2014-10-09 14:17:22 -05:00
|
|
|
// The function given by the user might panic.
|
2014-09-18 18:38:50 -05:00
|
|
|
let u = f(t);
|
|
|
|
|
|
|
|
ptr::write(pv.end_u, u);
|
|
|
|
// start_u start_t
|
|
|
|
// | |
|
|
|
|
// +-+-+-+-+-+-+-+-+-+
|
|
|
|
// |U|...|U|U|T|...|T|
|
|
|
|
// +-+-+-+-+-+-+-+-+-+
|
|
|
|
// | |
|
|
|
|
// end_u end_t
|
2014-10-09 14:17:22 -05:00
|
|
|
// We should not panic here, because that would leak the `U`
|
2014-09-18 18:38:50 -05:00
|
|
|
// pointed to by `end_u`.
|
|
|
|
|
|
|
|
pv.end_u = pv.end_u.offset(1);
|
|
|
|
// start_u start_t
|
|
|
|
// | |
|
|
|
|
// +-+-+-+-+-+-+-+-+-+
|
|
|
|
// |U|...|U|U|T|...|T|
|
|
|
|
// +-+-+-+-+-+-+-+-+-+
|
|
|
|
// | |
|
|
|
|
// end_u end_t
|
2014-10-09 14:17:22 -05:00
|
|
|
// We may panic again.
|
2014-09-18 18:38:50 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// start_u start_t
|
|
|
|
// | |
|
|
|
|
// +-+-+-+-+-+-+
|
|
|
|
// |U|...|U|U|U|
|
|
|
|
// +-+-+-+-+-+-+
|
|
|
|
// |
|
|
|
|
// end_t
|
|
|
|
// end_u
|
|
|
|
// Extract `vec` and prevent the destructor of
|
|
|
|
// `PartialVecNonZeroSized` from running. Note that none of the
|
2014-10-09 14:17:22 -05:00
|
|
|
// function calls can panic, thus no resources can be leaked (as the
|
2014-09-18 18:38:50 -05:00
|
|
|
// `vec` member of `PartialVec` is the only one which holds
|
|
|
|
// allocations -- and it is returned from this function. None of
|
2014-10-09 14:17:22 -05:00
|
|
|
// this can panic.
|
2014-09-18 18:38:50 -05:00
|
|
|
unsafe {
|
|
|
|
let vec_len = pv.vec.len();
|
|
|
|
let vec_cap = pv.vec.capacity();
|
|
|
|
let vec_ptr = pv.vec.as_mut_ptr() as *mut U;
|
|
|
|
mem::forget(pv);
|
2014-10-24 21:31:17 -05:00
|
|
|
Vec::from_raw_parts(vec_ptr, vec_len, vec_cap)
|
2014-09-18 18:38:50 -05:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Put the `Vec` into the `PartialVecZeroSized` structure and
|
|
|
|
// prevent the destructor of the `Vec` from running. Since the
|
|
|
|
// `Vec` contained zero-sized objects, it did not allocate, so we
|
|
|
|
// are not leaking memory here.
|
|
|
|
let mut pv = PartialVecZeroSized::<T,U> {
|
|
|
|
num_t: vec.len(),
|
|
|
|
num_u: 0,
|
|
|
|
marker_t: InvariantType,
|
|
|
|
marker_u: InvariantType,
|
2014-07-01 08:10:22 -05:00
|
|
|
};
|
2014-09-18 18:38:50 -05:00
|
|
|
unsafe { mem::forget(vec); }
|
|
|
|
|
|
|
|
while pv.num_t != 0 {
|
|
|
|
unsafe {
|
|
|
|
// Create a `T` out of thin air and decrement `num_t`. This
|
2014-10-09 14:17:22 -05:00
|
|
|
// must not panic between these steps, as otherwise a
|
2014-09-18 18:38:50 -05:00
|
|
|
// destructor of `T` which doesn't exist runs.
|
|
|
|
let t = mem::uninitialized();
|
|
|
|
pv.num_t -= 1;
|
|
|
|
|
2014-10-09 14:17:22 -05:00
|
|
|
// The function given by the user might panic.
|
2014-09-18 18:38:50 -05:00
|
|
|
let u = f(t);
|
|
|
|
|
|
|
|
// Forget the `U` and increment `num_u`. This increment
|
|
|
|
// cannot overflow the `uint` as we only do this for a
|
|
|
|
// number of times that fits into a `uint` (and start with
|
2014-10-09 14:17:22 -05:00
|
|
|
// `0`). Again, we should not panic between these steps.
|
2014-09-18 18:38:50 -05:00
|
|
|
mem::forget(u);
|
|
|
|
pv.num_u += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Create a `Vec` from our `PartialVecZeroSized` and make sure the
|
2014-10-09 14:17:22 -05:00
|
|
|
// destructor of the latter will not run. None of this can panic.
|
2014-09-18 18:38:50 -05:00
|
|
|
let mut result = Vec::new();
|
|
|
|
unsafe { result.set_len(pv.num_u); }
|
|
|
|
result
|
2014-07-01 08:10:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-15 19:38:03 -06:00
|
|
|
impl<'a> fmt::FormatWriter for Vec<u8> {
|
|
|
|
fn write(&mut self, buf: &[u8]) -> fmt::Result {
|
|
|
|
self.push_all(buf);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-03 14:46:24 -06:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2014-06-20 22:08:17 -05:00
|
|
|
extern crate test;
|
|
|
|
|
2014-05-29 21:03:06 -05:00
|
|
|
use std::prelude::*;
|
|
|
|
use std::mem::size_of;
|
2014-06-20 22:08:17 -05:00
|
|
|
use test::Bencher;
|
2014-08-23 19:26:53 -05:00
|
|
|
use super::{as_vec, unzip, raw, Vec};
|
2014-03-12 15:01:33 -05:00
|
|
|
|
2014-08-23 19:26:53 -05:00
|
|
|
struct DropCounter<'a> {
|
|
|
|
count: &'a mut int
|
|
|
|
}
|
|
|
|
|
|
|
|
#[unsafe_destructor]
|
|
|
|
impl<'a> Drop for DropCounter<'a> {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
*self.count += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_as_vec() {
|
|
|
|
let xs = [1u8, 2u8, 3u8];
|
|
|
|
assert_eq!(as_vec(xs).as_slice(), xs.as_slice());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_as_vec_dtor() {
|
|
|
|
let (mut count_x, mut count_y) = (0, 0);
|
|
|
|
{
|
|
|
|
let xs = &[DropCounter { count: &mut count_x }, DropCounter { count: &mut count_y }];
|
|
|
|
assert_eq!(as_vec(xs).len(), 2);
|
|
|
|
}
|
|
|
|
assert_eq!(count_x, 1);
|
|
|
|
assert_eq!(count_y, 1);
|
|
|
|
}
|
|
|
|
|
2014-03-12 15:01:33 -05:00
|
|
|
#[test]
|
|
|
|
fn test_small_vec_struct() {
|
|
|
|
assert!(size_of::<Vec<u8>>() == size_of::<uint>() * 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_double_drop() {
|
|
|
|
struct TwoVec<T> {
|
|
|
|
x: Vec<T>,
|
|
|
|
y: Vec<T>
|
|
|
|
}
|
|
|
|
|
2014-07-28 13:33:06 -05:00
|
|
|
let (mut count_x, mut count_y) = (0, 0);
|
2014-03-12 15:01:33 -05:00
|
|
|
{
|
|
|
|
let mut tv = TwoVec {
|
|
|
|
x: Vec::new(),
|
|
|
|
y: Vec::new()
|
|
|
|
};
|
|
|
|
tv.x.push(DropCounter {count: &mut count_x});
|
|
|
|
tv.y.push(DropCounter {count: &mut count_y});
|
|
|
|
|
|
|
|
// If Vec had a drop flag, here is where it would be zeroed.
|
|
|
|
// Instead, it should rely on its internal state to prevent
|
|
|
|
// doing anything significant when dropped multiple times.
|
|
|
|
drop(tv.x);
|
|
|
|
|
|
|
|
// Here tv goes out of scope, tv.y should be dropped, but not tv.x.
|
|
|
|
}
|
|
|
|
|
|
|
|
assert_eq!(count_x, 1);
|
|
|
|
assert_eq!(count_y, 1);
|
|
|
|
}
|
2014-03-03 14:46:24 -06:00
|
|
|
|
|
|
|
#[test]
|
2014-11-06 11:24:47 -06:00
|
|
|
fn test_reserve() {
|
2014-03-03 14:46:24 -06:00
|
|
|
let mut v = Vec::new();
|
|
|
|
assert_eq!(v.capacity(), 0);
|
|
|
|
|
2014-11-06 11:24:47 -06:00
|
|
|
v.reserve(2);
|
2014-03-03 14:46:24 -06:00
|
|
|
assert!(v.capacity() >= 2);
|
|
|
|
|
2014-04-21 16:58:52 -05:00
|
|
|
for i in range(0i, 16) {
|
2014-03-03 14:46:24 -06:00
|
|
|
v.push(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert!(v.capacity() >= 16);
|
2014-11-06 11:24:47 -06:00
|
|
|
v.reserve(16);
|
2014-03-03 14:46:24 -06:00
|
|
|
assert!(v.capacity() >= 32);
|
|
|
|
|
|
|
|
v.push(16);
|
|
|
|
|
2014-11-06 11:24:47 -06:00
|
|
|
v.reserve(16);
|
2014-03-03 14:46:24 -06:00
|
|
|
assert!(v.capacity() >= 33)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_extend() {
|
|
|
|
let mut v = Vec::new();
|
|
|
|
let mut w = Vec::new();
|
|
|
|
|
2014-04-21 16:58:52 -05:00
|
|
|
v.extend(range(0i, 3));
|
|
|
|
for i in range(0i, 3) { w.push(i) }
|
2014-03-03 14:46:24 -06:00
|
|
|
|
|
|
|
assert_eq!(v, w);
|
|
|
|
|
2014-04-21 16:58:52 -05:00
|
|
|
v.extend(range(3i, 10));
|
|
|
|
for i in range(3i, 10) { w.push(i) }
|
2014-03-03 14:46:24 -06:00
|
|
|
|
|
|
|
assert_eq!(v, w);
|
|
|
|
}
|
2014-03-17 22:52:06 -05:00
|
|
|
|
|
|
|
#[test]
|
2014-10-05 05:11:17 -05:00
|
|
|
fn test_slice_from_mut() {
|
|
|
|
let mut values = vec![1u8,2,3,4,5];
|
2014-03-17 22:52:06 -05:00
|
|
|
{
|
2014-09-14 22:27:36 -05:00
|
|
|
let slice = values.slice_from_mut(2);
|
2014-03-17 22:52:06 -05:00
|
|
|
assert!(slice == [3, 4, 5]);
|
2014-09-14 22:27:36 -05:00
|
|
|
for p in slice.iter_mut() {
|
2014-03-17 22:52:06 -05:00
|
|
|
*p += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert!(values.as_slice() == [1, 2, 5, 6, 7]);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2014-10-05 05:11:17 -05:00
|
|
|
fn test_slice_to_mut() {
|
|
|
|
let mut values = vec![1u8,2,3,4,5];
|
2014-03-17 22:52:06 -05:00
|
|
|
{
|
2014-09-14 22:27:36 -05:00
|
|
|
let slice = values.slice_to_mut(2);
|
2014-03-17 22:52:06 -05:00
|
|
|
assert!(slice == [1, 2]);
|
2014-09-14 22:27:36 -05:00
|
|
|
for p in slice.iter_mut() {
|
2014-03-17 22:52:06 -05:00
|
|
|
*p += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert!(values.as_slice() == [2, 3, 3, 4, 5]);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2014-10-05 05:11:17 -05:00
|
|
|
fn test_split_at_mut() {
|
|
|
|
let mut values = vec![1u8,2,3,4,5];
|
2014-03-17 22:52:06 -05:00
|
|
|
{
|
2014-09-14 22:27:36 -05:00
|
|
|
let (left, right) = values.split_at_mut(2);
|
2014-09-24 06:41:09 -05:00
|
|
|
{
|
|
|
|
let left: &[_] = left;
|
2014-10-31 04:41:25 -05:00
|
|
|
assert!(left[0..left.len()] == [1, 2][]);
|
2014-09-24 06:41:09 -05:00
|
|
|
}
|
2014-09-14 22:27:36 -05:00
|
|
|
for p in left.iter_mut() {
|
2014-03-17 22:52:06 -05:00
|
|
|
*p += 1;
|
|
|
|
}
|
|
|
|
|
2014-09-24 06:41:09 -05:00
|
|
|
{
|
|
|
|
let right: &[_] = right;
|
2014-10-31 04:41:25 -05:00
|
|
|
assert!(right[0..right.len()] == [3, 4, 5][]);
|
2014-09-24 06:41:09 -05:00
|
|
|
}
|
2014-09-14 22:27:36 -05:00
|
|
|
for p in right.iter_mut() {
|
2014-03-17 22:52:06 -05:00
|
|
|
*p += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-05 05:11:17 -05:00
|
|
|
assert!(values == vec![2u8, 3, 5, 6, 7]);
|
2014-03-17 22:52:06 -05:00
|
|
|
}
|
2014-04-03 06:28:45 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_clone() {
|
|
|
|
let v: Vec<int> = vec!();
|
2014-04-21 16:58:52 -05:00
|
|
|
let w = vec!(1i, 2, 3);
|
2014-04-03 06:28:45 -05:00
|
|
|
|
|
|
|
assert_eq!(v, v.clone());
|
|
|
|
|
|
|
|
let z = w.clone();
|
|
|
|
assert_eq!(w, z);
|
|
|
|
// they should be disjoint in memory.
|
|
|
|
assert!(w.as_ptr() != z.as_ptr())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_clone_from() {
|
|
|
|
let mut v = vec!();
|
2014-04-21 16:58:52 -05:00
|
|
|
let three = vec!(box 1i, box 2, box 3);
|
|
|
|
let two = vec!(box 4i, box 5);
|
2014-04-03 06:28:45 -05:00
|
|
|
// zero, long
|
|
|
|
v.clone_from(&three);
|
|
|
|
assert_eq!(v, three);
|
|
|
|
|
|
|
|
// equal
|
|
|
|
v.clone_from(&three);
|
|
|
|
assert_eq!(v, three);
|
|
|
|
|
|
|
|
// long, short
|
|
|
|
v.clone_from(&two);
|
|
|
|
assert_eq!(v, two);
|
|
|
|
|
|
|
|
// short, long
|
|
|
|
v.clone_from(&three);
|
|
|
|
assert_eq!(v, three)
|
|
|
|
}
|
2014-04-02 22:10:36 -05:00
|
|
|
|
2014-04-07 15:30:48 -05:00
|
|
|
#[test]
|
2014-04-02 22:10:36 -05:00
|
|
|
fn test_grow_fn() {
|
2014-10-05 05:11:17 -05:00
|
|
|
let mut v = vec![0u, 1];
|
2014-04-02 22:10:36 -05:00
|
|
|
v.grow_fn(3, |i| i);
|
2014-10-05 05:11:17 -05:00
|
|
|
assert!(v == vec![0u, 1, 0, 1, 2]);
|
2014-04-02 22:10:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_retain() {
|
2014-10-05 05:11:17 -05:00
|
|
|
let mut vec = vec![1u, 2, 3, 4];
|
2014-10-31 04:41:25 -05:00
|
|
|
vec.retain(|&x| x % 2 == 0);
|
2014-10-05 05:11:17 -05:00
|
|
|
assert!(vec == vec![2u, 4]);
|
2014-04-02 22:10:36 -05:00
|
|
|
}
|
2014-04-11 16:34:21 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn zero_sized_values() {
|
|
|
|
let mut v = Vec::new();
|
|
|
|
assert_eq!(v.len(), 0);
|
|
|
|
v.push(());
|
|
|
|
assert_eq!(v.len(), 1);
|
|
|
|
v.push(());
|
|
|
|
assert_eq!(v.len(), 2);
|
|
|
|
assert_eq!(v.pop(), Some(()));
|
|
|
|
assert_eq!(v.pop(), Some(()));
|
|
|
|
assert_eq!(v.pop(), None);
|
|
|
|
|
2014-06-06 01:18:51 -05:00
|
|
|
assert_eq!(v.iter().count(), 0);
|
2014-04-11 16:34:21 -05:00
|
|
|
v.push(());
|
2014-06-06 01:18:51 -05:00
|
|
|
assert_eq!(v.iter().count(), 1);
|
2014-04-11 16:34:21 -05:00
|
|
|
v.push(());
|
2014-06-06 01:18:51 -05:00
|
|
|
assert_eq!(v.iter().count(), 2);
|
2014-04-11 16:34:21 -05:00
|
|
|
|
|
|
|
for &() in v.iter() {}
|
|
|
|
|
2014-09-14 22:27:36 -05:00
|
|
|
assert_eq!(v.iter_mut().count(), 2);
|
2014-04-11 16:34:21 -05:00
|
|
|
v.push(());
|
2014-09-14 22:27:36 -05:00
|
|
|
assert_eq!(v.iter_mut().count(), 3);
|
2014-04-11 16:34:21 -05:00
|
|
|
v.push(());
|
2014-09-14 22:27:36 -05:00
|
|
|
assert_eq!(v.iter_mut().count(), 4);
|
2014-04-11 16:34:21 -05:00
|
|
|
|
2014-09-14 22:27:36 -05:00
|
|
|
for &() in v.iter_mut() {}
|
2014-04-11 16:34:21 -05:00
|
|
|
unsafe { v.set_len(0); }
|
2014-09-14 22:27:36 -05:00
|
|
|
assert_eq!(v.iter_mut().count(), 0);
|
2014-04-11 16:34:21 -05:00
|
|
|
}
|
2014-05-03 18:13:35 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_partition() {
|
|
|
|
assert_eq!(vec![].partition(|x: &int| *x < 3), (vec![], vec![]));
|
2014-04-21 16:58:52 -05:00
|
|
|
assert_eq!(vec![1i, 2, 3].partition(|x: &int| *x < 4), (vec![1, 2, 3], vec![]));
|
|
|
|
assert_eq!(vec![1i, 2, 3].partition(|x: &int| *x < 2), (vec![1], vec![2, 3]));
|
|
|
|
assert_eq!(vec![1i, 2, 3].partition(|x: &int| *x < 0), (vec![], vec![1, 2, 3]));
|
2014-05-03 18:13:35 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_partitioned() {
|
2014-05-08 14:03:33 -05:00
|
|
|
assert_eq!(vec![].partitioned(|x: &int| *x < 3), (vec![], vec![]))
|
2014-04-21 16:58:52 -05:00
|
|
|
assert_eq!(vec![1i, 2, 3].partitioned(|x: &int| *x < 4), (vec![1, 2, 3], vec![]));
|
|
|
|
assert_eq!(vec![1i, 2, 3].partitioned(|x: &int| *x < 2), (vec![1], vec![2, 3]));
|
|
|
|
assert_eq!(vec![1i, 2, 3].partitioned(|x: &int| *x < 0), (vec![], vec![1, 2, 3]));
|
2014-05-03 18:13:35 -05:00
|
|
|
}
|
2014-05-03 20:10:04 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_zip_unzip() {
|
2014-04-21 16:58:52 -05:00
|
|
|
let z1 = vec![(1i, 4i), (2, 5), (3, 6)];
|
2014-05-03 20:10:04 -05:00
|
|
|
|
|
|
|
let (left, right) = unzip(z1.iter().map(|&x| x));
|
|
|
|
|
|
|
|
let (left, right) = (left.as_slice(), right.as_slice());
|
|
|
|
assert_eq!((1, 4), (left[0], right[0]));
|
|
|
|
assert_eq!((2, 5), (left[1], right[1]));
|
|
|
|
assert_eq!((3, 6), (left[2], right[2]));
|
|
|
|
}
|
2014-05-03 20:20:35 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_unsafe_ptrs() {
|
|
|
|
unsafe {
|
|
|
|
// Test on-stack copy-from-buf.
|
2014-04-21 16:58:52 -05:00
|
|
|
let a = [1i, 2, 3];
|
2014-05-03 20:20:35 -05:00
|
|
|
let ptr = a.as_ptr();
|
|
|
|
let b = raw::from_buf(ptr, 3u);
|
|
|
|
assert_eq!(b, vec![1, 2, 3]);
|
|
|
|
|
|
|
|
// Test on-heap copy-from-buf.
|
2014-04-21 16:58:52 -05:00
|
|
|
let c = vec![1i, 2, 3, 4, 5];
|
2014-05-03 20:20:35 -05:00
|
|
|
let ptr = c.as_ptr();
|
|
|
|
let d = raw::from_buf(ptr, 5u);
|
|
|
|
assert_eq!(d, vec![1, 2, 3, 4, 5]);
|
|
|
|
}
|
|
|
|
}
|
2014-05-06 22:14:54 -05:00
|
|
|
|
2014-05-14 16:57:27 -05:00
|
|
|
#[test]
|
|
|
|
fn test_vec_truncate_drop() {
|
|
|
|
static mut drops: uint = 0;
|
|
|
|
struct Elem(int);
|
|
|
|
impl Drop for Elem {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe { drops += 1; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut v = vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)];
|
|
|
|
assert_eq!(unsafe { drops }, 0);
|
|
|
|
v.truncate(3);
|
|
|
|
assert_eq!(unsafe { drops }, 2);
|
|
|
|
v.truncate(0);
|
|
|
|
assert_eq!(unsafe { drops }, 5);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_fail]
|
|
|
|
fn test_vec_truncate_fail() {
|
|
|
|
struct BadElem(int);
|
|
|
|
impl Drop for BadElem {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
let BadElem(ref mut x) = *self;
|
|
|
|
if *x == 0xbadbeef {
|
2014-10-09 14:17:22 -05:00
|
|
|
panic!("BadElem panic: 0xbadbeef")
|
2014-05-14 16:57:27 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut v = vec![BadElem(1), BadElem(2), BadElem(0xbadbeef), BadElem(4)];
|
|
|
|
v.truncate(0);
|
|
|
|
}
|
2014-06-02 23:56:29 -05:00
|
|
|
|
2014-07-13 18:03:23 -05:00
|
|
|
#[test]
|
|
|
|
fn test_index() {
|
|
|
|
let vec = vec!(1i, 2, 3);
|
|
|
|
assert!(vec[1] == 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_fail]
|
|
|
|
fn test_index_out_of_bounds() {
|
|
|
|
let vec = vec!(1i, 2, 3);
|
|
|
|
let _ = vec[3];
|
|
|
|
}
|
|
|
|
|
2014-09-15 03:48:58 -05:00
|
|
|
#[test]
|
|
|
|
#[should_fail]
|
|
|
|
fn test_slice_out_of_bounds_1() {
|
|
|
|
let x: Vec<int> = vec![1, 2, 3, 4, 5];
|
|
|
|
x[-1..];
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_fail]
|
|
|
|
fn test_slice_out_of_bounds_2() {
|
|
|
|
let x: Vec<int> = vec![1, 2, 3, 4, 5];
|
|
|
|
x[..6];
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_fail]
|
|
|
|
fn test_slice_out_of_bounds_3() {
|
|
|
|
let x: Vec<int> = vec![1, 2, 3, 4, 5];
|
|
|
|
x[-1..4];
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_fail]
|
|
|
|
fn test_slice_out_of_bounds_4() {
|
|
|
|
let x: Vec<int> = vec![1, 2, 3, 4, 5];
|
|
|
|
x[1..6];
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_fail]
|
|
|
|
fn test_slice_out_of_bounds_5() {
|
|
|
|
let x: Vec<int> = vec![1, 2, 3, 4, 5];
|
|
|
|
x[3..2];
|
|
|
|
}
|
|
|
|
|
2014-08-02 13:36:51 -05:00
|
|
|
#[test]
|
|
|
|
fn test_swap_remove_empty() {
|
|
|
|
let mut vec: Vec<uint> = vec!();
|
|
|
|
assert_eq!(vec.swap_remove(0), None);
|
|
|
|
}
|
|
|
|
|
2014-08-31 08:29:22 -05:00
|
|
|
#[test]
|
|
|
|
fn test_move_iter_unwrap() {
|
|
|
|
let mut vec: Vec<uint> = Vec::with_capacity(7);
|
|
|
|
vec.push(1);
|
|
|
|
vec.push(2);
|
|
|
|
let ptr = vec.as_ptr();
|
2014-09-14 22:27:36 -05:00
|
|
|
vec = vec.into_iter().unwrap();
|
2014-08-31 08:29:22 -05:00
|
|
|
assert_eq!(vec.as_ptr(), ptr);
|
|
|
|
assert_eq!(vec.capacity(), 7);
|
|
|
|
assert_eq!(vec.len(), 0);
|
2014-09-12 18:38:16 -05:00
|
|
|
}
|
2014-07-01 08:10:22 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_fail]
|
2014-09-18 18:38:50 -05:00
|
|
|
fn test_map_in_place_incompatible_types_fail() {
|
2014-07-01 08:10:22 -05:00
|
|
|
let v = vec![0u, 1, 2];
|
2014-09-10 19:04:51 -05:00
|
|
|
v.map_in_place(|_| ());
|
2014-07-01 08:10:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2014-09-10 19:04:51 -05:00
|
|
|
fn test_map_in_place() {
|
2014-07-01 08:10:22 -05:00
|
|
|
let v = vec![0u, 1, 2];
|
2014-09-14 14:33:48 -05:00
|
|
|
assert_eq!(v.map_in_place(|i: uint| i as int - 1).as_slice(), [-1i, 0, 1].as_slice());
|
2014-08-31 08:29:22 -05:00
|
|
|
}
|
|
|
|
|
2014-09-18 18:38:50 -05:00
|
|
|
#[test]
|
|
|
|
fn test_map_in_place_zero_sized() {
|
|
|
|
let v = vec![(), ()];
|
|
|
|
#[deriving(PartialEq, Show)]
|
|
|
|
struct ZeroSized;
|
|
|
|
assert_eq!(v.map_in_place(|_| ZeroSized).as_slice(), [ZeroSized, ZeroSized].as_slice());
|
|
|
|
}
|
|
|
|
|
2014-10-02 10:19:47 -05:00
|
|
|
#[test]
|
|
|
|
fn test_move_items() {
|
2014-10-05 05:11:17 -05:00
|
|
|
let vec = vec![1, 2, 3];
|
|
|
|
let mut vec2 : Vec<i32> = vec![];
|
2014-10-02 13:06:31 -05:00
|
|
|
for i in vec.into_iter() {
|
2014-10-02 10:19:47 -05:00
|
|
|
vec2.push(i);
|
|
|
|
}
|
2014-10-05 05:11:17 -05:00
|
|
|
assert!(vec2 == vec![1, 2, 3]);
|
2014-10-02 10:19:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_move_items_reverse() {
|
2014-10-05 05:11:17 -05:00
|
|
|
let vec = vec![1, 2, 3];
|
|
|
|
let mut vec2 : Vec<i32> = vec![];
|
2014-10-02 13:06:31 -05:00
|
|
|
for i in vec.into_iter().rev() {
|
2014-10-02 10:19:47 -05:00
|
|
|
vec2.push(i);
|
|
|
|
}
|
2014-10-05 05:11:17 -05:00
|
|
|
assert!(vec2 == vec![3, 2, 1]);
|
2014-10-02 10:19:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_move_items_zero_sized() {
|
2014-10-05 05:11:17 -05:00
|
|
|
let vec = vec![(), (), ()];
|
|
|
|
let mut vec2 : Vec<()> = vec![];
|
2014-10-02 13:06:31 -05:00
|
|
|
for i in vec.into_iter() {
|
2014-10-02 10:19:47 -05:00
|
|
|
vec2.push(i);
|
|
|
|
}
|
2014-10-05 05:11:17 -05:00
|
|
|
assert!(vec2 == vec![(), (), ()]);
|
2014-10-02 10:19:47 -05:00
|
|
|
}
|
|
|
|
|
2014-10-10 04:18:42 -05:00
|
|
|
#[test]
|
|
|
|
fn test_into_boxed_slice() {
|
|
|
|
let xs = vec![1u, 2, 3];
|
|
|
|
let ys = xs.into_boxed_slice();
|
2014-10-10 05:19:40 -05:00
|
|
|
assert_eq!(ys.as_slice(), [1u, 2, 3].as_slice());
|
2014-10-10 04:18:42 -05:00
|
|
|
}
|
|
|
|
|
2014-06-02 23:56:29 -05:00
|
|
|
#[bench]
|
|
|
|
fn bench_new(b: &mut Bencher) {
|
|
|
|
b.iter(|| {
|
2014-07-06 01:07:28 -05:00
|
|
|
let v: Vec<uint> = Vec::new();
|
|
|
|
assert_eq!(v.len(), 0);
|
2014-06-02 23:56:29 -05:00
|
|
|
assert_eq!(v.capacity(), 0);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2014-07-06 01:07:28 -05:00
|
|
|
fn do_bench_with_capacity(b: &mut Bencher, src_len: uint) {
|
|
|
|
b.bytes = src_len as u64;
|
|
|
|
|
2014-06-02 23:56:29 -05:00
|
|
|
b.iter(|| {
|
2014-07-06 01:07:28 -05:00
|
|
|
let v: Vec<uint> = Vec::with_capacity(src_len);
|
|
|
|
assert_eq!(v.len(), 0);
|
|
|
|
assert_eq!(v.capacity(), src_len);
|
2014-06-02 23:56:29 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2014-07-06 01:07:28 -05:00
|
|
|
#[bench]
|
|
|
|
fn bench_with_capacity_0000(b: &mut Bencher) {
|
|
|
|
do_bench_with_capacity(b, 0)
|
|
|
|
}
|
2014-06-02 23:56:29 -05:00
|
|
|
|
|
|
|
#[bench]
|
2014-07-06 01:07:28 -05:00
|
|
|
fn bench_with_capacity_0010(b: &mut Bencher) {
|
|
|
|
do_bench_with_capacity(b, 10)
|
2014-06-02 23:56:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-06 01:07:28 -05:00
|
|
|
fn bench_with_capacity_0100(b: &mut Bencher) {
|
|
|
|
do_bench_with_capacity(b, 100)
|
2014-06-02 23:56:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-06 01:07:28 -05:00
|
|
|
fn bench_with_capacity_1000(b: &mut Bencher) {
|
|
|
|
do_bench_with_capacity(b, 1000)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn do_bench_from_fn(b: &mut Bencher, src_len: uint) {
|
|
|
|
b.bytes = src_len as u64;
|
|
|
|
|
2014-06-02 23:56:29 -05:00
|
|
|
b.iter(|| {
|
2014-07-06 01:07:28 -05:00
|
|
|
let dst = Vec::from_fn(src_len, |i| i);
|
|
|
|
assert_eq!(dst.len(), src_len);
|
|
|
|
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
2014-06-02 23:56:29 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-06 01:07:28 -05:00
|
|
|
fn bench_from_fn_0000(b: &mut Bencher) {
|
|
|
|
do_bench_from_fn(b, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_from_fn_0010(b: &mut Bencher) {
|
|
|
|
do_bench_from_fn(b, 10)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_from_fn_0100(b: &mut Bencher) {
|
|
|
|
do_bench_from_fn(b, 100)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_from_fn_1000(b: &mut Bencher) {
|
|
|
|
do_bench_from_fn(b, 1000)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn do_bench_from_elem(b: &mut Bencher, src_len: uint) {
|
|
|
|
b.bytes = src_len as u64;
|
|
|
|
|
2014-06-02 23:56:29 -05:00
|
|
|
b.iter(|| {
|
2014-07-06 01:07:28 -05:00
|
|
|
let dst: Vec<uint> = Vec::from_elem(src_len, 5);
|
|
|
|
assert_eq!(dst.len(), src_len);
|
|
|
|
assert!(dst.iter().all(|x| *x == 5));
|
2014-06-02 23:56:29 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-06 01:07:28 -05:00
|
|
|
fn bench_from_elem_0000(b: &mut Bencher) {
|
|
|
|
do_bench_from_elem(b, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_from_elem_0010(b: &mut Bencher) {
|
|
|
|
do_bench_from_elem(b, 10)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_from_elem_0100(b: &mut Bencher) {
|
|
|
|
do_bench_from_elem(b, 100)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_from_elem_1000(b: &mut Bencher) {
|
|
|
|
do_bench_from_elem(b, 1000)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn do_bench_from_slice(b: &mut Bencher, src_len: uint) {
|
|
|
|
let src: Vec<uint> = FromIterator::from_iter(range(0, src_len));
|
|
|
|
|
|
|
|
b.bytes = src_len as u64;
|
|
|
|
|
2014-06-02 23:56:29 -05:00
|
|
|
b.iter(|| {
|
2014-10-05 05:11:17 -05:00
|
|
|
let dst = src.clone().as_slice().to_vec();
|
2014-07-06 01:07:28 -05:00
|
|
|
assert_eq!(dst.len(), src_len);
|
|
|
|
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_from_slice_0000(b: &mut Bencher) {
|
|
|
|
do_bench_from_slice(b, 0)
|
2014-06-02 23:56:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-06 01:07:28 -05:00
|
|
|
fn bench_from_slice_0010(b: &mut Bencher) {
|
|
|
|
do_bench_from_slice(b, 10)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_from_slice_0100(b: &mut Bencher) {
|
|
|
|
do_bench_from_slice(b, 100)
|
2014-06-02 23:56:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-06 01:07:28 -05:00
|
|
|
fn bench_from_slice_1000(b: &mut Bencher) {
|
|
|
|
do_bench_from_slice(b, 1000)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn do_bench_from_iter(b: &mut Bencher, src_len: uint) {
|
|
|
|
let src: Vec<uint> = FromIterator::from_iter(range(0, src_len));
|
|
|
|
|
|
|
|
b.bytes = src_len as u64;
|
|
|
|
|
2014-06-02 23:56:29 -05:00
|
|
|
b.iter(|| {
|
2014-09-14 22:27:36 -05:00
|
|
|
let dst: Vec<uint> = FromIterator::from_iter(src.clone().into_iter());
|
2014-07-06 01:07:28 -05:00
|
|
|
assert_eq!(dst.len(), src_len);
|
|
|
|
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_from_iter_0000(b: &mut Bencher) {
|
|
|
|
do_bench_from_iter(b, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_from_iter_0010(b: &mut Bencher) {
|
|
|
|
do_bench_from_iter(b, 10)
|
2014-06-02 23:56:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-06 01:07:28 -05:00
|
|
|
fn bench_from_iter_0100(b: &mut Bencher) {
|
|
|
|
do_bench_from_iter(b, 100)
|
2014-06-02 23:56:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-06 01:07:28 -05:00
|
|
|
fn bench_from_iter_1000(b: &mut Bencher) {
|
|
|
|
do_bench_from_iter(b, 1000)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn do_bench_extend(b: &mut Bencher, dst_len: uint, src_len: uint) {
|
|
|
|
let dst: Vec<uint> = FromIterator::from_iter(range(0, dst_len));
|
|
|
|
let src: Vec<uint> = FromIterator::from_iter(range(dst_len, dst_len + src_len));
|
|
|
|
|
|
|
|
b.bytes = src_len as u64;
|
|
|
|
|
2014-06-02 23:56:29 -05:00
|
|
|
b.iter(|| {
|
2014-07-06 01:07:28 -05:00
|
|
|
let mut dst = dst.clone();
|
2014-09-14 22:27:36 -05:00
|
|
|
dst.extend(src.clone().into_iter());
|
2014-07-06 01:07:28 -05:00
|
|
|
assert_eq!(dst.len(), dst_len + src_len);
|
|
|
|
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_extend_0000_0000(b: &mut Bencher) {
|
|
|
|
do_bench_extend(b, 0, 0)
|
2014-06-02 23:56:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-06 01:07:28 -05:00
|
|
|
fn bench_extend_0000_0010(b: &mut Bencher) {
|
|
|
|
do_bench_extend(b, 0, 10)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_extend_0000_0100(b: &mut Bencher) {
|
|
|
|
do_bench_extend(b, 0, 100)
|
2014-06-02 23:56:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-06 01:07:28 -05:00
|
|
|
fn bench_extend_0000_1000(b: &mut Bencher) {
|
|
|
|
do_bench_extend(b, 0, 1000)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_extend_0010_0010(b: &mut Bencher) {
|
|
|
|
do_bench_extend(b, 10, 10)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_extend_0100_0100(b: &mut Bencher) {
|
|
|
|
do_bench_extend(b, 100, 100)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_extend_1000_1000(b: &mut Bencher) {
|
|
|
|
do_bench_extend(b, 1000, 1000)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn do_bench_push_all(b: &mut Bencher, dst_len: uint, src_len: uint) {
|
|
|
|
let dst: Vec<uint> = FromIterator::from_iter(range(0, dst_len));
|
|
|
|
let src: Vec<uint> = FromIterator::from_iter(range(dst_len, dst_len + src_len));
|
|
|
|
|
|
|
|
b.bytes = src_len as u64;
|
|
|
|
|
2014-06-02 23:56:29 -05:00
|
|
|
b.iter(|| {
|
2014-07-06 01:07:28 -05:00
|
|
|
let mut dst = dst.clone();
|
|
|
|
dst.push_all(src.as_slice());
|
|
|
|
assert_eq!(dst.len(), dst_len + src_len);
|
|
|
|
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_push_all_0000_0000(b: &mut Bencher) {
|
|
|
|
do_bench_push_all(b, 0, 0)
|
2014-06-02 23:56:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-06 01:07:28 -05:00
|
|
|
fn bench_push_all_0000_0010(b: &mut Bencher) {
|
|
|
|
do_bench_push_all(b, 0, 10)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_push_all_0000_0100(b: &mut Bencher) {
|
|
|
|
do_bench_push_all(b, 0, 100)
|
2014-06-02 23:56:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-06 01:07:28 -05:00
|
|
|
fn bench_push_all_0000_1000(b: &mut Bencher) {
|
|
|
|
do_bench_push_all(b, 0, 1000)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_push_all_0010_0010(b: &mut Bencher) {
|
|
|
|
do_bench_push_all(b, 10, 10)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_push_all_0100_0100(b: &mut Bencher) {
|
|
|
|
do_bench_push_all(b, 100, 100)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_push_all_1000_1000(b: &mut Bencher) {
|
|
|
|
do_bench_push_all(b, 1000, 1000)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn do_bench_push_all_move(b: &mut Bencher, dst_len: uint, src_len: uint) {
|
|
|
|
let dst: Vec<uint> = FromIterator::from_iter(range(0u, dst_len));
|
|
|
|
let src: Vec<uint> = FromIterator::from_iter(range(dst_len, dst_len + src_len));
|
|
|
|
|
|
|
|
b.bytes = src_len as u64;
|
|
|
|
|
2014-06-02 23:56:29 -05:00
|
|
|
b.iter(|| {
|
2014-07-06 01:07:28 -05:00
|
|
|
let mut dst = dst.clone();
|
2014-10-05 05:11:17 -05:00
|
|
|
dst.extend(src.clone().into_iter());
|
2014-07-06 01:07:28 -05:00
|
|
|
assert_eq!(dst.len(), dst_len + src_len);
|
|
|
|
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_push_all_move_0000_0000(b: &mut Bencher) {
|
|
|
|
do_bench_push_all_move(b, 0, 0)
|
2014-06-02 23:56:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-06 01:07:28 -05:00
|
|
|
fn bench_push_all_move_0000_0010(b: &mut Bencher) {
|
|
|
|
do_bench_push_all_move(b, 0, 10)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_push_all_move_0000_0100(b: &mut Bencher) {
|
|
|
|
do_bench_push_all_move(b, 0, 100)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_push_all_move_0000_1000(b: &mut Bencher) {
|
|
|
|
do_bench_push_all_move(b, 0, 1000)
|
2014-06-02 23:56:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-06 01:07:28 -05:00
|
|
|
fn bench_push_all_move_0010_0010(b: &mut Bencher) {
|
|
|
|
do_bench_push_all_move(b, 10, 10)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_push_all_move_0100_0100(b: &mut Bencher) {
|
|
|
|
do_bench_push_all_move(b, 100, 100)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_push_all_move_1000_1000(b: &mut Bencher) {
|
|
|
|
do_bench_push_all_move(b, 1000, 1000)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn do_bench_clone(b: &mut Bencher, src_len: uint) {
|
|
|
|
let src: Vec<uint> = FromIterator::from_iter(range(0, src_len));
|
|
|
|
|
|
|
|
b.bytes = src_len as u64;
|
|
|
|
|
2014-06-02 23:56:29 -05:00
|
|
|
b.iter(|| {
|
2014-07-06 01:07:28 -05:00
|
|
|
let dst = src.clone();
|
|
|
|
assert_eq!(dst.len(), src_len);
|
|
|
|
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
|
|
|
});
|
2014-06-02 23:56:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-06 01:07:28 -05:00
|
|
|
fn bench_clone_0000(b: &mut Bencher) {
|
|
|
|
do_bench_clone(b, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_clone_0010(b: &mut Bencher) {
|
|
|
|
do_bench_clone(b, 10)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_clone_0100(b: &mut Bencher) {
|
|
|
|
do_bench_clone(b, 100)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_clone_1000(b: &mut Bencher) {
|
|
|
|
do_bench_clone(b, 1000)
|
|
|
|
}
|
|
|
|
|
2014-07-07 11:07:49 -05:00
|
|
|
fn do_bench_clone_from(b: &mut Bencher, times: uint, dst_len: uint, src_len: uint) {
|
2014-07-06 01:07:28 -05:00
|
|
|
let dst: Vec<uint> = FromIterator::from_iter(range(0, src_len));
|
|
|
|
let src: Vec<uint> = FromIterator::from_iter(range(dst_len, dst_len + src_len));
|
|
|
|
|
2014-07-07 11:07:49 -05:00
|
|
|
b.bytes = (times * src_len) as u64;
|
2014-07-06 01:07:28 -05:00
|
|
|
|
2014-06-02 23:56:29 -05:00
|
|
|
b.iter(|| {
|
2014-07-06 01:07:28 -05:00
|
|
|
let mut dst = dst.clone();
|
2014-07-07 11:07:49 -05:00
|
|
|
|
|
|
|
for _ in range(0, times) {
|
|
|
|
dst.clone_from(&src);
|
|
|
|
|
|
|
|
assert_eq!(dst.len(), src_len);
|
|
|
|
assert!(dst.iter().enumerate().all(|(i, x)| dst_len + i == *x));
|
|
|
|
}
|
2014-07-06 01:07:28 -05:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-07 11:07:49 -05:00
|
|
|
fn bench_clone_from_01_0000_0000(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 1, 0, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_clone_from_01_0000_0010(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 1, 0, 10)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_clone_from_01_0000_0100(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 1, 0, 100)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_clone_from_01_0000_1000(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 1, 0, 1000)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_clone_from_01_0010_0010(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 1, 10, 10)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_clone_from_01_0100_0100(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 1, 100, 100)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_clone_from_01_1000_1000(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 1, 1000, 1000)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_clone_from_01_0010_0100(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 1, 10, 100)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_clone_from_01_0100_1000(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 1, 100, 1000)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_clone_from_01_0010_0000(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 1, 10, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_clone_from_01_0100_0010(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 1, 100, 10)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_clone_from_01_1000_0100(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 1, 1000, 100)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_clone_from_10_0000_0000(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 10, 0, 0)
|
2014-07-06 01:07:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-07 11:07:49 -05:00
|
|
|
fn bench_clone_from_10_0000_0010(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 10, 0, 10)
|
2014-07-06 01:07:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-07 11:07:49 -05:00
|
|
|
fn bench_clone_from_10_0000_0100(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 10, 0, 100)
|
2014-07-06 01:07:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-07 11:07:49 -05:00
|
|
|
fn bench_clone_from_10_0000_1000(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 10, 0, 1000)
|
2014-07-06 01:07:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-07 11:07:49 -05:00
|
|
|
fn bench_clone_from_10_0010_0010(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 10, 10, 10)
|
2014-07-06 01:07:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-07 11:07:49 -05:00
|
|
|
fn bench_clone_from_10_0100_0100(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 10, 100, 100)
|
2014-07-06 01:07:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-07 11:07:49 -05:00
|
|
|
fn bench_clone_from_10_1000_1000(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 10, 1000, 1000)
|
2014-07-06 01:07:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-07 11:07:49 -05:00
|
|
|
fn bench_clone_from_10_0010_0100(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 10, 10, 100)
|
2014-07-06 01:07:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-07 11:07:49 -05:00
|
|
|
fn bench_clone_from_10_0100_1000(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 10, 100, 1000)
|
2014-07-06 01:07:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-07 11:07:49 -05:00
|
|
|
fn bench_clone_from_10_0010_0000(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 10, 10, 0)
|
2014-07-06 01:07:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-07 11:07:49 -05:00
|
|
|
fn bench_clone_from_10_0100_0010(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 10, 100, 10)
|
2014-07-06 01:07:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-07-07 11:07:49 -05:00
|
|
|
fn bench_clone_from_10_1000_0100(b: &mut Bencher) {
|
|
|
|
do_bench_clone_from(b, 10, 1000, 100)
|
2014-06-02 23:56:29 -05:00
|
|
|
}
|
2014-03-03 14:46:24 -06:00
|
|
|
}
|