Expand description
purrdf-iri — the native IRI/URI value space for the RDF 1.2 query stack.
A pure-Rust, zero-runtime-dependency, wasm-clean leaf crate: the drop-in
replacement for the oxigraph-family oxiri, and the second foundation slice of
the native SPARQL engine (purrdf S2). It is deliberately decoupled
from purrdf-core (no dependency in either direction yet); the IR keeps
IRIs lexical-verbatim (Constitution C0.1) and this crate is the
validation/resolution layer beside it.
§Coverage (a superset of oxiri)
- Parse + validate — RFC-3987 IRIs (
parse) and the strict-ASCII RFC-3986 URI subset (parse_uri). Component spans (scheme/authority/path/query/ fragment) are exposed without re-encoding. - Reference resolution — RFC-3986 §5 strict resolution (
Iri::resolve). - Syntax normalization — RFC-3986 §6.2.2 (
Iri::normalize): case, percent- encoding, and dot-segment normalization. Idempotent. - CURIE/prefix —
expand_curie/resolve/contractover aPrefixMap, subsuming the SSSOM serializer’s hand-rolled prefix logic.oxirihas none of this — it is the EXTEND deliverable for this slice.
§Hard-fail
Malformed input is a typed IriError, never a degraded fallback or silent
default (repo no-optionality doctrine). The one Option-returning surface is
CURIE expansion, where None is a semantic “not a CURIE / undeclared prefix”
signal, faithful to the SSSOM behavior this crate subsumes.
§Examples
Parse an absolute IRI, resolve a relative reference against it, and normalize a messy spelling — the three core entry points:
use purrdf_iri::parse;
// Parse + validate, with zero-copy component access.
let base = parse("http://example.org/a/b/c")?;
assert_eq!(base.scheme(), Some("http"));
assert_eq!(base.path(), "/a/b/c");
// RFC-3986 §5 strict reference resolution.
let joined = base.resolve("../d?x=1")?;
assert_eq!(joined.as_str(), "http://example.org/a/d?x=1");
// RFC-3986 §6.2.2 syntax normalization: case, percent-encoding, dot segments.
let messy = parse("HTTP://EXAMPLE.org/a/./b/../c/%7Ename")?;
assert_eq!(messy.normalize().as_str(), "http://example.org/a/c/~name");Expand and contract CURIEs over a caller-supplied PrefixMap:
use purrdf_iri::{PrefixMap, contract, expand_curie};
let mut prefixes = PrefixMap::new();
prefixes.insert("ex", "http://example.org/ns#");
assert_eq!(
expand_curie("ex:Thing", &prefixes),
Some("http://example.org/ns#Thing".to_owned())
);
assert_eq!(
contract("http://example.org/ns#Thing", &prefixes),
Some("ex:Thing".to_owned())
);Re-exports§
Modules§
- pos
- Source-text position math: byte offset → 1-based line/column.
Structs§
- Iri
- A parsed, validated IRI (or URI) with byte-offset spans for each component.
- Prefix
Map - A prefix → namespace-IRI map.
BTreeMapfor deterministic iteration (the contraction longest-match must be reproducible).
Enums§
- IriError
- Why an IRI/URI string (or a reference-resolution / CURIE operation) failed.
Functions§
- contract
- Contract an absolute IRI to a CURIE using the longest matching namespace
(ties broken by prefix name, deterministically). Returns
Noneif no declared namespace is a prefix ofiri. - curie_
prefix - The CURIE prefix of
entity, orNoneif it is not a CURIE. - expand_
curie - Expand a CURIE against
prefixes. ReturnsSome(absolute-iri)only whenentityis a CURIE and its prefix is declared; otherwiseNone. - parse
- Parse and validate an IRI (RFC-3987). Non-ASCII
ucschar/iprivatecode points are permitted in the appropriate components. - parse_
uri - Parse and validate a URI (RFC-3986). Non-ASCII code points are rejected
(they must be percent-encoded); everything else matches
parse. - resolve
- Resolve
entityto an IRI string: expand a declared CURIE, else return the entity verbatim. This is the exact behavior ofsssom::resolve_iri.
Type Aliases§
- Result
- Convenience alias for fallible IRI operations.