#![doc = include_str!("../README.md")]
#![cfg_attr(not(test), warn(
missing_debug_implementations,
missing_docs,
//trivial_casts,
trivial_numeric_casts,
unused_extern_crates,
unused_import_braces,
unused_qualifications,
//unused_results
))]
#![cfg_attr(test, deny(
missing_debug_implementations,
missing_docs,
//trivial_casts,
trivial_numeric_casts,
unused_extern_crates,
unused_import_braces,
unused_qualifications,
unused_must_use,
//unused_results
))]
#![cfg_attr(
test,
deny(
bad_style,
dead_code,
improper_ctypes,
non_shorthand_field_patterns,
overflowing_literals,
path_statements,
patterns_in_fns_without_body,
unconditional_recursion,
unused,
unused_allocation,
unused_comparisons,
unused_parens,
while_true
)
)]
use core::{
any::TypeId,
hash::{BuildHasher, Hash, Hasher},
};
use std::{env, fs::File, io, sync::OnceLock};
use ahash::RandomState;
use uuid::Uuid;
static BUILD_ID: OnceLock<Uuid> = OnceLock::new();
#[inline]
#[must_use]
pub fn get() -> Uuid {
*BUILD_ID.get_or_init(calculate)
}
fn from_exe<H: Hasher>(mut hasher: H) -> Result<H, ()> {
#[cfg(not(target_arch = "wasm32"))]
{
if cfg!(miri) {
return Err(());
}
let file = File::open(env::current_exe().map_err(drop)?).map_err(drop)?;
let _: u64 = io::copy(&mut &file, &mut HashWriter(&mut hasher)).map_err(drop)?;
Ok(hasher)
}
#[cfg(target_arch = "wasm32")]
{
let _ = &mut hasher;
Err(())
}
}
fn from_type_id<H: Hasher>(mut hasher: H) -> H {
fn type_id_of<T: 'static>(_: &T) -> TypeId {
TypeId::of::<T>()
}
TypeId::of::<()>().hash(&mut hasher);
TypeId::of::<u8>().hash(&mut hasher);
let a = |x: ()| x;
type_id_of(&a).hash(&mut hasher);
let b = |x: u8| x;
type_id_of(&b).hash(&mut hasher);
hasher
}
fn calculate() -> Uuid {
let hasher = RandomState::with_seeds(0, 0, 0, 0).build_hasher();
let hasher = from_exe(hasher.clone()).unwrap_or(hasher);
let mut hasher = from_type_id(hasher);
let mut bytes = [0; 16];
bytes[..8].copy_from_slice(&hasher.finish().to_ne_bytes());
hasher.write_u8(0);
bytes[8..].copy_from_slice(&hasher.finish().to_ne_bytes());
*uuid::Builder::from_bytes(bytes)
.set_variant(uuid::Variant::RFC4122)
.set_version(uuid::Version::Random)
.as_uuid()
}
struct HashWriter<T: Hasher>(T);
impl<T: Hasher> io::Write for HashWriter<T> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf);
Ok(buf.len())
}
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.write(buf).map(|_| ())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}