use std::ffi::OsStr;
use std::hash::{Hash, Hasher};
use std::path::{Path, PathBuf};
use twox_hash::XxHash;
pub(crate) type HashCode = u64;
pub(crate) fn hash_buf(buf: &[u8]) -> HashCode {
hash(buf)
}
pub(crate) fn hash<T: Hash>(something: T) -> HashCode {
let mut hasher = XxHash::with_seed(42);
something.hash(&mut hasher);
hasher.finish()
}
pub(crate) fn add_hash_to_path(path: &Path, hash: HashCode) -> PathBuf {
let mut path = path.to_owned();
let name = path
.file_stem()
.expect("path is missing a file name")
.to_str()
.expect("file name contains invalid UTF-8");
let ext = path
.extension()
.map(|ext| format!(".{}", ext.to_str().unwrap()))
.unwrap_or_else(|| "".to_owned());
let new_name = &format!("{}-{:x}{}", name, hash, ext);
path.set_file_name(OsStr::new(new_name));
path
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn hash_equality() {
assert_eq!(hash("foo"), hash(&"foo".to_owned()));
}
#[test]
fn hash_inequality() {
assert_ne!(hash("foo"), hash("foo1"));
}
#[test]
fn file_name_generation() {
let path = &Path::new("/foo/bar/baz/mylib.a");
let hash: HashCode = 0xcafebabedeadbeef;
assert_eq!(
Path::new("/foo/bar/baz/mylib-cafebabedeadbeef.a"),
add_hash_to_path(&path, hash)
);
}
}