Time and IDs

Readable ids

Readable ids such as brave-blue-fox for projects, preview URLs and invite codes: random, alliterating, or always the same name for a given number.

Version 1.0.0 · 4 functions · 2 crates

#ids#urls#naming#testing

Functions

What use human_ids.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use human_id, human_id_alliterating from human_ids (Quillo 0.6).

human_id(words: int, separator: str) → stror an error

A random name of words words (1 to 8; 3 reads well) joined by separator: "neatly-bold-otter". Words are short, common and inoffensive English.

human_id_alliterating(words: int, separator: str) → stror an error

A random name whose words all start with the same letter: "busy-brown-badger".

human_id_for(number: int, words: int, separator: str) → stror an error

The name of a number, the same every time: a readable stand-in for a database id or a hash, such as a build number's name. Not reversible, and two numbers may share a name (see human_id_count).

human_id_count(words: int) → intor an error

How many different names of words words there are: about 200,000 for 2 words, 52 million for 3. Pick enough words for the ids you will make, or add a number.

Get it

$ quillo install human_ids               # human_ids.qwer into this folder$ quillo install human_ids --example     # and its example, human_ids.qwe

Or with curl:

$ curl -O https://quillolang.org/plugins/files/human_ids.qwer$ curl -O https://quillolang.org/plugins/files/human_ids.qwe

Then, in your program, all of it or only what you call:

main.qwe
use human_ids.qweruse human_id, human_id_alliterating from human_ids      // Quillo 0.6: only these

It uses these crates, which cargo fetches the first time the plugin is built:

[dependencies]
petname = { version = "3.2", default-features = false, features = ["default-rng", "default-words"] }rand = { version = "0.10", default-features = false, features = ["thread_rng"] }

Example

human_ids.qwe
// Preview deployments named like "brave-blue-fox" instead of numbers.////   quillo run human_ids.qwe      then open http://localhost:8080/deploysuse "human_ids.qwer"route GET /deploys = [101, 102, 103] | map((n) => { build: n, url: `https://${human_id_for(n, 3, "-")?}.preview.example.com` })route GET /new = { names_of_2: human_id_count(2)?, project: human_id(2, "-")?, invite: human_id(3, "-")?, alliterating: human_id_alliterating(3, "-")?, names_of_3: human_id_count(3)? }
$ quillo run human_ids.qwe$ curl 'localhost:8080/deploys'$ curl 'localhost:8080/new'

Source

human_ids.qwer
//! Readable ids such as "brave-blue-fox" for project names, preview URLs, invite codes and test accounts: random, or always the same for a given number.//! version: 1.0.0//!//! [dependencies]//! petname = { version = "3.2", default-features = false, features = ["default-rng", "default-words"] }//! rand = { version = "0.10", default-features = false, features = ["thread_rng"] }use petname::{Alliterations, Generator, Petnames};use std::sync::OnceLock;fn names() -> &'static Petnames<'static> {    static P: OnceLock<Petnames<'static>> = OnceLock::new();    P.get_or_init(Petnames::small)}fn words(n: i64) -> Result<u8, String> {    if (1..=8).contains(&n) { Ok(n as u8) } else { Err("from 1 to 8 words".into()) }}/// A random name of `words` words (1 to 8; 3 reads well) joined by `separator`: "neatly-bold-otter". Words are short, common and inoffensive English.pub fn human_id(words: i64, separator: &str) -> Result<String, String> {    let w = self::words(words)?;    names().namer(w, separator).iter(&mut rand::rng()).next().ok_or_else(|| "no names".to_string())}/// A random name whose words all start with the same letter: "busy-brown-badger".pub fn human_id_alliterating(words: i64, separator: &str) -> Result<String, String> {    let w = self::words(words)?;    let a: Alliterations = names().clone().into();    let mut buf = String::new();    a.generate_into(&mut buf, &mut rand::rng(), w, separator);    Ok(buf)}/// The name of a number, the same every time: a readable stand-in for a database id or a hash, such as a build number's name. Not reversible, and two numbers may share a name (see `human_id_count`).pub fn human_id_for(number: i64, words: i64, separator: &str) -> Result<String, String> {    let w = self::words(words)?;    let p = names();    // splitmix64: neighbouring numbers get unrelated names.    let mut x = number as u64;    let mut next = || {        x = x.wrapping_add(0x9E37_79B9_7F4A_7C15);        let mut z = x;        z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);        z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);        z ^ (z >> 31)    };    fn pick<'a>(list: &[&'a str], r: u64) -> &'a str {        list.get((r % list.len().max(1) as u64) as usize).copied().unwrap_or("")    }    let mut out: Vec<&str> = Vec::new();    for _ in 0..w.saturating_sub(2) {        out.push(pick(&p.adverbs, next()));    }    if w >= 2 {        out.push(pick(&p.adjectives, next()));    }    out.push(pick(&p.nouns, next()));    Ok(out.join(separator))}/// How many different names of `words` words there are: about 200,000 for 2 words, 52 million for 3. Pick enough words for the ids you will make, or add a number.pub fn human_id_count(words: i64) -> Result<i64, String> {    Ok(names().cardinality(self::words(words)?).min(i64::MAX as u128) as i64)}
Thread
77Useful? Like it, or add to its thread below.

Thread 0 posts

On Readable ids: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.