mongreldb_core/page.rs
1use crate::epoch::Epoch;
2use serde::{Deserialize, Serialize};
3
4/// On-disk page encoding. Mirrors the strategies used by modern columnar
5/// formats, plus `BinaryQuantized` for AI embedding columns.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7#[repr(u8)]
8pub enum Encoding {
9 Plain = 0,
10 Dictionary = 1,
11 Delta = 2,
12 ByteStreamSplit = 3,
13 RunLength = 4,
14 /// 1 bit per dimension; similarity via SIMD popcount(XOR).
15 BinaryQuantized = 5,
16 /// Plain-encode then zstd-compress (default for fixed-width and high-card columns).
17 Zstd = 6,
18}
19
20/// Per-page statistics enabling file/page-level pruning (analogous to Parquet's
21/// page index, but always present and tighter). Serialized in the run's column
22/// directory.
23#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct PageStat {
25 pub first_row_id: u64,
26 pub last_row_id: u64,
27 pub null_count: u64,
28 pub row_count: u32,
29 pub min: Option<Vec<u8>>,
30 pub max: Option<Vec<u8>>,
31 /// Absolute offset of the (possibly encrypted + compressed) page payload.
32 pub offset: u64,
33 pub compressed_len: u32,
34 pub uncompressed_len: u32,
35}
36
37/// A cached, decrypted, decompressed page tagged with the epoch at which it was
38/// committed. The tag is what makes the cache self-invalidating under MVCC.
39#[derive(Debug, Clone)]
40pub struct CachedPage {
41 pub committed_epoch: Epoch,
42 pub content_hash: [u8; 32],
43 pub bytes: bytes::Bytes,
44}
45
46impl CachedPage {
47 /// Cache key for content-addressed, MVCC-safe storage.
48 pub fn cache_key(&self) -> ([u8; 32], Epoch) {
49 (self.content_hash, self.committed_epoch)
50 }
51}