use crate::id_worker::IdWorker;
use crate::id_worker_config::IdWorkerConfig;
use crate::internal::id_worker_utils::IdWorkerUtils;
use crate::IdWorkerError;
use std::sync::atomic::{AtomicU32, Ordering};
pub struct SnowflakeIdWorker {
epoch: u64,
epoch_precision: i8,
timestamp_shift: u8,
worker: u16,
sequence_bits: u8,
sequence_mask: u32,
sequence: AtomicU32,
}
impl SnowflakeIdWorker {
pub fn new(config: IdWorkerConfig) -> Self {
let IdWorkerConfig {
epoch,
epoch_precision,
data_center,
data_center_bits,
node,
node_bits,
sequence_bits,
..
} = config;
let worker_bits = data_center_bits + node_bits;
let worker = ((data_center as u16) << node_bits) + node as u16;
let sequence_mask = (1 << sequence_bits) - 1;
let timestamp_shift = worker_bits + sequence_bits;
SnowflakeIdWorker {
epoch,
epoch_precision,
timestamp_shift,
worker,
sequence_bits,
sequence_mask,
sequence: AtomicU32::new(0),
}
}
}
impl IdWorker for SnowflakeIdWorker {
fn next_id(&self) -> Result<u64, IdWorkerError> {
let timestamp = IdWorkerUtils::calc_timestamp(self.epoch, self.epoch_precision)?;
let sequence = self.sequence.fetch_add(1, Ordering::Relaxed) & self.sequence_mask;
Ok(IdWorkerUtils::calc_id(
timestamp,
self.timestamp_shift,
self.worker,
sequence,
self.sequence_bits,
))
}
}