|
6 | 6 | pub use hashbrown::hash_map; |
7 | 7 |
|
8 | 8 | mod hashbrown_tables { |
9 | | - #[cfg(feature = "std")] |
| 9 | + #[cfg(all(feature = "std", not(test)))] |
10 | 10 | mod hasher { |
11 | 11 | pub use std::collections::hash_map::RandomState; |
12 | 12 | } |
| 13 | + #[cfg(all(feature = "std", test))] |
| 14 | + mod hasher { |
| 15 | + #![allow(deprecated)] // hash::SipHasher was deprecated in favor of something only in std. |
| 16 | + use core::hash::{BuildHasher, Hasher}; |
| 17 | + |
| 18 | + /// A [`BuildHasher`] for tests that supports deterministic behavior via environment variable. |
| 19 | + /// |
| 20 | + /// When `LDK_TEST_DETERMINISTIC_HASHES` is set, uses fixed keys for deterministic iteration. |
| 21 | + /// Otherwise, delegates to std's RandomState for random hashing. |
| 22 | + #[derive(Clone)] |
| 23 | + pub enum RandomState { |
| 24 | + Std(std::collections::hash_map::RandomState), |
| 25 | + Deterministic, |
| 26 | + } |
| 27 | + |
| 28 | + impl RandomState { |
| 29 | + pub fn new() -> RandomState { |
| 30 | + if std::env::var("LDK_TEST_DETERMINISTIC_HASHES").map(|v| v == "1").unwrap_or(false) |
| 31 | + { |
| 32 | + RandomState::Deterministic |
| 33 | + } else { |
| 34 | + RandomState::Std(std::collections::hash_map::RandomState::new()) |
| 35 | + } |
| 36 | + } |
| 37 | + } |
| 38 | + |
| 39 | + impl Default for RandomState { |
| 40 | + fn default() -> RandomState { |
| 41 | + RandomState::new() |
| 42 | + } |
| 43 | + } |
| 44 | + |
| 45 | + /// A hasher wrapper that delegates to either std's DefaultHasher or a deterministic SipHasher. |
| 46 | + pub enum RandomStateHasher { |
| 47 | + Std(std::collections::hash_map::DefaultHasher), |
| 48 | + Deterministic(core::hash::SipHasher), |
| 49 | + } |
| 50 | + |
| 51 | + impl Hasher for RandomStateHasher { |
| 52 | + fn finish(&self) -> u64 { |
| 53 | + match self { |
| 54 | + RandomStateHasher::Std(h) => h.finish(), |
| 55 | + RandomStateHasher::Deterministic(h) => h.finish(), |
| 56 | + } |
| 57 | + } |
| 58 | + fn write(&mut self, bytes: &[u8]) { |
| 59 | + match self { |
| 60 | + RandomStateHasher::Std(h) => h.write(bytes), |
| 61 | + RandomStateHasher::Deterministic(h) => h.write(bytes), |
| 62 | + } |
| 63 | + } |
| 64 | + } |
| 65 | + |
| 66 | + impl BuildHasher for RandomState { |
| 67 | + type Hasher = RandomStateHasher; |
| 68 | + fn build_hasher(&self) -> RandomStateHasher { |
| 69 | + match self { |
| 70 | + RandomState::Std(s) => RandomStateHasher::Std(s.build_hasher()), |
| 71 | + RandomState::Deterministic => { |
| 72 | + RandomStateHasher::Deterministic(core::hash::SipHasher::new_with_keys(0, 0)) |
| 73 | + }, |
| 74 | + } |
| 75 | + } |
| 76 | + } |
| 77 | + } |
13 | 78 | #[cfg(not(feature = "std"))] |
14 | 79 | mod hasher { |
15 | 80 | #![allow(deprecated)] // hash::SipHasher was deprecated in favor of something only in std. |
|
0 commit comments