1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
//! Hash functions and data structures.
/// Turn a string into a uniquely corresponding number. Useful for if you don't
/// need to refer back to the original string again. Also see
/// `zaplib_shader_compiler::ident::Interner` for if you do need access to original
/// strings.
/// TODO(JP): Might be good to replace all of this wholesale with an existing
/// "interner" library. See `zaplib_shader_compiler::ident::Interner` for more details.
#[derive(PartialEq, Copy, Clone, Hash, Eq, Debug, PartialOrd, Ord)]
struct StringHash<'a> {
hash: u64,
string: &'a str,
}
impl<'a> StringHash<'a> {
/// Get a new [`StringHash`] for a given [`str`].
const fn new(string: &'a str) -> Self {
let bytes = string.as_bytes();
let len = bytes.len();
let mut hash = 1125899906842597u64;
let mut i = 0;
while i < len {
hash = hash.wrapping_mul(31).wrapping_add(bytes[i] as u64);
i += 1;
}
Self { hash, string }
}
}
/// Represents a particular place in the code. Useful e.g. for shaders; see the
/// documentation of [`crate::Shader`].
///
/// TODO(JP): Having [`Default`] on [`LocationHash`] is not so great, because you
/// typically want to define it explicitly. Would be good to remove at some
/// point.
#[derive(Default, PartialEq, Copy, Clone, Hash, Eq, Debug, PartialOrd, Ord)]
pub struct LocationHash(pub u64);
impl LocationHash {
/// Get a [`LocationHash`] for the given file/line/column. See also [`location_hash!`].
pub const fn new(path: &str, line: u64, col: u64) -> Self {
let val = StringHash::new(path).hash;
LocationHash(val.wrapping_mul(31).wrapping_add(line).wrapping_mul(31).wrapping_add(col))
}
}