A lightweight, high-performance Rust library for generating secure, URL-friendly unique string IDs, with WASM support.
npm install ridgenCargo.toml:
toml
[dependencies]
ridgen = "0.1.0"
`
$3
`bash
npm install ridgen
`
Usage
$3
`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),
}
}
`
$3
This package is built with WASM and supports modern environments.
`javascript
import { generate } from "ridgen";
const id = generate(16);
console.log(Generated ID: ${id});
`
$3
- 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
$3
- Date: 2026-01-20
- CPU: x86_64
- Rust: 1.92.0
- Build: release
- Node.js: v24.12.0
$3
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:
- 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.
$3
- 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.
$3
- ✅ 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:
`rust
index = random_byte % 62
`
$3
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
$3
- 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
$3
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
$3
`bash
cargo run --release
`
$3
`bash
cd ../js-nanoid-bench
npm install
node benchmark.js
``