Address concerns
This commit is contained in:
parent
87e51cb8fe
commit
bb01f914e0
63
.github/workflows/build.yml
vendored
63
.github/workflows/build.yml
vendored
@ -44,7 +44,7 @@ jobs:
|
|||||||
flags:
|
flags:
|
||||||
- ""
|
- ""
|
||||||
- "--features debugging"
|
- "--features debugging"
|
||||||
- "--features metadata,serde,internals"
|
- "--features metadata,serde,internals,static_hash"
|
||||||
- "--features unchecked,serde,metadata,internals,debugging"
|
- "--features unchecked,serde,metadata,internals,debugging"
|
||||||
- "--features sync,serde,metadata,internals,debugging"
|
- "--features sync,serde,metadata,internals,debugging"
|
||||||
- "--features no_position,serde,metadata,internals,debugging"
|
- "--features no_position,serde,metadata,internals,debugging"
|
||||||
@ -89,35 +89,35 @@ jobs:
|
|||||||
command: test
|
command: test
|
||||||
args: ${{matrix.flags}}
|
args: ${{matrix.flags}}
|
||||||
|
|
||||||
nightly_features_build:
|
# nightly_features_build:
|
||||||
name: NightlyFeatureBuild
|
# name: NightlyFeatureBuild
|
||||||
runs-on: ${{matrix.os}}
|
# runs-on: ${{matrix.os}}
|
||||||
continue-on-error: ${{matrix.experimental}}
|
# continue-on-error: ${{matrix.experimental}}
|
||||||
strategy:
|
# strategy:
|
||||||
matrix:
|
# matrix:
|
||||||
os: [ubuntu-latest]
|
# os: [ubuntu-latest]
|
||||||
flags:
|
# flags:
|
||||||
- "--features stable_hash"
|
# - "--features stable_hash"
|
||||||
toolchain: [ nightly ]
|
# toolchain: [ nightly ]
|
||||||
experimental: [ false ]
|
# experimental: [ false ]
|
||||||
include:
|
# include:
|
||||||
# smoketests for different toolchains
|
# # smoketests for different toolchains
|
||||||
- { toolchain: nightly, os: windows-latest, experimental: false, flags: "" }
|
# - { toolchain: nightly, os: windows-latest, experimental: false, flags: "" }
|
||||||
- { toolchain: nightly, os: macos-latest, experimental: false, flags: "" }
|
# - { toolchain: nightly, os: macos-latest, experimental: false, flags: "" }
|
||||||
fail-fast: false
|
# fail-fast: false
|
||||||
steps:
|
# steps:
|
||||||
- name: Checkout
|
# - name: Checkout
|
||||||
uses: actions/checkout@v2
|
# uses: actions/checkout@v2
|
||||||
- name: Setup Toolchain
|
# - name: Setup Toolchain
|
||||||
uses: actions-rs/toolchain@v1
|
# uses: actions-rs/toolchain@v1
|
||||||
with:
|
# with:
|
||||||
toolchain: ${{matrix.toolchain}}
|
# toolchain: ${{matrix.toolchain}}
|
||||||
override: true
|
# override: true
|
||||||
- name: Test
|
# - name: Test
|
||||||
uses: actions-rs/cargo@v1
|
# uses: actions-rs/cargo@v1
|
||||||
with:
|
# with:
|
||||||
command: test
|
# command: test
|
||||||
args: ${{matrix.flags}}
|
# args: ${{matrix.flags}}
|
||||||
|
|
||||||
|
|
||||||
# no-std builds are a bit more extensive to test
|
# no-std builds are a bit more extensive to test
|
||||||
@ -127,6 +127,9 @@ jobs:
|
|||||||
continue-on-error: ${{matrix.experimental}}
|
continue-on-error: ${{matrix.experimental}}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
|
flags:
|
||||||
|
- ""
|
||||||
|
- "--features static_hash"
|
||||||
include:
|
include:
|
||||||
- {os: ubuntu-latest, flags: "--profile unix", experimental: false}
|
- {os: ubuntu-latest, flags: "--profile unix", experimental: false}
|
||||||
- {os: windows-latest, flags: "--profile windows", experimental: true}
|
- {os: windows-latest, flags: "--profile windows", experimental: true}
|
||||||
|
@ -63,7 +63,7 @@ unicode-xid-ident = ["unicode-xid"] # allow Unicode Standard Annex #31 for ident
|
|||||||
metadata = ["serde", "serde_json", "rhai_codegen/metadata", "smartstring/serde"] # enable exporting functions metadata
|
metadata = ["serde", "serde_json", "rhai_codegen/metadata", "smartstring/serde"] # enable exporting functions metadata
|
||||||
internals = [] # expose internal data structures
|
internals = [] # expose internal data structures
|
||||||
debugging = ["internals"] # enable debugging
|
debugging = ["internals"] # enable debugging
|
||||||
stable_hash = ["std"]
|
static_hash = []
|
||||||
serde = ["dep:serde", "smartstring/serde", "smallvec/serde"] # implement serde for rhai types
|
serde = ["dep:serde", "smartstring/serde", "smallvec/serde"] # implement serde for rhai types
|
||||||
|
|
||||||
# compiling for no-std
|
# compiling for no-std
|
||||||
|
4
build.rs
4
build.rs
@ -20,9 +20,9 @@ fn main() {
|
|||||||
|
|
||||||
contents = contents.replace("{{AHASH_SEED}}", &seed);
|
contents = contents.replace("{{AHASH_SEED}}", &seed);
|
||||||
|
|
||||||
File::create("src/config.rs")
|
File::create("src/config/hashing.rs")
|
||||||
.expect("cannot create `config.rs`")
|
.expect("cannot create `config.rs`")
|
||||||
.write_all(contents.as_bytes())
|
.write_all(contents.as_bytes())
|
||||||
.expect("cannot write to `config.rs`");
|
.expect("cannot write to `config/hashing.rs`");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
171
build.template
171
build.template
@ -1,60 +1,129 @@
|
|||||||
#[cfg(feature = "stable_hash")]
|
//! Fixed hashing seeds for stable hashing.
|
||||||
use core::cell::OnceCell;
|
//!
|
||||||
|
//! Set to [`None`] to disable stable hashing.
|
||||||
|
//!
|
||||||
|
//! See [`set_rhai_ahash_seed`] for more.
|
||||||
|
//!
|
||||||
|
//! Alternatively, You can also set this at compile time by disabling `stable_hash` and setting the `RHAI_AHASH_SEED`
|
||||||
|
//! environment variable instead.
|
||||||
|
//!
|
||||||
|
//! E.g. `env RHAI_AHASH_SEED ="[236,800,954,213]"`
|
||||||
|
// [236,800,954,213], haha funny yume nikki reference epic uboachan face numberworld nexus moment 100
|
||||||
|
|
||||||
// [236,800,954,213], haha funny yume nikki reference
|
pub use internal::get_ahash_seed;
|
||||||
|
#[cfg(feature = "static_hash")]
|
||||||
|
pub use internal::set_ahash_seed;
|
||||||
|
|
||||||
#[cfg(not(feature = "stable_hash"))]
|
#[cfg(feature = "static_hash")]
|
||||||
/// Fixed hashing seeds for stable hashing.
|
mod internal {
|
||||||
///
|
use core::{
|
||||||
/// Set to [`None`] to disable stable hashing.
|
cell::UnsafeCell,
|
||||||
///
|
marker::PhantomData,
|
||||||
/// See [`set_rhai_ahash_seed`] for more.
|
mem::MaybeUninit,
|
||||||
///
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
/// You can also set this at compile time by disabling `stable_hash` and setting the `RHAI_AHASH_SEED`
|
panic::{RefUnwindSafe, UnwindSafe}
|
||||||
/// environment variable instead.
|
};
|
||||||
///
|
|
||||||
/// E.g. `env RHAI_AHASH_SEED ="[236,800,954,213]"`
|
|
||||||
const AHASH_SEED: Option<[u64; 4]> = {{AHASH_SEED}};
|
|
||||||
#[cfg(feature = "stable_hash")]
|
|
||||||
/// Fixed hashing seeds for stable hashing.
|
|
||||||
///
|
|
||||||
/// Set to [`None`] to disable stable hashing.
|
|
||||||
///
|
|
||||||
/// See [`set_rhai_ahash_seed`] for more.
|
|
||||||
///
|
|
||||||
/// You can also set this at compile time by disabling `stable_hash` and setting the `RHAI_AHASH_SEED`
|
|
||||||
/// environment variable instead.
|
|
||||||
///
|
|
||||||
/// E.g. `env RHAI_AHASH_SEED ="[236,800,954,213]"`
|
|
||||||
static AHASH_SEED: OnceCell<Option<[u64; 4]>> = OnceCell::new();
|
|
||||||
|
|
||||||
#[cfg(feature = "stable_hash")]
|
struct SusLock<T> where T: 'static {
|
||||||
#[doc(cfg(feature = "stable_hash"))]
|
initalized: AtomicBool,
|
||||||
/// Sets the Rhai Ahash seed. This is used to hash functions and the like.
|
data: UnsafeCell<MaybeUninit<T>>,
|
||||||
///
|
_marker: PhantomData<T>,
|
||||||
/// This is a global variable, and thus will affect every Rhai instance.
|
}
|
||||||
/// This should not be used _unless_ you know you need it.
|
|
||||||
///
|
impl<T> SusLock<T> {
|
||||||
/// **WARNING**:
|
pub const fn new() -> SusLock<T> {
|
||||||
/// - You can only call this function **ONCE** for the whole of your program execution.
|
SusLock {
|
||||||
/// - You should gracefully handle the `Err(())`.
|
initalized: AtomicBool::new(false),
|
||||||
/// - You **MUST** call this before **ANY** Rhai operation occurs (e.g. creating an [`Engine`]).
|
data: UnsafeCell::new(MaybeUninit::uninit()),
|
||||||
pub fn set_rhai_ahash_seed(new_seed: Option<[u64; 4]>) -> Result<(), Option<[u64; 4]>> {
|
_marker: PhantomData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self) -> Option<&T> {
|
||||||
|
if self.initalized.load(Ordering::SeqCst) {
|
||||||
|
Some(
|
||||||
|
unsafe {
|
||||||
|
(&*self.data.get()).assume_init_ref()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_or_init(&self, f: impl FnOnce() -> T) -> Option<&T> {
|
||||||
|
let value = f();
|
||||||
|
if !self.initalized.load(Ordering::SeqCst) {
|
||||||
|
unsafe {
|
||||||
|
self.data.get().write(MaybeUninit::new(value));
|
||||||
|
}
|
||||||
|
self.initalized.store(true, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set(&self, value: T) -> Result<(), T> {
|
||||||
|
if self.initalized.load(Ordering::SeqCst) {
|
||||||
|
Err(value)
|
||||||
|
} else {
|
||||||
|
let _ = self.get_or_init(|| value);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<T: Sync + Send> Sync for SusLock<T> {}
|
||||||
|
unsafe impl<T: Send> Send for SusLock<T> {}
|
||||||
|
impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for SusLock<T> {}
|
||||||
|
|
||||||
|
impl<T> Drop for SusLock<T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if self.initalized.load(Ordering::SeqCst) {
|
||||||
|
unsafe { (&mut *self.data.get()).assume_init_drop() };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static AHASH_SEED: SusLock<Option<[u64; 4]>> = SusLock::new();
|
||||||
|
|
||||||
|
// #[doc(cfg(feature = "stable_hash"))]
|
||||||
|
/// Sets the Rhai Ahash seed. This is used to hash functions and the like.
|
||||||
|
///
|
||||||
|
/// This is a global variable, and thus will affect every Rhai instance.
|
||||||
|
/// This should not be used _unless_ you know you need it.
|
||||||
|
///
|
||||||
|
/// # Warnings
|
||||||
|
/// - You can only call this function **ONCE** for the whole of your program execution.
|
||||||
|
/// - You should gracefully handle the `Err(())`.
|
||||||
|
/// - You **MUST** call this before **ANY** Rhai operation occurs (e.g. creating an [`Engine`]).
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// This will error if the AHashSeed is already set.
|
||||||
|
pub fn set_ahash_seed(new_seed: Option<[u64; 4]>) -> Result<(), Option<[u64; 4]>> {
|
||||||
AHASH_SEED.set(new_seed)
|
AHASH_SEED.set(new_seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the current Rhai Ahash Seed. If the seed is not yet defined, this will automatically set a seed.
|
||||||
|
/// The default seed is not stable and may change between versions.
|
||||||
|
///
|
||||||
|
/// See [`set_rhai_ahash_seed`] for more.
|
||||||
|
pub fn get_ahash_seed() -> Option<[u64; 4]> {
|
||||||
|
const FUNNY_YUMENIKKI_REFERENCE: [u64; 4] = [236,800,954,213];
|
||||||
|
|
||||||
|
AHASH_SEED.get_or_init(|| Some(FUNNY_YUMENIKKI_REFERENCE)).map(|x| *x).flatten()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "stable_hash")]
|
#[cfg(not(feature = "static_hash"))]
|
||||||
/// Gets the current Rhai Ahash Seed.
|
mod internal {
|
||||||
///
|
const AHASH_SEED: Option<[u64; 4]> = {{ AHASH_SEED }};
|
||||||
/// See [`set_rhai_ahash_seed`] for more.
|
|
||||||
pub fn get_rhai_ahash_seed() -> Option<[u64; 4]> {
|
|
||||||
AHASH_SEED.get().map(|x| *x).flatten()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "stable_hash"))]
|
/// Gets the current Rhai Ahash Seed. If the seed is not yet defined, this will automatically set a seed.
|
||||||
/// Gets the current Rhai Ahash Seed.
|
/// The default seed is not stable and may change between versions.
|
||||||
///
|
///
|
||||||
/// See [`AHASH_SEED`] and [`set_rhai_ahash_seed`] for more.
|
/// See [`set_ahash_seed`] for more.
|
||||||
pub fn get_rhai_ahash_seed() -> Option<[u64; 4]> {
|
pub fn get_ahash_seed() -> Option<[u64; 4]> {
|
||||||
AHASH_SEED
|
AHASH_SEED
|
||||||
|
}
|
||||||
}
|
}
|
142
src/config.rs
142
src/config.rs
@ -10,44 +10,120 @@
|
|||||||
//! E.g. `env RHAI_AHASH_SEED ="[236,800,954,213]"`
|
//! E.g. `env RHAI_AHASH_SEED ="[236,800,954,213]"`
|
||||||
// [236,800,954,213], haha funny yume nikki reference epic uboachan face numberworld nexus moment 100
|
// [236,800,954,213], haha funny yume nikki reference epic uboachan face numberworld nexus moment 100
|
||||||
|
|
||||||
#[cfg(feature = "stable_hash")]
|
pub use internal::get_ahash_seed;
|
||||||
use std::sync::OnceLock;
|
#[cfg(feature = "static_hash")]
|
||||||
|
pub use internal::set_ahash_seed;
|
||||||
|
|
||||||
#[cfg(not(feature = "stable_hash"))]
|
#[cfg(feature = "static_hash")]
|
||||||
const AHASH_SEED: Option<[u64; 4]> = None;
|
mod internal {
|
||||||
#[cfg(feature = "stable_hash")]
|
use core::{
|
||||||
static AHASH_SEED: OnceLock<Option<[u64; 4]>> = OnceLock::new();
|
cell::UnsafeCell,
|
||||||
|
marker::PhantomData,
|
||||||
|
mem::MaybeUninit,
|
||||||
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
|
panic::{RefUnwindSafe, UnwindSafe}
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(feature = "stable_hash")]
|
struct SusLock<T> where T: 'static {
|
||||||
// #[doc(cfg(feature = "stable_hash"))]
|
initalized: AtomicBool,
|
||||||
/// Sets the Rhai Ahash seed. This is used to hash functions and the like.
|
data: UnsafeCell<MaybeUninit<T>>,
|
||||||
///
|
_marker: PhantomData<T>,
|
||||||
/// This is a global variable, and thus will affect every Rhai instance.
|
}
|
||||||
/// This should not be used _unless_ you know you need it.
|
|
||||||
///
|
impl<T> SusLock<T> {
|
||||||
/// # Warning:
|
pub const fn new() -> SusLock<T> {
|
||||||
/// - You can only call this function **ONCE** for the whole of your program execution.
|
SusLock {
|
||||||
/// - You should gracefully handle the `Err(())`.
|
initalized: AtomicBool::new(false),
|
||||||
/// - You **MUST** call this before **ANY** Rhai operation occurs (e.g. creating an [`Engine`]).
|
data: UnsafeCell::new(MaybeUninit::uninit()),
|
||||||
///
|
_marker: PhantomData
|
||||||
/// # Errors
|
}
|
||||||
/// This will error if the AHashSeed is already set.
|
}
|
||||||
pub fn set_rhai_ahash_seed(new_seed: Option<[u64; 4]>) -> Result<(), Option<[u64; 4]>> {
|
|
||||||
|
pub fn get(&self) -> Option<&T> {
|
||||||
|
if self.initalized.load(Ordering::SeqCst) {
|
||||||
|
Some(
|
||||||
|
unsafe {
|
||||||
|
(&*self.data.get()).assume_init_ref()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_or_init(&self, f: impl FnOnce() -> T) -> Option<&T> {
|
||||||
|
let value = f();
|
||||||
|
if !self.initalized.load(Ordering::SeqCst) {
|
||||||
|
unsafe {
|
||||||
|
self.data.get().write(MaybeUninit::new(value));
|
||||||
|
}
|
||||||
|
self.initalized.store(true, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set(&self, value: T) -> Result<(), T> {
|
||||||
|
if self.initalized.load(Ordering::SeqCst) {
|
||||||
|
Err(value)
|
||||||
|
} else {
|
||||||
|
let _ = self.get_or_init(|| value);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<T: Sync + Send> Sync for SusLock<T> {}
|
||||||
|
unsafe impl<T: Send> Send for SusLock<T> {}
|
||||||
|
impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for SusLock<T> {}
|
||||||
|
|
||||||
|
impl<T> Drop for SusLock<T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if self.initalized.load(Ordering::SeqCst) {
|
||||||
|
unsafe { (&mut *self.data.get()).assume_init_drop() };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static AHASH_SEED: SusLock<Option<[u64; 4]>> = SusLock::new();
|
||||||
|
|
||||||
|
// #[doc(cfg(feature = "stable_hash"))]
|
||||||
|
/// Sets the Rhai Ahash seed. This is used to hash functions and the like.
|
||||||
|
///
|
||||||
|
/// This is a global variable, and thus will affect every Rhai instance.
|
||||||
|
/// This should not be used _unless_ you know you need it.
|
||||||
|
///
|
||||||
|
/// # Warnings
|
||||||
|
/// - You can only call this function **ONCE** for the whole of your program execution.
|
||||||
|
/// - You should gracefully handle the `Err(())`.
|
||||||
|
/// - You **MUST** call this before **ANY** Rhai operation occurs (e.g. creating an [`Engine`]).
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// This will error if the AHashSeed is already set.
|
||||||
|
pub fn set_ahash_seed(new_seed: Option<[u64; 4]>) -> Result<(), Option<[u64; 4]>> {
|
||||||
AHASH_SEED.set(new_seed)
|
AHASH_SEED.set(new_seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the current Rhai Ahash Seed. If the seed is not yet defined, this will automatically set a seed.
|
||||||
|
/// The default seed is not stable and may change between versions.
|
||||||
|
///
|
||||||
|
/// See [`set_rhai_ahash_seed`] for more.
|
||||||
|
pub fn get_ahash_seed() -> Option<[u64; 4]> {
|
||||||
|
const FUNNY_YUMENIKKI_REFERENCE: [u64; 4] = [236,800,954,213];
|
||||||
|
|
||||||
|
AHASH_SEED.get_or_init(|| Some(FUNNY_YUMENIKKI_REFERENCE)).map(|x| *x).flatten()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "stable_hash")]
|
#[cfg(not(feature = "static_hash"))]
|
||||||
/// Gets the current Rhai Ahash Seed.
|
mod internal {
|
||||||
///
|
const AHASH_SEED: Option<[u64; 4]> = {{ AHASH_SEED }};
|
||||||
/// See [`set_rhai_ahash_seed`] for more.
|
|
||||||
pub fn get_rhai_ahash_seed() -> Option<[u64; 4]> {
|
|
||||||
AHASH_SEED.get().map(|x| *x).flatten()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "stable_hash"))]
|
/// Gets the current Rhai Ahash Seed. If the seed is not yet defined, this will automatically set a seed.
|
||||||
/// Gets the current Rhai Ahash Seed.
|
/// The default seed is not stable and may change between versions.
|
||||||
///
|
///
|
||||||
/// See [`AHASH_SEED`] and [`set_rhai_ahash_seed`] for more.
|
/// See [`set_ahash_seed`] for more.
|
||||||
pub fn get_rhai_ahash_seed() -> Option<[u64; 4]> {
|
pub fn get_ahash_seed() -> Option<[u64; 4]> {
|
||||||
AHASH_SEED
|
AHASH_SEED
|
||||||
|
}
|
||||||
}
|
}
|
129
src/config/hashing.rs
Normal file
129
src/config/hashing.rs
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
//! Fixed hashing seeds for stable hashing.
|
||||||
|
//!
|
||||||
|
//! Set to [`None`] to disable stable hashing.
|
||||||
|
//!
|
||||||
|
//! See [`set_rhai_ahash_seed`] for more.
|
||||||
|
//!
|
||||||
|
//! Alternatively, You can also set this at compile time by disabling `stable_hash` and setting the `RHAI_AHASH_SEED`
|
||||||
|
//! environment variable instead.
|
||||||
|
//!
|
||||||
|
//! E.g. `env RHAI_AHASH_SEED ="[236,800,954,213]"`
|
||||||
|
// [236,800,954,213], haha funny yume nikki reference epic uboachan face numberworld nexus moment 100
|
||||||
|
|
||||||
|
pub use internal::get_ahash_seed;
|
||||||
|
#[cfg(feature = "static_hash")]
|
||||||
|
pub use internal::set_ahash_seed;
|
||||||
|
|
||||||
|
#[cfg(feature = "static_hash")]
|
||||||
|
mod internal {
|
||||||
|
use core::{
|
||||||
|
cell::UnsafeCell,
|
||||||
|
marker::PhantomData,
|
||||||
|
mem::MaybeUninit,
|
||||||
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
|
panic::{RefUnwindSafe, UnwindSafe}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SusLock<T> where T: 'static {
|
||||||
|
initalized: AtomicBool,
|
||||||
|
data: UnsafeCell<MaybeUninit<T>>,
|
||||||
|
_marker: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> SusLock<T> {
|
||||||
|
pub const fn new() -> SusLock<T> {
|
||||||
|
SusLock {
|
||||||
|
initalized: AtomicBool::new(false),
|
||||||
|
data: UnsafeCell::new(MaybeUninit::uninit()),
|
||||||
|
_marker: PhantomData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self) -> Option<&T> {
|
||||||
|
if self.initalized.load(Ordering::SeqCst) {
|
||||||
|
Some(
|
||||||
|
unsafe {
|
||||||
|
(&*self.data.get()).assume_init_ref()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_or_init(&self, f: impl FnOnce() -> T) -> Option<&T> {
|
||||||
|
let value = f();
|
||||||
|
if !self.initalized.load(Ordering::SeqCst) {
|
||||||
|
unsafe {
|
||||||
|
self.data.get().write(MaybeUninit::new(value));
|
||||||
|
}
|
||||||
|
self.initalized.store(true, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set(&self, value: T) -> Result<(), T> {
|
||||||
|
if self.initalized.load(Ordering::SeqCst) {
|
||||||
|
Err(value)
|
||||||
|
} else {
|
||||||
|
let _ = self.get_or_init(|| value);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<T: Sync + Send> Sync for SusLock<T> {}
|
||||||
|
unsafe impl<T: Send> Send for SusLock<T> {}
|
||||||
|
impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for SusLock<T> {}
|
||||||
|
|
||||||
|
impl<T> Drop for SusLock<T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if self.initalized.load(Ordering::SeqCst) {
|
||||||
|
unsafe { (&mut *self.data.get()).assume_init_drop() };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static AHASH_SEED: SusLock<Option<[u64; 4]>> = SusLock::new();
|
||||||
|
|
||||||
|
// #[doc(cfg(feature = "stable_hash"))]
|
||||||
|
/// Sets the Rhai Ahash seed. This is used to hash functions and the like.
|
||||||
|
///
|
||||||
|
/// This is a global variable, and thus will affect every Rhai instance.
|
||||||
|
/// This should not be used _unless_ you know you need it.
|
||||||
|
///
|
||||||
|
/// # Warnings
|
||||||
|
/// - You can only call this function **ONCE** for the whole of your program execution.
|
||||||
|
/// - You should gracefully handle the `Err(())`.
|
||||||
|
/// - You **MUST** call this before **ANY** Rhai operation occurs (e.g. creating an [`Engine`]).
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// This will error if the AHashSeed is already set.
|
||||||
|
pub fn set_ahash_seed(new_seed: Option<[u64; 4]>) -> Result<(), Option<[u64; 4]>> {
|
||||||
|
AHASH_SEED.set(new_seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the current Rhai Ahash Seed. If the seed is not yet defined, this will automatically set a seed.
|
||||||
|
/// The default seed is not stable and may change between versions.
|
||||||
|
///
|
||||||
|
/// See [`set_rhai_ahash_seed`] for more.
|
||||||
|
pub fn get_ahash_seed() -> Option<[u64; 4]> {
|
||||||
|
const FUNNY_YUMENIKKI_REFERENCE: [u64; 4] = [236,800,954,213];
|
||||||
|
|
||||||
|
AHASH_SEED.get_or_init(|| Some(FUNNY_YUMENIKKI_REFERENCE)).map(|x| *x).flatten()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "static_hash"))]
|
||||||
|
mod internal {
|
||||||
|
const AHASH_SEED: Option<[u64; 4]> = {{ AHASH_SEED }};
|
||||||
|
|
||||||
|
/// Gets the current Rhai Ahash Seed. If the seed is not yet defined, this will automatically set a seed.
|
||||||
|
/// The default seed is not stable and may change between versions.
|
||||||
|
///
|
||||||
|
/// See [`set_ahash_seed`] for more.
|
||||||
|
pub fn get_ahash_seed() -> Option<[u64; 4]> {
|
||||||
|
AHASH_SEED
|
||||||
|
}
|
||||||
|
}
|
3
src/config/mod.rs
Normal file
3
src/config/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
//! Contains Configuration for Rhai.
|
||||||
|
|
||||||
|
pub mod hashing;
|
@ -77,7 +77,7 @@ impl BuildHasher for StraightHasherBuilder {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn get_hasher() -> ahash::AHasher {
|
pub fn get_hasher() -> ahash::AHasher {
|
||||||
match config::get_rhai_ahash_seed() {
|
match config::hashing::get_ahash_seed() {
|
||||||
Some([seed1, seed2, seed3, seed4]) if seed1 | seed2 | seed3 | seed4 != 0 => {
|
Some([seed1, seed2, seed3, seed4]) if seed1 | seed2 | seed3 | seed4 != 0 => {
|
||||||
ahash::RandomState::with_seeds(seed1, seed2, seed3, seed4).build_hasher()
|
ahash::RandomState::with_seeds(seed1, seed2, seed3, seed4).build_hasher()
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
#![allow(clippy::negative_feature_names)]
|
#![allow(clippy::negative_feature_names)]
|
||||||
#![allow(clippy::module_inception)]
|
#![allow(clippy::module_inception)]
|
||||||
|
|
||||||
#![cfg_attr(feature = "stable_hash", feature(once_cell))]
|
#![cfg_attr(feature = "static_hash", feature(once_cell))]
|
||||||
|
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
Loading…
Reference in New Issue
Block a user