use sha2::{Digest, Sha256};
use std::sync::OnceLock;
use std::time::UNIX_EPOCH;
pub(super) fn token() -> Option<u32> {
static TOKEN: OnceLock<Option<u32>> = OnceLock::new();
*TOKEN.get_or_init(|| {
let exe = std::env::current_exe().ok()?;
let meta = std::fs::metadata(exe).ok()?;
let modified = meta.modified().ok()?.duration_since(UNIX_EPOCH).ok()?;
Some(fold(modified.as_nanos(), meta.len()))
})
}
fn fold(modified_nanos: u128, len: u64) -> u32 {
let mut hasher = Sha256::new();
hasher.update(modified_nanos.to_le_bytes());
hasher.update(len.to_le_bytes());
let digest: [u8; 32] = hasher.finalize().into();
u32::from_le_bytes([digest[0], digest[1], digest[2], digest[3]])
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_same_binary_folds_to_the_same_token() {
assert_eq!(
fold(1_700_000_000_000_000_000, 4096),
fold(1_700_000_000_000_000_000, 4096)
);
}
#[test]
fn a_rebuilt_binary_folds_to_another_token() {
let base = fold(1_700_000_000_000_000_000, 4096);
assert_ne!(base, fold(1_700_000_000_000_000_001, 4096));
assert_ne!(base, fold(1_700_000_000_000_000_000, 4097));
}
#[test]
fn the_running_binary_has_a_token() {
assert!(token().is_some());
}
}