rete_graph/lib.rs
1//! `rete-graph` — the Rust library for [Rete](https://github.com/caviri/rete)
2//! graph files, under the name it already has on PyPI and npm.
3//!
4//! This crate is a **facade**: every item is re-exported from
5//! [`rete_core`](https://docs.rs/rete-core), which is where the engine actually
6//! lives and where the implementation documentation belongs. Depending on either
7//! gets you the same code; this one exists so that
8//!
9//! ```text
10//! pip install rete-graph # Python
11//! npm install rete-graph # JavaScript
12//! cargo add rete-graph # Rust
13//! ```
14//!
15//! all name the same thing. Before it existed, a Rust user following any of the
16//! project's other install instructions had to know that the crate was called
17//! something else.
18//!
19//! ## What this is NOT
20//!
21//! It does not pull in the whole workspace, because the three published crates
22//! are not interchangeable:
23//!
24//! - **`rete-core`** is the library — what a Rust program depends on, and what
25//! this crate re-exports.
26//! - **`rete-cli`** is a *binary*. You install it (`cargo install rete-cli`);
27//! depending on it from a library would drag an executable into your build for
28//! nothing.
29//! - **`rete-wasm`** is the browser binding, meaningful only on `wasm32`
30//! targets.
31//!
32//! PyPI's and npm's `rete-graph` are likewise the *library* for their language,
33//! not the CLI, so re-exporting the library is the faithful mapping.
34//!
35//! ## Features
36//!
37//! `compression` (default), `parallel` and `wasm-js` are forwarded verbatim to
38//! `rete-core`, so this crate can be configured exactly like it.
39//!
40//! ## Example
41//!
42//! ```no_run
43//! use rete_graph::Rete;
44//!
45//! let bytes = std::fs::read("graph.rete")?;
46//! let graph = Rete::open(&bytes)?;
47//! println!("{} quads", graph.dump(None).len());
48//! # Ok::<(), Box<dyn std::error::Error>>(())
49//! ```
50#![doc(html_root_url = "https://docs.rs/rete-graph")]
51
52pub use rete_core::*;
53
54/// The `rete-core` version this facade re-exports.
55///
56/// Identical to [`rete_core::VERSION`] by construction — the dependency is
57/// pinned with `=`, so the two can never disagree — and re-stated here because a
58/// caller who only knows `rete_graph` should not have to reach for another crate
59/// to answer "which engine am I on?".
60pub const ENGINE_VERSION: &str = rete_core::VERSION;
61
62#[cfg(test)]
63mod tests {
64 /// The facade must expose the engine, not an empty shell: build a tiny graph
65 /// through the re-exported API and read it back. If `pub use` ever stopped
66 /// covering the types a user needs, this would not compile.
67 #[test]
68 fn the_facade_round_trips_a_graph() {
69 use crate::{DictionaryBuilder, GraphIndexBuilder, Rete};
70
71 let triples = [(
72 "<http://ex/alice>".to_string(),
73 "<http://ex/knows>".to_string(),
74 "<http://ex/bob>".to_string(),
75 )];
76 let mut db = DictionaryBuilder::new();
77 for (s, p, o) in &triples {
78 db.observe(s, p, o);
79 }
80 let dict = db.build();
81 let mut ib = GraphIndexBuilder::new();
82 for (s, p, o) in &triples {
83 ib.push(dict.encode(s, p, o).unwrap());
84 }
85 let bytes = crate::file::write_file(&dict, &ib.build(), false, &[], 0);
86
87 let graph = Rete::open(&bytes).unwrap();
88 assert_eq!(graph.dump(None).len(), 1);
89 assert_eq!(crate::ENGINE_VERSION, rete_core::VERSION);
90 }
91}