manifold_graph/
lib.rs

1//! # manifold-graph
2//!
3//! Graph storage optimizations for the Manifold embedded database.
4//!
5//! This crate provides ergonomic, type-safe wrappers around Manifold's core primitives
6//! for storing and querying graph edges with bidirectional indexes.
7//!
8//! ## Features
9//!
10//! - **Automatic bidirectional indexes**: Efficient queries for both outgoing and incoming edges
11//! - **UUID-based vertices**: Fixed-width 16-byte vertex IDs with proper ordering
12//! - **Type-safe edge properties**: Fixed-width tuple `(bool, f32, u64, Option<u64>)` for `is_active`, `weight`, and temporal tracking
13//! - **Atomic updates**: Both forward and reverse indexes updated in same transaction
14//! - **Efficient traversal**: Range scans leverage tuple key ordering for fast queries
15//!
16//! ## Quick Start
17//!
18//! ```rust,no_run
19//! use manifold::column_family::ColumnFamilyDatabase;
20//! use manifold_graph::{GraphTable, GraphTableRead, Edge};
21//! use uuid::Uuid;
22//!
23//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
24//! let db = ColumnFamilyDatabase::open("my.db")?;
25//! let cf = db.column_family_or_create("social")?;
26//!
27//! let user1 = Uuid::new_v4();
28//! let user2 = Uuid::new_v4();
29//!
30//! // Write edges
31//! {
32//!     let write_txn = cf.begin_write()?;
33//!     let mut graph = GraphTable::open(&write_txn, "edges")?;
34//!     graph.add_edge(&user1, "follows", &user2, true, 1.0, None)?;
35//!     drop(graph);
36//!     write_txn.commit()?;
37//! }
38//!
39//! // Read with efficient traversal
40//! let read_txn = cf.begin_read()?;
41//! let graph = GraphTableRead::open(&read_txn, "edges")?;
42//!
43//! // Get all outgoing edges (range scan on forward table)
44//! for edge_result in graph.outgoing_edges(&user1)? {
45//!     let edge = edge_result?;
46//!     println!("{:?} -[{}]-> {:?}", edge.source, edge.edge_type, edge.target);
47//! }
48//!
49//! // Get all incoming edges (range scan on reverse table)
50//! for edge_result in graph.incoming_edges(&user2)? {
51//!     let edge = edge_result?;
52//!     println!("{:?} -[{}]-> {:?}", edge.source, edge.edge_type, edge.target);
53//! }
54//! # Ok(())
55//! # }
56//! ```
57//!
58//! ## Architecture
59//!
60//! This crate does **not** implement graph algorithms (BFS, DFS, `PageRank`, etc.).
61//! Instead, it focuses on efficient storage and provides integration traits for external
62//! graph libraries. The `EdgeSource` trait enables graph algorithm libraries to consume
63//! edges efficiently.
64//!
65//! ## Edge Properties
66//!
67//! Edges store fixed-width properties with temporal tracking:
68//! - `is_active: bool` - For active/passive edges, soft deletes, hidden edges
69//! - `weight: f32` - General-purpose edge weight or score
70//! - `created_at: u64` - Creation timestamp in nanoseconds since Unix epoch
71//! - `deleted_at: Option<u64>` - Deletion timestamp (None if not deleted)
72//!
73//! These properties are stored as a fixed-width tuple `(bool, f32, u64, Option<u64>)` for
74//! efficient serialization (21 bytes total).
75
76#![deny(missing_docs)]
77#![deny(clippy::all, clippy::pedantic)]
78#![allow(
79    clippy::module_name_repetitions,
80    clippy::must_use_candidate,
81    clippy::missing_errors_doc,
82    clippy::missing_panics_doc
83)]
84
85pub mod edge;
86pub mod graph;
87pub mod integration;
88
89pub use edge::Edge;
90pub use graph::{AllEdgesIter, GraphTable, GraphTableRead, IncomingEdgeIter, OutgoingEdgeIter};
91pub use integration::EdgeSource;