Last active
November 2, 2023 12:43
-
-
Save ddjerqq/8975e1f871a8306a16914d6de8b002e8 to your computer and use it in GitHub Desktop.
snowflake.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::time::{SystemTime, UNIX_EPOCH}; | |
const EPOCH: u64 = 1420070400000; | |
pub struct Id { | |
internal_worker: u128, | |
internal_process: u128, | |
increment: u128, | |
} | |
impl Id { | |
pub fn get_timestamp() -> u64 { | |
SystemTime::now() | |
.duration_since(UNIX_EPOCH) | |
.unwrap() | |
.as_millis() as u64 | |
} | |
pub fn generate(&mut self) -> u64 { | |
let mut id = Id::get_timestamp(); | |
id -= &EPOCH; | |
id <<= 5; | |
id += (self.internal_worker % 32) as u64; | |
id <<= 5; | |
id += (self.internal_process % 32) as u64; | |
id <<= 12; | |
id += (self.increment % 4096) as u64; | |
self.internal_process += 1; | |
self.increment += 1; | |
self.internal_worker += 1; | |
id | |
} | |
pub fn created_at(id: u64) -> u64 { | |
((id >> 22) + EPOCH) as u64 | |
} | |
pub fn new() -> Self { | |
Self { | |
internal_worker: 0, | |
internal_process: 0, | |
increment: 0, | |
} | |
} | |
} | |
#[cfg(test)] | |
mod tests { | |
use super::*; | |
const AMOUNT: usize = 10000; | |
#[test] | |
fn does_not_repeat() { | |
let mut generator = Id::new(); | |
let mut ids: [u64; AMOUNT] = [0; AMOUNT]; | |
for i in 0..AMOUNT { | |
let id= generator.generate(); | |
assert!(!ids.contains(&id)); | |
ids[i] = id; | |
assert!(ids.contains(&id)); | |
} | |
} | |
#[test] | |
fn created_at() { | |
let mut generator = Id::new(); | |
let id = generator.generate(); | |
assert_eq!(Id::get_timestamp(), Id::created_at(id)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment