10 stable releases
Uses new Rust 2024
| 2.1.4 | Jun 7, 2026 |
|---|---|
| 2.1.1 | Mar 2, 2026 |
| 1.3.7 | Jan 3, 2023 |
| 1.3.4 | Jan 1, 2022 |
| 0.1.6 |
|
#224 in Algorithms
Used in dmslite
57KB
840 lines
ids_service
A Rust library for generating unique, random IDs derived from a cryptographically secure random source, using a pre-filled, multi-threaded cache. Background worker threads keep the cache full so that callers receive a pre-computed ID instantly without blocking.
If the cache is temporarily exhausted (burst traffic), an ID is generated on the fly — no error, no panic, just a small latency spike.
Generated IDs are purely random and carry no temporal information, making them non-sortable by time. This is a deliberate trade-off: unlike ULID or UUID v7, which embed a timestamp to allow chronological ordering, this library prioritises unpredictability over sortability. If time-based ordering is a requirement, consider using a dedicated crate such as uuid7 or uuid with the v7 feature.
How it works
┌──────────────────────────────────────────────────────┐
│ IdsService │
│ │
│ ┌──────────┐ push ┌─────────────────────────┐ │
│ │ Worker 0 │ ────────► │ │ │
│ ├──────────┤ │ Arc<Mutex<VecDeque>> │ │ get_id()
│ │ Worker 1 │ ────────► │ (cache) │ ├──────────► caller
│ ├──────────┤ │ │ │
│ │ Worker N │ ────────► │ size = cache_size │ │
│ └──────────┘ └─────────────────────────┘ │
│ │
│ Each ID = hash( random_bytes || timestamp_ns ) │
└──────────────────────────────────────────────────────┘
Each ID is derived from:
- A random byte block (size = 2 × hash output length — see Birthday problem)
- The current timestamp in nanoseconds since the Unix epoch
Modules
crypto_hash
Uses one of the SHA-3 family algorithms from the sha3 crate:
| Mode | Output | Random block |
|---|---|---|
Sha3Mode::Sha3_224 |
28 bytes | 56 bytes |
Sha3Mode::Sha3_256 |
32 bytes | 64 bytes |
Sha3Mode::Sha3_384 |
48 bytes | 96 bytes |
Sha3Mode::Sha3_512 |
64 bytes | 128 bytes |
IDs can be encoded as:
| Method | Output |
|---|---|
.as_hex() |
Lowercase hexadecimal String |
.as_base64() |
Standard Base64 String |
.as_base64_url() |
URL-safe Base64 String |
.as_base32() |
Base32 String |
.as_json() |
JSON array of byte values |
rust_hash ⚠️ Deprecated
Deprecated since 2.1.0. Use the
cryptofeature andcrypto_hashmodule instead, or consider theuuidcrate.
Feature flags
| Flag | Default | Description |
|---|---|---|
crypto |
✅ | Enables crypto_hash module (requires sha3 dep) |
rust |
❌ | Deprecated. Enables rust_hash module |
To use only the crypto module:
ids_service = { version = "2.1.2", features = ["crypto"] }
Quick Start
Cryptographic hash (crypto_hash)
use ids_service::crypto_hash::{IdsService, Sha3Mode};
use ids_service::common::{Encode, Service, Uids};
fn main() {
// Cache size = 100 000, SHA3-256, thread count = number of logical CPUs
let mut ids = IdsService::new(100_000, Sha3Mode::Sha3_256, None);
ids.start();
// Optional: block until the cache is at least 10 % full
let _ = ids.filled_at_percent_event(10).recv();
println!("hex: {}", ids.get_id().as_hex());
println!("base64: {}", ids.get_id().as_base64());
println!("base32: {}", ids.get_id().as_base32());
// Returns None when the cache is empty instead of generating on the fly
if let Some(id) = ids.get_id_from_cache() {
println!("from cache: {}", id.as_hex());
}
println!("cache len: {}", ids.get_cache_len());
// Graceful shutdown — joins worker threads
ids.stop();
}
Or use the default configuration (SHA3-256, 100 000 items, CPU-count threads):
use ids_service::crypto_hash::IdsService;
use ids_service::common::{Encode, Service, Uids};
fn main() {
let mut ids = IdsService::default();
ids.start();
let _ = ids.filled_event().recv(); // wait for full cache
println!("{}", ids.get_id().as_hex());
ids.stop();
}
Iterator interface
IdsService implements Iterator, yielding one ID per call:
use ids_service::crypto_hash::{IdsService, Sha3Mode};
use ids_service::common::{Encode, Service};
fn main() {
let mut ids = IdsService::new(10_000, Sha3Mode::Sha3_512, None);
ids.start();
for id in ids.by_ref().take(5) {
println!("{}", id.as_hex());
}
ids.stop();
}
Standalone (no service, no cache)
use ids_service::crypto_hash::{create_id_as_sha256, create_id_as_sha512};
fn main() {
println!("{}", create_id_as_sha256()); // hex-encoded SHA3-256
println!("{}", create_id_as_sha512()); // hex-encoded SHA3-512
}
Performance
Benchmarks run with Criterion.rs on an
AMD Ryzen AI 7 350 — cargo bench.
| Benchmark | Median time | Throughput |
|---|---|---|
crypto_hash/standalone/sha256 |
~379 ns | ~2.64 Melem/s |
crypto_hash/standalone/sha512 |
~926 ns | ~1.08 Melem/s |
crypto_hash/service/get_id/Sha3_256 |
~149–170 ns | ~5.9–6.8 Melem/s |
crypto_hash/service/get_id/Sha3_512 |
~102–120 ns | ~8.4–9.8 Melem/s |
crypto_hash/encoding/as_hex |
~24.9 ns | — |
crypto_hash/encoding/as_base64 |
~28.4 ns | — |
crypto_hash/encoding/as_base32 |
~29.4 ns | — |
Cache hit ≈ 149–170 ns — 2–6× faster than standalone SHA3-256/SHA3-512 generation.
Run the full benchmark suite:
cargo bench --bench throughput
Results are saved as HTML reports in target/criterion/.
Examples
# Cryptographic hasher examples
cargo run --example quickstart
cargo run --example quickstart2
cargo run --example examples
cargo run --example iterator_example
# Generate 10 million IDs and measure throughput
cargo run --release --example ten_million
Running tests
# All unit and doc tests
cargo test
# With a specific feature set
cargo test --no-default-features --features crypto
Platforms
Compiled and tested on:
- x86_64 GNU/Linux (primary development + CI)
- macOS (Apple Silicon M1)
License
MIT — see LICENSE. ID
Dependencies
~530–760KB
~12K SLoC