Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

This book is also published in Simplified Chinese (简体中文).

PurRDF is an RDF 1.2 toolkit: primitives, codecs, SPARQL, SHACL, ShEx, entailment, and graph transport, implemented once in Rust and carried verbatim into Python, WebAssembly/JavaScript, and C, with one exception stated up front: the GTS container reaches Rust, the CLI (as an input format), Python and C, and is not exposed by the wasm/JavaScript package. Every published crate builds for wasm32-unknown-unknown, so the engine that answers a query on a server answers it, byte for byte, in a browser tab. It is developed by Blackcat Informatics® Inc. and published under MIT OR Apache-2.0 OR MulanPSL-2.0.

One RDF engine. One behavior. Every language.

What it removes from your architecture. The three jobs that usually keep a PostgreSQL instance running beside a triple store — ranked full-text search, spatial predicates, and vector similarity — are answered inside PurRDF: in-process, over the same dataset, from the same SPARQL query, with no second database and no sync job. The numeric contracts are explicit: exact text scores, certified geographic results, and deterministic binary64 vector scores. See One engine instead of three databases below.

Why does PurRDF exist?

RDF tooling fragments along two axes.

Across languages: every ecosystem has its own parser, with its own bugs, its own corner-case interpretations, and its own subset of the spec. Move a graph from a Rust service to a Python pipeline to a browser and you have silently changed what the data means three times.

Across time: RDF 1.2 — triple terms, reifiers, base-direction literals — is the current revision of the standard, and almost no incumbent library carries it.

PurRDF exists so that a graph is the same graph everywhere. It is a from-scratch, dependency-light Rust core — parser to SPARQL engine to SHACL validator to binary transport — exposed through native bindings rather than reimplemented per language.

What’s inside

  • RDF 1.2 primitives — an immutable, value-interned dataset IR (TermId space, string arena, copy-on-write mutation), with triple terms in object position, reifier/annotation side-tables, and base-direction literals. See The Interned Dataset IR.
  • Native codecs — first-party parsers/serializers for Turtle, TriG, N-Triples, N-Quads, RDF/XML, TriX, HexTuples, JSON-LD (star), and YAML-LD, with byte-deterministic output. See Codecs & Determinism. Every syntax resolves relative IRI references through one RFC 3986 layer, and a relative reference with no base in scope is a hard error. See Base IRIs & Relative References.
  • Canonicalization — W3C RDFC-1.0 on the RDF 1.1 subset; over RDF 1.2 constructs, either the flat form (RDFC-1.0 over rdf:reifies triples) or the first-party purrdf-rdfc12 profile, named apart — plus dataset diff and isomorphism. See Canonicalization & Diff.
  • Projections & carriers — deterministic LPG, CSVW, OBO Graphs, dataset-description, and research-object projections, each with a located loss ledger. See Graph, Tabular & Research-Object Projections.
  • SPARQL 1.1/1.2 — native parser → algebra → multiset evaluator, with full Update, SEP-0002 temporal arithmetic, LATERAL (SEP-0006), the SEP-0008 SHA-3 hash builtins (SHA3-224/256/384/512), quad templates that CONSTRUCT into named graphs (a first-party extension, not a SPARQL 1.2 feature), the SEP-0009 composite datatypes (cdt:List/cdt:Map, FOLD, UNFOLD — with one stated divergence: PurRDF admits RDF 1.2 triple terms and directional language-tagged literals as composite elements, a lexical superset a conformant SEP-0009 reader will call ill-formed), caller-registered aggregates and property functions (including path witnesses that bind a traversal hop by hop), governed execution with per-node explain receipts, and a SERVICE seam — a host-injected resolver carrying per-service context; no HTTP client and no resolver ship, so SERVICE and LOAD fail by name on every shipped surface unless written SILENT — gated by the W3C conformance suites. See SPARQL.
  • SPARQL extensions outside purrdf-core — deterministic full-text search with exact fixed-point BM25 (Full-Text Search), certified GeoSPARQL 1.1 over exact coordinate inputs (GeoSPARQL), and nearest-neighbour search over a PURREMB embedding space (Embedding Nearest Neighbours) — each a consumer of the extension seams, registered under IRIs the caller supplies.
  • SHACL and ShEx — native validators for both shape languages; the SHACL engine implements SHACL 1.2 Core, SPARQL Extensions, Node Expressions and Inference Rules, and the SPARQL 1.2 RL rule language. See Validation.
  • Entailment — Simple/RDF/RDFS/OWL-RL/D materialization (all 78 OWL 2 RL rules implemented — rule-table coverage, distinct from entailment conformance, where the OWL 2 RL entailment tests score 27 of 27 positive and 23 of 23 negative on this vendored W3C corpus), an OWL-Direct tableau, and RIF-Core rules, with a reasoning report on every closure. See Entailment, evaluated on the Datalog fixpoint engine.
  • GTS graph transport — a single-file, content-addressed, append-only container for RDF 1.2 graphs and binary payloads. See GTS Graph Transport.
  • Slices, mappings, and provenance — a slice catalog, an explicit RDF↔GTS loss ledger, SSSOM, and FnO. See Slices, Mappings & Provenance.

