use std::sync::atomic::{AtomicI64, Ordering};
use std::time::{SystemTime, UNIX_EPOCH};
#[derive(Debug)]
pub struct IdGenerator {
counter: AtomicI64,
}
impl IdGenerator {
pub fn new(init: i64) -> Self {
Self {
counter: AtomicI64::new(init),
}
}
pub fn id(&self) -> i64 {
self.counter.fetch_add(1, Ordering::SeqCst)
}
pub fn reset(&self, value: i64) {
self.counter.store(value, Ordering::SeqCst);
}
pub fn current_value(&self) -> i64 {
self.counter.load(Ordering::SeqCst)
}
}
impl Clone for IdGenerator {
fn clone(&self) -> Self {
Self {
counter: AtomicI64::new(self.current_value()),
}
}
}
impl Default for IdGenerator {
fn default() -> Self {
Self::new(0)
}
}
pub fn generate_id() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_nanos() as u64
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_id_generator() {
let gen = IdGenerator::new(0);
assert_eq!(gen.id(), 0);
assert_eq!(gen.id(), 1);
assert_eq!(gen.id(), 2);
gen.reset(100);
assert_eq!(gen.current_value(), 100);
assert_eq!(gen.id(), 100);
}
#[test]
fn test_generate_id() {
let id1 = generate_id();
let id2 = generate_id();
assert_ne!(id1, id2);
}
}