https://github.com/structured-world/structured-public-domains
Compact Public Suffix List (PSL) trie for Rust. 32KB embedded, O(depth) lookup. Auto-updated monthly.
https://github.com/structured-world/structured-public-domains
domain-validation psl public-suffix-list pure-rust rust trie
Last synced: about 2 months ago
JSON representation
Compact Public Suffix List (PSL) trie for Rust. 32KB embedded, O(depth) lookup. Auto-updated monthly.
- Host: GitHub
- URL: https://github.com/structured-world/structured-public-domains
- Owner: structured-world
- License: apache-2.0
- Created: 2026-03-24T23:44:56.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2026-04-02T18:52:06.000Z (4 months ago)
- Last Synced: 2026-04-03T06:16:13.863Z (4 months ago)
- Topics: domain-validation, psl, public-suffix-list, pure-rust, rust, trie
- Language: Rust
- Size: 158 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# structured-public-domains
Compact Public Suffix List (PSL) for Rust.
[](https://github.com/structured-world/structured-public-domains/actions/workflows/ci.yml)
[](https://crates.io/crates/structured-public-domains)
[](https://docs.rs/structured-public-domains)
[](LICENSE)
- **Zero** runtime dependencies
- **~108KB** embedded data (compact binary trie)
- **~2.4M lookups/sec** on a single core (~420 ns per lookup)
- **O(depth * log k)** trie traversal with per-node binary search (typically 2-3 steps)
- Wildcard (`*.jp`) and exception (`!metro.tokyo.jp`) rules
- Based on the official Public Suffix List (ICANN and private sections)
- Checked daily against [publicsuffix.org](https://publicsuffix.org/)
**Terminology:** A *public suffix* (e.g., `com`, `co.uk`) is the part of a domain under which users can register names. The *registrable domain* (eTLD+1) is one label above the suffix (e.g., `example.co.uk`).
## Usage
```rust
use structured_public_domains::{lookup, registrable_domain, is_known_suffix};
let info = lookup("www.example.co.uk").unwrap();
assert_eq!(info.suffix(), "co.uk");
assert_eq!(info.registrable_domain(), Some("example.co.uk"));
assert!(info.is_known());
// Helpers
assert_eq!(registrable_domain("sub.example.com"), Some("example.com".to_string()));
assert!(is_known_suffix("example.com"));
```
## Performance
Benchmarks on Apple M-series (criterion, `cargo bench`):
| Benchmark | Time | Throughput |
|-----------|------|-----------|
| Simple (`example.com`) | ~420 ns | ~2.4M/s |
| Nested (`www.example.co.uk`) | ~425 ns | ~2.4M/s |
| Deep subdomain (`a.b.c.d.example.com`) | ~500 ns | ~2.0M/s |
| Bare TLD (`com`) | ~195 ns | ~5.1M/s |
| Private domain (`mysite.github.io`) | ~450 ns | ~2.2M/s |
| Long chain (`very.deep...co.uk`) | ~500 ns | ~2.0M/s |
**Runtime memory:** The PSL trie is parsed lazily on first call (`OnceLock`), then cached for the lifetime of the process. Runtime footprint is ~530 KB (sorted `Vec` children with binary search lookup). The ~108KB binary blob is embedded in the binary at compile time.
## Why not `psl`?
| | `psl` | `structured-public-domains` |
|---|---|---|
| Embedded data | ~876KB (codegen match tree) | **108KB** (compact binary trie) |
| Source size | 2.4MB codegen | 300 lines + 108KB blob |
| Runtime deps | None | **None** |
| Runtime memory | N/A (static) | **~530KB** |
| Lookup | O(depth) match tree | O(depth * log k) trie walk |
| Auto-update | New crate version | Daily GitHub Actions check |
Both crates have comparable lookup speed and zero runtime dependencies. `structured-public-domains` has ~8x smaller embedded data and auto-updates daily via GitHub Actions with domain-level changelogs.
## Support the Project

USDT (TRC-20): `TFDsezHa1cBkoeZT5q2T49Wp66K8t2DmdA`
## License
Apache License 2.0