Skip to main content

smol_ulid/
lib.rs

1use rand::Rng;
2use std::time::{Duration, SystemTime};
3
4#[derive(PartialOrd, Ord, PartialEq, Eq, Hash, Clone, Copy)]
5pub struct SUlid(u64);
6
7impl SUlid {
8    #[allow(dead_code)]
9    const TIME_BITS: u8 = 43;
10    const TIME_BITMASK: u64 = 0b1111111111111111111111111111111111111111111;
11
12    const RAND_BITS: u8 = 21;
13    const RAND_BITMASK: u64 = 0b111111111111111111111;
14
15    /// Create a Ulid with the current time and random bits
16    pub fn new() -> Self {
17        let timestamp = SystemTime::now()
18            .duration_since(SystemTime::UNIX_EPOCH)
19            .unwrap_or(Duration::ZERO) // TODO: How to handle this?
20            .as_millis();
21
22        let val = ((timestamp as u64 & Self::TIME_BITMASK) << Self::RAND_BITS)
23            | (rand::rng().random::<u64>() & Self::TIME_BITMASK);
24
25        Self(val)
26    }
27
28    /// Get the SystemTime the Ulid was created at
29    pub fn datetime(self) -> SystemTime {
30        SystemTime::UNIX_EPOCH + Duration::from_millis(self.0 >> Self::RAND_BITS)
31    }
32
33    /// Get the random bits in the Ulid
34    pub fn random(self) -> u64 {
35        self.0 & Self::RAND_BITMASK
36    }
37}
38
39impl Default for SUlid {
40    fn default() -> Self {
41        Self::new()
42    }
43}