From 4c922bae72597eb3c9f1b020f20f590423c6b87b Mon Sep 17 00:00:00 2001 From: Declan Kelly Date: Sun, 20 Nov 2022 19:19:50 -0800 Subject: [PATCH] Remove hasher_prefixfree_extras unstable feature **Description** Remove last nightly feature, `hasher_prefixfree_extras` and replace with copy from the standard library implementation. **Motivation** This change should allow us to compile the crate on stable, part of the work tracked in issue #20. **Testing Done** - `cargo test` - `cargo clippy` - `cargo fmt` --- src/collections/map.rs | 2 +- src/lib.rs | 2 -- src/nightly_rust_apis.rs | 30 ++++++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/collections/map.rs b/src/collections/map.rs index 76dc8c0..82e3309 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 2324186..3765622 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 bbf1866..b03753f 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); +}