Skip to main content

Ulid

Struct Ulid 

Source
pub struct Ulid(/* private fields */);
Available on crate feature ulid only.
Expand description

A 128-bit ULID.

Internally stored as 16 big-endian bytes: 6 bytes of millisecond timestamp followed by 10 bytes of randomness.

§Example

use id_forge::ulid::Ulid;

let id = Ulid::new();
assert_eq!(id.to_string().len(), 26);

Implementations§

Source§

impl Ulid

Source

pub const fn nil() -> Self

The Nil ULID: all 128 bits set to zero.

§Example
use id_forge::ulid::Ulid;

assert_eq!(Ulid::nil().to_string(), "00000000000000000000000000");
Source

pub const fn max() -> Self

The Max ULID: all 128 bits set to one — the largest value the 26-character display can represent (7ZZZ… since the spec reserves the top two bits of the leading character).

§Example
use id_forge::ulid::Ulid;

assert_eq!(Ulid::max().to_string(), "7ZZZZZZZZZZZZZZZZZZZZZZZZZ");
Source

pub fn new() -> Self

Construct a new ULID at the current wall-clock millisecond.

Two ULIDs minted in the same millisecond by the same process are strictly ordered: the second one is the first one’s random suffix plus one. Across milliseconds, the randomness is freshly drawn.

§Example
use id_forge::ulid::Ulid;

let a = Ulid::new();
let b = Ulid::new();
assert!(b > a);
Examples found in repository?
examples/basic.rs (line 13)
7fn main() {
8    let v4 = Uuid::v4();
9    println!("UUID v4:    {v4} (version={})", v4.version());
10    println!("UUID v7:    {}", Uuid::v7());
11    println!("UUID nil:   {}", Uuid::nil());
12
13    let a = Ulid::new();
14    let b = Ulid::new();
15    println!("ULID a:     {a}");
16    println!("ULID b:     {b} (monotonic: {})", b > a);
17
18    let gen = Snowflake::new(1);
19    let sf = gen.next_id();
20    let (ts_offset, worker, seq) = Snowflake::parts(sf);
21    println!(
22        "Snowflake:  {sf}  (ts+epoch={}, worker={worker}, seq={seq})",
23        ts_offset + gen.epoch_ms()
24    );
25
26    println!("NanoID 21:  {}", nanoid::generate());
27    println!("NanoID 8:   {}", nanoid::with_length(8));
28
29    assert_eq!(v4, Uuid::parse_str(&v4.to_string()).unwrap());
30    assert_eq!(a, Ulid::parse_str(&a.to_string()).unwrap());
31}
More examples
Hide additional examples
examples/ulid_monotonic.rs (line 18)
13fn main() {
14    println!("== Single-millisecond burst ==");
15
16    // 1000 ULIDs back-to-back. Most will share the same ms prefix;
17    // the monotonic factory guarantees b > a for every consecutive pair.
18    let mut ids: Vec<Ulid> = (0..1000).map(|_| Ulid::new()).collect();
19
20    let same_ms = ids
21        .windows(2)
22        .filter(|w| w[0].timestamp_ms() == w[1].timestamp_ms())
23        .count();
24    println!("count        = {}", ids.len());
25    println!("same-ms pairs = {same_ms} of {}", ids.len() - 1);
26
27    let strictly_increasing = ids.windows(2).all(|w| w[1] > w[0]);
28    println!("monotonic    = {strictly_increasing}");
29
30    let unique: HashSet<&Ulid> = ids.iter().collect();
31    println!("unique       = {} of {}", unique.len(), ids.len());
32
33    println!("\n== First and last of the burst ==");
34    let first = ids.first().unwrap();
35    let last = ids.last().unwrap();
36    println!("first        = {first}");
37    println!("last         = {last}");
38    println!("ts_first     = {} ms", first.timestamp_ms());
39    println!("ts_last      = {} ms", last.timestamp_ms());
40
41    println!("\n== Crockford base32 round-trip ==");
42    let sample = Ulid::new();
43    let s = sample.to_string();
44    let parsed = Ulid::parse_str(&s).unwrap();
45    println!("sample       = {sample}");
46    println!("parsed       = {parsed}");
47    println!("equal        = {}", sample == parsed);
48
49    println!("\n== Substitutions accepted by parse_str ==");
50    let with_subs = Ulid::parse_str("0IIIIIIIIIIIIIIIIIIIIIIIII").unwrap();
51    let canonical = Ulid::parse_str("01111111111111111111111111").unwrap();
52    println!("\"0III...\" == \"0111...\" = {}", with_subs == canonical);
53
54    println!("\n== Sorting by Display is sorting by time ==");
55    ids.sort_by_key(|u| u.to_string());
56    let same = ids.windows(2).all(|w| w[1] >= w[0]);
57    println!("string sort  = byte sort = {same}");
58}
Source

