On 02/24/2014 10:15 PM, Erick Tryzelaar wrote:
Brian: yes, at the moment `#[deriving(Hash)]` does support more than
SipHash. However this PR temporarily removes that feature to replace
`#[allow(default_type_param_usage)]` with `#[feature(default_type_params)]`:

https://github.com/mozilla/rust/pull/12525

If we land that change, we could try two things. First, we could just
turn on default_type_params permanently. Second, we could allow a syntax
extension to check if a feature has been enabled in a crate. Brian, I
know you were talking about this earlier on IRC, did you end up making a
decision on what to do?

I am hoping that somebody will prototype allocators before we turn default_type_params on permanently.


György: Yep, there is. I went through approximately 13 iterations to
converge on this design :) The reason why the `impl`'s need to know what
kind of state they are dealing with is to support custom hashers. In
most cases, people will want to compute a hash over the bytes of a
value, so that value's hash impl needs to know that it can pass the
value's bytes in with `state.write(...)`. Other values may actually have
a hash baked into them, or want to use an integer value as a hash. These
can just return the hash value by directly assigning the hash to the
`*state` as I did in the example. While not  cryptographically safe,
this can be dramatically faster than using something like SipHash. Yet
another value may want to use two completely different hashing
algorithms depending depending on some property. Letting the `Hash`ee
know about the state type allows for this level of flexibility. It also
adds some type safety, in that it'll prevent you from accidentally
passing a `Writer`-based hash state into a type that should only be used
with a specific hasher.



On Mon, Feb 24, 2014 at 9:35 PM, Niko Matsakis <[email protected]
<mailto:[email protected]>> wrote:

    This looks very cool.


    On Mon, Feb 24, 2014 at 11:31:19AM -0500, Erick Tryzelaar wrote:
     > I'm happy to announce that Rust's new hashing framework has
    landed in:
     >
     > https://github.com/mozilla/rust/pull/11863
     > https://github.com/mozilla/rust/pull/12492
     >
     > This PR has has changed how to declare a type is hashable. Here's
    a full
     > example on how to hash a value using either the new
    `#[deriving(Hash)]` or
     > manual implementation.
     >
     > ```
     > use std::hash::{Hash, hash};
     > use std::hash::sip::SipState;
     >
     > #[deriving(Hash)]
     > struct Foo {
     >     a: ~str,
     >     b: uint,
     >     c: bool,
     > }
     >
     > struct Bar {
     >     a: ~str,
     >     b: uint,
     >     c: bool,
     > }
     >
     > impl Hash for Bar {
     >     fn hash(&self, state: &mut SipState) {
     >         self.a.hash(state);
     >         self.b.hash(state);
     >         self.c.hash(state);
     >     }
     > }
     >
     > fn main() {
     >     let foo = Foo { a: ~"hello world", b: 5, c: true };
     >     println!("{}", hash(&foo));
     >
     >     let bar = Bar { a: ~"hello world", b: 5, c: true };
     >     println!("{}", hash(&bar));
     > }
     > ```
     >
     > We also have experimental support for hashers that compute a
    value off a
     > stream of bytes:
     >
     > ```
     > use std::hash::{Hash, Hasher};
     > use std::io::IoResult;
     >
     > #[deriving(Hash)] // automatically provides hashing from a stream
    of bytes
     > struct Foo {
     >     a: ~str,
     >     b: uint,
     >     c: bool,
     > }
     >
     > struct Bar {
     >     a: ~str,
     >     b: uint,
     >     c: bool,
     > }
     >
     > #[allow(default_type_param_usage)]
     > impl<S: Writer> Hash<S> for Bar {
     >     fn hash(&self, state: &mut S) {
     >         self.a.hash(state);
     >         self.b.hash(state);
     >         self.c.hash(state);
     >     }
     > }
     >
     > struct SumState {
     >     sum: u64,
     > }
     >
     > impl Writer for SumState {
     >     fn write(&mut self, bytes: &[u8]) -> IoResult<()> {
     >         for byte in bytes.iter() {
     >             self.sum += *byte as u64;
     >         }
     >         Ok(())
     >     }
     > }
     >
     > struct SumHasher;
     >
     > #[allow(default_type_param_usage)]
     > impl Hasher<SumState> for SumHasher {
     >     fn hash<T: Hash<SumState>>(&self, value: &T) -> u64 {
     >         let mut state = SumState { sum: 0 };
     >         value.hash(&mut state);
     >         state.sum
     >     }
     > }
     >
     > fn main() {
     >     let hasher = SumHasher;
     >     let foo = Foo { a: ~"hello world", b: 5, c: true };
     >     println!("{}", hasher.hash(&foo));
     >     let bar = Bar { a: ~"hello world", b: 5, c: true };
     >     println!("{}", hasher.hash(&bar));
     > }
     > ```
     >
     > Finally, we also support completely custom hash computation:
     >
     > ```
     > use std::hash::{Hash, Hasher};
     >
     > struct Foo {
     >     hash: u64
     > }
     >
     > #[allow(default_type_param_usage)]
     > impl Hash<u64> for Foo {
     >     fn hash(&self, state: &mut u64) {
     >         *state = self.hash
     >     }
     > }
     >
     > struct CustomHasher;
     >
     > #[allow(default_type_param_usage)]
     > impl Hasher<u64> for CustomHasher {
     >     fn hash<T: Hash<u64>>(&self, value: &T) -> u64 {
     >         let mut state = 0;
     >         value.hash(&mut state);
     >         state
     >     }
     > }
     >
     > fn main() {
     >     let hasher = CustomHasher;
     >     let foo = Foo { hash: 5 };
     >     println!("{}", hasher.hash(&foo));
     > }
     > ```
     >
     > This may break over the next couple days/weeks as we figure out
    the right
     > way to do this. Furthermore, HashMaps have not yet been updated
    to take
     > advantage of the custom hashers, but that should be coming later
    on this
     > week.
     >
     > I hope they work well for all of you. If you run into any
    trouble, please
     > file bugs and cc @erickt on the ticket.
     >
     > Thanks,
     > Erick

     > _______________________________________________
     > Rust-dev mailing list
     > [email protected] <mailto:[email protected]>
     > https://mail.mozilla.org/listinfo/rust-dev




_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev


_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to