Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

入门:Rust

Rust 下游唯一需要的依赖是总括 crate purrdf。它在根部重新导出 RDF 1.2 实现接口,并把其他每个已发布的 crate 置于一个稳定的模块之下(purrdf::sparql、purrdf::shapes、purrdf::shex、purrdf::gts、purrdf::entail、purrdf::validate、purrdf::slice、purrdf::iri、purrdf::xsd、purrdf::events)——使用方合理导入的任何内容都只凭 purrdf 即可到达,绝不需要深入某个子 crate。

cargo add purrdf

MSRV 为 Rust 1.98,位于 stable 通道:按政策,代码不使用任何 nightly(不稳定)特性,因此 stable 1.98 即可构建。仓库自身的工具链浮动跟随 nightly,以获得更锐利的 lint;参见版本管理与发布。

译注:中国大陆镜像。 如需使用 crates.io 镜像,可参考 TUNA、USTC 与 rsproxy.cn 的说明,在 ~/.cargo/config.toml 中通过 [source] 配置源替换。具体配置以各镜像站的说明为准。

构建、冻结、序列化、解析

use purrdf::{parse_dataset, serialize_dataset, RdfDatasetBuilder, RdfLiteral, SerializeGraph};

// 在驻留的 TermId 空间中构建数据集。
let mut b = RdfDatasetBuilder::new();
let alice = b.intern_iri("https://example.org/alice").unwrap();
let knows = b.intern_iri("http://xmlns.com/foaf/0.1/knows").unwrap();
let bob = b.intern_iri("https://example.org/bob").unwrap();
let name = b.intern_iri("http://xmlns.com/foaf/0.1/name").unwrap();
let hi = b.intern_literal(RdfLiteral::simple("Alice")).unwrap();
b.push_quad(alice, knows, bob, None).unwrap();
b.push_quad(alice, name, hi, None).unwrap();
let ds = b.freeze().expect("freeze");

// 序列化为任一原生编解码器的格式并解析回来,不丢失信息。
let ttl = serialize_dataset(&ds, "text/turtle", SerializeGraph::Dataset).unwrap();
let back = parse_dataset(&ttl, "text/turtle", None).unwrap();
assert_eq!(back.quad_count(), 2);

构建器→冻结的拆分是这套 API 的核心:在可变的 RdfDatasetBuilder 上驻留项并推入四元组,然后 freeze() 为一个不可变、带索引的 RdfDataset,每个引擎(SPARQL、SHACL、ShEx、蕴涵)都在其上求值。项驻留与插入会返回带类型的存储失败;应用代码应向上传递这些错误,而不是忽略它们。参见驻留数据集 IR。

直接解析文本

let turtle = r#"
    @prefix ex: <https://example.org/> .
    ex:cat ex:says "meow" .
"#;
let dataset = purrdf::parse_dataset(turtle.as_bytes(), "text/turtle", None)
    .expect("valid Turtle");
assert_eq!(dataset.quad_count(), 1);

格式错误的输入会得到一个带类型的 RdfDiagnostic,并在编解码器能够提供时附带源位置——绝不会是静默的部分解析。

到达其他引擎

每个引擎都挂在同一个门面之下。例如,IRI 层(不依赖任何第三方包)与 ShEx 模式层:

let iri = purrdf::iri::parse("https://example.org/cat").expect("valid IRI");
assert_eq!(iri.as_str(), "https://example.org/cat");

let schema = purrdf::shex::parse_shexc(
    "PREFIX ex: <https://example.org/>\nex:Cat { ex:says . }",
    None,
).expect("valid ShExC");

何时应改为依赖子 crate

大多数应用只需依赖 purrdf。子 crate(purrdf-core、purrdf-rdf、purrdf-columnar、purrdf-sparql-algebra、purrdf-sparql-eval、purrdf-sparql-results、purrdf-cdt、purrdf-shapes、purrdf-jsonschema、purrdf-shex、purrdf-gts、purrdf-datalog、purrdf-entail、purrdf-geo、purrdf-text、purrdf-validate、purrdf-slice、purrdf-iri、purrdf-lex、purrdf-xsd、purrdf-events、purrdf-hash、purrdf-wasm)是为只想要恰好一个引擎的使用方准备的——例如,只需要 IRI 解析的工具可以仅依赖 purrdf-iri,它的依赖是第一方词法层 purrdf-lex 与零依赖的 purrdf-hash。crate 一览见仓库 README。

每个发布的 crate 都能干净地构建到 wasm32-unknown-unknown,因此同样的 Rust 代码路径在原生宿主与 wasm 宿主中都能工作。

后续步骤