1use std::sync::atomic::{AtomicU64, Ordering};
4use std::time::{SystemTime, UNIX_EPOCH};
5
6static NONCE_COUNTER: AtomicU64 = AtomicU64::new(0);
8
9pub fn generate_nonce(prefix: NoncePrefix) -> String {
34 let timestamp = SystemTime::now()
35 .duration_since(UNIX_EPOCH)
36 .unwrap_or_default()
37 .as_nanos() as u64;
38
39 let count = NONCE_COUNTER.fetch_add(1, Ordering::Relaxed);
40
41 match prefix {
42 NoncePrefix::SotW => format!("{:x}-{:x}", timestamp, count),
43 NoncePrefix::Delta => format!("d{:x}-{:x}", timestamp, count),
44 }
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49pub enum NoncePrefix {
50 SotW,
52 Delta,
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn nonce_unique() {
62 let n1 = generate_nonce(NoncePrefix::SotW);
63 let n2 = generate_nonce(NoncePrefix::SotW);
64 assert_ne!(n1, n2, "nonces should be unique");
65 }
66
67 #[test]
68 fn nonce_format_sotw() {
69 let nonce = generate_nonce(NoncePrefix::SotW);
70 assert!(nonce.contains('-'), "nonce should contain separator");
71 assert!(!nonce.starts_with('d'), "SotW nonce should not start with 'd'");
72 }
73
74 #[test]
75 fn nonce_format_delta() {
76 let nonce = generate_nonce(NoncePrefix::Delta);
77 assert!(nonce.starts_with('d'), "Delta nonce should start with 'd'");
78 assert!(nonce.contains('-'), "nonce should contain separator");
79 }
80}