One engine instead of three databases

An RDF project that needs ranked text search, spatial predicates, or nearest-neighbour search has usually run PostgreSQL beside its triple store for exactly those three jobs. PurRDF answers all three from SPARQL, over the dataset already in memory, through the evaluator’s caller-keyed extension seams — and each page below opens with what its surface replaces and where it stops.

You neededUsually fromNow inside PurRDFWhere it stops
Ranked full-text searchPostgreSQL tsvector/tsqueryFull-Text Search: purrdf-text, an inverted index over RDF 1.2 literals with BM25 ranking in exact i128 fixed point and no floating point in the crate.Exact BM25F, explicit stemming/dictionaries and independent Han retrieval; no stop-word lists or query dialect; an in-memory index over frozen datasets.
Spatial predicatesPostGISGeoSPARQL: purrdf-geo-kernel through purrdf-geo, with exact WKT/GeoJSON coordinates, DE-9IM relations, geographic metrics, buffers and explicit coordinate operations; no GEOS or PROJ.References, units, operation chains, numerical limits and tolerances are explicit. No raster; concave hulls and overlay set operations remain named refusals. See the chapter’s function coverage.
Vector similaritypgvectorEmbedding Nearest Neighbours: exact top-k over a PURREMB embedding space, binary64 in a pinned accumulation order.Exact scan bounded by a caller-supplied KnnGuard, three metrics, no approximate index; PurRDF computes no embeddings — the vectors come from a PURREMB artifact the caller fills, which PurRDF itself writes (EmbeddingBuilder, EmbeddingStreamWriter; Rust only) and opens fail-closed.

Text ranking uses exact fixed point; embedding search uses a pinned binary64 accumulation order and canonical tie-breaks. Geographic requests retain exact coordinate inputs and use explicit numerical certification. Native tests pin numeric and serialized expectations. make wasm builds their release crates for wasm32-unknown-unknown; focused portable tests exercise dispatch, kernels and hosts. Text indexes and embedding spaces use Rust-host registration seams under caller-supplied IRIs, including hosts compiled to wasm32. The packaged geographic host entries are documented in GeoSPARQL.

Two design rules worth knowing on day one

No semantic Cargo features. Every consumer gets the same byte-identical semantics. The sole feature declaration is the empty purrdf-capi:capi = [] compatibility marker required by cargo-c; it gates no code. CI refuses other features, optional dependencies and feature-gated behavior.

Application vocabularies are explicit. PurRDF is a toolkit, not an ontology. Structural Markdown and ordered JSON provide named standard profiles; callers select them deliberately or supply a vocabulary. Other application vocabularies are caller-supplied configuration with no fabricated default. A feature used without its vocabulary hard-errors or stays inactive. Test fixtures use example.org.

The full invariant list is in Design Rules & Invariants.

What the version number commits to

From 1.0.0 the suite follows semantic versioning in full: a breaking change bumps the major version, a minor bump is additive, a patch bump is bugfix-only, and the crates.io, PyPI and npm packages ship one workspace version in lockstep. The one exception is the C ABI (purrdf.h), which carries its own 0.x ABI version, bumped on every exported-signature change, and is not frozen. See Versioning & Releases.

Why RDF 1.2?

RDF 1.2 (and SPARQL 1.2) add first-class statement-level metadata to the data model: triple terms that can appear in object position, reifiers that name occurrences of a triple, and base-direction literals (rdf:dirLangString) for bidirectional text. PurRDF treats these as core data model, not an extension: they flow through the IR, the codecs, SPARQL, SHACL 1.2 (reifier shapes and triple-term node kinds), the RDF/JS surface, and the GTS transport. See RDF 1.2 Features.

Where PurRDF sits

PurRDF is the library layer of a small family of linked-data projects: it is the data backbone of the GMEOW stack and the reference home of the Rust GTS engine — but it assumes nothing about your ontology or application.

How to read this book

API reference documentation lives on docs.rs/purrdf; the repository is github.com/Blackcat-Informatics/purrdf.