hyperflake-rs 0.1.1

A simple and lightweight Rust crate library to generate unique snowflake like IDs starting from beginning of the 21th century.
Documentation
use crate::helper::{get_valid_node_id, wait_until_next_timestamp, defaults};

pub struct SnowflakeId {
    node_id_bits: i32,
    sequence_bits: i32,
    epoch: u64,
    last_timestamp: i64,
    sequence: u32,
    node_id: i32,
    max_sequence: u32,
}

impl SnowflakeId {
    pub fn new() -> Self {
        let worker_id = defaults::WORKER_ID;
        let node_id_bits = defaults::NODE_ID_BITS;
        let sequence_bits = defaults::SEQUENCE_BITS;
        let epoch = defaults::EPOCH;

        let last_timestamp = -1;
        let sequence = 0;
        let node_id = get_valid_node_id(worker_id as f64, node_id_bits);
        let max_sequence = (1 << sequence_bits) - 1;

        SnowflakeId {
            node_id_bits,
            sequence_bits,
            epoch,
            last_timestamp,
            sequence,
            node_id,
            max_sequence,
        }
    }

    pub fn generate(&mut self) -> String {
        let timestamp: i64 = std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .unwrap()
            .as_millis() as i64;

        if timestamp < self.last_timestamp {
            panic!("Clock is moving backwards!");
        }

        if timestamp == self.last_timestamp {
            self.sequence = (self.sequence + 1) & self.max_sequence;
            if self.sequence == 0 {
                let new_timestamp = wait_until_next_timestamp(timestamp as u64);
                self.last_timestamp = new_timestamp as i64;
            }
        } else {
            self.sequence = 0;
        }

        self.last_timestamp = timestamp;

        let high = ((timestamp - self.epoch as i64) << (self.node_id_bits + self.sequence_bits))
            | ((self.node_id as i64) << self.sequence_bits)
            | self.sequence as i64;

        let snowflake_id = high;

        snowflake_id.to_string()
    }

    pub fn decode(&self, hfid: &str) -> u64 {
        let high = hfid.parse::<i64>().unwrap();
        let timestamp = ((high >> (self.node_id_bits + self.sequence_bits)) + self.epoch as i64) as u64;
        timestamp
    }
}