Skip to content

Move hash module from collections to core #19800

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 17, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/liballoc/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use core::clone::Clone;
use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering};
use core::default::Default;
use core::fmt;
use core::hash::{mod, Hash};
use core::kinds::Sized;
use core::mem;
use core::option::Option;
Expand Down Expand Up @@ -93,6 +94,14 @@ impl<Sized? T: Ord> Ord for Box<T> {
}
impl<Sized? T: Eq> Eq for Box<T> {}

impl<S: hash::Writer, Sized? T: Hash<S>> Hash<S> for Box<T> {
#[inline]
fn hash(&self, state: &mut S) {
(**self).hash(state);
}
}


/// Extension methods for an owning `Any` trait object.
#[unstable = "post-DST and coherence changes, this will not be a trait but \
rather a direct `impl` on `Box<Any>`"]
Expand Down
2 changes: 1 addition & 1 deletion src/liballoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
html_root_url = "http://doc.rust-lang.org/nightly/")]

#![no_std]
#![feature(lang_items, phase, unsafe_destructor)]
#![feature(lang_items, phase, unsafe_destructor, default_type_params)]

#[phase(plugin, link)]
extern crate core;
Expand Down
9 changes: 9 additions & 0 deletions src/liballoc/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ use core::clone::Clone;
use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering};
use core::default::Default;
use core::fmt;
use core::hash::{mod, Hash};
use core::kinds::marker;
use core::mem::{transmute, min_align_of, size_of, forget};
use core::ops::{Deref, Drop};
Expand Down Expand Up @@ -594,6 +595,14 @@ impl<T: Ord> Ord for Rc<T> {
fn cmp(&self, other: &Rc<T>) -> Ordering { (**self).cmp(&**other) }
}

// FIXME (#18248) Make `T` `Sized?`
impl<S: hash::Writer, T: Hash<S>> Hash<S> for Rc<T> {
#[inline]
fn hash(&self, state: &mut S) {
(**self).hash(state);
}
}

#[experimental = "Show is experimental."]
impl<T: fmt::Show> fmt::Show for Rc<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Expand Down
3 changes: 1 addition & 2 deletions src/libcollections/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ pub mod slice;
pub mod str;
pub mod string;
pub mod vec;
pub mod hash;
pub mod vec_map;

pub mod bitv {
Expand Down Expand Up @@ -116,5 +115,5 @@ mod std {
pub use core::clone; // deriving(Clone)
pub use core::cmp; // deriving(Eq, Ord, etc.)
pub use core::kinds; // deriving(Copy)
pub use hash; // deriving(Hash)
pub use core::hash; // deriving(Hash)
}
2 changes: 1 addition & 1 deletion src/libcollections/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ use self::DecompositionType::*;
use core::borrow::{BorrowFrom, Cow, ToOwned};
use core::default::Default;
use core::fmt;
use core::hash;
use core::cmp;
use core::iter::AdditiveIterator;

use hash;
use ring_buf::RingBuf;
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 @@ -17,13 +17,13 @@ use core::prelude::*;
use core::borrow::{Cow, IntoCow};
use core::default::Default;
use core::fmt;
use core::hash;
use core::mem;
use core::ptr;
use core::ops;
// FIXME: ICE's abound if you import the `Slice` type while importing `Slice` trait
use core::raw::Slice as RawSlice;

use hash;
use slice::CloneSliceExt;
use str;
use str::{CharRange, CowString, FromStr, StrAllocating, Owned};
Expand Down
8 changes: 8 additions & 0 deletions src/libcollections/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use core::borrow::{Cow, IntoCow};
use core::cmp::max;
use core::default::Default;
use core::fmt;
use core::hash::{mod, Hash};
use core::kinds::marker::{ContravariantLifetime, InvariantType};
use core::kinds::Sized;
use core::mem;
Expand Down Expand Up @@ -619,6 +620,13 @@ impl<T: Ord> Ord for Vec<T> {
}
}

impl<S: hash::Writer, T: Hash<S>> Hash<S> for Vec<T> {
#[inline]
fn hash(&self, state: &mut S) {
self.as_slice().hash(state);
}
}

