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]
This commit is contained in:
Alex Crichton 2014-05-29 18:50:12 -07:00
parent d70a9b93d0
commit 6a585375a0
30 changed files with 397 additions and 371 deletions

View File

@ -60,36 +60,36 @@ DEPS_core :=
DEPS_rlibc :=
DEPS_alloc := core libc native:jemalloc
DEPS_debug := std
DEPS_std := core rand libc alloc native:rustrt native:backtrace
DEPS_std := core rand libc alloc collections native:rustrt native:backtrace
DEPS_graphviz := std
DEPS_green := std native:context_switch
DEPS_rustuv := std native:uv native:uv_support
DEPS_native := std
DEPS_syntax := std term serialize collections log fmt_macros debug
DEPS_syntax := std term serialize log fmt_macros debug
DEPS_rustc := syntax native:rustllvm flate arena serialize sync getopts \
collections time log graphviz debug
DEPS_rustdoc := rustc native:hoedown serialize sync getopts collections \
time log graphviz debug
DEPS_rustdoc := rustc native:hoedown serialize sync getopts \
test time debug
DEPS_flate := std native:miniz
DEPS_arena := std collections
DEPS_arena := std
DEPS_graphviz := std
DEPS_glob := std
DEPS_serialize := std collections log
DEPS_term := std collections log
DEPS_serialize := std log
DEPS_term := std log
DEPS_semver := std
DEPS_uuid := std serialize
DEPS_sync := std alloc
DEPS_getopts := std
DEPS_collections := std debug
DEPS_collections := core alloc
DEPS_fourcc := syntax std
DEPS_hexfloat := syntax std
DEPS_num := std
DEPS_test := std collections getopts serialize term time regex
DEPS_test := std getopts serialize term time regex
DEPS_time := std serialize sync
DEPS_rand := core
DEPS_url := std collections
DEPS_url := std
DEPS_log := std sync
DEPS_regex := std collections
DEPS_regex := std
DEPS_regex_macros = syntax std regex
DEPS_fmt_macros = std
@ -105,6 +105,7 @@ ONLY_RLIB_libc := 1
ONLY_RLIB_rlibc := 1
ONLY_RLIB_alloc := 1
ONLY_RLIB_rand := 1
ONLY_RLIB_collections := 1
################################################################################
# You should not need to edit below this line

View File

