Skip to main content

nanoid_short_url/
nanoid_short_url.rs

1//! NanoID for URL-shortener-style short IDs.
2//!
3//! Demonstrates:
4//!   * `nanoid::with_length` for shorter-than-default codes
5//:   * `nanoid::custom` with alphabets tailored to readability
6//!     (no ambiguous characters like 0/O, 1/l/I)
7//!   * Collision math at common lengths and rates
8//!
9//! Run with: `cargo run --release --example nanoid_short_url`
10
11use id_forge::nanoid;
12use std::collections::HashSet;
13
14/// Crockford-flavoured alphabet — 32 chars, no 0/O/I/L/U
15/// confusables, safe to read aloud.
16const READABLE_32: &[u8] = b"23456789ABCDEFGHJKMNPQRSTUVWXYZ";
17
18/// URL-safe lowercase 36-char alphabet.
19const URL_36: &[u8] = b"abcdefghijklmnopqrstuvwxyz0123456789";
20
21fn main() {
22    println!("== Default 21-char URL-safe IDs ==");
23    for _ in 0..5 {
24        println!("  {}", nanoid::generate());
25    }
26
27    println!("\n== Short codes (8 chars, URL-safe default) ==");
28    for _ in 0..5 {
29        println!("  {}", nanoid::with_length(8));
30    }
31
32    println!("\n== Readable alphabet (no 0/O/I/L/U), 10 chars ==");
33    println!("  alphabet has {} chars", READABLE_32.len());
34    for _ in 0..5 {
35        println!("  {}", nanoid::custom(10, READABLE_32));
36    }
37
38    println!("\n== URL-safe lowercase, 12 chars ==");
39    for _ in 0..5 {
40        println!("  {}", nanoid::custom(12, URL_36));
41    }
42
43    println!("\n== Collision sweep at length 8 on URL_36 ==");
44    let n = 100_000;
45    let mut seen = HashSet::with_capacity(n);
46    let mut collisions = 0usize;
47    for _ in 0..n {
48        if !seen.insert(nanoid::custom(8, URL_36)) {
49            collisions += 1;
50        }
51    }
52    println!("  drew {n} IDs of length 8");
53    println!("  collisions = {collisions}");
54    println!("  (URL_36^8 = {} ids/space)", (URL_36.len() as u64).pow(8));
55}