Skip to main content

cuid/
lib.rs

1//! # CUID generation in rust
2//!
3//! This crate contains implementations of both the [v1] and [v2] CUID
4//! algorithms. By default, both v1 and v2 CUIDs are available. If you
5//! are optimizing for binary size, you can exclude one or the other
6//! by setting `default_features = false` and selecting the one you
7//! need (see [Features](#Features), below).
8//!
9//! In addition, both CUID algorithms are provided as their own
10//! independent crates, which this one merely wraps. They are creatively
11//! named [cuid1](https://docs.rs/cuid/latest/cuid1/) and [cuid2](https://docs.rs/cuid/latest/cuid2/).
12//!
13//! ## Usage
14//!
15//! ```rust
16//! use cuid;
17//!
18//! // Get a v1 CUID
19//! println!("{}", cuid::cuid1());
20//! println!("{}", cuid::v1::cuid());
21//!
22//! // Get a v2 CUID
23//! println!("{}", cuid::cuid2());
24//! println!("{}", cuid::v2::cuid());
25//! ```
26//!
27//! Note that this crate also provides a very simple, single purpose
28//! commandline interface:
29//!
30//! ```sh
31//! $> cuid
32//! ckfritrvg0000kdtwc766fful
33//! ```
34//!
35//! You can generate v2 CUIDs via the commandline like so:
36//!
37//! ```sh
38//! $> cuid --v2
39//! i12sf8k69lbvktlr7qb4p6xv
40//! ```
41//!
42//! v2 CUIDs also support some customization, allowing the specification
43//! of:
44//! - length
45//! - a counter function
46//! - a system fingerprint function
47//!
48//! See the [v2 CuidConstructor](https://docs.rs/cuid2/0.1.5/cuid2/struct.CuidConstructor.html)
49//! docs for more details.
50//!
51//! ## Should I Use v1 or v2?
52//!
53//! According to the original implementation, v1 CUIDs are deprecated
54//! because they are "insecure," due to the fact that they are k-sortable,
55//! which is to say, as one goes forward in time, v1 CUIDs go up.
56//!
57//! K-sortability is actually a common property of IDs, and is sometimes
58//! desired. For example, k-sortable IDs are great for PKs for high-volume
59//! timeseries data, since they significantly improve index locality of
60//! adjacent rows. As an example, v7 UUIDs are k-sortable, and you can find
61//! plenty of material online discussing performance improvements using
62//! them for primary keys in postgres or other databases.
63//!
64//! That said, k-sortable IDs are significantly more "guessable" than
65//! non-k-sortable IDs, which can potentially be a security issue for
66//! certain applications.
67//!
68//! For CUID, the v1 algorithm is simpler and faster than the v2
69//! algorithm. Generating a v1 CUID is around 7-8x faster than a v2
70//! CUID (~127 ns vs ~962 ns on my machine).
71//!
72//! As such, if your use-case is not sensitive to guessability, I
73//! would recommend going with v1.
74//!
75//! For more information, see [this issue](https://github.com/mplanchard/cuid-rust/issues/17)
76//!
77//! ## Prior Art
78//!
79//! See the [original v1 implementation][v1] and [original v2
80//! implementation][v2] for more details on CUIDs in general.
81//!
82//! [v1]: https://github.com/ericelliott/cuid
83//! [v2]: https://github.com/paralleldrive/cuid2
84//!
85//! ## Features
86//! - `v1` (enabled by default): provides access to v1 CUIDs
87//! - `v2` (enabled by default): provides access to v2 CUIDs
88//!
89
90#[cfg(feature = "v1")]
91pub use cuid1::{
92    self as v1, cuid as cuid1, is_cuid as is_cuid1, is_slug as is_cuid1_slug, slug as cuid1_slug,
93};
94#[cfg(feature = "v1")]
95#[doc(hidden)]
96pub use cuid1::{one_off_cuid1, one_off_cuid1_slug};
97
98#[cfg(feature = "v2")]
99pub use cuid2::{
100    self as v2, CuidConstructor as Cuid2Constructor, cuid as cuid2, is_cuid2,
101    is_slug as is_cuid2_slug, slug as cuid2_slug,
102};
103
104#[cfg(test)]
105mod test {
106    use super::*;
107
108    /// Run an already-defined test in WASM as well.
109    macro_rules! wasm_test {
110        ($name:ident) => {
111            paste::paste! {
112                #[wasm_bindgen_test::wasm_bindgen_test]
113                fn [<wasm_ $name>]() {
114                    $name()
115                }
116            }
117        };
118    }
119
120    #[cfg(feature = "v1")]
121    #[test]
122    fn test_v1() {
123        is_cuid1(cuid1());
124        is_cuid1_slug(cuid1_slug());
125    }
126    wasm_test!(test_v1);
127
128    #[cfg(feature = "v2")]
129    #[test]
130    fn test_v2() {
131        is_cuid2(cuid2());
132        is_cuid2_slug(cuid2_slug());
133    }
134    wasm_test!(test_v2);
135}