use once_cell::sync::Lazy;
use rust_mcp_sdk::id_generator::IdGenerator;
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::{SystemTime, UNIX_EPOCH};
static SHORTER_EPOCH: Lazy<u64> = Lazy::new(|| {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("invalid system time!")
.as_millis() as u64
});
pub struct SnowflakeIdGenerator {
machine_id: u16, last_timestamp: AtomicU64,
sequence: AtomicU64,
}
impl SnowflakeIdGenerator {
pub fn new(machine_id: u16) -> Self {
assert!(
machine_id < 1024,
"Machine ID must be less than 1024 (10 bits)"
);
SnowflakeIdGenerator {
machine_id,
last_timestamp: AtomicU64::new(0),
sequence: AtomicU64::new(0),
}
}
fn current_timestamp(&self) -> u64 {
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("invalid system time!")
.as_millis() as u64;
now.saturating_sub(*SHORTER_EPOCH)
}
fn next_id(&self) -> u64 {
let mut timestamp = self.current_timestamp();
let last_ts = self.last_timestamp.load(Ordering::Relaxed);
let sequence = if timestamp == last_ts {
let seq = self.sequence.fetch_add(1, Ordering::Relaxed) & 0xFFF; if seq == 0 {
while timestamp <= last_ts {
timestamp = self.current_timestamp();
}
self.sequence.store(0, Ordering::Relaxed);
self.last_timestamp.store(timestamp, Ordering::Relaxed);
0
} else {
seq
}
} else {
self.sequence.store(0, Ordering::Relaxed);
self.last_timestamp.store(timestamp, Ordering::Relaxed);
0
};
((timestamp & 0x1FFFFFFFFFF) << 22) | ((self.machine_id as u64 & 0x3FF) << 12) | (sequence & 0xFFF) }
}
impl<T> IdGenerator<T> for SnowflakeIdGenerator
where
T: From<String>,
{
fn generate(&self) -> T {
let id = self.next_id();
T::from(id.to_string()) }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn generates_id() {
let generator = SnowflakeIdGenerator::new(1);
let id: String = generator.generate();
assert!(!id.is_empty(), "Generated ID should not be empty");
}
#[test]
fn generates_unique_ids() {
let generator = SnowflakeIdGenerator::new(1);
let mut ids = std::collections::HashSet::new();
for _ in 0..1000 {
let id: String = generator.generate();
assert!(ids.insert(id), "Duplicate ID generated");
}
}
#[test]
fn ids_are_monotonic_increasing() {
let generator = SnowflakeIdGenerator::new(1);
let mut prev_id = 0u64;
for _ in 0..1000 {
let id: String = generator.generate();
let current_id: u64 = id.parse().expect("ID should be a valid u64");
assert!(
current_id > prev_id,
"ID not strictly increasing: {current_id} <= {prev_id}"
);
prev_id = current_id;
}
}
#[test]
fn handles_sequence_rollover() {
let generator = SnowflakeIdGenerator::new(1);
for _ in 0..2000 {
let _id: String = generator.generate();
}
}
#[test]
fn respects_machine_id_limit() {
let _ = SnowflakeIdGenerator::new(1023);
}
#[test]
#[should_panic(expected = "Machine ID must be less than 1024")]
fn rejects_invalid_machine_id() {
let _ = SnowflakeIdGenerator::new(1024);
}
}