@ -10,14 +10,17 @@
#![allow(missing_doc)]
use core::prelude::*;
use std::cmp;
use std::fmt;
use std::iter::RandomAccessIterator;
use std::iter::{Enumerate, Repeat, Map, Zip};
use std::ops;
use std::slice;
use std::uint;
use core::cmp;
use core::fmt;
use core::iter::{Enumerate, Repeat, Map, Zip};
use core::ops;
use core::slice;
use core::uint;
use string::String;
use vec::Vec;
#[deriving(Clone)]
struct SmallBitv {

View File

@ -18,8 +18,13 @@
///a length (the height of the tree), and lower and upper bounds on the
///number of elements that a given node can contain.
use std::fmt;
use std::fmt::Show;
use core::prelude::*;
use alloc::owned::Box;
use core::fmt;
use core::fmt::Show;
use vec::Vec;
#[allow(missing_doc)]
pub struct BTree<K, V> {

View File

@ -10,7 +10,7 @@
//! Container traits for collections
use std::container::Mutable;
use core::prelude::*;
/// A double-ended sequence that allows querying, insertion and deletion at both ends.
pub trait Deque<T> : Mutable {

View File

@ -21,9 +21,12 @@
// Backlinks over DList::prev are raw pointers that form a full chain in
// the reverse direction.
use std::iter;
use std::mem;
use std::ptr;
use core::prelude::*;
use alloc::owned::Box;
use core::iter;
use core::mem;
use core::ptr;
use deque::Deque;

View File

@ -13,7 +13,9 @@
//! This module defines a container which uses an efficient bit mask
//! representation to hold C-like enum variants.
use std::num::Bitwise;
use core::prelude::*;
use core::num::Bitwise;
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
/// A specialized Set implementation to use enum types.

View File

@ -63,22 +63,17 @@
#![allow(unused_must_use)]
use container::Container;
use intrinsics::TypeId;
use iter::Iterator;
use option::{Option, Some, None};
use owned::Box;
use rc::Rc;
use result::{Result, Ok, Err};
use slice::{Vector, ImmutableVector};
use str::{Str, StrSlice};
use core::prelude::*;
use alloc::owned::Box;
use alloc::rc::Rc;
use core::intrinsics::TypeId;
use vec::Vec;
/// Reexport the `sip::hash` function as our default hasher.
pub use hash = self::sip::hash;
pub use Writer = io::Writer;
pub mod sip;
/// A trait that represents a hashable type. The `S` type parameter is an
@ -96,33 +91,29 @@ pub trait Hasher<S> {
fn hash<T: Hash<S>>(&self, value: &T) -> u64;
}
pub trait Writer {
fn write(&mut self, bytes: &[u8]);
}
//////////////////////////////////////////////////////////////////////////////
macro_rules! impl_hash(
( $( $ty:ty => $method:ident;)* ) => (
( $($ty:ident)* ) => (
$(
impl<S: Writer> Hash<S> for $ty {
#[inline]
fn hash(&self, state: &mut S) {
state.$method(*self);
let a: [u8, ..::core::$ty::BYTES] = unsafe {
::core::mem::transmute(*self)
};
state.write(a.as_slice())
}
}
)*
)
)
impl_hash!(
u8 => write_u8;
u16 => write_le_u16;
u32 => write_le_u32;
u64 => write_le_u64;
uint => write_le_uint;
i8 => write_i8;
i16 => write_le_i16;
i32 => write_le_i32;
i64 => write_le_i64;
int => write_le_int;
)
impl_hash!( u8 u16 u32 u64 uint i8 i16 i32 i64 int )
impl<S: Writer> Hash<S> for bool {
#[inline]
@ -142,7 +133,7 @@ impl<'a, S: Writer> Hash<S> for &'a str {
#[inline]
fn hash(&self, state: &mut S) {
state.write(self.as_bytes());
state.write_u8(0xFF);
0xffu8.hash(state)
}
}

View File

@ -24,17 +24,11 @@
* discouraged.
*/
use clone::Clone;
use container::Container;
use default::Default;
use int;
use io::{IoResult, Writer};
use iter::Iterator;
use result::Ok;
use slice::ImmutableVector;
use uint;
use core::prelude::*;
use super::{Hash, Hasher};
use core::default::Default;
use super::{Hash, Hasher, Writer};
/// `SipState` computes a SipHash 2-4 hash over a stream of bytes.
pub struct SipState {
@ -151,41 +145,11 @@ impl SipState {
v0 ^ v1 ^ v2 ^ v3
}
#[inline]
fn write_le(&mut self, n: u64, size: uint) {
self.tail |= n << 8*self.ntail;
self.ntail += size;
if self.ntail >= 8 {
let m = self.tail;
self.v3 ^= m;
compress!(self.v0, self.v1, self.v2, self.v3);
compress!(self.v0, self.v1, self.v2, self.v3);
self.v0 ^= m;
self.ntail -= 8;
if self.ntail == 0 {
self.tail = 0;
} else {
self.tail = n >> 64 - 8*self.ntail;
}
}
}
}
macro_rules! make_write_le(
($this:expr, $n:expr, $size:expr) => ({
$this.write_le($n as u64, $size);
$this.length += $size;
Ok(())
})
)
impl Writer for SipState {
#[inline]
fn write(&mut self, msg: &[u8]) -> IoResult<()> {
fn write(&mut self, msg: &[u8]) {
let length = msg.len();
self.length += length;
@ -196,7 +160,7 @@ impl Writer for SipState {
if length < needed {
self.tail |= u8to64_le!(msg, 0, length) << 8*self.ntail;
self.ntail += length;
return Ok(());
return
}
let m = self.tail | u8to64_le!(msg, 0, needed) << 8*self.ntail;
@ -228,60 +192,7 @@ impl Writer for SipState {
self.tail = u8to64_le!(msg, i, left);
self.ntail = left;
Ok(())
}
#[inline]
fn write_u8(&mut self, n: u8) -> IoResult<()> {
make_write_le!(self, n, 1)
}
#[inline]
fn write_le_u16(&mut self, n: u16) -> IoResult<()> {
make_write_le!(self, n, 2)
}
#[inline]
fn write_le_u32(&mut self, n: u32) -> IoResult<()> {
make_write_le!(self, n, 4)
}
#[inline]
fn write_le_u64(&mut self, n: u64) -> IoResult<()> {
make_write_le!(self, n, 8)
}
#[inline]
fn write_le_uint(&mut self, n: uint) -> IoResult<()> {
make_write_le!(self, n, uint::BYTES)
}
#[inline]
fn write_i8(&mut self, n: i8) -> IoResult<()> {
make_write_le!(self, n, 1)
}
#[inline]
fn write_le_i16(&mut self, n: i16) -> IoResult<()> {
make_write_le!(self, n, 2)
}
#[inline]
fn write_le_i32(&mut self, n: i32) -> IoResult<()> {
make_write_le!(self, n, 4)
}
#[inline]
fn write_le_i64(&mut self, n: i64) -> IoResult<()> {
make_write_le!(self, n, 8)
}
#[inline]
fn write_le_int(&mut self, n: int) -> IoResult<()> {
make_write_le!(self, n, int::BYTES)
}
}
impl Clone for SipState {

View File

@ -14,43 +14,66 @@
#![crate_id = "collections#0.11.0-pre"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![license = "MIT/ASL2"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/")]
#![feature(macro_rules, managed_boxes, default_type_params, phase)]
#![feature(macro_rules, managed_boxes, default_type_params, phase, globs)]
#![no_std]
#![deny(deprecated_owned_vector)]
extern crate debug;
#[phase(syntax, link)] extern crate core;
extern crate alloc;
#[cfg(test)] extern crate native;
#[cfg(test)] extern crate std;
#[cfg(test)] extern crate test;
#[cfg(test)] #[phase(syntax, link)] extern crate log;
pub use bitv::Bitv;
pub use bitv::{Bitv, BitvSet};
pub use btree::BTree;
pub use deque::Deque;
pub use dlist::DList;
pub use enum_set::EnumSet;
pub use hashmap::{HashMap, HashSet};
pub use lru_cache::LruCache;
pub use priority_queue::PriorityQueue;
pub use ringbuf::RingBuf;
pub use smallintmap::SmallIntMap;
pub use treemap::{TreeMap, TreeSet};
pub use trie::{TrieMap, TrieSet};
mod macros;
pub mod bitv;
pub mod btree;
pub mod deque;
pub mod dlist;
pub mod enum_set;
pub mod hashmap;
pub mod lru_cache;
pub mod priority_queue;
pub mod ringbuf;
pub mod smallintmap;
pub mod treemap;
pub mod trie;
pub mod slice;
pub mod str;
pub mod string;
pub mod vec;
pub mod hash;
// Internal unicode fiddly bits for the str module
mod unicode;
// FIXME(#14008) should this actually exist, or should a method be added?
fn expect<T>(a: core::option::Option<T>, b: &str) -> T {
match a {
core::option::Some(a) => a,
core::option::None => fail!(b),
}
}
mod std {
pub use core::fmt; // necessary for fail!()
pub use core::option; // necessary for fail!()
pub use core::clone; // deriving(Clone)
pub use core::cmp; // deriving(Eq, Ord, etc.)
pub use hash; // deriving(Hash)
}

View File

@ -0,0 +1,22 @@
// 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.
#![macro_escape]
/// Create a `std::vec::Vec` containing the arguments.
macro_rules! vec(
($($e:expr),*) => ({
// leading _ to allow empty construction without a warning.
let mut _temp = ::vec::Vec::new();
$(_temp.push($e);)*
_temp
});
($($e:expr),+,) => (vec!($($e),+))
)

View File

@ -12,10 +12,12 @@
#![allow(missing_doc)]
use std::clone::Clone;
use std::mem::{zeroed, replace, swap};
use std::ptr;
use std::slice;
use core::prelude::*;
use core::mem::{overwrite, zeroed, replace, swap};
use slice;
use vec::Vec;
/// A priority queue implemented with a binary heap
#[deriving(Clone)]

View File

@ -13,12 +13,14 @@
//! RingBuf implements the trait Deque. It should be imported with `use
//! collections::deque::Deque`.
use std::cmp;
use std::fmt;
use std::fmt::Show;
use std::iter::RandomAccessIterator;
use core::prelude::*;
use core::cmp;
use core::fmt;
use core::iter::RandomAccessIterator;
use deque::Deque;
use vec::Vec;
static INITIAL_CAPACITY: uint = 8u; // 2^3
static MINIMUM_CAPACITY: uint = 2u;
@ -393,7 +395,7 @@ impl<A> Extendable<A> for RingBuf<A> {
}
}
impl<T: Show> Show for RingBuf<T> {
impl<T: fmt::Show> fmt::Show for RingBuf<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "["));

View File

@ -99,20 +99,16 @@ There are a number of free functions that create or take vectors, for example:
#![doc(primitive = "slice")]
use mem::transmute;
use clone::Clone;
use cmp::{Ord, Ordering, Less, Greater};
use cmp;
use container::Container;
use iter::*;
use mem::size_of;
use mem;
use ops::Drop;
use option::{None, Option, Some};
use ptr::RawPtr;
use ptr;
use rt::heap::{allocate, deallocate};
use finally::try_finally;
use core::prelude::*;
use alloc::heap::{allocate, deallocate};
use core::cmp;
use core::finally::try_finally;
use core::mem::size_of;
use core::mem::transmute;
use core::mem;
use core::ptr;
use core::iter::{range_step, MultiplicativeIterator};
use vec::Vec;
pub use core::slice::{ref_slice, mut_ref_slice, Splits, Windows};
@ -295,13 +291,13 @@ impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
#[inline]
fn to_owned(&self) -> ~[T] {
use RawVec = core::raw::Vec;
use num::{CheckedAdd, CheckedMul};
use core::num::{CheckedAdd, CheckedMul};
let len = self.len();
let data_size = len.checked_mul(&mem::size_of::<T>());
let data_size = data_size.expect("overflow in to_owned()");
let data_size = ::expect(data_size, "overflow in to_owned()");
let size = mem::size_of::<RawVec<()>>().checked_add(&data_size);
let size = size.expect("overflow in to_owned()");
let size = ::expect(size, "overflow in to_owned()");
unsafe {
// this should pass the real required alignment

View File

@ -15,9 +15,13 @@
#![allow(missing_doc)]
use std::iter::{Enumerate, FilterMap};
use std::mem::replace;
use std::{vec, slice};
use core::prelude::*;
use core::iter::{Enumerate, FilterMap};
use core::mem::replace;
use {vec, slice};
use vec::Vec;
#[allow(missing_doc)]
pub struct SmallIntMap<T> {
@ -118,7 +122,7 @@ impl<V> SmallIntMap<V> {
}
pub fn get<'a>(&'a self, key: &uint) -> &'a V {
self.find(key).expect("key not present")
::expect(self.find(key), "key not present")
}
/// An iterator visiting all key-value pairs in ascending order by the keys.

View File

@ -67,21 +67,17 @@ is the same as `&[u8]`.
#![doc(primitive = "str")]
use char::Char;
use char;
use clone::Clone;
use cmp::{PartialEq, Eq, PartialOrd, Ord, Equiv, Ordering};
use container::Container;
use default::Default;
use fmt;
use io::Writer;
use iter::{Iterator, range, AdditiveIterator};
use mem::transmute;
use mem;
use option::{None, Option, Some};
use result::Result;
use slice::Vector;
use slice::{ImmutableVector, MutableVector};
use core::prelude::*;
use core::char;
use core::default::Default;
use core::fmt;
use core::cmp;
use core::iter::AdditiveIterator;
use core::mem;
use hash;
use slice::CloneableVector;
use string::String;
use vec::Vec;
@ -201,9 +197,6 @@ Section: Iterators
// Helper functions used for Unicode normalization
fn canonical_sort(comb: &mut [(char, u8)]) {
use iter::range;
use tuple::Tuple2;
let len = comb.len();
for i in range(0, len) {
let mut swapped = false;
@ -638,13 +631,10 @@ impl<'a> Default for MaybeOwned<'a> {
fn default() -> MaybeOwned<'a> { Slice("") }
}
impl<'a, H: Writer> ::hash::Hash<H> for MaybeOwned<'a> {
impl<'a, H: hash::Writer> hash::Hash<H> for MaybeOwned<'a> {
#[inline]
fn hash(&self, hasher: &mut H) {
match *self {
Slice(s) => s.hash(hasher),
Owned(ref s) => s.as_slice().hash(hasher),
}
self.as_slice().hash(hasher)
}
}
@ -660,10 +650,10 @@ impl<'a> fmt::Show for MaybeOwned<'a> {
/// Unsafe operations
pub mod raw {
use c_str::CString;
use libc;
use mem;
use raw::Slice;
use core::prelude::*;
use core::mem;
use core::raw::Slice;
use string::String;
use vec::Vec;
@ -681,9 +671,16 @@ pub mod raw {
}
/// Create a Rust string from a null-terminated C string
pub unsafe fn from_c_str(c_string: *libc::c_char) -> String {
pub unsafe fn from_c_str(c_string: *i8) -> String {
let mut buf = String::new();
buf.push_bytes(CString::new(c_string, false).as_bytes_no_nul());
let mut len = 0;
while *c_string.offset(len) != 0 {
len += 1;
}
buf.push_bytes(mem::transmute(Slice {
data: c_string,
len: len as uint,
}));
buf
}
@ -800,10 +797,8 @@ pub trait StrAllocating: Str {
#[deprecated = "obsolete, use `to_string`"]
#[inline]
fn to_owned(&self) -> String {
use slice::Vector;
unsafe {
::mem::transmute(Vec::from_slice(self.as_slice().as_bytes()))
mem::transmute(Vec::from_slice(self.as_slice().as_bytes()))
}
}
@ -852,9 +847,9 @@ pub trait StrAllocating: Str {
if sc == tc {
*dcol.get_mut(j + 1) = current;
} else {
*dcol.get_mut(j + 1) = ::cmp::min(current, next);
*dcol.get_mut(j + 1) = ::cmp::min(*dcol.get(j + 1),
*dcol.get(j)) + 1;
*dcol.get_mut(j + 1) = cmp::min(current, next);
*dcol.get_mut(j + 1) = cmp::min(*dcol.get(j + 1),
*dcol.get(j)) + 1;
}
current = next;

View File

@ -10,23 +10,17 @@
//! An owned, growable string that enforces that its contents are valid UTF-8.
use c_vec::CVec;
use char::Char;
use cmp::Equiv;
use container::{Container, Mutable};
use default::Default;
use fmt;
use from_str::FromStr;
use io::Writer;
use iter::{Extendable, FromIterator, Iterator, range};
use mem;
use option::{None, Option, Some};
use ptr::RawPtr;
use ptr;
use result::{Result, Ok, Err};
use slice::Vector;
use str::{CharRange, Str, StrSlice, StrAllocating};
use core::prelude::*;
use core::default::Default;
use core::fmt;
use core::mem;
use core::ptr;
use core::raw::Slice;
use hash;
use str;
use str::{CharRange, StrAllocating};
use vec::Vec;
/// A growable string stored as a UTF-8 encoded buffer.
@ -168,14 +162,17 @@ impl String {
#[inline]
pub fn push_char(&mut self, ch: char) {
let cur_len = self.len();
unsafe {
// This may use up to 4 bytes.
self.vec.reserve_additional(4);
// This may use up to 4 bytes.
self.vec.reserve_additional(4);
unsafe {
// Attempt to not use an intermediate buffer by just pushing bytes
// directly onto this string.
let mut c_vector = CVec::new(self.vec.as_mut_ptr().offset(cur_len as int), 4);
let used = ch.encode_utf8(c_vector.as_mut_slice());
let slice = Slice {
data: self.vec.as_ptr().offset(cur_len as int),
len: 4,
};
let used = ch.encode_utf8(mem::transmute(slice));
self.vec.set_len(cur_len + used);
}
}
@ -340,7 +337,7 @@ impl fmt::Show for String {
}
}
impl<H:Writer> ::hash::Hash<H> for String {
impl<H: hash::Writer> hash::Hash<H> for String {
#[inline]
fn hash(&self, hasher: &mut H) {
self.as_slice().hash(hasher)
@ -354,13 +351,6 @@ impl<'a, S: Str> Equiv<S> for String {
}
}
impl FromStr for String {
#[inline]
fn from_str(s: &str) -> Option<String> {
Some(s.to_string())
}
}
#[cfg(test)]
mod tests {
extern crate test;

View File

@ -12,13 +12,17 @@
//! trees. The only requirement for the types is that the key implements
//! `Ord`.
use std::cmp::Ordering;
use std::fmt::Show;
use std::fmt;
use std::iter::Peekable;
use std::iter;
use std::mem::{replace, swap};
use std::ptr;
use core::prelude::*;
use alloc::owned::Box;
use core::fmt;
use core::fmt::Show;
use core::iter::Peekable;
use core::iter;
use core::mem::{replace, swap};
use core::ptr;
use vec::Vec;
// This is implemented as an AA tree, which is a simplified variation of
// a red-black tree where red (horizontal) nodes can only be added

View File

@ -10,11 +10,15 @@
//! Ordered containers with integer keys, implemented as radix tries (`TrieSet` and `TrieMap` types)
use std::mem::zeroed;
use std::mem;
use std::slice::{Items, MutItems};
use std::slice;
use std::uint;
use core::prelude::*;
use alloc::owned::Box;
use core::mem::zeroed;
use core::mem;
use core::uint;
use slice::{Items, MutItems};
use slice;
// FIXME: #5244: need to manually update the TrieNode constructor
static SHIFT: uint = 4;
@ -457,7 +461,7 @@ fn insert<T>(count: &mut uint, child: &mut Child<T>, key: uint, value: T,
*child = Internal(new);
return ret;
}
_ => unreachable!()
_ => fail!("unreachable code"),
}
}

View File

@ -13,11 +13,9 @@
#![allow(missing_doc, non_uppercase_statics)]
pub mod normalization {
use option::{Some, None};
use slice::ImmutableVector;
use core::prelude::*;
fn bsearch_range_value_table(c: char, r: &'static [(char, char, u8)]) -> u8 {
use cmp::{Equal, Less, Greater};
match r.bsearch(|&(lo, hi, _)| {
if lo <= c && c <= hi { Equal }
else if hi < c { Less }

View File

@ -10,25 +10,22 @@
//! An owned, growable vector.
use RawVec = raw::Vec;
use clone::Clone;
use cmp::{PartialOrd, PartialEq, Ordering, Eq, Ord, max};
use container::{Container, Mutable};
use default::Default;
use fmt;
use iter::{DoubleEndedIterator, FromIterator, Extendable, Iterator, range};
use mem;
use num::{CheckedMul, CheckedAdd};
use num;
use ops::{Add, Drop};
use option::{None, Option, Some};
use ptr::RawPtr;
use ptr;
use raw::Slice;
use rt::heap::{allocate, reallocate, deallocate};
use slice::{ImmutableEqVector, ImmutableVector, Items, MutItems, MutableVector};
use slice::{MutableOrdVector, OwnedVector, Vector};
use slice::{MutableVectorAllocating};
use core::prelude::*;
use alloc::heap::{allocate, reallocate, deallocate};
use RawVec = core::raw::Vec;
use core::raw::Slice;
use core::cmp::max;
use core::default::Default;
use core::fmt;
use core::mem;
use core::num::{CheckedMul, CheckedAdd};
use core::num;
use core::ptr;
use core::uint;
use slice::{MutableTotalOrdVector, OwnedVector, MutableVectorAllocating};
use slice::{Items, MutItems};
/// An owned, growable vector.
///
@ -90,12 +87,12 @@ impl<T> Vec<T> {
/// ```
pub fn with_capacity(capacity: uint) -> Vec<T> {
if mem::size_of::<T>() == 0 {
Vec { len: 0, cap: ::uint::MAX, ptr: 0 as *mut T }
Vec { len: 0, cap: uint::MAX, ptr: 0 as *mut T }
} else if capacity == 0 {
Vec::new()
} else {
let size = capacity.checked_mul(&mem::size_of::<T>())
.expect("capacity overflow");
let size = ::expect(capacity.checked_mul(&mem::size_of::<T>()),
"capacity overflow");
let ptr = unsafe { allocate(size, mem::min_align_of::<T>()) };
Vec { len: 0, cap: capacity, ptr: ptr as *mut T }
}
@ -503,8 +500,8 @@ impl<T> Vec<T> {
if mem::size_of::<T>() == 0 { return }
if capacity > self.cap {
let size = capacity.checked_mul(&mem::size_of::<T>())
.expect("capacity overflow");
let size = ::expect(capacity.checked_mul(&mem::size_of::<T>()),
"capacity overflow");
unsafe {
self.ptr = alloc_or_realloc(self.ptr, size,
self.cap * mem::size_of::<T>());
@ -583,7 +580,7 @@ impl<T> Vec<T> {
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");
self.len = ::expect(self.len.checked_add(&1), "length overflow");
unsafe { mem::forget(value); }
return
}
@ -1530,9 +1527,9 @@ impl<T> FromVec<T> for ~[T] {
fn from_vec(mut v: Vec<T>) -> ~[T] {
let len = v.len();
let data_size = len.checked_mul(&mem::size_of::<T>());
let data_size = data_size.expect("overflow in from_vec()");
let data_size = ::expect(data_size, "overflow in from_vec()");
let size = mem::size_of::<RawVec<()>>().checked_add(&data_size);
let size = size.expect("overflow in from_vec()");
let size = ::expect(size, "overflow in from_vec()");
// In a post-DST world, we can attempt to reuse the Vec allocation by calling
// shrink_to_fit() on it. That may involve a reallocation+memcpy, but that's no
@ -1563,7 +1560,7 @@ impl<T> FromVec<T> for ~[T] {
/// Unsafe operations
pub mod raw {
use super::Vec;
use ptr;
use core::ptr;
/// Constructs a vector from an unsafe pointer to a buffer.
///

View File

@ -61,9 +61,7 @@
//! types to reintroduce mutability:
//!
//! ```
//! extern crate collections;
//!
//! use collections::HashMap;
//! use std::collections::HashMap;
//! use std::cell::RefCell;
//! use std::rc::Rc;
//!
@ -86,8 +84,6 @@
//! to take `&self`.
//!
//! ```
//! extern crate collections;
//!
//! use std::cell::RefCell;
//!
//! struct Graph {

View File

@ -31,12 +31,6 @@ pub use self::num::radix;
pub use self::num::Radix;
pub use self::num::RadixFmt;
macro_rules! write(
($dst:expr, $($arg:tt)*) => ({
format_args!(|args| { $dst.write_fmt(args) }, $($arg)*)
})
)
mod num;
mod float;
pub mod rt;

View File

@ -54,7 +54,18 @@ macro_rules! assert(
);
)
/// Runtime assertion, only without `--cfg ndebug`
#[macro_export]
macro_rules! debug_assert(
($(a:tt)*) => ({
if cfg!(not(ndebug)) {
assert!($($a)*);
}
})
)
/// Runtime assertion for equality, for details see std::macros
#[macro_export]
macro_rules! assert_eq(
($cond1:expr, $cond2:expr) => ({
let c1 = $cond1;
@ -65,6 +76,16 @@ macro_rules! assert_eq(
})
)
/// Runtime assertion for equality, only without `--cfg ndebug`
#[macro_export]
macro_rules! debug_assert_eq(
($($a:tt)*) => ({
if cfg!(not(ndebug)) {
assert_eq!($($a)*);
}
})
)
/// Runtime assertion, disableable at compile time
#[macro_export]
macro_rules! debug_assert(
@ -86,3 +107,13 @@ macro_rules! vec( ($($e:expr),*) => ({
#[cfg(test)]
macro_rules! format( ($($arg:tt)*) => (format_args!(::fmt::format, $($arg)*)) )
/// Write some formatted data into a stream.
///
/// Identical to the macro in `std::macros`
#[macro_export]
macro_rules! write(
($dst:expr, $($arg:tt)*) => ({
format_args_method!($dst, write_fmt, $($arg)*)
})
)

View File

@ -10,40 +10,39 @@
//! Unordered containers, implemented as hash-tables (`HashSet` and `HashMap` types)
use std::container::{Container, Mutable, Map, MutableMap, Set, MutableSet};
use std::clone::Clone;
use std::cmp::{PartialEq, Eq, Equiv, max};
use std::default::Default;
use std::fmt;
use std::fmt::Show;
use std::hash::{Hash, Hasher, sip};
use std::iter;
use std::iter::{Iterator, FromIterator, Extendable};
use std::iter::{FilterMap, Chain, Repeat, Zip};
use std::iter::{range, range_inclusive};
use std::mem::replace;
use std::num;
use std::option::{Option, Some, None};
use std::rand;
use std::rand::Rng;
use std::result::{Ok, Err};
use std::slice::ImmutableVector;
use clone::Clone;
use cmp::{max, Eq, Equiv, PartialEq};
use container::{Container, Mutable, Set, MutableSet, Map, MutableMap};
use default::Default;
use fmt::Show;
use fmt;
use hash::{Hash, Hasher, sip};
use iter::{Iterator, FilterMap, Chain, Repeat, Zip, Extendable};
use iter::{range, range_inclusive, FromIterator};
use iter;
use mem::replace;
use num;
use option::{Some, None, Option};
use rand::Rng;
use rand;
use result::{Ok, Err};
mod table {
use std::clone::Clone;
use std::cmp;
use std::cmp::PartialEq;
use std::hash::{Hash, Hasher};
use std::kinds::marker;
use std::num::{CheckedMul, is_power_of_two};
use std::option::{Option, Some, None};
use std::prelude::Drop;
use std::ptr;
use std::ptr::RawPtr;
use std::mem::{min_align_of, size_of};
use std::intrinsics::{move_val_init, set_memory, transmute};
use std::iter::{Iterator, range_step_inclusive};
use std::rt::heap::{allocate, deallocate};
use clone::Clone;
use cmp;
use hash::{Hash, Hasher};
use iter::range_step_inclusive;
use iter::{Iterator, range};
use kinds::marker;
use mem::{min_align_of, size_of};
use mem::{overwrite, transmute};
use num::{CheckedMul, is_power_of_two};
use ops::Drop;
use option::{Some, None, Option, Expect};
use ptr::RawPtr;
use ptr::set_memory;
use ptr;
use rt::heap::{allocate, deallocate};
static EMPTY_BUCKET: u64 = 0u64;
@ -217,12 +216,12 @@ mod table {
/// Does not initialize the buckets. The caller should ensure they,
/// at the very least, set every hash to EMPTY_BUCKET.
unsafe fn new_uninitialized(capacity: uint) -> RawTable<K, V> {
let hashes_size =
capacity.checked_mul(&size_of::<u64>()).expect("capacity overflow");
let keys_size =
capacity.checked_mul(&size_of::< K >()).expect("capacity overflow");
let vals_size =
capacity.checked_mul(&size_of::< V >()).expect("capacity overflow");
let hashes_size = capacity.checked_mul(&size_of::<u64>())
.expect("capacity overflow");
let keys_size = capacity.checked_mul(&size_of::< K >())
.expect("capacity overflow");
let vals_size = capacity.checked_mul(&size_of::< V >())
.expect("capacity overflow");
// Allocating hashmaps is a little tricky. We need to allocate three
// arrays, but since we know their sizes and alignments up front,
@ -339,8 +338,8 @@ mod table {
unsafe {
debug_assert_eq!(*self.hashes.offset(idx), EMPTY_BUCKET);
*self.hashes.offset(idx) = hash.inspect();
move_val_init(&mut *self.keys.offset(idx), k);
move_val_init(&mut *self.vals.offset(idx), v);
overwrite(&mut *self.keys.offset(idx), k);
overwrite(&mut *self.vals.offset(idx), v);
}
self.size += 1;
@ -519,8 +518,8 @@ mod table {
let hash = idx.hash().inspect();
let (k, v) = self.read(&idx);
*new_ht.hashes.offset(i as int) = hash;
move_val_init(&mut *new_ht.keys.offset(i as int), (*k).clone());
move_val_init(&mut *new_ht.vals.offset(i as int), (*v).clone());
overwrite(&mut *new_ht.keys.offset(i as int), (*k).clone());
overwrite(&mut *new_ht.vals.offset(i as int), (*v).clone());
}
}
}
@ -1037,6 +1036,7 @@ impl<K: Hash + Eq, V> HashMap<K, V, sip::SipHasher> {
HashMap::with_capacity(INITIAL_CAPACITY)
}
/// Creates an empty hash map with the given initial capacity.
pub fn with_capacity(capacity: uint) -> HashMap<K, V, sip::SipHasher> {
let mut r = rand::task_rng();
let r0 = r.gen();
@ -1047,6 +1047,9 @@ impl<K: Hash + Eq, V> HashMap<K, V, sip::SipHasher> {
}
impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
/// Creates an empty hashmap which will use the given hasher to hash keys.
///
/// The creates map has the default initial capacity.
pub fn with_hasher(hasher: H) -> HashMap<K, V, H> {
HashMap::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
}
@ -1326,7 +1329,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
pub fn get<'a>(&'a self, k: &K) -> &'a V {
match self.find(k) {
Some(v) => v,
None => fail!("No entry found for key: {:?}", k)
None => fail!("no entry found for key")
}
}
@ -1334,7 +1337,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
pub fn get_mut<'a>(&'a mut self, k: &K) -> &'a mut V {
match self.find_mut(k) {
Some(v) => v,
None => fail!("No entry found for key: {:?}", k)
None => fail!("no entry found for key")
}
}
@ -1533,6 +1536,10 @@ impl<T: Hash + Eq> HashSet<T, sip::SipHasher> {
}
impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
/// Creates a new empty hash set which will use the given hasher to hash
/// keys.
///
/// The hash set is also created with the default initial capacity.
pub fn with_hasher(hasher: H) -> HashSet<T, H> {
HashSet::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
}
@ -1632,8 +1639,10 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Extendable<T> for HashSet<T, H>
}
}
impl<T: Eq + Hash> Default for HashSet<T, sip::SipHasher> {
fn default() -> HashSet<T> { HashSet::new() }
impl<T: TotalEq + Hash<S>, S, H: Hasher<S> + Default> Default for HashSet<T, H> {
fn default() -> HashSet<T, H> {
HashSet::with_hasher(Default::default())
}
}
// `Repeat` is used to feed the filter closure an explicit capture

View File

@ -37,13 +37,18 @@
//! assert!(cache.get(&2).is_none());
//! ```
use std::container::Container;
use std::hash::Hash;
use std::fmt;
use std::mem;
use std::ptr;
use HashMap;
use cmp::{Eq, TotalEq};
use collections::HashMap;
use container::{Container, Mutable, MutableMap};
use fmt;
use hash::Hash;
use iter::{range, Iterator};
use mem;
use ops::Drop;
use option::{Some, None, Option};
use owned::Box;
use ptr;
use result::{Ok, Err};
struct KeyRef<K> { k: *K }

View File

@ -0,0 +1,25 @@
// Copyright 2013-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.
/*!
* Collection types.
*/
pub use core_collections::{Bitv, BitvSet, BTree, Deque, DList, EnumSet};
pub use core_collections::{PriorityQueue, RingBuf, SmallIntMap};
pub use core_collections::{TreeMap, TreeSet, TrieMap, TrieSet};
pub use core_collections::{bitv, btree, deque, dlist, enum_set};
pub use core_collections::{priority_queue, ringbuf, smallintmap, treemap, trie};
pub use self::hashmap::{HashMap, HashSet};
pub use self::lru_cache::LruCache;
pub mod hashmap;
pub mod lru_cache;

View File

@ -11,6 +11,8 @@
//! The `FromStr` trait for types that can be created from strings
use option::{Option, Some, None};
use string::String;
use str::StrAllocating;
/// A trait to abstract the idea of creating a new instance of a type from a
/// string.
@ -47,6 +49,13 @@ impl FromStr for bool {
}
}
impl FromStr for String {
#[inline]
fn from_str(s: &str) -> Option<String> {
Some(s.to_string())
}
}
#[cfg(test)]
mod test {
use prelude::*;

View File

@ -124,6 +124,7 @@ extern crate alloc;
extern crate core;
extern crate libc;
extern crate core_rand = "rand";
extern crate core_collections = "collections";
// Make std testable by not duplicating lang items. See #2912
#[cfg(test)] extern crate realstd = "std";
@ -160,6 +161,12 @@ pub use core::option;
pub use alloc::owned;
pub use alloc::rc;
pub use core_collections::hash;
pub use core_collections::slice;
pub use core_collections::str;
pub use core_collections::string;
pub use core_collections::vec;
// Run tests with libgreen instead of libnative.
//
// FIXME: This egregiously hacks around starting the test runner in a different
@ -203,10 +210,6 @@ pub mod prelude;
#[path = "num/f32.rs"] pub mod f32;
#[path = "num/f64.rs"] pub mod f64;
pub mod slice;
pub mod vec;
pub mod str;
pub mod string;
pub mod rand;
pub mod ascii;
@ -218,7 +221,10 @@ pub mod gc;
pub mod from_str;
pub mod num;
pub mod to_str;
pub mod hash;
/* Common data structures */
pub mod collections;
/* Tasks and communication */
@ -242,10 +248,6 @@ pub mod cleanup;
#[unstable]
pub mod unstable;
/* For internal use, not exported */
mod unicode;
// FIXME #7809: This shouldn't be pub, and it should be reexported under 'unstable'
// but name resolution doesn't work without it being pub.
#[unstable]

View File

@ -10,16 +10,17 @@
//! POSIX file path handling
use container::Container;
use c_str::{CString, ToCStr};
use clone::Clone;
use cmp::{PartialEq, Eq};
use container::Container;
use from_str::FromStr;
use hash;
use io::Writer;
use iter::{DoubleEndedIterator, AdditiveIterator, Extendable, Iterator, Map};
use option::{Option, None, Some};
use str;
use str::Str;
use str;
use slice::{CloneableVector, Splits, Vector, VectorVector,
ImmutableEqVector, OwnedVector, ImmutableVector};
use vec::Vec;
@ -105,7 +106,7 @@ impl<'a> ToCStr for &'a Path {
}
}
impl<S: Writer> ::hash::Hash<S> for Path {
impl<S: hash::Writer> hash::Hash<S> for Path {
#[inline]
fn hash(&self, state: &mut S) {
self.repr.hash(state)

View File

@ -16,6 +16,7 @@ use clone::Clone;
use cmp::{PartialEq, Eq};
use container::Container;
use from_str::FromStr;
use hash;
use io::Writer;
use iter::{AdditiveIterator, DoubleEndedIterator, Extendable, Iterator, Map};
use mem;
@ -126,7 +127,7 @@ impl<'a> ToCStr for &'a Path {
}
}
impl<S: Writer> ::hash::Hash<S> for Path {
impl<S: hash::Writer> hash::Hash<S> for Path {
#[cfg(not(test))]
#[inline]
fn hash(&self, state: &mut S) {