iri-rs
An allocation-conscious Rust implementation of URIs and IRIs (RFC 3986 / RFC 3987) — parse, access components, mutate in-place, resolve references, normalize, compare.
A URI/IRI is a sequence of characters split into distinguishable components:
foo://user@example.com:8042/over/there?name=ferret#nose
└┬┘ └──────────┬────────┘└────┬────┘└────┬─────┘└┬─┘
│ │ │ │ │
scheme authority path query fragment
This crate gives you typed borrowed and owned views over each of them.
use Iri;
let iri = parse?;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
Mutate in place, no per-component allocations:
use IriBuf;
let mut iri = new?;
iri.set_authority?;
iri.set_path?;
iri.set_query?;
assert_eq!;
Why this fork
Fork of iref, static-iref, and iref-enum by Timothée Haudebourg. Public API and RFC behavior largely unchanged; this fork adds:
- Workspace split into
iri-rs-core,iri-rs-static,iri-rs-enumunder theiri-rsfacade. - Reworked
IriEnumderive (iri-rs-enum) — compile-time prefix resolution,const-friendly output viafrom_raw_parts. - Reworked compile-time macros (
iri!,uri!,iri_ref!,uri_ref!) — validate at macro expansion, emitconst-friendlyfrom_raw_partswith pre-computed component positions. - SIMD-accelerated UTF-8 validation via
simdutf8,memchr-accelerated percent scan, SWAR/byte-level fast paths onnew,eq,ord,hash,len. - Opt-in
fast-hashfeature for hashing without re-parsing. - Criterion bench suite (
parse,accessors,resolve,normalize,mutate,normalize_eq,validate). - Rust 2024 edition, MSRV 1.85.
- Renamed crates:
iref→iri-rs,static-iref→iri-rs-static,iref-enum→iri-rs-enum.
Credit and history preserved — see Attribution.
Install
Feature flags
| Flag | Default | Enables |
|---|---|---|
static |
Compile-time iri!, uri!, iri_ref!, uri_ref! macros |
|
enum |
#[derive(IriEnum)] for vocabulary enums |
|
serde |
Serialize / Deserialize for borrowed and owned types |
|
fast-hash |
Skip re-parse on Hash — trades stricter invariants for speed |
Compile-time IRIs
With static, IRIs are validated at macro expansion and emitted as const expressions — zero runtime parsing, zero allocation:
use ;
const HOME: = iri!;
Invalid literals fail to compile. Same for uri!, iri_ref!, uri_ref!.
Vocabulary enums
With enum, map a known vocabulary to a plain enum — cheap storage and comparison, compile-time prefix resolution:
use ;
let term = try_from.unwrap;
assert_eq!;
References and resolution
IriRef / IriRefBuf cover absolute and relative references. A strict implementation of the RFC 3986 §5 reference resolution algorithm with Errata 4547:
use ;
let base = parse?;
let mut r = new?;
assert_eq!;
r.resolve?;
assert_eq!;
Equivalence
Equality, ordering and hashing normalize:
- Dot segments —
a/../a/./b/../b/c≡a/b/c. - Percent encoding —
http://example.org≡http://exa%6dple.org(viapct). - Protocol-agnostic —
http://example.organdhttp://example.org:80are not equal. This crate knows nothing about scheme defaults. - Every
/counts —/foo/barand/foo/bar/are not equal.
Two values whose as_str() differs can still hash equal — keep that in mind when used as map keys.
Examples
Benchmarks
Criterion output: target/criterion/.
MSRV
Rust 1.85 (edition 2024).
Workspace layout
iri-rs— facade crate. Re-exports everything behind feature flags. Start here.iri-rs-core— types, parser, resolver, normalizer.iri-rs-static—iri!/uri!/iri_ref!/uri_ref!compile-time macros.iri-rs-enum—#[derive(IriEnum)]for vocabulary enums.
Attribution
Original crates: iref, static-iref, and iref-enum by Timothée Haudebourg. Upstream commits are preserved in this repo's history under their original authorship. This fork is a workspace reorganization and a layer of performance work on top of the original design.
License
Dual-licensed, same as upstream. Pick whichever fits: