uuid7/lib.rs
1//! A Rust implementation of UUID version 7
2//!
3//! ```rust
4//! let uuid = uuid7::uuid7();
5//! println!("{}", uuid); // e.g., "01809424-3e59-7c05-9219-566f82fff672"
6//! println!("{:?}", uuid.as_bytes()); // as 16-byte big-endian array
7//!
8//! let uuid_string: String = uuid7::uuid7().to_string();
9//! ```
10//!
11//! See [RFC 9562](https://www.rfc-editor.org/rfc/rfc9562).
12//!
13//! # Field and bit layout
14//!
15//! This implementation produces identifiers with the following bit layout:
16//!
17//! ```text
18//! 0 1 2 3
19//! 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
20//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21//! | unix_ts_ms |
22//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23//! | unix_ts_ms | ver | counter |
24//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25//! |var| counter |
26//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27//! | rand |
28//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29//! ```
30//!
31//! Where:
32//!
33//! - The 48-bit `unix_ts_ms` field is dedicated to the Unix timestamp in
34//! milliseconds.
35//! - The 4-bit `ver` field is set at `0111`.
36//! - The 42-bit `counter` field accommodates a counter that ensures the increasing
37//! order of IDs generated within a millisecond. The counter is incremented by one
38//! for each new ID and is reset to a random number when the `unix_ts_ms` changes.
39//! - The 2-bit `var` field is set at `10`.
40//! - The remaining 32 `rand` bits are filled with a cryptographically strong random
41//! number.
42//!
43//! The 42-bit `counter` is sufficiently large, so you do not usually need to worry
44//! about overflow, but in an extremely rare circumstance where it overflows, this
45//! library increments the `unix_ts_ms` field to continue instant monotonic
46//! generation. As a result, the `unix_ts_ms` may have a greater value than that of
47//! the system's real-time clock. (See also [Why so large counter? (42bits)]).
48//!
49//! UUIDv7, by design, relies on the system clock to guarantee the monotonically
50//! increasing order of generated IDs. A generator may not be able to produce a
51//! monotonic sequence if the system clock goes backwards. This library ignores a
52//! clock rollback and reuses the previous `unix_ts_ms` unless the clock rollback is
53//! considered significant (by default, more than ten seconds). If such a
54//! significant rollback takes place, this library resets the generator by default
55//! and thus breaks the increasing order of generated IDs.
56//!
57//! [Why so large counter? (42bits)]: https://github.com/LiosK/uuidv7/issues/13#issuecomment-2306922356
58//!
59//! # Crate features
60//!
61//! Default features:
62//!
63//! - `std` integrates the library with, among others, the system clock to draw
64//! current timestamps. Without `std`, this crate provides limited functionality
65//! available under `no_std` environments.
66//! - `global_gen` (implies `std`) enables the primary [`uuid7()`] function and the
67//! process-wide global generator under the hood.
68//!
69//! Optional features:
70//!
71//! - `rand09` enables [`V7Generator::with_rand09()`] that integrates `rand` crate
72//! (v0.9).
73//! - `rand08` enables [`V7Generator::with_rand08()`] that integrates `rand` crate
74//! (v0.8). Currently, this feature is always enabled and cannot be turned off.
75//! This behavior is deprecated and for backward compatibility only. Enable this
76//! feature explicitly when needed.
77//! - `serde` enables the serialization and deserialization of [`Uuid`] objects.
78//! - `uuid` (together with `global_gen`) enables the [`new_v7()`] function that
79//! returns the popular [uuid](https://crates.io/crates/uuid) crate's [`Uuid`](uuid::Uuid)
80//! objects.
81//!
82//! # Other functionality
83//!
84//! This library also supports the generation of UUID version 4:
85//!
86//! ```rust
87//! let uuid = uuid7::uuid4();
88//! println!("{}", uuid); // e.g., "2ca4b2ce-6c13-40d4-bccf-37d222820f6f"
89//! ```
90//!
91//! [`V7Generator`] provides an interface that allows finer control over the various
92//! aspects of the UUIDv7 generation:
93//!
94//! ```rust
95//! # #[cfg(feature = "rand09")]
96//! # {
97//! use uuid7::V7Generator;
98//!
99//! let mut g = V7Generator::with_rand09(rand::rng());
100//! let custom_unix_ts_ms = 0x0123_4567_8901u64;
101//! let x = g.generate_or_reset_core(custom_unix_ts_ms, 10_000);
102//! println!("{}", x);
103//!
104//! let y = g
105//! .generate_or_abort_core(custom_unix_ts_ms, 10_000)
106//! .expect("clock went backwards by more than 10_000 milliseconds");
107//! println!("{}", y);
108//! # }
109//! ```
110
111#![cfg_attr(not(feature = "std"), no_std)]
112#![cfg_attr(docsrs, feature(doc_cfg))]
113
114mod id;
115pub use id::{ParseError, Uuid, Variant};
116
117pub mod generator;
118pub use generator::V7Generator;
119
120mod global_gen;
121#[cfg(feature = "global_gen")]
122pub use global_gen::{uuid4, uuid7};
123
124/// Generates a UUIDv7 and returns it as an instance of [`uuid::Uuid`].
125#[cfg(all(feature = "global_gen", feature = "uuid"))]
126pub fn new_v7() -> uuid::Uuid {
127 uuid7().into()
128}