Skip to main content

Crate iri_rfc3987

Crate iri_rfc3987 

Source
Expand description

§iri-rfc3987

Crates.io Documentation CI License: MIT OR Apache-2.0 Downloads

Zero-copy parsing, validation, and resolution for Internationalized Resource Identifiers (IRIs), based on RFC 3987 and RFC 3986.

§Why this crate

IRIs are structured identifiers, not arbitrary strings. Parsing at the boundary lets applications reject malformed values early while retaining the original text and avoiding an allocation when the input is already borrowed.

iri-rfc3987 keeps the public API deliberately small:

  • parsing is explicit and fallible;
  • borrowed and owned forms use the same generic types;
  • relative references can be resolved against an absolute base;
  • parse and resolution failures are typed and carry useful context;
  • URI-only types and builder APIs are outside the scope of this crate.

The crate provides two validated types:

  • Iri<T> for an absolute IRI with a required scheme.
  • IriRef<T> for an IRI reference, including relative references.

Both types support borrowed parsing with &str and owned storage with String:

use iri_rfc3987::{Iri, IriRef};

let iri = Iri::parse("https://example.org/resource")?;
assert_eq!(iri.as_str(), "https://example.org/resource");

let reference = IriRef::parse("../other")?;
assert!(!reference.has_scheme());

§Borrowed and owned values

Parsing an &str produces a zero-copy Iri<&str> or IriRef<&str>. Convert to an owned value only when it must outlive the source string:

use iri_rfc3987::{Iri, IriRef};

let borrowed: Iri<&str> = Iri::parse("https://example.org/resource")?;
let owned: Iri<String> = borrowed.to_owned();
assert_eq!(owned.as_str(), "https://example.org/resource");

let reference: IriRef<String> = IriRef::parse_owned("../other".to_owned()).unwrap();
assert_eq!(reference.as_str(), "../other");

§Resolving references

IriRef accepts absolute and relative references. Resolution follows the path-merging rules from RFC 3986:

use iri_rfc3987::{Iri, IriRef};

let base = Iri::parse("https://example.org/a/b/").unwrap();
let reference = IriRef::parse("../image.svg").unwrap();
let resolved = reference.resolve_against(&base).unwrap();

assert_eq!(resolved.as_str(), "https://example.org/a/image.svg");

An absolute reference is returned as its own resolved IRI, while an empty or relative reference inherits the appropriate components from the base. A base with a fragment and invalid opaque-base combinations are rejected with a typed ResolveError.

§Validation errors

Parsing never silently accepts an invalid value. IriParseError::index identifies the byte position where validation stopped:

use iri_rfc3987::Iri;

let error = Iri::<&str>::parse("not an absolute iri").unwrap_err();
assert_eq!(error.index(), 3);

For a known compile-time constant, Iri::known is available when a panic is preferable to carrying a construction error:

use iri_rfc3987::Iri;

let rdf_type = Iri::known("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
assert_eq!(rdf_type.as_str(), "http://www.w3.org/1999/02/22-rdf-syntax-ns#type");

§Serde

Iri and IriRef serialize as their validated string representation and validate again when deserialized:

use iri_rfc3987::Iri;

let iri = Iri::parse_owned("https://example.org/resource".to_owned()).unwrap();
let encoded = serde_json::to_string(&iri)?;
let decoded: Iri<String> = serde_json::from_str(&encoded)?;

assert_eq!(decoded, iri);

§API overview

TypePurpose
Iri<T>Absolute IRI with a required scheme.
IriRef<T>Absolute or relative IRI reference.
IriParseErrorTyped parse failure with a byte index.
ResolveErrorTyped failure while resolving a reference.
TryIntoIriFallible conversion into Iri<String>.

The implementation retains the IRI-specific portion of the parser adapted from fluent-uri 0.4.1. URI-only types and builder APIs are intentionally not included.

§License

Copyright © 2026 DataRoad Inc, Delaware, USA, trading as Legra.

Licensed under either of:

at your option.

Structs§

Iri
An IRI (Internationalized Resource Identifier) compliant with RFC 3987.
IriParseError
An error occurred when parsing an IRI or IRI reference.
IriRef
An IRI reference, i.e., either an IRI or a relative reference.

Enums§

ResolveError
An error occurred while resolving an IRI reference against a base IRI.

Traits§

TryIntoIri
Fallible conversion into a validated Iri<String>.