ridgen

Crates.ioridgen
lib.rsridgen
version0.1.0
created_at2026-01-21 14:39:38.29725+00
updated_at2026-01-21 14:39:38.29725+00
descriptionA lightweight, high-performance Rust library for generating secure, URL-friendly unique string IDs, with WASM support.
homepage
repositoryhttps://github.com/Taniyama2024/ridgen
max_upload_size
id2059435
size78,451
Takuma Harada (Taniyama2024)

documentation

README

ridgen

日本語 | English

A lightweight, high-performance Rust library for generating secure, URL-friendly unique string IDs.

Comparison with JavaScript Libraries

All tests performed with 1,000,000 iterations:

Library Language Time (ms) Throughput (million IDs/sec) Notes
ridgen Rust ~340 ~3.0 This implementation ⚡
uuid (v4) JavaScript 375 ~2.7 Standard UUID v4
nanoid JavaScript 431 ~2.3 Widely used original     
shortid JavaScript 3,220 ~0.3 Deprecated, slower
cuid2 JavaScript 34,274 ~0.03 Collision-resistant

Key Takeaways

  • ridgen achieves ~3.0 million IDs/sec throughput
  • ~11% faster than uuid v4 while providing URL-friendly IDs
  • ~30% faster than nanoid
  • 9.5x faster than shortid
  • 88x faster than cuid2
  • Achieves maximum performance through batch random number generation

Note: The comparison is against JavaScript implementations running on Node.js. Rust implementations of UUID are not included in this benchmark.

Features

  • 🚀 Fast: ~3.0 million IDs/sec
  • 🔒 Secure: Uses cryptographically strong random number generation
  • 📦 Lightweight: Minimal dependencies
  • Simple API: Easy to use with error handling
  • Optimized: Batch random number generation for maximum performance

Installation

For Rust

Add this to your Cargo.toml:

[dependencies]
ridgen = "0.1.0"

For JavaScript/TypeScript (WASM)

npm install ridgen

Usage

Rust

use ridgen::generate;

fn main() {
    // Generate a 16-character ID
    match generate(16) {
        Ok(id) => println!("Generated ID: {}", id),
        Err(e) => eprintln!("Error: {:?}", e),
    }
}

JavaScript/TypeScript

This package is built with WASM and supports modern environments.

import { generate } from "ridgen";

const id = generate(16);
console.log(`Generated ID: ${id}`);

Supported Environments

  • Node.js: (ESM) v14.16.0 or later
  • Bun: Native support
  • Deno: Supported
  • Modern bundlers: Vite, Webpack, Rollup

[!IMPORTANT]

  • ESM Only: This package only supports ECMAScript Modules (ESM). CommonJS (require) is not supported.
  • WASM Initialization: In environments that support top-level WASM (like Bun or Webpack), it works immediately. For other environments, ensure your bundler is configured to handle .wasm files.

Benchmarks

Environment

  • Date: 2026-01-20
  • CPU: x86_64
  • Rust: 1.92.0
  • Build: release
  • Node.js: v24.12.0

Rust (ridgen)

Performance test with 1,000,000 iterations generating 16-character IDs:

- Total time: ~340ms (average)
- Throughput: ~2.9-3.0 million IDs/sec

Note: Uses thread_rng (Default) for random number generation. Why no SmallRng?: Although SmallRng is faster, it is not cryptographically secure. ridgen prioritizes security by using thread_rng to ensure IDs are unpredictable, while maintaining high performance through batch generation. Optimization: Uses batch random number generation (RngCore::fill_bytes) instead of calling gen_range() for each character, reducing CPU instruction count and improving performance by ~20-25%.

Character Set

The library uses a URL-safe character set:

  • Lowercase letters: a-z
  • Uppercase letters: A-Z
  • Numbers: 0-9

Total: 62 characters

Error Handling

The generate function returns a Result<String, RidgenError>:

  • Ok(String): Successfully generated ID
  • Err(RidgenError::InvalidLength): If length is 0

Safety and unsafe Usage

This library uses a small amount of unsafe code for performance reasons.

Specifically, String::from_utf8_unchecked is used when constructing the final ID string.

Why is this safe?

  • The character set consists only of ASCII characters (a-zA-Z0-9)
  • Each byte pushed into the buffer is guaranteed to be valid UTF-8
  • No user input or external data is involved

Because these invariants are strictly controlled, skipping UTF-8 validation is safe and avoids unnecessary runtime checks.

Trade-off

  • ✅ Improved performance (avoids an extra UTF-8 validation pass)
  • ⚠️ Requires careful maintenance if the character set changes

If the character set is ever modified to include non-ASCII characters, this unsafe usage must be revisited.

Distribution Characteristics

This implementation uses a simple modulo operation to map random bytes to the character set:

index = random_byte % 62

Modulo Bias

Since 256 is not evenly divisible by 62, this introduces a small distribution bias:

  • The first 8 characters in the charset have a slightly higher probability
  • The bias is approximately 1/256 per character

Why this is acceptable here

  • The bias is extremely small and negligible for most ID generation use cases
  • This approach avoids additional branching and rejection sampling, improving performance
  • Many real-world ID systems accept this trade-off for speed

Security Note

This library prioritizes performance and simplicity over perfect uniform distribution. If strict cryptographic uniformity is required, consider using rejection sampling or other methods.

Running Benchmarks

Rust Benchmark

cargo run --release

JavaScript Benchmark

cd ../js-nanoid-bench
npm install
node benchmark.js

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Commit count: 1

cargo fmt