From 2ecf44a48e791e1576586075477c88ad635d2af1 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Tue, 27 Sep 2022 13:23:47 +0800 Subject: [PATCH] Remove stable_hash feature and use environment variable. --- CHANGELOG.md | 4 +++- Cargo.toml | 1 - build.rs | 27 +++++++++++++++++++++++++++ src/config.rs | 4 ++++ src/func/hashing.rs | 5 +++-- src/lib.rs | 7 ++++--- 6 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 build.rs create mode 100644 src/config.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 9340630c..70fc8550 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,9 @@ Version 1.11.0 New features ------------ -* A new feature flag, `stable_hash`, is added that forces hashing to be consistent using a fixed seed. +### Stable hashing + +* It is now possible to specify a fixed _seed_ for use with the `ahash` hasher in order to force stable (i.e. deterministic) hashes for function signatures. Enhancements ------------ diff --git a/Cargo.toml b/Cargo.toml index 6451af51..1034f923 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,7 +62,6 @@ metadata = ["serde", "serde_json", "rhai_codegen/metadata", "smartstring/serde"] internals = [] # expose internal data structures debugging = ["internals"] # enable debugging serde = ["dep:serde", "smartstring/serde", "smallvec/serde"] # implement serde for rhai types -stable_hash = [] # perform all hashing with fixed seed value # compiling for no-std no_std = ["no-std-compat", "num-traits/libm", "core-error", "libm", "ahash/compile-time-rng", "hashbrown/ahash-compile-time-rng"] diff --git a/build.rs b/build.rs new file mode 100644 index 00000000..d17bb3da --- /dev/null +++ b/build.rs @@ -0,0 +1,27 @@ +use std::{env, fs::File, io::Write}; + +const WRITE_ERROR: &str = "cannot write to `config.rs`"; + +fn main() { + // Tell Cargo that if the given environment variable changes, to rerun this build script. + println!("cargo:rerun-if-env-changed=RHAI_AHASH_SEED"); + + let mut f = File::create("src/config.rs").expect("cannot create `config.rs`"); + + f.write_fmt(format_args!( + "//! Configuration settings for this Rhai build +#![allow(dead_code)] + +" + )) + .expect(WRITE_ERROR); + + let seed = env::var("RHAI_AHASH_SEED").map_or_else(|_| "None".into(), |s| format!("Some({s})")); + + f.write_fmt(format_args!( + "pub const AHASH_SEED: Option<[u64; 4]> = {seed};\n" + )) + .expect(WRITE_ERROR); + + f.flush().expect("cannot flush `config.rs`"); +} diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 00000000..43d49b6a --- /dev/null +++ b/src/config.rs @@ -0,0 +1,4 @@ +//! Configuration settings for this Rhai build +#![allow(dead_code)] + +pub const AHASH_SEED: Option<[u64; 4]> = None; diff --git a/src/func/hashing.rs b/src/func/hashing.rs index ae0a57bc..53eac8c3 100644 --- a/src/func/hashing.rs +++ b/src/func/hashing.rs @@ -1,5 +1,6 @@ //! Module containing utilities to hash functions and function calls. +use crate::config; #[cfg(feature = "no_std")] use std::prelude::v1::*; use std::{ @@ -74,8 +75,8 @@ impl BuildHasher for StraightHasherBuilder { #[inline(always)] #[must_use] pub fn get_hasher() -> ahash::AHasher { - if cfg!(feature = "stable_hash") { - ahash::RandomState::with_seeds(42, 999, 123, 0).build_hasher() + if let Some([seed1, seed2, seed3, seed4]) = config::AHASH_SEED { + ahash::RandomState::with_seeds(seed1, seed2, seed3, seed4).build_hasher() } else { ahash::AHasher::default() } diff --git a/src/lib.rs b/src/lib.rs index bb26d72b..4976d4b7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -83,6 +83,7 @@ use std::prelude::v1::*; // Internal modules mod api; mod ast; +mod config; mod engine; mod eval; mod func; @@ -224,7 +225,7 @@ pub mod debugger { /// An identifier in Rhai. [`SmartString`](https://crates.io/crates/smartstring) is used because most /// identifiers are ASCII and short, fewer than 23 characters, so they can be stored inline. #[cfg(not(feature = "internals"))] -pub(crate) type Identifier = SmartString; +type Identifier = SmartString; /// An identifier in Rhai. [`SmartString`](https://crates.io/crates/smartstring) is used because most /// identifiers are ASCII and short, fewer than 23 characters, so they can be stored inline. @@ -237,7 +238,7 @@ pub use func::Shared; /// Alias to [`RefCell`][std::cell::RefCell] or [`RwLock`][std::sync::RwLock] depending on the `sync` feature flag. pub use func::Locked; -pub(crate) use func::{calc_fn_hash, calc_fn_params_hash, calc_var_hash, combine_hashes}; +use func::{calc_fn_hash, calc_fn_params_hash, calc_var_hash, combine_hashes}; pub use rhai_codegen::*; @@ -429,7 +430,7 @@ type FnArgsVec = smallvec::SmallVec<[T; 5]>; #[cfg(feature = "no_closure")] type FnArgsVec = crate::StaticVec; -pub(crate) type SmartString = smartstring::SmartString; +type SmartString = smartstring::SmartString; // Compiler guards against mutually-exclusive feature flags