use crate::IdWorkerError;
use serde::{Deserialize, Serialize};
use std::time::{SystemTime, UNIX_EPOCH};
use typed_builder::TypedBuilder;
const TIMESTAMP_MIN_BITS: u8 = 41;
#[derive(Clone, Serialize, Deserialize, Debug)]
pub enum Mode {
Normal,
Faster,
Fastest,
}
pub const ID_WORKER_CONFIG_KEY: &str = "id-worker";
#[derive(Debug, Clone, Serialize, Deserialize, TypedBuilder)]
#[builder(build_method(into = Result<IdWorkerConfig, IdWorkerError>))]
#[serde(default, rename_all = "kebab-case")]
pub struct IdWorkerConfig {
#[builder(default = Mode::Normal)]
pub mode: Mode,
#[builder(default = 1758159446615)]
pub epoch: u64,
#[builder(default = 1)]
pub epoch_precision: i8,
#[builder(default = 0)]
pub data_center: u8,
#[builder(default = 0)]
pub data_center_bits: u8,
#[builder(default = 0)]
pub node: u8,
#[builder(default = 4)]
pub node_bits: u8,
#[builder(default = 12)]
pub sequence_bits: u8,
}
impl From<IdWorkerConfig> for Result<IdWorkerConfig, IdWorkerError> {
fn from(config: IdWorkerConfig) -> Self {
let IdWorkerConfig {
epoch,
data_center,
data_center_bits,
node,
node_bits,
sequence_bits,
..
} = config;
let now = SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis() as u64;
if epoch > now {
Err(IdWorkerError::Config(format!(
"epoch {epoch} cannot be greater than current timestamp"
)))?;
}
if data_center_bits > 8 {
Err(IdWorkerError::Config(format!(
"data_center_bits {data_center_bits} is out of range for u8"
)))?;
}
let max_data_center = (1u16 << data_center_bits) - 1;
if data_center as u16 > max_data_center {
Err(IdWorkerError::Config(format!(
"data_center {} is out of range for {} bits",
data_center, data_center_bits
)))?;
}
if node_bits > 8 {
Err(IdWorkerError::Config(format!(
"node_bits {} is out of range for u8",
node_bits
)))?;
}
let max_node = (1u16 << node_bits) - 1;
if node as u16 > max_node {
Err(IdWorkerError::Config(format!(
"node {} is out of range for {} bits",
node, node_bits
)))?;
}
let max_sequence_bits = 64 - TIMESTAMP_MIN_BITS - data_center_bits - node_bits;
if sequence_bits > max_sequence_bits {
Err(IdWorkerError::Config(format!(
"sequence_bits {} cannot be greater than {}",
sequence_bits, max_sequence_bits
)))?;
}
Ok(config)
}
}
impl Default for IdWorkerConfig {
fn default() -> Self {
IdWorkerConfig::builder().build().unwrap() }
}