oxgraph_postgres/
builder.rs1use alloc::{boxed::Box, vec::Vec};
4use core::cell::{Cell, RefCell};
5
6use oxgraph_snapshot::Snapshot;
7use yoke::Yoke;
8
9use crate::{
10 artifact::read_metadata,
11 config::Config,
12 engine::{Engine, EngineCart, EngineState},
13 error::{BuildError, PostgresGraphError},
14 overlay::OverlayState,
15 topology::{GraphTopology, UniqueAdjacency},
16 traverse::TraverseScratch,
17};
18
19#[derive(Clone, Debug, Default)]
21pub struct EngineBuilder {
22 backing: Option<Vec<u8>>,
24 overlay: OverlayState,
26 config: Config,
28}
29
30impl EngineBuilder {
31 #[must_use]
33 pub fn new() -> Self {
34 Self {
35 backing: None,
36 overlay: OverlayState::default(),
37 config: Config::default(),
38 }
39 }
40
41 #[must_use]
43 pub fn snapshot_owned(mut self, bytes: Vec<u8>) -> Self {
44 self.backing = Some(bytes);
45 self
46 }
47
48 #[must_use]
50 pub fn overlay(mut self, overlay: OverlayState) -> Self {
51 self.overlay = overlay;
52 self
53 }
54
55 #[must_use]
57 #[expect(
58 clippy::missing_const_for_fn,
59 reason = "Config is not a const-constructible snapshot"
60 )]
61 pub fn config(mut self, config: Config) -> Self {
62 self.config = config;
63 self
64 }
65
66 pub fn build(self) -> Result<Engine, PostgresGraphError> {
76 let backing = self
77 .backing
78 .ok_or(PostgresGraphError::Build(BuildError::MissingSnapshotBytes))?;
79 self.config.validate()?;
80 let snapshot = Snapshot::open(&backing)?;
81 let metadata = read_metadata(&snapshot)?;
82 let cart = Box::new(EngineCart { backing, metadata });
83 let inner = Yoke::try_attach_to_cart(cart, |cart: &EngineCart| {
84 let snapshot = Snapshot::open(cart.backing.as_slice())?;
85 let topology = GraphTopology::open(&snapshot)?;
86 Ok::<EngineState<'_>, PostgresGraphError>(EngineState { topology })
87 })?;
88 let mut overlay = self.overlay;
89 if !overlay.added_edges.is_empty() {
90 overlay.rebuild_indexes();
91 }
92 let node_count = inner.backing_cart().metadata.node_count.get() as usize;
93 let mut traverse_scratch = TraverseScratch::default();
94 traverse_scratch.resize_for_nodes(node_count);
95 Ok(Engine::from_parts(
96 inner,
97 overlay,
98 self.config,
99 traverse_scratch,
100 RefCell::new(UniqueAdjacency::default()),
101 Cell::new(false),
102 ))
103 }
104}