Expand description
IRI validity — what may appear between the angle brackets of an
N-Triples / N-Quads IRIREF, and the one lossy repair the exporter offers.
rete’s line-based N-Triples/N-Quads reader is deliberately tolerant: it takes
whatever sits between < and the next > and stores it as a dictionary key.
That makes the file a faithful container of what it was given, but it also
means a .rete can hold IRIs that no strict parser accepts — and
rete export --format nq then names a grammar it does not emit. Oxigraph,
Jena and rapper reject such a dump; a bulk loader rejects the chunk, not
the line, so one bad IRI can cost a hundred thousand good statements.
This module is the single definition of “invalid” used by the build-time
audit (rete build, rete validate) and the export-time repair
(rete export --sanitize-iris).
§Validity is decided by a parser; the classes only say how to repair
Two documents apply, and both must hold:
- the N-Triples/N-Quads
IRIREFproduction ('<' ([^#x00-#x20<>"{}|^] | UCHAR)* ‘>’`), which excludes a fixed set of characters outright, and - RFC 3987, which the same grammar requires the content to satisfy as an absolute IRI (with an optional fragment).
The first is a character set, so a one-pass scan settles it. The second is a
grammar, and it is not settled by enumerating bad shapes: a taxonomy of
known defects can only recognise what has already been seen, so making it the
arbiter of validity guarantees that the next unseen shape is published as
valid. That is not hypothetical — <https://::1> (an IPv6 literal in the
authority without the brackets 3987 requires) matched none of the five
classes, and a dump carrying it passed the export gate and was rejected by
Oxigraph.
So the two questions are separated:
- Is it valid?
oxirianswers, and nothing else does. That is the crate Oxigraph’s own N-Triples reader validates with —oxttl’s lexer tokenises<…>per theIRIREFproduction and hands the content tooxiri::Iri::parse— so rete’s verdict agrees with the reference loader’s by construction rather than by our keeping a list up to date.oxiriis already in this crate’s dependency tree viaoxrdf/oxttl, so deciding it properly costs no new dependency and no new wasm surface. - Can we repair it, and how? The classes below answer, and only that. Each names a shape percent-encoding can fix without inventing information.
| class | example | repairable by escaping |
|---|---|---|
IriDefect::NotAbsolute | <noscheme/path> | no |
IriDefect::ForbiddenChar | <http://ex/a b>, <http://ex/a"b> | yes |
IriDefect::Bracket | <http://ex/a[b]> | yes |
IriDefect::ExtraHash | <http://ex/c#d#e> | yes |
IriDefect::BadPercent | <http://ex/%x> | yes |
IriDefect::Unclassified | <https://::1> | no |
IriDefect::Unclassified is the load-bearing one: an IRI the parser
rejects that no class recognises. It is still counted and it is still
unrepairable, so it still blocks. A gap in the taxonomy is now benign — we
failed to repair something we might have — instead of harmful, which is a
published dump that does not load. A class that is added later only moves
occurrences out of this bucket; it never changes a verdict from invalid to
valid.
A repairable class is only reported when escaping actually lands a valid
IRI: <https://::1/a[b]> has a bracket, but encoding it leaves an IRI the
parser still rejects, so it is reported as IriDefect::Unclassified rather
than as a Bracket the sanitizer would claim to have fixed.
§UCHAR escapes are syntax, not content
<http://ex/café> is a legal IRIREF whose IRI is http://ex/café —
the backslash belongs to N-Triples, not to the IRI. The escapes are therefore
resolved before the parser sees the string, exactly as oxttl does.
Handing the raw bracket content to an RFC 3987 parser would reject \ and
make every escaped dump a false positive.
§What this deliberately does not judge
- Scheme semantics.
<nonsense://x>is syntactically a fine IRI and is accepted. Whether the scheme is registered, resolvable or meaningful is not this module’s question. - Whether the IRI names anything. A 404, a typo’d host and a dead DOI are all valid IRIs.
- Normalisation.
<HTTP://EX/a/../b>is valid and is left exactly as it was given; rete never case-folds a scheme or removes a dot segment, because both change the dictionary key and break the round-trip. - Anything escaping cannot fix. A relative IRI (
IriDefect::NotAbsolute) and anIriDefect::Unclassifiedone are reported and left alone —sanitize_iri_contentreturnsNoneand the term is emitted verbatim. A dump containing one is still not valid N-Quads, and--sanitize-irissays so rather than implying a fix it did not make.
Non-ASCII used to be on this list and no longer is. RFC 3987 admits
ucschar, so <http://ex/café> is valid — but the narrow sub-ranges 3987
excludes (surrogates, iprivate outside the query) were previously not
policed at all. The parser polices them now, because it is the same parser
the loader uses: if it accepts a character, so does the dump’s reader.
Structs§
- IriReport
- A bounded tally of invalid IRIs — the shape both the build-time audit and the export-time sanitizer report.
Enums§
- IriDefect
- Why an IRI is not one — a repair classification, not the validity
verdict.
iri_content_defectdecides validity with an RFC 3987 parser and uses these only to say what, if anything, can be done about it.
Constants§
- DEFECT_
CLASSES - Number of
IriDefectclasses — the width of a report’s counter array.
Functions§
- iri_
content_ defect - Classify the content of an
IRIREF— what sits between<and>— returningNonewhen it is a valid absolute IRI, and otherwise the class that says what can be done about it. - sanitize_
iri_ content - Percent-encode the offending characters of an
IRIREF’s content. - sanitize_
term - Percent-encode every repairable IRI inside a canonical term token, returning
Nonewhen nothing changed. The token-level counterpart ofsanitize_iri_content; it rebuilds quoted triples and literal datatypes around the repaired IRI so the result is still a canonical token. - term_
defect - Classify a canonical N-Triples term token —
<iri>,_:b,"lit","lit"^^<dt>,"lit"@en, or an RDF-star<<s p o>>— returning the first IRI defect it carries, orNone. - term_
defects - Every defect a term carries, not only the first.