use std::sync::atomic::{AtomicU64, Ordering};
use std::time::{SystemTime, UNIX_EPOCH};
static COUNTER: AtomicU64 = AtomicU64::new(0);
struct SplitMix64(u64);
impl SplitMix64 {
fn next(&mut self) -> u64 {
self.0 = self.0.wrapping_add(0x9E37_79B9_7F4A_7C15);
let mut z = self.0;
z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
z ^ (z >> 31)
}
}
fn seed_mix() -> u64 {
let nanos = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_nanos() as u64)
.unwrap_or(0);
let pid = std::process::id() as u64;
let ctr = COUNTER.fetch_add(1, Ordering::Relaxed);
nanos ^ pid.rotate_left(17) ^ ctr.rotate_left(31)
}
pub fn uuid_v7() -> String {
let ms: u64 = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_millis() as u64)
.unwrap_or(0);
let mut sm = SplitMix64(seed_mix());
let r1 = sm.next();
let r2 = sm.next();
let mut bytes = [0u8; 16];
bytes[0..6].copy_from_slice(&ms.to_be_bytes()[2..8]);
bytes[6] = ((ms >> 8) & 0x0f) as u8 | 0x70;
bytes[7] = (ms & 0xff) as u8;
bytes[8] = ((r1 & 0x3f) as u8) | 0x80;
bytes[9] = ((r1 >> 8) & 0xff) as u8;
bytes[10] = ((r1 >> 16) & 0xff) as u8;
bytes[11] = ((r1 >> 24) & 0xff) as u8;
bytes[12] = ((r1 >> 32) & 0xff) as u8;
bytes[13] = ((r1 >> 40) & 0xff) as u8;
bytes[14] = (r2 & 0xff) as u8;
bytes[15] = ((r2 >> 8) & 0xff) as u8;
format!(
"{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
bytes[0], bytes[1], bytes[2], bytes[3],
bytes[4], bytes[5],
bytes[6], bytes[7],
bytes[8], bytes[9],
bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15],
)
}
pub fn is_canonical_uuid_v7(id: &str) -> bool {
if id.len() != 36 {
return false;
}
let bytes = id.as_bytes();
bytes[8] == b'-'
&& bytes[13] == b'-'
&& bytes[18] == b'-'
&& bytes[23] == b'-'
&& bytes[14] == b'7'
&& matches!(bytes[19], b'8' | b'9' | b'a' | b'b')
}
pub fn message_id(row_seq: i64) -> String {
format!("message-{row_seq}")
}
pub fn tool_call_origin_id(call_id: &str, row_seq: i64) -> String {
format!("tool_call_origin:{call_id}:{row_seq}")
}
pub fn tool_result_id(call_id: &str, row_seq: i64) -> String {
format!("tool:{call_id}:{row_seq}")
}
pub fn assistant_message_id(row_seq: i64) -> String {
format!("assistant:{row_seq}")
}