use std::time::{SystemTime, UNIX_EPOCH};
pub fn new_idempotency_key() -> String {
uuidv7(SystemTime::now())
}
pub(crate) fn uuidv7(now: SystemTime) -> String {
let mut b = [0u8; 16];
getrandom::fill(&mut b).expect("honk: the operating system's random number generator failed");
let ms = now
.duration_since(UNIX_EPOCH)
.map_or(0, |d| d.as_millis() as u64);
b[..6].copy_from_slice(&ms.to_be_bytes()[2..]);
b[6] = (b[6] & 0x0f) | 0x70; b[8] = (b[8] & 0x3f) | 0x80; let h: String = b.iter().map(|x| format!("{x:02x}")).collect();
format!(
"{}-{}-{}-{}-{}",
&h[0..8],
&h[8..12],
&h[12..16],
&h[16..20],
&h[20..32]
)
}
pub(crate) fn random_u64() -> u64 {
let mut b = [0u8; 8];
getrandom::fill(&mut b).expect("honk: the operating system's random number generator failed");
u64::from_le_bytes(b)
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;
#[test]
fn version_variant_and_time_order() {
let a = uuidv7(UNIX_EPOCH + Duration::from_millis(1_791_116_405_123));
let b = uuidv7(UNIX_EPOCH + Duration::from_millis(1_791_116_405_124));
assert_eq!(a.len(), 36);
assert_eq!([&a[8..9], &a[13..14], &a[18..19], &a[23..24]], ["-"; 4]);
assert_eq!(&a[14..15], "7");
assert!(matches!(&a[19..20], "8" | "9" | "a" | "b"));
assert!(a < b, "{a} < {b}");
assert_eq!(
u64::from_str_radix(&a[0..8], 16).unwrap() << 16
| u64::from_str_radix(&a[9..13], 16).unwrap(),
1_791_116_405_123
);
}
}