pub const fn from_bytes(bytes: &[u8; 16]) -> Self

Wrap a 16-byte big-endian representation as-is.

§Example
use id_forge::ulid::Ulid;

let id = Ulid::new();
let copy = Ulid::from_bytes(id.as_bytes());
assert_eq!(id, copy);
Source

pub const fn as_bytes(&self) -> &[u8; 16]

Return the raw 16-byte big-endian representation.

§Example
use id_forge::ulid::Ulid;

assert_eq!(Ulid::nil().as_bytes(), &[0u8; 16]);
Source

pub const fn timestamp_ms(&self) -> u64

Return the 48-bit millisecond timestamp prefix.

§Example
use id_forge::ulid::Ulid;

let id = Ulid::new();
assert!(id.timestamp_ms() > 0);
Examples found in repository?
examples/ulid_monotonic.rs (line 22)
13fn main() {
14    println!("== Single-millisecond burst ==");
15
16    // 1000 ULIDs back-to-back. Most will share the same ms prefix;
17    // the monotonic factory guarantees b > a for every consecutive pair.
18    let mut ids: Vec<Ulid> = (0..1000).map(|_| Ulid::new()).collect();
19
20    let same_ms = ids
21        .windows(2)
22        .filter(|w| w[0].timestamp_ms() == w[1].timestamp_ms())
23        .count();
24    println!("count        = {}", ids.len());
25    println!("same-ms pairs = {same_ms} of {}", ids.len() - 1);
26
27    let strictly_increasing = ids.windows(2).all(|w| w[1] > w[0]);
28    println!("monotonic    = {strictly_increasing}");
29
30    let unique: HashSet<&Ulid> = ids.iter().collect();
31    println!("unique       = {} of {}", unique.len(), ids.len());
32
33    println!("\n== First and last of the burst ==");
34    let first = ids.first().unwrap();
35    let last = ids.last().unwrap();
36    println!("first        = {first}");
37    println!("last         = {last}");
38    println!("ts_first     = {} ms", first.timestamp_ms());
39    println!("ts_last      = {} ms", last.timestamp_ms());
40
41    println!("\n== Crockford base32 round-trip ==");
42    let sample = Ulid::new();
43    let s = sample.to_string();
44    let parsed = Ulid::parse_str(&s).unwrap();
45    println!("sample       = {sample}");
46    println!("parsed       = {parsed}");
47    println!("equal        = {}", sample == parsed);
48
49    println!("\n== Substitutions accepted by parse_str ==");
50    let with_subs = Ulid::parse_str("0IIIIIIIIIIIIIIIIIIIIIIIII").unwrap();
51    let canonical = Ulid::parse_str("01111111111111111111111111").unwrap();
52    println!("\"0III...\" == \"0111...\" = {}", with_subs == canonical);
53
54    println!("\n== Sorting by Display is sorting by time ==");
55    ids.sort_by_key(|u| u.to_string());
56    let same = ids.windows(2).all(|w| w[1] >= w[0]);
57    println!("string sort  = byte sort = {same}");
58}
Source

pub fn parse_str(input: &str) -> Result<Self, ParseError>

Parse a 26-character Crockford base32 ULID, case-insensitive.

Accepts the substitution rules from the spec: I, L decode to 1; O decodes to 0. U is reserved and rejected. Returns ParseError on length, character, or leading-bits violations.

§Example
use id_forge::ulid::Ulid;

