Browse Source

Patch `std` to be compatible with Rust nightly-2017-12-01

This only fixes things enough so that the project compiles again. More standard library changes from upstream Rust will be pulled in later.
pull/10/head
Fenrir 7 years ago committed by FenrirWolf
parent
commit
8ba058552b
  1. 175
      ctr-std/src/collections/hash/map.rs
  2. 64
      ctr-std/src/collections/hash/set.rs
  3. 40
      ctr-std/src/collections/hash/table.rs
  4. 14
      ctr-std/src/lib.rs
  5. 1
      ctr-std/src/panic.rs
  6. 1
      ctr-std/src/path.rs
  7. 286
      ctr-std/src/rand/mod.rs
  8. 108
      ctr-std/src/rand/reader.rs
  9. 2
      ctr-std/src/sync/once.rs
  10. 2
      ctr-std/src/sys/unix/mod.rs
  11. 57
      ctr-std/src/sys/unix/rand.rs

175
ctr-std/src/collections/hash/map.rs

@ -20,8 +20,8 @@ use hash::{Hash, Hasher, BuildHasher, SipHasher13}; @@ -20,8 +20,8 @@ use hash::{Hash, Hasher, BuildHasher, SipHasher13};
use iter::{FromIterator, FusedIterator};
use mem::{self, replace};
use ops::{Deref, Index, InPlace, Place, Placer};
use rand::{self, Rng};
use ptr;
use sys;
use super::table::{self, Bucket, EmptyBucket, FullBucket, FullBucketMut, RawTable, SafeHash};
use super::table::BucketState::{Empty, Full};
@ -203,7 +203,7 @@ const DISPLACEMENT_THRESHOLD: usize = 128; @@ -203,7 +203,7 @@ const DISPLACEMENT_THRESHOLD: usize = 128;
// so we round that up to 128.
//
// At a load factor of α, the odds of finding the target bucket after exactly n
// unsuccesful probes[1] are
// unsuccessful probes[1] are
//
// Pr_α{displacement = n} =
// (1 - α) / α * ∑_{k≥1} e^(-kα) * (kα)^(k+n) / (k + n)! * (1 - kα / (k + n + 1))
@ -419,7 +419,7 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> Inter @@ -419,7 +419,7 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> Inter
Empty(bucket) => {
// Found a hole!
return InternalEntry::Vacant {
hash: hash,
hash,
elem: NoElem(bucket, displacement),
};
}
@ -433,7 +433,7 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> Inter @@ -433,7 +433,7 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> Inter
// We can finish the search early if we hit any bucket
// with a lower distance to initial bucket than we've probed.
return InternalEntry::Vacant {
hash: hash,
hash,
elem: NeqElem(full, probe_displacement),
};
}
@ -588,6 +588,9 @@ impl<K, V, S> HashMap<K, V, S> @@ -588,6 +588,9 @@ impl<K, V, S> HashMap<K, V, S>
impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
/// Creates an empty `HashMap`.
///
/// The hash map is initially created with a capacity of 0, so it will not allocate until it
/// is first inserted into.
///
/// # Examples
///
/// ```
@ -646,7 +649,7 @@ impl<K, V, S> HashMap<K, V, S> @@ -646,7 +649,7 @@ impl<K, V, S> HashMap<K, V, S>
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
pub fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
HashMap {
hash_builder: hash_builder,
hash_builder,
resize_policy: DefaultResizePolicy::new(),
table: RawTable::new(0),
}
@ -679,8 +682,8 @@ impl<K, V, S> HashMap<K, V, S> @@ -679,8 +682,8 @@ impl<K, V, S> HashMap<K, V, S>
let resize_policy = DefaultResizePolicy::new();
let raw_cap = resize_policy.raw_capacity(capacity);
HashMap {
hash_builder: hash_builder,
resize_policy: resize_policy,
hash_builder,
resize_policy,
table: RawTable::new(raw_cap),
}
}
@ -688,6 +691,17 @@ impl<K, V, S> HashMap<K, V, S> @@ -688,6 +691,17 @@ impl<K, V, S> HashMap<K, V, S>
/// Returns a reference to the map's [`BuildHasher`].
///
/// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html
///
/// # Examples
///
/// ```
/// use std::collections::HashMap;
/// use std::collections::hash_map::RandomState;
///
/// let hasher = RandomState::new();
/// let map: HashMap<isize, isize> = HashMap::with_hasher(hasher);
/// let hasher: &RandomState = map.hasher();
/// ```
#[stable(feature = "hashmap_public_hasher", since = "1.9.0")]
pub fn hasher(&self) -> &S {
&self.hash_builder
@ -1099,6 +1113,7 @@ impl<K, V, S> HashMap<K, V, S> @@ -1099,6 +1113,7 @@ impl<K, V, S> HashMap<K, V, S>
/// assert_eq!(map.get(&2), None);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where K: Borrow<Q>,
Q: Hash + Eq
@ -1347,7 +1362,7 @@ pub struct Iter<'a, K: 'a, V: 'a> { @@ -1347,7 +1362,7 @@ pub struct Iter<'a, K: 'a, V: 'a> {
inner: table::Iter<'a, K, V>,
}
// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V> Clone for Iter<'a, K, V> {
fn clone(&self) -> Iter<'a, K, V> {
@ -1400,7 +1415,7 @@ pub struct Keys<'a, K: 'a, V: 'a> { @@ -1400,7 +1415,7 @@ pub struct Keys<'a, K: 'a, V: 'a> {
inner: Iter<'a, K, V>,
}
// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V> Clone for Keys<'a, K, V> {
fn clone(&self) -> Keys<'a, K, V> {
@ -1429,7 +1444,7 @@ pub struct Values<'a, K: 'a, V: 'a> { @@ -1429,7 +1444,7 @@ pub struct Values<'a, K: 'a, V: 'a> {
inner: Iter<'a, K, V>,
}
// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V> Clone for Values<'a, K, V> {
fn clone(&self) -> Values<'a, K, V> {
@ -1496,14 +1511,14 @@ impl<'a, K, V> InternalEntry<K, V, &'a mut RawTable<K, V>> { @@ -1496,14 +1511,14 @@ impl<'a, K, V> InternalEntry<K, V, &'a mut RawTable<K, V>> {
InternalEntry::Occupied { elem } => {
Some(Occupied(OccupiedEntry {
key: Some(key),
elem: elem,
elem,
}))
}
InternalEntry::Vacant { hash, elem } => {
Some(Vacant(VacantEntry {
hash: hash,
key: key,
elem: elem,
hash,
key,
elem,
}))
}
InternalEntry::TableIsEmpty => None,
@ -1618,7 +1633,7 @@ impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S> @@ -1618,7 +1633,7 @@ impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S>
type Item = (&'a K, &'a mut V);
type IntoIter = IterMut<'a, K, V>;
fn into_iter(mut self) -> IterMut<'a, K, V> {
fn into_iter(self) -> IterMut<'a, K, V> {
self.iter_mut()
}
}
@ -1999,6 +2014,68 @@ impl<'a, K, V> Entry<'a, K, V> { @@ -1999,6 +2014,68 @@ impl<'a, K, V> Entry<'a, K, V> {
Vacant(ref entry) => entry.key(),
}
}
/// Provides in-place mutable access to an occupied entry before any
/// potential inserts into the map.
///
/// # Examples
///
/// ```
/// #![feature(entry_and_modify)]
/// use std::collections::HashMap;
///
/// let mut map: HashMap<&str, u32> = HashMap::new();
///
/// map.entry("poneyland")
/// .and_modify(|e| { *e += 1 })
/// .or_insert(42);
/// assert_eq!(map["poneyland"], 42);
///
/// map.entry("poneyland")
/// .and_modify(|e| { *e += 1 })
/// .or_insert(42);
/// assert_eq!(map["poneyland"], 43);
/// ```
#[unstable(feature = "entry_and_modify", issue = "44733")]
pub fn and_modify<F>(self, mut f: F) -> Self
where F: FnMut(&mut V)
{
match self {
Occupied(mut entry) => {
f(entry.get_mut());
Occupied(entry)
},
Vacant(entry) => Vacant(entry),
}
}
}
impl<'a, K, V: Default> Entry<'a, K, V> {
#[unstable(feature = "entry_or_default", issue = "44324")]
/// Ensures a value is in the entry by inserting the default value if empty,
/// and returns a mutable reference to the value in the entry.
///
/// # Examples
///
/// ```
/// #![feature(entry_or_default)]
/// # fn main() {
/// use std::collections::HashMap;
///
/// let mut map: HashMap<&str, Option<u32>> = HashMap::new();
/// map.entry("poneyland").or_default();
///
/// assert_eq!(map["poneyland"], None);
/// # }
/// ```
pub fn or_default(self) -> &'a mut V {
match self {
Occupied(entry) => entry.into_mut(),
Vacant(entry) => entry.insert(Default::default()),
}
}
}
impl<'a, K, V> OccupiedEntry<'a, K, V> {
@ -2161,6 +2238,68 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> { @@ -2161,6 +2238,68 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
fn take_key(&mut self) -> Option<K> {
self.key.take()
}
/// Replaces the entry, returning the old key and value. The new key in the hash map will be
/// the key used to create this entry.
///
/// # Examples
///
/// ```
/// #![feature(map_entry_replace)]
/// use std::collections::hash_map::{Entry, HashMap};
/// use std::rc::Rc;
///
/// let mut map: HashMap<Rc<String>, u32> = HashMap::new();
/// map.insert(Rc::new("Stringthing".to_string()), 15);
///
/// let my_key = Rc::new("Stringthing".to_string());
///
/// if let Entry::Occupied(entry) = map.entry(my_key) {
/// // Also replace the key with a handle to our other key.
/// let (old_key, old_value): (Rc<String>, u32) = entry.replace_entry(16);
/// }
///
/// ```
#[unstable(feature = "map_entry_replace", issue = "44286")]
pub fn replace_entry(mut self, value: V) -> (K, V) {
let (old_key, old_value) = self.elem.read_mut();
let old_key = mem::replace(old_key, self.key.unwrap());
let old_value = mem::replace(old_value, value);
(old_key, old_value)
}
/// Replaces the key in the hash map with the key used to create this entry.
///
/// # Examples
///
/// ```
/// #![feature(map_entry_replace)]
/// use std::collections::hash_map::{Entry, HashMap};
/// use std::rc::Rc;
///
/// let mut map: HashMap<Rc<String>, u32> = HashMap::new();
/// let mut known_strings: Vec<Rc<String>> = Vec::new();
///
/// // Initialise known strings, run program, etc.
///
/// reclaim_memory(&mut map, &known_strings);
///
/// fn reclaim_memory(map: &mut HashMap<Rc<String>, u32>, known_strings: &[Rc<String>] ) {
/// for s in known_strings {
/// if let Entry::Occupied(entry) = map.entry(s.clone()) {
/// // Replaces the entry's key with our version of it in `known_strings`.
/// entry.replace_key();
/// }
/// }
/// }
/// ```
#[unstable(feature = "map_entry_replace", issue = "44286")]
pub fn replace_key(mut self) -> K {
let (old_key, _) = self.elem.read_mut();
mem::replace(old_key, self.key.unwrap())
}
}
impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
@ -2354,9 +2493,7 @@ impl RandomState { @@ -2354,9 +2493,7 @@ impl RandomState {
// increment one of the seeds on every RandomState creation, giving
// every corresponding HashMap a different iteration order.
thread_local!(static KEYS: Cell<(u64, u64)> = {
let r = rand::OsRng::new();
let mut r = r.expect("failed to create an OS RNG");
Cell::new((r.gen(), r.gen()))
Cell::new(sys::hashmap_random_keys())
});
KEYS.with(|keys| {
@ -2448,6 +2585,7 @@ impl<K, S, Q: ?Sized> super::Recover<Q> for HashMap<K, (), S> @@ -2448,6 +2585,7 @@ impl<K, S, Q: ?Sized> super::Recover<Q> for HashMap<K, (), S>
{
type Key = K;
#[inline]
fn get(&self, key: &Q) -> Option<&K> {
self.search(key).into_occupied_bucket().map(|bucket| bucket.into_refs().0)
}
@ -2460,6 +2598,7 @@ impl<K, S, Q: ?Sized> super::Recover<Q> for HashMap<K, (), S> @@ -2460,6 +2598,7 @@ impl<K, S, Q: ?Sized> super::Recover<Q> for HashMap<K, (), S>
self.search_mut(key).into_occupied_bucket().map(|bucket| pop_internal(bucket).0)
}
#[inline]
fn replace(&mut self, key: K) -> Option<K> {
self.reserve(1);

64
ctr-std/src/collections/hash/set.rs

@ -123,13 +123,16 @@ pub struct HashSet<T, S = RandomState> { @@ -123,13 +123,16 @@ pub struct HashSet<T, S = RandomState> {
}
impl<T: Hash + Eq> HashSet<T, RandomState> {
/// Creates an empty HashSet.
/// Creates an empty `HashSet`.
///
/// The hash set is initially created with a capacity of 0, so it will not allocate until it
/// is first inserted into.
///
/// # Examples
///
/// ```
/// use std::collections::HashSet;
/// let mut set: HashSet<i32> = HashSet::new();
/// let set: HashSet<i32> = HashSet::new();
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -146,7 +149,8 @@ impl<T: Hash + Eq> HashSet<T, RandomState> { @@ -146,7 +149,8 @@ impl<T: Hash + Eq> HashSet<T, RandomState> {
///
/// ```
/// use std::collections::HashSet;
/// let mut set: HashSet<i32> = HashSet::with_capacity(10);
/// let set: HashSet<i32> = HashSet::with_capacity(10);
/// assert!(set.capacity() >= 10);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -215,6 +219,17 @@ impl<T, S> HashSet<T, S> @@ -215,6 +219,17 @@ impl<T, S> HashSet<T, S>
/// Returns a reference to the set's [`BuildHasher`].
///
/// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html
///
/// # Examples
///
/// ```
/// use std::collections::HashSet;
/// use std::collections::hash_map::RandomState;
///
/// let hasher = RandomState::new();
/// let set: HashSet<i32> = HashSet::with_hasher(hasher);
/// let hasher: &RandomState = set.hasher();
/// ```
#[stable(feature = "hashmap_public_hasher", since = "1.9.0")]
pub fn hasher(&self) -> &S {
self.map.hasher()
@ -249,6 +264,7 @@ impl<T, S> HashSet<T, S> @@ -249,6 +264,7 @@ impl<T, S> HashSet<T, S>
/// use std::collections::HashSet;
/// let mut set: HashSet<i32> = HashSet::new();
/// set.reserve(10);
/// assert!(set.capacity() >= 10);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn reserve(&mut self, additional: usize) {
@ -312,19 +328,19 @@ impl<T, S> HashSet<T, S> @@ -312,19 +328,19 @@ impl<T, S> HashSet<T, S>
/// println!("{}", x); // Print 1
/// }
///
/// let diff: HashSet<_> = a.difference(&b).cloned().collect();
/// assert_eq!(diff, [1].iter().cloned().collect());
/// let diff: HashSet<_> = a.difference(&b).collect();
/// assert_eq!(diff, [1].iter().collect());
///
/// // Note that difference is not symmetric,
/// // and `b - a` means something else:
/// let diff: HashSet<_> = b.difference(&a).cloned().collect();
/// assert_eq!(diff, [4].iter().cloned().collect());
/// let diff: HashSet<_> = b.difference(&a).collect();
/// assert_eq!(diff, [4].iter().collect());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn difference<'a>(&'a self, other: &'a HashSet<T, S>) -> Difference<'a, T, S> {
Difference {
iter: self.iter(),
other: other,
other,
}
}
@ -343,11 +359,11 @@ impl<T, S> HashSet<T, S> @@ -343,11 +359,11 @@ impl<T, S> HashSet<T, S>
/// println!("{}", x);
/// }
///
/// let diff1: HashSet<_> = a.symmetric_difference(&b).cloned().collect();
/// let diff2: HashSet<_> = b.symmetric_difference(&a).cloned().collect();
/// let diff1: HashSet<_> = a.symmetric_difference(&b).collect();
/// let diff2: HashSet<_> = b.symmetric_difference(&a).collect();
///
/// assert_eq!(diff1, diff2);
/// assert_eq!(diff1, [1, 4].iter().cloned().collect());
/// assert_eq!(diff1, [1, 4].iter().collect());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn symmetric_difference<'a>(&'a self,
@ -371,14 +387,14 @@ impl<T, S> HashSet<T, S> @@ -371,14 +387,14 @@ impl<T, S> HashSet<T, S>
/// println!("{}", x);
/// }
///
/// let intersection: HashSet<_> = a.intersection(&b).cloned().collect();
/// assert_eq!(intersection, [2, 3].iter().cloned().collect());
/// let intersection: HashSet<_> = a.intersection(&b).collect();
/// assert_eq!(intersection, [2, 3].iter().collect());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn intersection<'a>(&'a self, other: &'a HashSet<T, S>) -> Intersection<'a, T, S> {
Intersection {
iter: self.iter(),
other: other,
other,
}
}
@ -397,8 +413,8 @@ impl<T, S> HashSet<T, S> @@ -397,8 +413,8 @@ impl<T, S> HashSet<T, S>
/// println!("{}", x);
/// }
///
/// let union: HashSet<_> = a.union(&b).cloned().collect();
/// assert_eq!(union, [1, 2, 3, 4].iter().cloned().collect());
/// let union: HashSet<_> = a.union(&b).collect();
/// assert_eq!(union, [1, 2, 3, 4].iter().collect());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn union<'a>(&'a self, other: &'a HashSet<T, S>) -> Union<'a, T, S> {
@ -440,6 +456,22 @@ impl<T, S> HashSet<T, S> @@ -440,6 +456,22 @@ impl<T, S> HashSet<T, S>
}
/// Clears the set, returning all elements in an iterator.
///
/// # Examples
///
/// ```
/// use std::collections::HashSet;
///
/// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
/// assert!(!set.is_empty());
///
/// // print 1, 2, 3 in an arbitrary order
/// for i in set.drain() {
/// println!("{}", i);
/// }
///
/// assert!(set.is_empty());
/// ```
#[inline]
#[stable(feature = "drain", since = "1.6.0")]
pub fn drain(&mut self) -> Drain<T> {

40
ctr-std/src/collections/hash/table.rs

@ -353,14 +353,14 @@ impl<K, V, M: Deref<Target = RawTable<K, V>>> Bucket<K, V, M> { @@ -353,14 +353,14 @@ impl<K, V, M: Deref<Target = RawTable<K, V>>> Bucket<K, V, M> {
let ib_index = ib_index & table.capacity_mask;
Bucket {
raw: table.raw_bucket_at(ib_index),
table: table,
table,
}
}
pub fn first(table: M) -> Bucket<K, V, M> {
Bucket {
raw: table.raw_bucket_at(0),
table: table,
table,
}
}
@ -455,7 +455,7 @@ impl<K, V, M: Deref<Target = RawTable<K, V>>> EmptyBucket<K, V, M> { @@ -455,7 +455,7 @@ impl<K, V, M: Deref<Target = RawTable<K, V>>> EmptyBucket<K, V, M> {
match self.next().peek() {
Full(bucket) => {
Ok(GapThenFull {
gap: gap,
gap,
full: bucket,
})
}
@ -563,7 +563,7 @@ impl<'t, K, V> FullBucket<K, V, &'t mut RawTable<K, V>> { @@ -563,7 +563,7 @@ impl<'t, K, V> FullBucket<K, V, &'t mut RawTable<K, V>> {
///
/// This works similarly to `put`, building an `EmptyBucket` out of the
/// taken bucket.
pub fn take(mut self) -> (EmptyBucket<K, V, &'t mut RawTable<K, V>>, K, V) {
pub fn take(self) -> (EmptyBucket<K, V, &'t mut RawTable<K, V>>, K, V) {
self.table.size -= 1;
unsafe {
@ -717,26 +717,25 @@ fn calculate_offsets(hashes_size: usize, @@ -717,26 +717,25 @@ fn calculate_offsets(hashes_size: usize,
(pairs_offset, end_of_pairs, oflo)
}
// Returns a tuple of (minimum required malloc alignment, hash_offset,
// Returns a tuple of (minimum required malloc alignment,
// array_size), from the start of a mallocated array.
fn calculate_allocation(hash_size: usize,
hash_align: usize,
pairs_size: usize,
pairs_align: usize)
-> (usize, usize, usize, bool) {
let hash_offset = 0;
-> (usize, usize, bool) {
let (_, end_of_pairs, oflo) = calculate_offsets(hash_size, pairs_size, pairs_align);
let align = cmp::max(hash_align, pairs_align);
(align, hash_offset, end_of_pairs, oflo)
(align, end_of_pairs, oflo)
}
#[test]
fn test_offset_calculation() {
assert_eq!(calculate_allocation(128, 8, 16, 8), (8, 0, 144, false));
assert_eq!(calculate_allocation(3, 1, 2, 1), (1, 0, 5, false));
assert_eq!(calculate_allocation(6, 2, 12, 4), (4, 0, 20, false));
assert_eq!(calculate_allocation(128, 8, 16, 8), (8, 144, false));
assert_eq!(calculate_allocation(3, 1, 2, 1), (1, 5, false));
assert_eq!(calculate_allocation(6, 2, 12, 4), (4, 20, false));
assert_eq!(calculate_offsets(128, 15, 4), (128, 143, false));
assert_eq!(calculate_offsets(3, 2, 4), (4, 6, false));
assert_eq!(calculate_offsets(6, 12, 4), (8, 20, false));
@ -768,7 +767,7 @@ impl<K, V> RawTable<K, V> { @@ -768,7 +767,7 @@ impl<K, V> RawTable<K, V> {
// This is great in theory, but in practice getting the alignment
// right is a little subtle. Therefore, calculating offsets has been
// factored out into a different function.
let (alignment, hash_offset, size, oflo) = calculate_allocation(hashes_size,
let (alignment, size, oflo) = calculate_allocation(hashes_size,
align_of::<HashUint>(),
pairs_size,
align_of::<(K, V)>());
@ -784,7 +783,7 @@ impl<K, V> RawTable<K, V> { @@ -784,7 +783,7 @@ impl<K, V> RawTable<K, V> {
let buffer = Heap.alloc(Layout::from_size_align(size, alignment).unwrap())
.unwrap_or_else(|e| Heap.oom(e));
let hashes = buffer.offset(hash_offset as isize) as *mut HashUint;
let hashes = buffer as *mut HashUint;
RawTable {
capacity_mask: capacity.wrapping_sub(1),
@ -860,8 +859,8 @@ impl<K, V> RawTable<K, V> { @@ -860,8 +859,8 @@ impl<K, V> RawTable<K, V> {
// Replace the marker regardless of lifetime bounds on parameters.
IntoIter {
iter: RawBuckets {
raw: raw,
elems_left: elems_left,
raw,
elems_left,
marker: marker::PhantomData,
},
table: self,
@ -873,8 +872,8 @@ impl<K, V> RawTable<K, V> { @@ -873,8 +872,8 @@ impl<K, V> RawTable<K, V> {
// Replace the marker regardless of lifetime bounds on parameters.
Drain {
iter: RawBuckets {
raw: raw,
elems_left: elems_left,
raw,
elems_left,
marker: marker::PhantomData,
},
table: Shared::from(self),
@ -925,7 +924,7 @@ struct RawBuckets<'a, K, V> { @@ -925,7 +924,7 @@ struct RawBuckets<'a, K, V> {
marker: marker::PhantomData<&'a ()>,
}
// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
impl<'a, K, V> Clone for RawBuckets<'a, K, V> {
fn clone(&self) -> RawBuckets<'a, K, V> {
RawBuckets {
@ -976,7 +975,7 @@ pub struct Iter<'a, K: 'a, V: 'a> { @@ -976,7 +975,7 @@ pub struct Iter<'a, K: 'a, V: 'a> {
unsafe impl<'a, K: Sync, V: Sync> Sync for Iter<'a, K, V> {}
unsafe impl<'a, K: Sync, V: Sync> Send for Iter<'a, K, V> {}
// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
impl<'a, K, V> Clone for Iter<'a, K, V> {
fn clone(&self) -> Iter<'a, K, V> {
Iter {
@ -1157,6 +1156,7 @@ impl<K: Clone, V: Clone> Clone for RawTable<K, V> { @@ -1157,6 +1156,7 @@ impl<K: Clone, V: Clone> Clone for RawTable<K, V> {
}
new_ht.size = self.size();
new_ht.set_tag(self.tag());
new_ht
}
@ -1183,7 +1183,7 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable<K, V> { @@ -1183,7 +1183,7 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable<K, V> {
let hashes_size = self.capacity() * size_of::<HashUint>();
let pairs_size = self.capacity() * size_of::<(K, V)>();
let (align, _, size, oflo) = calculate_allocation(hashes_size,
let (align, size, oflo) = calculate_allocation(hashes_size,
align_of::<HashUint>(),
pairs_size,
align_of::<(K, V)>());

14
ctr-std/src/lib.rs

@ -64,8 +64,6 @@ use prelude::v1::*; @@ -64,8 +64,6 @@ use prelude::v1::*;
debug_assert_ne, unreachable, unimplemented, write, writeln, try)]
extern crate core as __core;
#[allow(deprecated)] extern crate rand as core_rand;
#[macro_use]
#[macro_reexport(vec, format)]
extern crate alloc;
@ -184,20 +182,8 @@ mod sys; @@ -184,20 +182,8 @@ mod sys;
// Private support modules
mod panicking;
mod rand;
mod memchr;
// The runtime entry point and a few unstable public functions used by the
// compiler
pub mod rt;
// Some external utilities of the standard library rely on randomness (aka
// rustc_back::TempDir and tests) and need a way to get at the OS rng we've got
// here. This module is not at all intended for stabilization as-is, however,
// but it may be stabilized long-term. As a result we're exposing a hidden,
// unstable module so we can get our build working.
#[doc(hidden)]
#[unstable(feature = "rand", issue = "0")]
pub mod __rand {
pub use rand::{thread_rng, ThreadRng, Rng};
}

1
ctr-std/src/panic.rs

@ -11,6 +11,7 @@ @@ -11,6 +11,7 @@
//! Panic support in the standard library
#![stable(feature = "std_panic", since = "1.9.0")]
#![allow(auto_impl)]
use any::Any;
use cell::UnsafeCell;

1
ctr-std/src/path.rs

@ -106,7 +106,6 @@ @@ -106,7 +106,6 @@
#![stable(feature = "rust1", since = "1.0.0")]
use ascii::*;
use borrow::{Borrow, Cow};
use cmp;
use error::Error;

286
ctr-std/src/rand/mod.rs

@ -1,286 +0,0 @@ @@ -1,286 +0,0 @@
// Copyright 2013 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.
//! Utilities for random number generation
//!
//! The key functions are `random()` and `Rng::gen()`. These are polymorphic
//! and so can be used to generate any type that implements `Rand`. Type inference
//! means that often a simple call to `rand::random()` or `rng.gen()` will
//! suffice, but sometimes an annotation is required, e.g. `rand::random::<f64>()`.
//!
//! See the `distributions` submodule for sampling random numbers from
//! distributions like normal and exponential.
//!
//! # Thread-local RNG
//!
//! There is built-in support for a RNG associated with each thread stored
//! in thread-local storage. This RNG can be accessed via `thread_rng`, or
//! used implicitly via `random`. This RNG is normally randomly seeded
//! from an operating-system source of randomness, e.g. `/dev/urandom` on
//! Unix systems, and will automatically reseed itself from this source
//! after generating 32 KiB of random data.
//!
//! # Cryptographic security
//!
//! An application that requires an entropy source for cryptographic purposes
//! must use `OsRng`, which reads randomness from the source that the operating
//! system provides (e.g. `/dev/urandom` on Unixes or `CryptGenRandom()` on Windows).
//! The other random number generators provided by this module are not suitable
//! for such purposes.
//!
//! *Note*: many Unix systems provide `/dev/random` as well as `/dev/urandom`.
//! This module uses `/dev/urandom` for the following reasons:
//!
//! - On Linux, `/dev/random` may block if entropy pool is empty; `/dev/urandom` will not block.
//! This does not mean that `/dev/random` provides better output than
//! `/dev/urandom`; the kernel internally runs a cryptographically secure pseudorandom
//! number generator (CSPRNG) based on entropy pool for random number generation,
//! so the "quality" of `/dev/random` is not better than `/dev/urandom` in most cases.
//! However, this means that `/dev/urandom` can yield somewhat predictable randomness
//! if the entropy pool is very small, such as immediately after first booting.
//! Linux 3.17 added the `getrandom(2)` system call which solves the issue: it blocks if entropy
//! pool is not initialized yet, but it does not block once initialized.
//! `getrandom(2)` was based on `getentropy(2)`, an existing system call in OpenBSD.
//! `OsRng` tries to use `getrandom(2)` if available, and use `/dev/urandom` fallback if not.
//! If an application does not have `getrandom` and likely to be run soon after first booting,
//! or on a system with very few entropy sources, one should consider using `/dev/random` via
//! `ReaderRng`.
//! - On some systems (e.g. FreeBSD, OpenBSD and Mac OS X) there is no difference
//! between the two sources. (Also note that, on some systems e.g. FreeBSD, both `/dev/random`
//! and `/dev/urandom` may block once if the CSPRNG has not seeded yet.)
#![unstable(feature = "rand", issue = "0")]
use cell::RefCell;
use fmt;
use io;
use mem;
use rc::Rc;
use sys;
#[cfg(target_pointer_width = "32")]
use core_rand::IsaacRng as IsaacWordRng;
#[cfg(target_pointer_width = "64")]
use core_rand::Isaac64Rng as IsaacWordRng;
pub use core_rand::{Rand, Rng, SeedableRng};
pub use core_rand::{XorShiftRng, IsaacRng, Isaac64Rng};
pub use core_rand::reseeding;
pub mod reader;
/// The standard RNG. This is designed to be efficient on the current
/// platform.
#[derive(Copy, Clone)]
pub struct StdRng {
rng: IsaacWordRng,
}
impl StdRng {
/// Create a randomly seeded instance of `StdRng`.
///
/// This is a very expensive operation as it has to read
/// randomness from the operating system and use this in an
/// expensive seeding operation. If one is only generating a small
/// number of random numbers, or doesn't need the utmost speed for
/// generating each number, `thread_rng` and/or `random` may be more
/// appropriate.
///
/// Reading the randomness from the OS may fail, and any error is
/// propagated via the `io::Result` return value.
pub fn new() -> io::Result<StdRng> {
OsRng::new().map(|mut r| StdRng { rng: r.gen() })
}
}
impl Rng for StdRng {
#[inline]
fn next_u32(&mut self) -> u32 {
self.rng.next_u32()
}
#[inline]
fn next_u64(&mut self) -> u64 {
self.rng.next_u64()
}
}
impl<'a> SeedableRng<&'a [usize]> for StdRng {
fn reseed(&mut self, seed: &'a [usize]) {
// the internal RNG can just be seeded from the above
// randomness.
self.rng.reseed(unsafe {mem::transmute(seed)})
}
fn from_seed(seed: &'a [usize]) -> StdRng {
StdRng { rng: SeedableRng::from_seed(unsafe {mem::transmute(seed)}) }
}
}
/// Controls how the thread-local RNG is reseeded.
struct ThreadRngReseeder;
impl reseeding::Reseeder<StdRng> for ThreadRngReseeder {
fn reseed(&mut self, rng: &mut StdRng) {
*rng = match StdRng::new() {
Ok(r) => r,
Err(e) => panic!("could not reseed thread_rng: {}", e)
}
}
}
const THREAD_RNG_RESEED_THRESHOLD: usize = 32_768;
type ThreadRngInner = reseeding::ReseedingRng<StdRng, ThreadRngReseeder>;
/// The thread-local RNG.
#[derive(Clone)]
pub struct ThreadRng {
rng: Rc<RefCell<ThreadRngInner>>,
}
impl fmt::Debug for ThreadRng {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("ThreadRng { .. }")
}
}
/// Retrieve the lazily-initialized thread-local random number
/// generator, seeded by the system. Intended to be used in method
/// chaining style, e.g. `thread_rng().gen::<isize>()`.
///
/// The RNG provided will reseed itself from the operating system
/// after generating a certain amount of randomness.
///
/// The internal RNG used is platform and architecture dependent, even
/// if the operating system random number generator is rigged to give
/// the same sequence always. If absolute consistency is required,
/// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`.
pub fn thread_rng() -> ThreadRng {
// used to make space in TLS for a random number generator
thread_local!(static THREAD_RNG_KEY: Rc<RefCell<ThreadRngInner>> = {
let r = match StdRng::new() {
Ok(r) => r,
Err(e) => panic!("could not initialize thread_rng: {}", e)
};
let rng = reseeding::ReseedingRng::new(r,
THREAD_RNG_RESEED_THRESHOLD,
ThreadRngReseeder);
Rc::new(RefCell::new(rng))
});
ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.clone()) }
}
impl Rng for ThreadRng {
fn next_u32(&mut self) -> u32 {
self.rng.borrow_mut().next_u32()
}
fn next_u64(&mut self) -> u64 {
self.rng.borrow_mut().next_u64()
}
#[inline]
fn fill_bytes(&mut self, bytes: &mut [u8]) {
self.rng.borrow_mut().fill_bytes(bytes)
}
}
/// A random number generator that retrieves randomness straight from
/// the operating system. Platform sources:
///
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
/// `/dev/urandom`, or from `getrandom(2)` system call if available.
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
/// service provider with the `PROV_RSA_FULL` type.
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
/// - OpenBSD: uses the `getentropy(2)` system call.
///
/// This does not block.
pub struct OsRng(sys::rand::OsRng);
impl OsRng {
/// Create a new `OsRng`.
pub fn new() -> io::Result<OsRng> {
sys::rand::OsRng::new().map(OsRng)
}
}
impl Rng for OsRng {
#[inline]
fn next_u32(&mut self) -> u32 {
self.0.next_u32()
}
#[inline]
fn next_u64(&mut self) -> u64 {
self.0.next_u64()
}
#[inline]
fn fill_bytes(&mut self, bytes: &mut [u8]) {
self.0.fill_bytes(bytes)
}
}
#[cfg(test)]
mod tests {
use sync::mpsc::channel;
use rand::Rng;
use super::OsRng;
use thread;
#[test]
fn test_os_rng() {
let mut r = OsRng::new().unwrap();
r.next_u32();
r.next_u64();
let mut v = [0; 1000];
r.fill_bytes(&mut v);
}
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
fn test_os_rng_tasks() {
let mut txs = vec![];
for _ in 0..20 {
let (tx, rx) = channel();
txs.push(tx);
thread::spawn(move|| {
// wait until all the threads are ready to go.
rx.recv().unwrap();
// deschedule to attempt to interleave things as much
// as possible (XXX: is this a good test?)
let mut r = OsRng::new().unwrap();
thread::yield_now();
let mut v = [0; 1000];
for _ in 0..100 {
r.next_u32();
thread::yield_now();
r.next_u64();
thread::yield_now();
r.fill_bytes(&mut v);
thread::yield_now();
}
});
}
// start all the threads
for tx in &txs {
tx.send(()).unwrap();
}
}
}

108
ctr-std/src/rand/reader.rs

@ -1,108 +0,0 @@ @@ -1,108 +0,0 @@
// Copyright 2013 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.
//! A wrapper around any Read to treat it as an RNG.
#![allow(dead_code)]
use io::prelude::*;
use rand::Rng;
/// An RNG that reads random bytes straight from a `Read`. This will
/// work best with an infinite reader, but this is not required.
///
/// # Panics
///
/// It will panic if it there is insufficient data to fulfill a request.
pub struct ReaderRng<R> {
reader: R
}
impl<R: Read> ReaderRng<R> {
/// Create a new `ReaderRng` from a `Read`.
pub fn new(r: R) -> ReaderRng<R> {
ReaderRng {
reader: r
}
}
}
impl<R: Read> Rng for ReaderRng<R> {
fn next_u32(&mut self) -> u32 {
// This is designed for speed: reading a LE integer on a LE
// platform just involves blitting the bytes into the memory
// of the u32, similarly for BE on BE; avoiding byteswapping.
let mut bytes = [0; 4];
self.fill_bytes(&mut bytes);
unsafe { *(bytes.as_ptr() as *const u32) }
}
fn next_u64(&mut self) -> u64 {
// see above for explanation.
let mut bytes = [0; 8];
self.fill_bytes(&mut bytes);
unsafe { *(bytes.as_ptr() as *const u64) }
}
fn fill_bytes(&mut self, mut v: &mut [u8]) {
while !v.is_empty() {
let t = v;
match self.reader.read(t) {
Ok(0) => panic!("ReaderRng.fill_bytes: EOF reached"),
Ok(n) => v = t.split_at_mut(n).1,
Err(e) => panic!("ReaderRng.fill_bytes: {}", e),
}
}
}
}
#[cfg(test)]
mod tests {
use super::ReaderRng;
use rand::Rng;
#[test]
fn test_reader_rng_u64() {
// transmute from the target to avoid endianness concerns.
let v = &[0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 2,
0, 0, 0, 0, 0, 0, 0, 3][..];
let mut rng = ReaderRng::new(v);
assert_eq!(rng.next_u64(), 1u64.to_be());
assert_eq!(rng.next_u64(), 2u64.to_be());
assert_eq!(rng.next_u64(), 3u64.to_be());
}
#[test]
fn test_reader_rng_u32() {
let v = &[0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3][..];
let mut rng = ReaderRng::new(v);
assert_eq!(rng.next_u32(), 1u32.to_be());
assert_eq!(rng.next_u32(), 2u32.to_be());
assert_eq!(rng.next_u32(), 3u32.to_be());
}
#[test]
fn test_reader_rng_fill_bytes() {
let v = [1, 2, 3, 4, 5, 6, 7, 8];
let mut w = [0; 8];
let mut rng = ReaderRng::new(&v[..]);
rng.fill_bytes(&mut w);
assert!(v == w);
}
#[test]
#[should_panic]
fn test_reader_rng_insufficient_bytes() {
let mut rng = ReaderRng::new(&[][..]);
let mut v = [0; 3];
rng.fill_bytes(&mut v);
}
}

2
ctr-std/src/sync/once.rs

@ -248,7 +248,7 @@ impl Once { @@ -248,7 +248,7 @@ impl Once {
#[cold]
fn call_inner(&'static self,
ignore_poisoning: bool,
mut init: &mut FnMut(bool)) {
init: &mut FnMut(bool)) {
let mut state = self.state.load(Ordering::SeqCst);
'outer: loop {

2
ctr-std/src/sys/unix/mod.rs

@ -13,6 +13,8 @@ @@ -13,6 +13,8 @@
use io::{self, ErrorKind};
use libc;
pub use self::rand::hashmap_random_keys;
pub mod condvar;
pub mod ext;
pub mod fast_thread_local;

57
ctr-std/src/sys/unix/rand.rs

@ -8,47 +8,36 @@ @@ -8,47 +8,36 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use io::{self, Error, ErrorKind};
use mem;
use rand::Rng;
use slice;
use libctru::{sslcInit, sslcExit, sslcGenerateRandomData};
pub struct OsRng(());
impl OsRng {
pub fn new() -> io::Result<OsRng> {
pub fn hashmap_random_keys() -> (u64, u64) {
let mut v = (0, 0);
unsafe {
let r = sslcInit(0);
if r < 0 {
Err(Error::new(ErrorKind::Other, "Unable to initialize the RNG"))
} else {
Ok(OsRng(()))
}
}
let view = slice::from_raw_parts_mut(&mut v as *mut _ as *mut u8,
mem::size_of_val(&v));
imp::fill_bytes(view);
}
return v
}
impl Rng for OsRng {
fn next_u32(&mut self) -> u32 {
let mut v = [0; 4];
self.fill_bytes(&mut v);
unsafe { mem::transmute(v) }
}
fn next_u64(&mut self) -> u64 {
let mut v = [0; 8];
self.fill_bytes(&mut v);
unsafe { mem::transmute(v) }
}
mod imp {
use libctru;
fn fill_bytes(&mut self, v: &mut [u8]) {
unsafe { sslcGenerateRandomData(v.as_ptr() as _, v.len() as u32); }
pub fn fill_bytes(v: &mut [u8]) {
unsafe {
// Initializing and de-initializing the sslC subsystem every time
// we initialize a hashmap is pretty dumb, but I can't think of a
// better method at the moment.
//
// lazy_static won't work because
// destructors (for closing the subsystem on exit) won't run.
//
// Perhaps overriding __appInit() and __appExit() will work,
// but that's an experiment for another time.
libctru::sslcInit(0);
libctru::sslcGenerateRandomData(v.as_ptr() as _, v.len() as u32);
libctru::sslcExit();
}
}
impl Drop for OsRng {
fn drop(&mut self) {
unsafe { sslcExit() }
}
}

Loading…
Cancel
Save