collections: Move push/pop to MutableSeq

Implement for Vec, DList, RingBuf. Add MutableSeq to the prelude.

Since the collections traits are in the prelude most consumers of
these methods will continue to work without change.

[breaking-change]
This commit is contained in:
Brian Anderson 2014-07-11 10:12:38 -07:00
parent c080d26d32
commit d36a8f3f9c
31 changed files with 142 additions and 86 deletions

View File

@ -268,6 +268,7 @@ impl<T: Share + Send> Drop for Weak<T> {
#[allow(experimental)]
mod tests {
use std::clone::Clone;
use std::collections::MutableSeq;
use std::comm::channel;
use std::mem::drop;
use std::ops::Drop;

View File

@ -72,7 +72,7 @@ use core::slice;
use core::uint;
use std::hash;
use {Collection, Mutable, Set, MutableSet};
use {Collection, Mutable, Set, MutableSet, MutableSeq};
use vec::Vec;

View File

@ -24,7 +24,7 @@ use alloc::boxed::Box;
use core::fmt;
use core::fmt::Show;
use Collection;
use {Collection, MutableSeq};
use vec::Vec;
#[allow(missing_doc)]

View File

@ -30,7 +30,7 @@ use core::iter;
use core::mem;
use core::ptr;
use {Collection, Mutable, Deque};
use {Collection, Mutable, Deque, MutableSeq};
/// A doubly-linked list.
pub struct DList<T> {
@ -265,6 +265,11 @@ impl<T> Deque<T> for DList<T> {
}
}
impl<T> MutableSeq<T> for DList<T> {
fn push(&mut self, elt: T) { self.push_back(elt) }
fn pop(&mut self) -> Option<T> { self.pop_back() }
}
impl<T> Default for DList<T> {
#[inline]
fn default() -> DList<T> { DList::new() }
@ -719,7 +724,7 @@ mod tests {
use test::Bencher;
use test;
use Deque;
use {Deque, MutableSeq};
use super::{DList, Node, ListInsertion};
use vec::Vec;

View File

@ -281,6 +281,8 @@ mod tests {
use super::super::{Hash, Writer};
use super::{SipState, hash, hash_with_keys};
use MutableSeq;
// Hash just the bytes of the slice, without length prefix
struct Bytes<'a>(&'a [u8]);

View File

@ -325,6 +325,11 @@ pub trait MutableSet<T>: Set<T> + Mutable {
fn remove(&mut self, value: &T) -> bool;
}
pub trait MutableSeq<T>: Mutable {
fn push(&mut self, t: T);
fn pop(&mut self) -> Option<T>;
}
/// A double-ended sequence that allows querying, insertion and deletion at both
/// ends.
///
@ -384,7 +389,7 @@ pub trait MutableSet<T>: Set<T> + Mutable {
/// println!("{}", (f, b));
/// }
/// ```
pub trait Deque<T> : Mutable {
pub trait Deque<T> : MutableSeq<T> {
/// Provide a reference to the front element, or `None` if the sequence is
/// empty.
///
@ -535,4 +540,8 @@ mod std {
pub use core::clone; // deriving(Clone)
pub use core::cmp; // deriving(Eq, Ord, etc.)
pub use hash; // deriving(Hash)
pub mod collections {
pub use MutableSeq;
}
}

View File

@ -11,8 +11,26 @@
#![macro_escape]
/// Create a `std::vec::Vec` containing the arguments.
#[cfg(not(test))]
macro_rules! vec(
($($e:expr),*) => ({
#[allow(unused_imports)]
use std::collections::MutableSeq;
// leading _ to allow empty construction without a warning.
let mut _temp = ::vec::Vec::new();
$(_temp.push($e);)*
_temp
});
($($e:expr),+,) => (vec!($($e),+))
)
#[cfg(test)]
macro_rules! vec(
($($e:expr),*) => ({
#[allow(unused_imports)]
use MutableSeq;
// leading _ to allow empty construction without a warning.
let mut _temp = ::vec::Vec::new();
$(_temp.push($e);)*

View File

@ -154,7 +154,7 @@ use core::default::Default;
use core::mem::{zeroed, replace, swap};
use core::ptr;
use {Collection, Mutable};
use {Collection, Mutable, MutableSeq};
use slice;
use vec::Vec;
@ -388,6 +388,7 @@ mod tests {
use priority_queue::PriorityQueue;
use vec::Vec;
use MutableSeq;
#[test]
fn test_iterator() {

View File

@ -20,7 +20,7 @@ use core::default::Default;
use core::fmt;
use core::iter::RandomAccessIterator;
use {Deque, Collection, Mutable};
use {Deque, Collection, Mutable, MutableSeq};
use vec::Vec;
static INITIAL_CAPACITY: uint = 8u; // 2^3
@ -114,6 +114,11 @@ impl<T> Deque<T> for RingBuf<T> {
}
}
impl<T> MutableSeq<T> for RingBuf<T> {
fn push(&mut self, t: T) { self.push_back(t) }
fn pop(&mut self) -> Option<T> { self.pop_back() }
}
impl<T> Default for RingBuf<T> {
#[inline]
fn default() -> RingBuf<T> { RingBuf::new() }

View File

@ -107,7 +107,7 @@ use core::mem;
use core::ptr;
use core::iter::{range_step, MultiplicativeIterator};
use Collection;
use {Collection, MutableSeq};
use vec::Vec;
pub use core::slice::{ref_slice, mut_ref_slice, Splits, Windows};
@ -731,7 +731,7 @@ mod tests {
use std::rt;
use slice::*;
use Mutable;
use {Mutable, MutableSeq};
use vec::Vec;
fn square(n: uint) -> uint { n * n }
@ -2133,6 +2133,7 @@ mod bench {
use test::Bencher;
use vec::Vec;
use MutableSeq;
#[bench]
fn iterator(b: &mut Bencher) {

View File

@ -77,7 +77,7 @@ use core::cmp;
use core::iter::AdditiveIterator;
use core::mem;
use Collection;
use {Collection, MutableSeq};
use hash;
use string::String;
use unicode;

View File

@ -20,7 +20,7 @@ use core::mem;
use core::ptr;
use core::raw::Slice;
use {Collection, Mutable};
use {Collection, Mutable, MutableSeq};
use hash;
use str;
use str::{CharRange, StrAllocating, MaybeOwned, Owned, Slice};

View File

@ -40,7 +40,7 @@ use core::mem::{replace, swap};
use core::ptr;
use std::hash::{Writer, Hash};
use {Collection, Mutable, Set, MutableSet, MutableMap, Map};
use {Collection, Mutable, Set, MutableSet, MutableMap, Map, MutableSeq};
use vec::Vec;
// This is implemented as an AA tree, which is a simplified variation of
@ -1127,7 +1127,7 @@ mod test_treemap {
use std::rand::Rng;
use std::rand;
use {Map, MutableMap, Mutable};
use {Map, MutableMap, Mutable, MutableSeq};
use super::{TreeMap, TreeNode};
#[test]

View File

@ -23,7 +23,7 @@ use core::num;
use core::ptr;
use core::uint;
use {Collection, Mutable};
use {Collection, Mutable, MutableSeq};
use slice::{MutableOrdVector, MutableVectorAllocating, CloneableVector};
use slice::{Items, MutItems};
@ -666,67 +666,6 @@ impl<T> Vec<T> {
}
}
/// Remove the last element from a vector and return it, or `None` if it is
/// empty.
///
/// # Example
///
/// ```
/// let mut vec = vec![1i, 2, 3];
/// assert_eq!(vec.pop(), Some(3));
/// assert_eq!(vec, vec![1, 2]);
/// ```
#[inline]
pub fn pop(&mut self) -> Option<T> {
if self.len == 0 {
None
} else {
unsafe {
self.len -= 1;
Some(ptr::read(self.as_slice().unsafe_ref(self.len())))
}
}
}
/// Append an element to a vector.
///
/// # Failure
///
/// Fails if the number of elements in the vector overflows a `uint`.
///
/// # Example
///
/// ```
/// let mut vec = vec![1i, 2];
/// vec.push(3);
/// assert_eq!(vec, vec![1, 2, 3]);
/// ```
#[inline]
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
self.len = self.len.checked_add(&1).expect("length overflow");
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 { fail!("capacity overflow") }
unsafe {
self.ptr = alloc_or_realloc(self.ptr, size,
self.cap * mem::size_of::<T>());
}
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;
}
}
/// Appends one element to the vector provided. The vector itself is then
/// returned for use again.
///
@ -1615,6 +1554,70 @@ impl<T:fmt::Show> fmt::Show for Vec<T> {
}
}
impl<T> MutableSeq<T> for Vec<T> {
/// Append an element to a vector.
///
/// # Failure
///
/// Fails if the number of elements in the vector overflows a `uint`.
///
/// # Example
///
/// ```rust
/// let mut vec = vec!(1i, 2);
/// vec.push(3);
/// assert_eq!(vec, vec!(1, 2, 3));
/// ```
#[inline]
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
self.len = self.len.checked_add(&1).expect("length overflow");
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 { fail!("capacity overflow") }
unsafe {
self.ptr = alloc_or_realloc(self.ptr, size,
self.cap * mem::size_of::<T>());
}
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;
}
}
/// Remove the last element from a vector and return 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));
/// ```
#[inline]
fn pop(&mut self) -> Option<T> {
if self.len == 0 {
None
} else {
unsafe {
self.len -= 1;
Some(ptr::read(self.as_slice().unsafe_ref(self.len())))
}
}
}
}
/// An iterator that moves out of a vector.
pub struct MoveItems<T> {
allocation: *mut T, // the block of memory allocated for the vector
@ -1704,6 +1707,8 @@ mod tests {
use test::Bencher;
use super::{unzip, raw, Vec};
use MutableSeq;
#[test]
fn test_small_vec_struct() {
assert!(size_of::<Vec<u8>>() == size_of::<uint>() * 3);

View File

@ -15,6 +15,7 @@
use core::prelude::*;
use alloc::boxed::Box;
use collections::MutableSeq;
use collections::vec::Vec;
use core::atomics;
use core::mem;

View File

@ -41,6 +41,7 @@ assert_eq!(*key_vector.get().unwrap(), vec![4]);
use core::prelude::*;
use alloc::boxed::Box;
use collections::MutableSeq;
use collections::vec::Vec;
use core::kinds::marker;
use core::mem;

View File

@ -15,7 +15,7 @@
#![experimental]
pub use core_collections::{Collection, Mutable, Map, MutableMap};
pub use core_collections::{Set, MutableSet, Deque};
pub use core_collections::{Set, MutableSet, Deque, MutableSeq};
pub use core_collections::{Bitv, BitvSet, BTree, DList, EnumSet};
pub use core_collections::{PriorityQueue, RingBuf, SmallIntMap};
pub use core_collections::{TreeMap, TreeSet, TrieMap, TrieSet};

View File

@ -20,6 +20,7 @@ A simple wrapper over the platform's dynamic library facilities
#![allow(missing_doc)]
use clone::Clone;
use collections::MutableSeq;
use c_str::ToCStr;
use iter::Iterator;
use mem;

View File

@ -15,7 +15,7 @@
// FIXME: Not sure how this should be structured
// FIXME: Iteration should probably be considered separately
use collections::Collection;
use collections::{Collection, MutableSeq};
use iter::Iterator;
use option::{Option, Some, None};
use result::{Ok, Err};

View File

@ -53,7 +53,7 @@ fs::unlink(&path);
use c_str::ToCStr;
use clone::Clone;
use collections::Collection;
use collections::{Collection, MutableSeq};
use io::standard_error;
use io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
use io::{IoResult, IoError, FileStat, SeekStyle, Seek, Writer, Reader};

View File

@ -20,6 +20,7 @@ definitions for a number of signals.
*/
use clone::Clone;
use collections::MutableSeq;
use comm::{Sender, Receiver, channel};
use io;
use iter::Iterator;

View File

@ -288,4 +288,6 @@ mod std {
#[cfg(test)] pub use os = realstd::os;
// The test runner requires std::slice::Vector, so re-export std::slice just for it.
#[cfg(test)] pub use slice;
pub use collections; // vec!() uses MutableSeq
}

View File

@ -315,6 +315,9 @@ macro_rules! try(
#[macro_export]
macro_rules! vec(
($($e:expr),*) => ({
#[allow(unused_imports)]
use std::collections::MutableSeq;
// leading _ to allow empty construction without a warning.
let mut _temp = ::std::vec::Vec::new();
$(_temp.push($e);)*

View File

@ -14,7 +14,7 @@
use char;
use clone::Clone;
use collections::Collection;
use collections::{Collection, MutableSeq};
use num::{NumCast, Zero, One, cast, Int};
use num::{Float, FPNaN, FPInfinite, ToPrimitive};
use num;

View File

@ -32,7 +32,7 @@
#![allow(non_snake_case_functions)]
use clone::Clone;
use collections::Collection;
use collections::{Collection, MutableSeq};
use fmt;
use io::{IoResult, IoError};
use iter::Iterator;

View File

@ -65,7 +65,7 @@ println!("path exists: {}", path.exists());
#![experimental]
use collections::Collection;
use collections::{Collection, MutableSeq};
use c_str::CString;
use clone::Clone;
use fmt;

View File

@ -13,7 +13,7 @@
use c_str::{CString, ToCStr};
use clone::Clone;
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use collections::Collection;
use collections::{Collection, MutableSeq};
use from_str::FromStr;
use hash;
use io::Writer;

View File

@ -16,7 +16,7 @@ use ascii::AsciiCast;
use c_str::{CString, ToCStr};
use clone::Clone;
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use collections::Collection;
use collections::{Collection, MutableSeq};
use from_str::FromStr;
use hash;
use io::Writer;

View File

@ -63,7 +63,7 @@
#[doc(no_inline)] pub use clone::Clone;
#[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
#[doc(no_inline)] pub use cmp::{Ordering, Less, Equal, Greater, Equiv};
#[doc(no_inline)] pub use collections::{Collection, Mutable, Map, MutableMap};
#[doc(no_inline)] pub use collections::{Collection, Mutable, Map, MutableMap, MutableSeq};
#[doc(no_inline)] pub use collections::{Set, MutableSet};
#[doc(no_inline)] pub use iter::{FromIterator, Extendable, ExactSize};
#[doc(no_inline)] pub use iter::{Iterator, DoubleEndedIterator};

View File

@ -55,7 +55,7 @@ use core::prelude::*;
use alloc::arc::Arc;
use alloc::heap::{allocate, deallocate};
use alloc::boxed::Box;
use collections::Vec;
use collections::{Vec, MutableSeq};
use core::kinds::marker;
use core::mem::{forget, min_align_of, size_of, transmute};
use core::ptr;

View File

@ -22,7 +22,7 @@ use core::finally::Finally;
use core::kinds::marker;
use core::mem;
use core::ty::Unsafe;
use collections::Vec;
use collections::{Vec, MutableSeq};
use mutex;
use comm::{Receiver, Sender, channel};