9 stable releases

1.3.3 Aug 19, 2024
1.3.2 Aug 2, 2023
1.3.1 Jan 22, 2023
1.2.0 Oct 4, 2021
0.1.0 Feb 5, 2019

#34 in #binary-search

Download history 2397/week @ 2024-07-10 2172/week @ 2024-07-17 2554/week @ 2024-07-24 2146/week @ 2024-07-31 2781/week @ 2024-08-07 3124/week @ 2024-08-14 3191/week @ 2024-08-21 2753/week @ 2024-08-28 2932/week @ 2024-09-04 2553/week @ 2024-09-11 1876/week @ 2024-09-18 2537/week @ 2024-09-25 2730/week @ 2024-10-02 2777/week @ 2024-10-09 3019/week @ 2024-10-16 1634/week @ 2024-10-23

10,527 downloads per month
Used in 16 crates (9 directly)

MIT license

60KB
855 lines

cuid-rust

Build Status Crates.io docs.rs

Cuids are "Collision-resistant ids optimized for horizontal scaling and binary search lookup performance."

This is a rust implementation of the CUID library, the original JavaScript implementation of which may be found here

This library provides two CUID algorithms: cuid1 and cuid2.

  • cuid1 is a k-sortable ID that is extremely fast to generate with very good randomness properties
  • cuid2 provides stronger randomness guarantees, but is slower to generate and is not k-sortable

NOTE: It is the position of the original authors of CUID that cuid1 is "insecure" due to its being k-sortable and potentially exposing information about generation order and/or time of generation. It is my position that these properties apply to a number of very good ID-generating algorithms (such as UUIDv7), and it is therefore up to the users of this crate to choose an ID appropriately. Therefore, this library will continue to support v1 CUIDs for the foreseeable future. See the original authors' position in more detail here.

If you only need cuid2, you can use the cuid2 crate: cuid2 crate.

Installation

In cargo.toml

cuid = "1.4.0"

Or install the binary:

> cargo install cuid

Usage

use cuid;

fn main() -> () {
    // V1 CUIDs and slugs
    println!("{}", cuid::cuid1().unwrap());
    println!("{}", cuid::cuid1_slug().unwrap());

    // V2 CUIDs and slugs
    println!("{}", cuid::cuid2());
    println!("{}", cuid::cuid2_slug());

    // There is a flexible constructor for v2 CUIDs to customize
    // the length, counter function, and fingerprinter (note that
    // these are const functions, so you can create a static
    // constructor if desired.
    let constructor = CuidConstructor::new()
        .with_length(20)
        .with_counter(const_counter)
        .with_fingerprinter(const_fingerprinter);
    println!("{}", constructor.create_id());
}

fn const_counter() -> u64 {
    42
}

fn const_fingerprinter() -> String {
    "fingers".to_string()
}

Both algorithms are safe to use across threads. When used in a multithreaded context, threads generating v1 CUIDs share the same atomic counter, which is used as a component of the generated CUID, while each thread generating v2 CUIDs has its own atomic counter.

This package also provides a binary if installed via cargo install.

Its default behavior is to generate a CUID:

> cuid
clzuo0vcy4djkx3p2e4p0j355

You can also generate a slug:

>  cuid --slug
9bag9gxz78

Or v2 CUIDs/slugs:

> cuid --v2
scwl6p78dpjwvdtg1rqgvi1p

>  cuid --v2 --slug
pa00dip6j2

See cuid --help for more information.

Performance

Performance is one of the primary concerns of this library (see Benchmarking, below).

This implementation is currently about 20x faster than the reference JavaScript implementation for v1 CUIDs. I have not benchmarked the JavaScript v2 CUIDs.

It takes about 280 nanoseconds to generate a CUID, or 200 nanoseconds to generate a CUID slug, on relatively modern desktop hardware.

In a long-running process or thread, CUID generation is faster, since the system fingerprint is calculated once and then re-used for the lifetime of the process. In this case, CUID generation takes about 125 ns.

Tests

Tests can be run with

cargo test -p cuid

Some tests are ignored because they're slow. To run them:

cargo test -p cuid -- collisions::test --ignored --test-threads=1

Some tests require to be run in a single thread and are ignored by default. To run them:

cargo test -p cuid -- collisions::single_thread --ignored --test-threads=1

Benchmarking

Inline benchmarks are available when running with the nightly toolchain. There are also criterion bnechmarks in benches/cuid.rs.

If you're on a Linux system, it's recommended to run benchmarks with the maximum possible priority, via nice, in order to avoid confounding effects from other processes running on the system:

$ nice -n -20 cargo bench

Note that you may need to run nice as root:

sudo nice -n -20 su <username> -l -c "cd $PWD && cargo bench"

Dependencies

~2–25MB
~353K SLoC