Skip to main content

core_storage/v8/
layout.rs

1//! rkyv-archived layout types for the V8 snapshot format.
2//!
3//! All primitive fields archive as little-endian via rend (rkyv's LE-primitive
4//! crate), which is the default for rkyv 0.8 on all targets.  The format is
5//! therefore architecture-portable and LE-pinned.
6
7use rkyv::{Archive, Deserialize, Serialize};
8
9// ---------------------------------------------------------------------------
10// CSR topology
11// ---------------------------------------------------------------------------
12
13/// One vertex's sorted adjacency list within an edge type and direction.
14#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
15pub struct CsrRow {
16    pub vertex: u32,
17    /// Sorted, unique neighbor ids.
18    pub neighbors: Vec<u32>,
19}
20
21/// All adjacency rows for one direction (out or in) of one edge type.
22/// Rows are sorted by `vertex` ascending so lookups can binary-search.
23#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
24pub struct CsrAdjMap {
25    pub rows: Vec<CsrRow>,
26}
27
28/// Full typed adjacency (out + in) for a single edge type.
29/// `etype` is the intern id of the edge-type label.
30#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
31pub struct CsrEtype {
32    pub etype: u32,
33    pub out_adj: CsrAdjMap,
34    pub in_adj: CsrAdjMap,
35}
36
37/// The full archived CSR topology: all edge types, sorted ascending by etype.
38#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
39pub struct CsrData {
40    /// Sorted by `etype` so lookups can binary-search.
41    pub etypes: Vec<CsrEtype>,
42    pub edge_count: u64,
43}
44
45// ---------------------------------------------------------------------------
46// Columns
47// ---------------------------------------------------------------------------
48
49/// Typed column payload.  Mixed/list columns fall back to a bincode blob.
50/// Tag 5 (`Vector`) stores raw f64 runs for all-float list properties,
51/// enabling zero-copy `&[f64]` access without boxing through `Value`.
52#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
53pub enum ColumnData {
54    /// Dense i64 column.  `present` is the presence bitmap as u64 words (LE).
55    Int { data: Vec<i64>, present: Vec<u64> },
56    /// Dense f64 column.
57    Float { data: Vec<f64>, present: Vec<u64> },
58    /// Dense bool column stored as u8 (0/1).
59    Bool { data: Vec<u8>, present: Vec<u64> },
60    /// String column: ids index into `strings`; `present` is the presence bitmap.
61    Str {
62        ids: Vec<u32>,
63        present: Vec<u64>,
64        strings: Vec<String>,
65    },
66    /// Mixed/list column: bincode-encoded `HashMap<u32, Value>`.
67    Mixed(Vec<u8>),
68    /// Raw f64 vector column (B2).  `dim` floats per node, stored contiguously.
69    ///
70    /// Layout: `data[id * dim .. (id + 1) * dim]` = the vector for node `id`.
71    /// `present[word]` bit `bit` is set iff `id = word*64 + bit` has a value.
72    /// Zero-copy `&[f64]` access via `ColumnsView::vector(id, field)`.
73    ///
74    /// **Overlay/archive asymmetry:** vectors written after the last snapshot
75    /// live in the owned overlay as `Value::List([Value::Float, ...])` and are
76    /// not accessible through `vector()`.  Callers must fall back to
77    /// `ColumnsView::get()` which returns `ValueRef::Owned(Value::List(...))`.
78    Vector {
79        dim: u32,
80        data: Vec<f64>,
81        present: Vec<u64>,
82    },
83}
84
85/// One field entry: name + typed column.
86#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
87pub struct FieldEntry {
88    pub name: String,
89    pub col: ColumnData,
90}
91
92/// The full archived column store.  Fields are sorted by name for determinism.
93#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
94pub struct ColumnsData {
95    pub fields: Vec<FieldEntry>,
96}
97
98// ---------------------------------------------------------------------------
99// IdMap
100// ---------------------------------------------------------------------------
101
102/// Archived id map: dense-allocated key → id table plus tombstones.
103#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
104pub struct IdMapData {
105    /// Keys in dense id order (to_key[id] = key).
106    pub to_key: Vec<String>,
107    /// Permanently retired ids, sorted ascending.
108    pub tombstones: Vec<u32>,
109}
110
111// ---------------------------------------------------------------------------
112// Interner
113// ---------------------------------------------------------------------------
114
115/// Archived symbol interner: symbol ids map to their string names.
116#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
117pub struct InternerData {
118    /// to_str[sym] = name.
119    pub to_str: Vec<String>,
120}
121
122// ---------------------------------------------------------------------------
123// Shared string table (section 12)
124// ---------------------------------------------------------------------------
125
126/// The one string table a V9 snapshot carries for *every* `ColumnData::Str` in
127/// the columns section: `ids[node]` indexes into `strings`.
128///
129/// Up to V8 each string column carried its own `strings: Vec<String>` copy of
130/// the whole intern table, so a snapshot with K string columns paid for K
131/// copies.  V9 writes the table once here and leaves every column's own
132/// `strings` empty.  The resolution rule, in `seam.rs`'s `Str` arm and in
133/// `encode::archived_to_columnstore`, is one sentence: if the shared table is
134/// present it is the table, otherwise the column's own `strings` is — which is
135/// what keeps a pre-V9 snapshot, whose directory has no section 12, readable.
136#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
137pub struct StringTableData {
138    pub strings: Vec<String>,
139}
140
141// ---------------------------------------------------------------------------
142// Edge props (section 5)
143// ---------------------------------------------------------------------------
144
145/// One edge's property blob: (etype, src, dst) + bincode(BTreeMap<String, Value>).
146/// Entries in `EdgePropsData` are sorted by (etype, src, dst) for binary search.
147#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
148pub struct EdgePropEntry {
149    pub etype: u32,
150    pub src: u32,
151    pub dst: u32,
152    /// bincode-encoded `BTreeMap<String, Value>`.
153    pub props_blob: Vec<u8>,
154}
155
156/// All archived edge properties, sorted by (etype, src, dst).
157#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
158pub struct EdgePropsData {
159    pub entries: Vec<EdgePropEntry>,
160}
161
162// ---------------------------------------------------------------------------
163// HNSW (section 6)
164// ---------------------------------------------------------------------------
165
166/// Blob-per-rule HNSW storage.  Each entry holds one rule's persisted graph for
167/// the src and dst sides.  Stored as **opaque** bytes so core-storage remains
168/// independent of core-rules; zero-copy blob slicing avoids loading unused
169/// rules.
170///
171/// The blobs are self-describing: since 0.6.6 each carries its own magic
172/// (`MHNS`) and version, and core-rules' decoder also accepts a 0.6.5 store's
173/// bare bincoded index as version 1.  Because this section never parses them,
174/// the blob format evolves without a snapshot format bump — and a reader that
175/// does not recognise a blob ignores it and falls back to a full scan.
176#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
177pub struct HnswRuleEntry {
178    pub name: String,
179    /// Opaque versioned HNSW blob for the source side.
180    pub src_blob: Vec<u8>,
181    /// Opaque versioned HNSW blob for the destination side.
182    pub dst_blob: Vec<u8>,
183}
184
185/// All per-rule HNSW graph blobs, sorted by rule name.
186#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
187pub struct HnswSectionData {
188    pub rules: Vec<HnswRuleEntry>,
189}
190
191// ---------------------------------------------------------------------------
192// Provenance (section 7)
193// ---------------------------------------------------------------------------
194
195/// A single provenance triple (etype, src, dst) serialized as three u32s.
196#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
197pub struct Triple {
198    pub etype: u32,
199    pub src: u32,
200    pub dst: u32,
201}
202
203/// Provenance triples for one rule, sorted by (etype, src, dst) ascending.
204/// Binary search replaces BTreeSet iteration on the read path.
205#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
206pub struct ProvenanceEntry {
207    pub rule: String,
208    pub triples: Vec<Triple>,
209}
210
211/// All per-rule provenance entries, sorted by rule name.
212#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
213pub struct ProvenanceSectionData {
214    pub entries: Vec<ProvenanceEntry>,
215}
216
217// ---------------------------------------------------------------------------
218// Rules meta (section 8)
219// ---------------------------------------------------------------------------
220
221/// Tripped (budget-trip) flag for one rule.
222#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
223pub struct RuleTripEntry {
224    pub rule: String,
225    pub tripped: bool,
226}
227
228/// Fire counter for one rule.
229#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
230pub struct RuleFireEntry {
231    pub rule: String,
232    pub fires: u64,
233}
234
235/// All rule definitions, trip flags, and fire counters.
236/// Entries in each sub-list are sorted by rule name.
237#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
238pub struct RulesMetaData {
239    /// One bincoded `RuleDef` per rule, in rule-name order.
240    pub rule_defs: Vec<Vec<u8>>,
241    pub tripped: Vec<RuleTripEntry>,
242    pub fires: Vec<RuleFireEntry>,
243}
244
245// ---------------------------------------------------------------------------
246// Views (section 9)
247// ---------------------------------------------------------------------------
248
249/// All materialized view definitions (one bincoded `ViewDef` per entry).
250#[derive(Archive, Serialize, Deserialize, Clone, Debug)]
251pub struct ViewsSectionData {
252    pub view_defs: Vec<Vec<u8>>,
253}
254
255// ---------------------------------------------------------------------------
256// Type aliases matching the binding interface
257// ---------------------------------------------------------------------------
258
259pub type ArchivedCsr = ArchivedCsrData;
260pub type ArchivedColumns = ArchivedColumnsData;
261pub type ArchivedIdMap = ArchivedIdMapData;
262pub type ArchivedInterner = ArchivedInternerData;
263pub type ArchivedEdgeProps = ArchivedEdgePropsData;
264pub type ArchivedHnsw = ArchivedHnswSectionData;
265pub type ArchivedProvenance = ArchivedProvenanceSectionData;
266pub type ArchivedRulesMeta = ArchivedRulesMetaData;
267pub type ArchivedViews = ArchivedViewsSectionData;
268pub type ArchivedStringTable = ArchivedStringTableData;