Skip to main content

Crate purrdf_iri

Crate purrdf_iri 

Source
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/prefixexpand_curie/resolve/contract over a PrefixMap, subsuming the SSSOM serializer’s hand-rolled prefix logic. oxiri has 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§

pub use pos::LineIndex;
pub use pos::Position;

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.
PrefixMap
A prefix → namespace-IRI map. BTreeMap for 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 None if no declared namespace is a prefix of iri.
curie_prefix
The CURIE prefix of entity, or None if it is not a CURIE.
expand_curie
Expand a CURIE against prefixes. Returns Some(absolute-iri) only when entity is a CURIE and its prefix is declared; otherwise None.
parse
Parse and validate an IRI (RFC-3987). Non-ASCII ucschar/iprivate code 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 entity to an IRI string: expand a declared CURIE, else return the entity verbatim. This is the exact behavior of sssom::resolve_iri.

Type Aliases§

Result
Convenience alias for fallible IRI operations.