An implementation of the ULID ("Universally Unique Lexicographically Sortable Identifier") standard.
A ULID is
- 128-bit compatible with UUID
- 1.21e+24 unique ULIDs per millisecond
- Lexicographically sortable!
- Canonically encoded as a 26 character string, as opposed to the 36 character UUID
- Uses Crockford's base32 for better efficiency and readability (5 bits per character)
- Case insensitive
- No special characters (URL safe)
The bundled application generates a ULID and prints it to stdout:
$ ulid
01F5QNHN4G55VHQHA8XG1N6H9HHere is a minimal application that uses this crate:
use ulid::ulid;
fn main() {
println!("{}", ulid());
}The primary API is the ulid() function, which returns a String.
If you would like access to the individual bits, then call ulid_raw().
ulid::ulid() -> String
ulid::ulid_raw() -> u128For more control, the ulid::Ulid type is also available.
ulid::Ulid::new() -> ulid::UlidThe Ulid struct is a wrapper around a u128, with a few extra methods.
let id = ulid::Ulid::new();
// They implement Display, LowerHex and UpperHex
println!("{}", id);
println!("{:x}", id);
println!("{:X}", id);More recent ULIDs are higher than older ones:
use std::thread::sleep;
use std::time::Duration;
let a = ulid();
sleep(Duration::from_millis(1));
let b = ulid();
assert!(a < b);To generate many ulid::Ulid values, you're recommended to use UlidGenerator.
It provides the ability to seed the internal pseudo-random number generator.
// use the system's clock as the initial seed...
let mut ulid_gen = ulid::UlidGenerator::new();
let ulids: Vec<_> = ulid_gen.take(1000).collect();// ...or use a fixed initial seed
let mut ulid_gen = ulid::UlidGenerator::from_seed(12345);
let ulid = ulid_gen.ulid();A C API is available at lib/ulid.h. Here is a minimal application that generates and prints a ULID:
#include <stdio.h>
#include "ulid.h"
int main(void) {
char str[27];
ulid_ctx ctx = ulid_init(0);
ulid_write_new(&ctx, str, sizeof(str));
printf("%s\n", str);
return 0;
}libulid also provides access to creating binary (128 bit)
ULIDs and converting those to strings (this example is
intentionally convoluted to showcase error handling):
#include <stdio.h>
#include "ulid.h"
int main(void) {
ulid_ctx ctx;
ulid_t id;
char buf[64], *cur = buf;
int n, size = sizeof(buf);
ctx = ulid_init(0);
ulid_new(&ctx, &id);
n = snprintf(cur, size, "Your ULID is ");
if (n >= size)
return 1;
cur += n;
size -= n;
n = ulid_write(&id, cur, size);
if (n < 0) /* failed, typically buffer is too small */
return 1;
cur += n;
size -= n;
n = snprintf(cur, size, ".");
if (n >= size)
return 1;
printf("%s\n", buf);
return 0;
}Add ulid-lite to your crate's Cargo.toml file:
[dependencies]
ulid-lite = "0.6.1"You can download and install ulid-lite directly from the main branch of the upstream repository:
$ cargo install --git https://github.com/timClicks/ulid-lite.gitTo regenerate the ulid.h header file, run make lib/ulid.h.
To build the libulid shared library, run make target/release/libulid.so.
You are very welcome to contribute to project in any form, however you must abide by the Rust Code of Conduct.
Your contribution is important! Please submit an issue with your suggested change.
Note: these instructions have only been tested on Ubuntu, please submit corrections/improvements for other operating systems.
To begin, you require the following tools:
- A Rust installation that includes
rustc,rustup, andcargo gitmake
From the root of the project, run setup-devenv to install dependencies that are managed by cargo or rustup, such as MIRI:
$ ./setup-devenvulid-lite follows the standard GitHub workflow for code changes.
Please fork the project, push commits to that fork and submit a pull request (PR).
Before submitting a PR, you should run make test && make from the project's root directory, rather than cargo test.
This will ensure that the MIRI tests run correctly and that artifacts can all be built.
I would like to use this crate to develop pg_ulid extension.
- parsing pre-existing ULIDs
- monotonicity within the same millisecond
- overflow checks
ulid-lite is currently only built for Linux. Patches are welcome to support more platforms.
I wanted to implement a crate with a minimalist feel. It is intended to be easy and fast to build.
ulid-lite has minimal dependencies. This keeps build times fast and binary size small.
ulid does not take a long time to compile:
$ cargo clean
$ cargo build --release
Compiling libc v0.2.94
Compiling lazy_static v0.2.11
Compiling rand v0.4.6
Compiling rand v0.3.23
Compiling xorshift v0.1.3
Compiling ulid-lite v0.4.0 (/.../ulid-lite)
Finished release [optimized] target(s) in 5.68sPerhaps more importantly however, ulid-lite is very fast.
A single CPU core can generate about 35,700 ULIDs per millisecond.
$ cargo bench
...
running 2 tests
test benchmark_generation ... bench: 28 ns/iter (+/- 2)
test benchmark_serialized ... bench: 71 ns/iter (+/- 12)I've relied on two other implementations to develop ulid-lite:
| Dylan Hart | github.com/dylanhart/ulid-rs |
| Marcos Macedo | github.com/mmacedoeu/rulid.rs |