//! Runtime support for precomputed constant hash tables. //! //! The shared module with the same name can generate constant hash tables using open addressing //! and quadratic probing. //! //! The hash tables are arrays that are guaranteed to: //! //! - Have a power-of-two size. //! - Contain at least one empty slot. //! //! This module provides runtime support for lookups in these tables. // Re-export entities from constant_hash for simplicity of use. pub use cranelift_codegen_shared::constant_hash::*; /// Trait that must be implemented by the entries in a constant hash table. pub trait Table { /// Get the number of entries in this table which must be a power of two. fn len(&self) -> usize; /// Get the key corresponding to the entry at `idx`, or `None` if the entry is empty. /// The `idx` must be in range. fn key(&self, idx: usize) -> Option; } /// Look for `key` in `table`. /// /// The provided `hash` value must have been computed from `key` using the same hash function that /// was used to construct the table. /// /// Returns `Ok(idx)` with the table index containing the found entry, or `Err(idx)` with the empty /// sentinel entry if no entry could be found. pub fn probe + ?Sized>( table: &T, key: K, hash: usize, ) -> Result { debug_assert!(table.len().is_power_of_two()); let mask = table.len() - 1; let mut idx = hash; let mut step = 0; loop { idx &= mask; match table.key(idx) { None => return Err(idx), Some(k) if k == key => return Ok(idx), _ => {} } // Quadratic probing. step += 1; // When `table.len()` is a power of two, it can be proven that `idx` will visit all // entries. This means that this loop will always terminate if the hash table has even // one unused entry. debug_assert!(step < table.len()); idx += step; } }