use std::sync::LazyLock;
#[cfg(target_os = "linux")]
mod linux;
#[cfg(target_os = "macos")]
mod macos;
#[cfg(windows)]
mod windows;
pub(crate) fn normalize_uuid(raw: &str) -> String {
let hex: String = raw
.chars()
.filter(|c| c.is_ascii_hexdigit())
.flat_map(char::to_lowercase)
.collect();
if hex.len() != 32 {
return String::new();
}
format!(
"{}-{}-{}-{}-{}",
&hex[0..8],
&hex[8..12],
&hex[12..16],
&hex[16..20],
&hex[20..32],
)
}
static MACHINE_ID: LazyLock<String> = LazyLock::new(|| {
let raw = {
#[cfg(target_os = "linux")]
{
linux::get_machine_id_impl()
}
#[cfg(target_os = "macos")]
{
macos::get_machine_id_impl()
}
#[cfg(windows)]
{
windows::get_machine_id_impl()
}
#[cfg(not(any(target_os = "linux", target_os = "macos", windows)))]
{
String::new()
}
};
normalize_uuid(&raw)
});
pub fn get_machine_id() -> &'static str {
MACHINE_ID.as_str()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn cached_value_is_stable() {
assert_eq!(get_machine_id(), get_machine_id());
}
#[test]
fn value_has_uuid_shape_if_nonempty() {
let id = get_machine_id();
if id.is_empty() {
return;
}
assert_eq!(id.len(), 36);
for (i, c) in id.chars().enumerate() {
if [8, 13, 18, 23].contains(&i) {
assert_eq!(c, '-');
} else {
assert!(c.is_ascii_hexdigit() && !c.is_ascii_uppercase());
}
}
}
#[test]
fn normalize_bare_hex_inserts_hyphens() {
assert_eq!(
normalize_uuid("b08fa8a2b01a4d2bbd95fec7e30c5aec"),
"b08fa8a2-b01a-4d2b-bd95-fec7e30c5aec"
);
}
#[test]
fn normalize_uppercase_uuid_lowercased() {
assert_eq!(
normalize_uuid("B08FA8A2-B01A-4D2B-BD95-FEC7E30C5AEC"),
"b08fa8a2-b01a-4d2b-bd95-fec7e30c5aec"
);
}
#[test]
fn normalize_lowercase_uuid_unchanged() {
assert_eq!(
normalize_uuid("b08fa8a2-b01a-4d2b-bd95-fec7e30c5aec"),
"b08fa8a2-b01a-4d2b-bd95-fec7e30c5aec"
);
}
#[test]
fn normalize_invalid_returns_empty() {
assert_eq!(normalize_uuid(""), "");
assert_eq!(normalize_uuid("b08fa8a2"), "");
assert_eq!(normalize_uuid("zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"), "");
}
}