Nano ID
Short random ids for links, invites and coupon codes: Nano ID with secure random, your own alphabet and length, readable codes for print, and the odds of a collision.
Version 1.0.0 · 3 functions · 1 crate
Functions
What use nanoid.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use nanoid, nanoid_with from nanoid (Quillo 0.6).
nanoid(size: int) → stror an errorA random id of size characters (0 for the usual 21) from A-Z, a-z, 0-9, "_" and "-": as unlikely to repeat as a UUID v4, and safe in URLs.
nanoid_with(size: int, alphabet: str) → stror an errorA random id of size characters (1 to 1,000) from alphabet: your own characters ("ABC123"), or "numbers", "lowercase", "hex", "readable" (no 0/O, 1/l/I to confuse) or "" (the default). Secure random, without bias toward any character.
nanoid_safe_count(size: int, alphabet: str) → floator an errorHow many ids of size characters from alphabet can be made before there is a 1% chance two are the same: 21 default characters is about 1.3 × 10^18; 8 readable ones about 1.4 million. Make ids longer when this is near the number you will make.
Get it
$ quillo install nanoid # nanoid.qwer into this folder$ quillo install nanoid --example # and its example, nanoid.qweOr with curl:
$ curl -O https://quillolang.org/plugins/files/nanoid.qwer$ curl -O https://quillolang.org/plugins/files/nanoid.qweThen, in your program, all of it or only what you call:
use nanoid.qweruse nanoid, nanoid_with from nanoid // Quillo 0.6: only theseIt uses this crate, which cargo fetches the first time the plugin is built:
nanoid = "0.5"Example
// Invite links and coupon codes: random ids in a URL-safe alphabet, and readable ones for print.//// quillo run nanoid.qwe then open http://localhost:8080/inviteuse "nanoid.qwer"route GET /invite = { url: `https://app.example.com/join/${nanoid(0)?}` }route GET /coupons ? { n: int = 3 } = range(0, n) | map((i) => `SALE-${nanoid_with(8, "readable")?}`)route GET /odds = { default_21: nanoid_safe_count(21, "")?, readable_8: nanoid_safe_count(8, "readable")?, pin: nanoid_with(6, "numbers")?, own: nanoid_with(10, "ABC123")?, length: len(nanoid(0)?),}$ quillo run nanoid.qwe$ curl 'localhost:8080/invite'$ curl 'localhost:8080/odds'Source
//! Short random ids for links, invites, coupon codes and public keys: Nano ID, secure random, with your own alphabet and length, and the odds of two ever being the same.//! version: 1.0.0//!//! [dependencies]//! nanoid = "0.5"const DEFAULT: &str = "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";fn alphabet(a: &str) -> Result<Vec<char>, String> { let chars: Vec<char> = match a { "" | "default" => DEFAULT.chars().collect(), "numbers" => "0123456789".chars().collect(), "lowercase" => "abcdefghijklmnopqrstuvwxyz0123456789".chars().collect(), "hex" => "0123456789abcdef".chars().collect(), // No 0/O, 1/l/I or other pairs people misread: for codes read aloud or typed from paper. "readable" => "23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz".chars().collect(), other => other.chars().collect(), }; let mut seen = std::collections::HashSet::new(); if chars.len() < 2 || chars.len() > 255 || !chars.iter().all(|c| seen.insert(*c)) { return Err("an alphabet has 2 to 255 different characters".into()); } Ok(chars)}/// A random id of `size` characters (0 for the usual 21) from A-Z, a-z, 0-9, "_" and "-": as unlikely to repeat as a UUID v4, and safe in URLs.pub fn nanoid(size: i64) -> Result<String, String> { nanoid_with(if size == 0 { 21 } else { size }, "")}/// A random id of `size` characters (1 to 1,000) from `alphabet`: your own characters ("ABC123"), or "numbers", "lowercase", "hex", "readable" (no 0/O, 1/l/I to confuse) or "" (the default). Secure random, without bias toward any character.pub fn nanoid_with(size: i64, alphabet: &str) -> Result<String, String> { if !(1..=1000).contains(&size) { return Err("size from 1 to 1,000".into()); } let a = self::alphabet(alphabet)?; Ok(nanoid::format(nanoid::rngs::default, &a, size as usize))}/// How many ids of `size` characters from `alphabet` can be made before there is a 1% chance two are the same: 21 default characters is about 1.3 × 10^18; 8 readable ones about 1.4 million. Make ids longer when this is near the number you will make.pub fn nanoid_safe_count(size: i64, alphabet: &str) -> Result<f64, String> { let n = self::alphabet(alphabet)?.len() as f64; let space = (size.clamp(1, 1000) as f64) * n.ln(); // Birthday bound: k ≈ sqrt(2 N ln(1 / (1 - p))), with N = n^size, in logs to stay finite. let k = (0.5 * (space + (2.0 * (1.0f64 / 0.99).ln()).ln())).exp(); Ok(if k.is_finite() { (k * 1000.0).round() / 1000.0 } else { f64::MAX })}Related
cuid2.qwer · 1.0.0CUID2 ids: secure, collision-resistant, starting with a letter, of the length you choose, that give away neither the time nor a count; and a check that a string is one.7 views · 7 downloadsReadable ids human_ids.qwer · 1.0.0Readable ids such as brave-blue-fox for projects, preview URLs and invite codes: random, alliterating, or always the same name for a given number.7 views · 7 downloadsShort ids short_ids.qwer · 1.0.0Short ids for URLs made from your database's numbers and read back (Sqids): your own alphabet, a minimum length, no rude words, and typos never reaching another row.6 views · 8 downloadsTypeID typeid.qwer · 1.0.0TypeIDs such as user_01h455vb4pex5vsknk084sn02q: a type prefix and a UUIDv7 in base32, made, read back to their UUID and time, and checked against the type a URL expects.6 views · 7 downloadsKSUID ksuid.qwer · 1.0.0KSUIDs, Segment's K-Sortable Unique IDs: 27 base62 characters sorted by the second they were made, with 128 random bits; made, read back and checked.8 views · 7 downloadsSnowflake ids snowflake.qwer · 1.0.0Snowflake ids: 64-bit numbers that sort by time, unique across 1,024 servers with no coordination, with their time, server and sequence read back and the first id of a time for range queries.7 views · 7 downloadsThread 0 posts
On Nano ID: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.