Skip to content

Commit

Permalink
collections: Move push/pop to MutableSeq
Browse files Browse the repository at this point in the history
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]
  • Loading branch information
brson committed Jul 23, 2014
1 parent c080d26 commit d36a8f3
Show file tree
Hide file tree
Showing 31 changed files with 142 additions and 86 deletions.
1 change: 1 addition & 0 deletions src/liballoc/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/libcollections/bitv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;


Expand Down
2 changes: 1 addition & 1 deletion src/libcollections/btree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
9 changes: 7 additions & 2 deletions src/libcollections/dlist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down Expand Up @@ -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() }
Expand Down Expand Up @@ -719,7 +724,7 @@ mod tests {
use test::Bencher;
use test;

use Deque;
use {Deque, MutableSeq};
use super::{DList, Node, ListInsertion};
use vec::Vec;

Expand Down
2 changes: 2 additions & 0 deletions src/libcollections/hash/sip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]);

Expand Down
11 changes: 10 additions & 1 deletion src/libcollections/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down Expand Up @@ -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.
///
Expand Down Expand Up @@ -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;
}
}
18 changes: 18 additions & 0 deletions src/libcollections/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);)*
Expand Down
3 changes: 2 additions & 1 deletion src/libcollections/priority_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -388,6 +388,7 @@ mod tests {

use priority_queue::PriorityQueue;
use vec::Vec;
use MutableSeq;

#[test]
fn test_iterator() {
Expand Down
7 changes: 6 additions & 1 deletion src/libcollections/ringbuf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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() }
Expand Down
5 changes: 3 additions & 2 deletions src/libcollections/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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 }
Expand Down Expand Up @@ -2133,6 +2133,7 @@ mod bench {
use test::Bencher;

use vec::Vec;
use MutableSeq;

#[bench]
fn iterator(b: &mut Bencher) {
Expand Down
2 changes: 1 addition & 1 deletion src/libcollections/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/libcollections/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down
4 changes: 2 additions & 2 deletions src/libcollections/treemap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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]
Expand Down
129 changes: 67 additions & 62 deletions src/libcollections/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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.
///
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/librustrt/at_exit_imp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use core::prelude::*;

use alloc::boxed::Box;
use collections::MutableSeq;
use collections::vec::Vec;
use core::atomics;
use core::mem;
Expand Down
1 change: 1 addition & 0 deletions src/librustrt/local_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading

0 comments on commit d36a8f3

Please sign in to comment.