Generate fun, safe-for-work, reproducible human-ish names from arbitrary input strings.
  • Rust 81.8%
  • Just 18.2%
Find a file
2026-05-27 00:09:41 +00:00
.forgejo/workflows release 2026-05-26 15:06:11 -07:00
data 2.x 2026-05-26 16:56:37 -07:00
docs 2.x 2026-05-26 16:56:37 -07:00
examples 2.x 2026-05-26 16:56:37 -07:00
src 2.x 2026-05-26 16:56:37 -07:00
.gitignore init 2026-05-26 11:24:40 -07:00
Cargo.lock chore: bump version to 2.0.0 2026-05-27 00:09:41 +00:00
Cargo.toml chore: bump version to 2.0.0 2026-05-27 00:09:41 +00:00
justfile 2.x 2026-05-26 16:56:37 -07:00
LICENSE init 2026-05-26 11:24:40 -07:00
README.md release 2026-05-26 15:06:11 -07:00
rust-toolchain.toml init 2026-05-26 12:16:59 -07:00

Lots of Names (Rust)

Generate fun, safe-for-work, reproducible human-ish names from arbitrary input strings. A Rust port of the Scala lots-of-names library.

The same input always maps to the same name. Handy for assigning stable, friendly labels to test data, or to tokenized identifiers where you want to study behavior without revealing the underlying value.

CAUTION: anonymizing PII is deceptively hard. A consistent mapping like this does not protect against correlation / de-anonymization attacks.

Reproducibility is tied to the major version of a release — the word lists and hashing are frozen within a major version. This port reproduces the Scala library byte-for-byte by faithfully reimplementing scala.util.hashing.MurmurHash3.stringHash (which hashes UTF-16 code units, not bytes).

Usage

use lots_of_names::lots_of_people;

// UUID -> readable name
assert_eq!(
    lots_of_people("a8f0bb4c-e921-46a7-af32-268c9fdd15c2"),
    "Moab Julie Harnist"
);

// arbitrary string -> alias
assert_eq!(lots_of_people("Edward John Sweeney"), "Sanjose Aldridge");

Most inputs yield a two-word name; a subset yield a three-word name that includes a middle component.

CLI demo

$ cargo run --example cli -- "Edward John Sweeney" a8f0bb4c-e921-46a7-af32-268c9fdd15c2
Edward John Sweeney	Sanjose Aldridge
a8f0bb4c-e921-46a7-af32-268c9fdd15c2	Moab Julie Harnist

# or pipe ids on stdin, one per line
$ printf '%s\n' id-1 id-2 | cargo run --example cli

Development

The justfile is the single source of truth for build/test/lint — Forgejo Actions calls just ci and nothing else, so local and CI never drift.

just ci      # fmt-check + clippy (warnings=errors) + test + release build
just test    # run the test suite
just fmt     # format in place
just stats   # LOC / largest files / module tree (needs scc + cargo-modules)

Run just ci before pushing — it runs exactly what CI runs. CI runs on the navicore-rust Forgejo runner image (Rust + just pre-installed); its Rust version matches the 1.95.0 channel pinned in rust-toolchain.toml.

Releasing

Publishing to crates.io is automated by .forgejo/workflows/release.yml. To cut a release, push a tag:

git tag v0.2.0
git push origin v0.2.0

The workflow then:

  1. bumps [package].version in Cargo.toml to match the tag and commits it back to main,
  2. runs the tests,
  3. publishes to crates.io.

It runs integrity checks before publishing (origin is the canonical repo, the working tree is clean, and the bumped commit reached origin/main) so a failed push never results in a mismatched publish.

Two repository secrets must be configured (Settings → Actions → Secrets):

  • PAT — Forgejo access token with write access, used to push the version-bump commit back to main.
  • CRATES_IO_TOKEN — a crates.io API token from https://crates.io/settings/tokens.

License

MIT © Ed Sweeney