harsh

A Rust implementation of Hashids for short, reversible IDs from numbers.

Library
Cargo
v0.2.2
64stars
MIT/Apache-2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
30/100Needs Attention
Development Activity0
Maintenance20
Community28
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
71/100Good
Architecture72
Code Quality76
Innovation62
Learning Curve85

Harsh is a Rust implementation of the Hashids algorithm: it encodes one or more numbers into a short, unique, YouTube-like string and decodes it back to the original numbers. It is the tool to reach for when you want to expose opaque identifiers in URLs or APIs instead of leaking sequential database ids.

The encoding is reversible and deterministic, not cryptographic — it obfuscates rather than encrypts. Harsh gives you a small builder API to customize the salt (making ids unique to your project), a minimum id length via padding, and a custom alphabet, so the generated ids fit your product’s look while staying decodable.

What You Get

  • encode and decode for turning number arrays into short strings and back
  • A builder to set a salt so ids are unique to your project
  • Minimum-length padding to make ids at least a chosen length
  • Custom alphabet support to control which characters appear
  • Hex-string encoding and decoding helpers

Common Use Cases

  • Hiding sequential database ids behind opaque public identifiers
  • Generating short, URL-friendly ids for links and API resources
  • Producing shareable codes that decode back to structured numbers
  • Creating project-scoped ids that differ across environments via salt

Under The Hood

Architecture — The crate is three small modules. src/lib.rs re-exports the public surface, src/builder.rs implements a HarshBuilder that validates configuration (salt, minimum length, alphabet, separators) and produces a Harsh instance, and src/harsh.rs holds the core algorithm — the alphabet shuffling, separator/guard handling, and the encode/decode/encode_hex/decode_hex methods. Construction does the expensive setup once so per-call encoding is cheap.

Tech Stack — Plain Rust (edition 2018) with zero runtime dependencies; criterion is used only as a dev-dependency for the benchmarks under benches/. The crate is categorized for encoding, value-formatting, and web-programming use.

Code Quality — For a ~1,000-line crate it is well tested: tests/ cover round-trip encode/decode against the reference Hashids vectors, and examples/ plus benches/ document real usage. Error cases (invalid alphabet, decode of malformed input) return Result, so failure modes are explicit rather than panicking.

API Design — Ergonomics are strong: Harsh::default() works out of the box, and the fluent builder (Harsh::builder().salt("...").length(10).build()) reads clearly for customization. encode takes a slice of u64 and decode returns a Result<Vec<u64>>, so the reversible contract is obvious from the signatures. The concepts are simple enough that the learning curve is minimal.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search