OXYGENHUB

Coverage / crates/spectra-core/src/ids.rs 100.0%

22 of 22 lines run, 11 of 11 functions · run #6 on main · run missed

1
//! Identifiers (spec §9.4): ULIDs, 26 characters of Crockford base32, time
2
//! ordered and globally unique, so an id made on one machine merges into a
3
//! hub without renaming.
4
5
use rand::RngCore;
6
7
const CROCKFORD: &[u8; 32] = b"0123456789ABCDEFGHJKMNPQRSTVWXYZ";
8
9
/// A new ULID for the current time.
1011520×
pub fn ulid() -> String {
1111520×
    let mut r = [0u8; 16];
1211520×
    rand::rngs::OsRng.fill_bytes(&mut r);
1311520×
    ulid_from(now_ms(), u128::from_be_bytes(r))
1411520×
}
15
16
/// A ULID from a millisecond time and 80 bits taken from `random`.
1711523×
pub fn ulid_from(ms: u64, random: u128) -> String {
1811523×
    let v: u128 = ((ms as u128 & ((1 << 48) - 1)) << 80) | (random & ((1u128 << 80) - 1));
19299598×
    (0..26).map(|i| CROCKFORD[((v >> (125 - 5 * i)) & 31) as usize] as char).collect()
2011523×
}
21
22
/// Milliseconds since the Unix epoch.
2325008×
pub fn now_ms() -> u64 {
2425008×
    std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).map(|d| d.as_millis() as u64).unwrap_or(0)
2525008×
}
26
27
#[cfg(test)]
28
mod tests {
29
    use super::*;
30
31
    #[test]
321×
    fn ulids_are_26_chars_and_sort_by_time() {
331×
        let a = ulid_from(1_000, 5);
341×
        let b = ulid_from(2_000, 0);
351×
        assert_eq!(a.len(), 26);
361×
        assert!(a < b);
371×
        assert_eq!(ulid_from(0, 0), "00000000000000000000000000");
381×
        assert_ne!(ulid(), ulid());
391×
    }
40
}