Rust toolkit for India Post DIGIPIN.
digipin-rs gives you a fast, offline, deterministic implementation of the
India Post DIGIPIN algorithm, plus developer utilities for CLI workflows, batch
conversion, GeoJSON export, and a tiny local HTTP API.
The core encoder/decoder stays compatible with the India Post reference logic. Everything else is built around it so developers can inspect cells, prefixes, bounds, neighboring cells, and structured JSON output without changing official DIGIPIN behavior.
DIGIPIN is useful, but the official reference implementation is only the start. Real developer workflows need more:
- Convert coordinates to DIGIPIN from CLI, code, CSV, JSONL, or HTTP.
- Decode a DIGIPIN into its center point and cell bounds.
- Inspect partial prefixes like
4P3as larger grid cells. - Export cells as GeoJSON for maps and GIS tools.
- Run everything offline with no network calls.
From this repository:
cargo install --path .Use it as a Rust library:
[dependencies]
digipin-rs = { path = "." }Encode latitude/longitude:
digipin encode 12.9716 77.59464P3-JK8-52C9
Decode a DIGIPIN:
digipin decode 4P3-JK8-52C912.971601,77.594584
Get JSON output:
digipin --json locate 12.9716 77.5946Trimmed preview:
{
"input": {
"latitude": 12.9716,
"longitude": 77.5946
},
"digipin": "4P3-JK8-52C9",
"cell": {
"center": {
"latitude": 12.971601,
"longitude": 77.594584
}
}
}| Need | Command/API |
|---|---|
| Encode coordinates | digipin encode <lat> <lon> |
| Decode DIGIPIN | digipin decode <digipin> |
| Validate and normalize | digipin validate <digipin> |
| Inspect cell bounds | digipin cell <digipin> |
| Inspect a prefix cell | digipin partial-cell <prefix> |
| Explore prefix hierarchy | digipin explore <digipin> |
| Export GeoJSON | digipin geojson <digipin> |
| List neighboring cells | digipin neighbors <digipin> |
| Compare code systems | digipin compare <lat> <lon> |
| Generate GeoHash | digipin geohash <lat> <lon> |
| Generate Plus Code | digipin plus-code <lat> <lon> |
| Measure distance | digipin distance <lat1> <lon1> <lat2> <lon2> |
| Convert CSV files | digipin batch-csv input.csv --mode encode |
| Convert JSONL streams | digipin batch-jsonl input.jsonl --mode decode |
| Run local API | digipin serve --port 8080 |
| Print OpenAPI | digipin openapi |
| Generate completions | digipin completions zsh |
Validate flexible input:
digipin validate " 4p3 jk8 52c9 "4P3-JK8-52C9
Inspect a full cell:
digipin --json cell 4P3-JK8-52C9Inspect a partial prefix:
digipin --json partial-cell 4P3Explore every prefix level:
digipin explore 4P3-JK8Export a cell as GeoJSON:
digipin geojson 4P3-JK8-52C9Process a CSV file:
digipin batch-csv input.csv --mode encode --output output.csvProcess JSONL from stdin:
printf '{"latitude":12.9716,"longitude":77.5946}\n' \
| digipin batch-jsonl - --mode encodeRun the local API:
digipin serve --host 127.0.0.1 --port 8080
curl 'http://127.0.0.1:8080/encode?latitude=12.9716&longitude=77.5946'Generate shell completions:
digipin completions zsh > _digipinCompare DIGIPIN, GeoHash, and Plus Code:
digipin compare 12.9716 77.5946DIGIPIN: 4P3-JK8-52C9
GeoHash: tdr1v9qtj1
Plus Code: 7J4VXHCV+JR
DIGIPIN cell: center=12.971601,77.594584 size=3.818m x 3.72m
let code = digipin::encode(12.9716, 77.5946)?;
let coords = digipin::decode(&code)?;
let cell = digipin::cell(&code)?;
let info = digipin::locate(12.9716, 77.5946)?;
let prefix = digipin::partial_cell("4P3")?;
let geojson = digipin::digipin_geojson_feature(&code)?;
let comparison = digipin::compare_codes(12.9716, 77.5946, 10)?;Run the included example:
cargo run --example quickstartRun the benchmark example:
cargo run --release --example benchmark -- 1000000Start the local server:
digipin serve --port 8080Available endpoints:
| Endpoint | Purpose |
|---|---|
GET /health |
Health check |
GET /encode?latitude=...&longitude=... |
Encode coordinates |
GET /decode?digipin=... |
Decode DIGIPIN |
GET /locate?latitude=...&longitude=... |
Encode with metadata |
GET /compare?latitude=...&longitude=... |
Compare DIGIPIN, GeoHash, and Plus Code |
GET /plus-code?latitude=...&longitude=... |
Encode coordinates to Plus Code |
GET /geohash?latitude=...&longitude=... |
Encode coordinates to GeoHash |
GET /explore?digipin=... |
Return all prefix levels |
GET /cell?digipin=... |
Return cell center and bounds |
GET /geojson?digipin=... |
Return cell as GeoJSON Feature |
GET /openapi.json |
Return OpenAPI document |
Build the image:
docker build -t digipin-rs .Run the API server:
docker run --rm -p 8080:8080 digipin-rs
curl 'http://127.0.0.1:8080/compare?latitude=12.9716&longitude=77.5946'- Official-compatible DIGIPIN encode/decode.
- Canonical
XXX-XXX-XXXXformatting. - Flexible normalization for lowercase, spaces, and missing separators.
- Typed errors through
DigiPinError. - Full cell center and bounds.
- Partial prefix cells for hierarchy exploration.
- Prefix explorer output for every DIGIPIN level.
- Approximate cell width and height in meters.
- Coordinate containment checks.
- Neighboring DIGIPIN cells.
- Haversine distance utility.
- GeoHash encoding.
- Plus Code / Open Location Code encoding.
- DIGIPIN vs GeoHash vs Plus Code comparison.
- GeoJSON Polygon and Feature export.
- CSV and JSONL batch workflows.
- Local HTTP API server.
- Dockerfile for one-command API deployment.
- Lightweight benchmark example.
- OpenAPI document generation.
- Shell completion generation.
- Unit and integration tests.
| Priority | Feature | Why It Matters |
|---|---|---|
| 1 | Web Playground | Browser UI for encode/decode, prefix explorer, GeoJSON preview, and map display. |
| 2 | WASM Build | Run the encoder directly in browser apps without a backend. |
| 3 | Python Package | Make it useful for data teams and notebooks. |
| 4 | Node Package | Make it easy to use from web apps and backend services. |
| 5 | Postgres Functions | Enable DIGIPIN conversion directly inside databases. |
- India Post DIGIPIN page: https://www.indiapost.gov.in/digipin
- India Post GitHub repository: https://github.com/INDIAPOST-gov/digipin
Run tests:
cargo testFormat:
cargo fmtCheck CLI:
cargo run -- --helpApache-2.0