diff --git a/src/collections/map.rs b/src/collections/map.rs index 76dc8c04..82e3309e 100644 --- a/src/collections/map.rs +++ b/src/collections/map.rs @@ -501,7 +501,7 @@ impl FromIterator<(Box<[u8]>, V)> for TreeMap { impl Hash for TreeMap { fn hash(&self, state: &mut H) { - state.write_length_prefix(self.num_entries); + crate::nightly_rust_apis::hasher_write_length_prefix(state, self.num_entries); for elt in self { elt.hash(state); } diff --git a/src/lib.rs b/src/lib.rs index 2324186f..3765622d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,3 @@ -// TODO(#20): Use rust stable distribution, remove usage of nightly features -#![feature(hasher_prefixfree_extras)] #![allow(unstable_name_collisions)] #![deny( missing_docs, diff --git a/src/nightly_rust_apis.rs b/src/nightly_rust_apis.rs index bbf18665..b03753fe 100644 --- a/src/nightly_rust_apis.rs +++ b/src/nightly_rust_apis.rs @@ -117,3 +117,33 @@ pub unsafe fn non_null_get_unchecked_mut(data: NonNull<[T]>, index: usize) -> unsafe { NonNull::new_unchecked(data.as_ptr().cast::().add(index)) } } + +/// Writes a length prefix into this hasher, as part of being prefix-free. +/// +/// If you're implementing [`Hash`] for a custom collection, call this before +/// writing its contents to this `Hasher`. That way +/// `(collection![1, 2, 3], collection![4, 5])` and +/// `(collection![1, 2], collection![3, 4, 5])` will provide different +/// sequences of values to the `Hasher` +/// +/// The `impl Hash for [T]` includes a call to this method, so if you're +/// hashing a slice (or array or vector) via its `Hash::hash` method, +/// you should **not** call this yourself. +/// +/// This method is only for providing domain separation. If you want to +/// hash a `usize` that represents part of the *data*, then it's important +/// that you pass it to [`Hasher::write_usize`] instead of to this method. +/// +/// # Note to Implementers +/// +/// If you've decided that your `Hasher` is willing to be susceptible to +/// Hash-DoS attacks, then you might consider skipping hashing some or all +/// of the `len` provided in the name of increased performance. +/// +/// **This is a unstable API copied from the Rust standard library, tracking +/// issue is [#96762][issue-96762]** +/// +/// [issue-96762]: https://github.com/rust-lang/rust/issues/96762 +pub fn hasher_write_length_prefix(state: &mut H, num_entries: usize) { + state.write_usize(num_entries); +}