// FIXME: #13996: need a way to mark the return value as `noalias`
#[inline(never)]
unsafe fn alloc_or_realloc<T>(ptr: *mut T, old_size: uint, size: uint) -> *mut T {
Expand Down
4 changes: 2 additions & 2 deletions src/libcollections/vec_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ use core::prelude::*;

use core::default::Default;
use core::fmt;
use core::hash::{Hash, Writer};
use core::iter;
use core::iter::{Enumerate, FilterMap};
use core::mem::replace;
use core::ops::FnOnce;

use hash::{Hash, Writer};
use {vec, slice};
use vec::Vec;

Expand Down Expand Up @@ -642,7 +642,7 @@ pub type MoveItems<V> = FilterMap<
mod test_map {
use std::prelude::*;
use vec::Vec;
use hash::hash;
use core::hash::hash;

use super::VecMap;

Expand Down
164 changes: 7 additions & 157 deletions src/libcollections/hash/mod.rs → src/libcore/hash/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,12 @@

#![allow(unused_must_use)]

use core::prelude::*;
use prelude::*;

use alloc::boxed::Box;
use alloc::rc::Rc;
use core::borrow::{Cow, ToOwned};
use core::intrinsics::TypeId;
use core::mem;
use core::num::Int;

use vec::Vec;
use borrow::{Cow, ToOwned};
use intrinsics::TypeId;
use mem;
use num::Int;

/// Reexport the `sip::hash` function as our default hasher.
pub use self::sip::hash as hash;
Expand All @@ -92,6 +88,7 @@ pub trait Hasher<S> {
fn hash<Sized? T: Hash<S>>(&self, value: &T) -> u64;
}

#[allow(missing_docs)]
pub trait Writer {
fn write(&mut self, bytes: &[u8]);
}
Expand All @@ -103,7 +100,7 @@ macro_rules! impl_hash {
impl<S: Writer> Hash<S> for $ty {
#[inline]
fn hash(&self, state: &mut S) {
let a: [u8, ..::core::$ty::BYTES] = unsafe {
let a: [u8, ..::$ty::BYTES] = unsafe {
mem::transmute((*self as $uty).to_le() as $ty)
};
state.write(a.as_slice())
Expand Down Expand Up @@ -197,13 +194,6 @@ impl<S: Writer, T: Hash<S>> Hash<S> for [T] {
}


impl<S: Writer, T: Hash<S>> Hash<S> for Vec<T> {
#[inline]
fn hash(&self, state: &mut S) {
self.as_slice().hash(state);
}
}

impl<'a, S: Writer, Sized? T: Hash<S>> Hash<S> for &'a T {
#[inline]
fn hash(&self, state: &mut S) {
Expand All @@ -218,36 +208,6 @@ impl<'a, S: Writer, Sized? T: Hash<S>> Hash<S> for &'a mut T {
}
}

impl<S: Writer, Sized? T: Hash<S>> Hash<S> for Box<T> {
#[inline]
fn hash(&self, state: &mut S) {
(**self).hash(state);
}
}

// FIXME (#18248) Make `T` `Sized?`
impl<S: Writer, T: Hash<S>> Hash<S> for Rc<T> {
#[inline]
fn hash(&self, state: &mut S) {
(**self).hash(state);
}
}

impl<S: Writer, T: Hash<S>> Hash<S> for Option<T> {
#[inline]
fn hash(&self, state: &mut S) {
match *self {
Some(ref x) => {
0u8.hash(state);
x.hash(state);
}
None => {
1u8.hash(state);
}
}
}
}

impl<S: Writer, T> Hash<S> for *const T {
#[inline]
fn hash(&self, state: &mut S) {
Expand All @@ -273,119 +233,9 @@ impl<S: Writer> Hash<S> for TypeId {
}
}

impl<S: Writer, T: Hash<S>, U: Hash<S>> Hash<S> for Result<T, U> {
#[inline]
fn hash(&self, state: &mut S) {
match *self {
Ok(ref t) => { 1u.hash(state); t.hash(state); }
Err(ref t) => { 2u.hash(state); t.hash(state); }
}
}
}

impl<'a, T, Sized? B, S> Hash<S> for Cow<'a, T, B> where B: Hash<S> + ToOwned<T> {
#[inline]
fn hash(&self, state: &mut S) {
Hash::hash(&**self, state)
}
}

//////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
use core::kinds::Sized;
use std::mem;

use slice::SliceExt;
use super::{Hash, Hasher, Writer};

struct MyWriterHasher;

impl Hasher<MyWriter> for MyWriterHasher {
fn hash<Sized? T: Hash<MyWriter>>(&self, value: &T) -> u64 {
let mut state = MyWriter { hash: 0 };
value.hash(&mut state);
state.hash
}
}

struct MyWriter {
hash: u64,
}

impl Writer for MyWriter {
// Most things we'll just add up the bytes.
fn write(&mut self, buf: &[u8]) {
for byte in buf.iter() {
self.hash += *byte as u64;
}
}
}

#[test]
fn test_writer_hasher() {
use alloc::boxed::Box;

let hasher = MyWriterHasher;

assert_eq!(hasher.hash(&()), 0);

assert_eq!(hasher.hash(&5u8), 5);
assert_eq!(hasher.hash(&5u16), 5);
assert_eq!(hasher.hash(&5u32), 5);
assert_eq!(hasher.hash(&5u64), 5);
assert_eq!(hasher.hash(&5u), 5);

assert_eq!(hasher.hash(&5i8), 5);
assert_eq!(hasher.hash(&5i16), 5);
assert_eq!(hasher.hash(&5i32), 5);
assert_eq!(hasher.hash(&5i64), 5);
assert_eq!(hasher.hash(&5i), 5);

assert_eq!(hasher.hash(&false), 0);
assert_eq!(hasher.hash(&true), 1);

assert_eq!(hasher.hash(&'a'), 97);

let s: &str = "a";
assert_eq!(hasher.hash(& s), 97 + 0xFF);
// FIXME (#18283) Enable test
//let s: Box<str> = box "a";
//assert_eq!(hasher.hash(& s), 97 + 0xFF);
let cs: &[u8] = &[1u8, 2u8, 3u8];
assert_eq!(hasher.hash(& cs), 9);
let cs: Box<[u8]> = box [1u8, 2u8, 3u8];
assert_eq!(hasher.hash(& cs), 9);

// FIXME (#18248) Add tests for hashing Rc<str> and Rc<[T]>

unsafe {
let ptr: *const int = mem::transmute(5i);
assert_eq!(hasher.hash(&ptr), 5);
}

unsafe {
let ptr: *mut int = mem::transmute(5i);
assert_eq!(hasher.hash(&ptr), 5);
}
}

struct Custom {
hash: u64
}

impl Hash<u64> for Custom {
fn hash(&self, state: &mut u64) {
*state = self.hash;
}
}

#[test]
fn test_custom_state() {
let custom = Custom { hash: 5 };
let mut state = 0;
custom.hash(&mut state);
assert_eq!(state, 5);
}
}
5 changes: 2 additions & 3 deletions src/libcollections/hash/sip.rs → src/libcore/hash/sip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@
//! As such, all cryptographic uses of this implementation are strongly
//! discouraged.

use core::prelude::*;

use core::default::Default;
use prelude::*;
use default::Default;

use super::{Hash, Hasher, Writer};

Expand Down
2 changes: 2 additions & 0 deletions src/libcore/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ pub mod simd;
pub mod slice;
pub mod str;
pub mod tuple;
pub mod hash;
// FIXME #15320: primitive documentation needs top-level modules, this
// should be `core::tuple::unit`.
#[path = "tuple/unit.rs"]
Expand All @@ -142,4 +143,5 @@ mod std {
pub use kinds;
pub use option;
pub use fmt;
pub use hash;
}
2 changes: 1 addition & 1 deletion src/libcore/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ use ops::{Deref, FnOnce};
// which basically means it must be `Option`.

/// The `Option` type.
#[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Show)]
#[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Show, Hash)]
#[stable]
pub enum Option<T> {
/// No value
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ use ops::{FnMut, FnOnce};
/// `Result` is a type that represents either success (`Ok`) or failure (`Err`).
///
/// See the [`std::result`](index.html) module documentation for details.
#[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Show)]
#[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Show, Hash)]
#[must_use]
#[stable]
pub enum Result<T, E> {
Expand Down
Loading