Getting started
oxgraph is a general-purpose, zero-copy graph and hypergraph engine for
Rust. It runs over any storage: in memory, memory-mapped files, an embedded
database, or Postgres.
The core is no_std and the substrate is unsafe-free. It is built around one
pipeline — bytes → validate → view → traverse: you point a view at a byte
slice, it validates the layout, and you walk the graph. No parse step, no heap
graph rebuilt from the bytes, no copy of the edges.
Install
Depend on the umbrella crate and turn on the features you need. Its default feature set is empty, so a feature is the only thing that pulls a layer in.
cargo add oxgraph --features csr,algo-stdYou can also depend on the individual crates directly if you want a tighter dependency graph. See Feature flags for the full map of features to layers.
Open a graph and traverse it
This builds a CSR snapshot, opens it, and runs breadth-first search over it —
the whole bytes → validate → view → traverse pipeline in one file. It is the
open_snapshot example shipped under oxgraph-csr (enable the csr,
snapshot-alloc, and algo-std features, or depend on oxgraph-csr,
oxgraph-snapshot, and oxgraph-algo directly).
use oxgraph_algo::breadth_first_search;
use oxgraph_csr::{CsrNodeId, CsrSnapshotGraph, CsrSnapshotIndex};
use oxgraph_graph::GraphCounts;
use oxgraph_layout_util::crc32c_append;
use oxgraph_snapshot::{Snapshot, SnapshotWriter};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// A four-node graph in compressed-sparse-row form.
let offsets: [u32; 5] = [0, 2, 3, 4, 4];
let targets: [u32; 4] = [1, 2, 2, 3];
// Pack the native slices into a checksummed, topology-agnostic snapshot
// container. Section kinds derive from the index width; the writer lowers
// native words to their little-endian storage form.
let mut writer = SnapshotWriter::new(2, crc32c_append)?;
writer.section_widths(
<u32 as CsrSnapshotIndex>::OFFSETS_KIND,
<u32 as CsrSnapshotIndex>::SECTION_VERSION,
&offsets,
)?;
writer.section_widths(
<u32 as CsrSnapshotIndex>::TARGETS_KIND,
<u32 as CsrSnapshotIndex>::SECTION_VERSION,
&targets,
)?;
let bytes = writer.finish()?;
// Validate the bytes, borrow a CSR view, and walk it — no rebuilt graph.
let snapshot = Snapshot::open(&bytes)?;
let graph = CsrSnapshotGraph::<u32, u32>::from_snapshot(&snapshot)?;
println!("graph: {} nodes, {} edges", graph.node_count(), graph.edge_count());
let order: Vec<u32> = breadth_first_search(&graph, CsrNodeId::new(0))?
.map(CsrNodeId::get)
.collect();
println!("bfs from node 0: {order:?}");
Ok(())
}The same breadth_first_search runs unchanged over an in-memory layout
(CsrNativeGraph::validate), a memory-mapped snapshot, or rows from a database,
because the algorithm binds to capability traits, not to a concrete container.
What you reach for, by task
| You want to | Reach for |
|---|---|
| Expose your own storage as a graph or hypergraph | the topology / graph / hyper traits |
| Borrow a CSR or bipartite-CSR layout over slices | oxgraph-csr, oxgraph-hyper-bcsr |
| Open a validated snapshot and traverse it without rebuilding | oxgraph-snapshot plus a layout |
Run BFS or PageRank at a no_std, alloc, or std tier | oxgraph-algo |
| Attach Arrow-backed named properties | oxgraph-property |
| Run an embedded database or a Postgres engine | oxgraph-db, oxgraph-postgres |
Every layer ships runnable examples under its crate's examples/ directory
(cargo run --example <name> -p <crate>).
Next
- Concepts — topology vs. meaning vs. storage
- The crate family — what each crate gives you
- Feature flags — features to layers
- Embedded database —
oxgraph-dband OxQL - Benchmarks — the 0.4.0 engine, end to end
Status
Pre-1.0 and still changing. The traits and crates are not stable yet. The snapshot byte format is an internal ABI candidate, not a stable interchange format — treat persisted snapshots as coupled to the crate version that wrote them. Licensed MIT.