pub fn custom(length: usize, alphabet: &[u8]) -> StringAvailable on crate feature
nanoid only.Expand description
Generate a NanoID with a custom length and alphabet.
This entry point is permissive: an empty alphabet returns the
empty string, and duplicate bytes in the alphabet are tolerated
(the repeated characters appear with higher probability). Use
try_custom when you want validation to surface those cases as
an error.
ยงExample
use id_forge::nanoid;
let id = nanoid::custom(8, b"0123456789ABCDEF");
assert_eq!(id.len(), 8);
assert!(id.chars().all(|c| "0123456789ABCDEF".contains(c)));Examples found in repository?
examples/bench.rs (line 50)
33fn main() {
34 println!("id-forge throughput (single thread, release build)");
35 println!("---------------------------------------------------");
36
37 let iters = 1_000_000;
38 bench("Uuid::v4", iters, Uuid::v4);
39 bench("Uuid::v7", iters, Uuid::v7);
40 bench("Ulid::new", iters, Ulid::new);
41
42 let sf = Snowflake::new(1);
43 bench("Snowflake::next_id", iters, || sf.next_id());
44
45 bench("nanoid::generate", iters / 5, nanoid::generate);
46 bench("nanoid::with_length(8)", iters / 5, || {
47 nanoid::with_length(8)
48 });
49 bench("nanoid::custom(16, hex)", iters / 5, || {
50 nanoid::custom(16, b"0123456789abcdef")
51 });
52 bench("nanoid::custom(21, 17-char)", iters / 5, || {
53 nanoid::custom(21, b"ABCDEFGHIJKLMNOPQ")
54 });
55}More examples
examples/nanoid_short_url.rs (line 35)
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}examples/nanoid_validate.rs (line 55)
15fn main() {
16 println!("== try_custom: happy path ==");
17 let id = nanoid::try_custom(16, b"0123456789abcdef").unwrap();
18 println!(" {id}");
19
20 println!("\n== try_custom: empty alphabet ==");
21 match nanoid::try_custom(8, b"") {
22 Ok(s) => println!(" unexpected ok: {s}"),
23 Err(e) => println!(" Err: {e}"),
24 }
25
26 println!("\n== try_custom: duplicate byte ==");
27 match nanoid::try_custom(8, b"abcda") {
28 Ok(s) => println!(" unexpected ok: {s}"),
29 Err(AlphabetError::Duplicate(b)) => {
30 println!(" Err: duplicate byte 0x{b:02x} ({:?})", b as char);
31 }
32 Err(e) => println!(" Err: {e}"),
33 }
34
35 println!("\n== validate_alphabet for startup-time config check ==");
36 let alphabets: &[(&str, &[u8])] = &[
37 (
38 "url-safe-64",
39 b"_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
40 ),
41 ("hex", b"0123456789abcdef"),
42 ("empty", b""),
43 ("dup", b"aab"),
44 ];
45 for (label, alphabet) in alphabets {
46 match nanoid::validate_alphabet(alphabet) {
47 Ok(()) => println!(" {label:<14} OK ({} chars)", alphabet.len()),
48 Err(e) => println!(" {label:<14} REJECTED: {e}"),
49 }
50 }
51
52 println!("\n== Permissive `custom` tolerates duplicates ==");
53 // Duplicates skew the output toward repeated chars. `custom`
54 // accepts this by design; `try_custom` does not.
55 let skewed = nanoid::custom(20, b"AAAAAA");
56 println!(" custom(20, b\"AAAAAA\") = {skewed}");
57
58 println!("\n== Cache a validated alphabet once at startup ==");
59 let alphabet = b"0123456789ABCDEFGHJKMNPQRSTVWXYZ";
60 nanoid::validate_alphabet(alphabet).expect("startup: config alphabet must be valid");
61 // ... hot path now uses `custom` since the alphabet has already
62 // been vetted; no per-call validation cost.
63 for _ in 0..3 {
64 println!(" {}", nanoid::custom(12, alphabet));
65 }
66}