let id = Ulid::parse_str("01ARZ3NDEKTSV4RRFFQ69G5FAV").unwrap();
assert_eq!(id.to_string(), "01ARZ3NDEKTSV4RRFFQ69G5FAV");
Examples found in repository?
examples/basic.rs (line 30)
7fn main() {
8    let v4 = Uuid::v4();
9    println!("UUID v4:    {v4} (version={})", v4.version());
10    println!("UUID v7:    {}", Uuid::v7());
11    println!("UUID nil:   {}", Uuid::nil());
12
13    let a = Ulid::new();
14    let b = Ulid::new();
15    println!("ULID a:     {a}");
16    println!("ULID b:     {b} (monotonic: {})", b > a);
17
18    let gen = Snowflake::new(1);
19    let sf = gen.next_id();
20    let (ts_offset, worker, seq) = Snowflake::parts(sf);
21    println!(
22        "Snowflake:  {sf}  (ts+epoch={}, worker={worker}, seq={seq})",
23        ts_offset + gen.epoch_ms()
24    );
25
26    println!("NanoID 21:  {}", nanoid::generate());
27    println!("NanoID 8:   {}", nanoid::with_length(8));
28
29    assert_eq!(v4, Uuid::parse_str(&v4.to_string()).unwrap());
30    assert_eq!(a, Ulid::parse_str(&a.to_string()).unwrap());
31}
More examples
Hide additional examples
examples/ulid_monotonic.rs (line 44)
13fn main() {
14    println!("== Single-millisecond burst ==");
15
16    // 1000 ULIDs back-to-back. Most will share the same ms prefix;
17    // the monotonic factory guarantees b > a for every consecutive pair.
18    let mut ids: Vec<Ulid> = (0..1000).map(|_| Ulid::new()).collect();
19
20    let same_ms = ids
21        .windows(2)
22        .filter(|w| w[0].timestamp_ms() == w[1].timestamp_ms())
23        .count();
24    println!("count        = {}", ids.len());
25    println!("same-ms pairs = {same_ms} of {}", ids.len() - 1);
26
27    let strictly_increasing = ids.windows(2).all(|w| w[1] > w[0]);
28    println!("monotonic    = {strictly_increasing}");
29
30    let unique: HashSet<&Ulid> = ids.iter().collect();
31    println!("unique       = {} of {}", unique.len(), ids.len());
32
33    println!("\n== First and last of the burst ==");
34    let first = ids.first().unwrap();
35    let last = ids.last().unwrap();
36    println!("first        = {first}");
37    println!("last         = {last}");
38    println!("ts_first     = {} ms", first.timestamp_ms());
39    println!("ts_last      = {} ms", last.timestamp_ms());
40
41    println!("\n== Crockford base32 round-trip ==");
42    let sample = Ulid::new();
43    let s = sample.to_string();
44    let parsed = Ulid::parse_str(&s).unwrap();
45    println!("sample       = {sample}");
46    println!("parsed       = {parsed}");
47    println!("equal        = {}", sample == parsed);
48
49    println!("\n== Substitutions accepted by parse_str ==");
50    let with_subs = Ulid::parse_str("0IIIIIIIIIIIIIIIIIIIIIIIII").unwrap();
51    let canonical = Ulid::parse_str("01111111111111111111111111").unwrap();
52    println!("\"0III...\" == \"0111...\" = {}", with_subs == canonical);
53
54    println!("\n== Sorting by Display is sorting by time ==");
55    ids.sort_by_key(|u| u.to_string());
56    let same = ids.windows(2).all(|w| w[1] >= w[0]);
57    println!("string sort  = byte sort = {same}");
58}

Trait Implementations§

Source§

impl Clone for Ulid

Source§

fn clone(&self) -> Ulid

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Ulid

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Ulid

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Display for Ulid

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl FromStr for Ulid

Source§

type Err = ParseError

The associated error which can be returned from parsing.
Source§

fn from_str(s: &str) -> Result<Self, Self::Err>

Parses a string s to return a value of this type. Read more
Source§

impl Hash for Ulid

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Ord for Ulid

Source§

fn cmp(&self, other: &Ulid) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 (const: unstable) · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 (const: unstable) · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 (const: unstable) · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl PartialEq for Ulid

Source§

fn eq(&self, other: &Ulid) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl PartialOrd for Ulid

Source§

fn partial_cmp(&self, other: &Ulid) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 (const: unstable) · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 (const: unstable) · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 (const: unstable) · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 (const: unstable) · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl Copy for Ulid

Source§

impl Eq for Ulid

Source§

impl StructuralPartialEq for Ulid

Auto Trait Implementations§

§

impl Freeze for Ulid

§

impl RefUnwindSafe for Ulid

§

impl Send for Ulid

§

impl Sync for Ulid

§

impl Unpin for Ulid

§

impl UnsafeUnpin for Ulid

§

impl UnwindSafe for Ulid

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.