Skip to main content

icydb_core/db/data/
store.rs

1//! Module: data::store
2//! Responsibility: stable BTreeMap-backed row persistence.
3//! Does not own: key/row validation policy beyond type boundaries.
4//! Boundary: commit/executor call into this layer after prevalidation.
5
6use crate::db::data::{CanonicalRow, DataKey, RawDataKey, RawRow};
7use canic_cdk::structures::{BTreeMap, DefaultMemoryImpl, memory::VirtualMemory};
8use derive_more::Deref;
9
10///
11/// DataStore
12///
13/// Thin persistence wrapper over one stable BTreeMap.
14///
15/// Invariant: callers provide already-validated `RawDataKey` and canonical row bytes.
16/// This type intentionally does not enforce commit-phase ordering.
17///
18
19#[derive(Deref)]
20pub struct DataStore(BTreeMap<RawDataKey, RawRow, VirtualMemory<DefaultMemoryImpl>>);
21
22impl DataStore {
23    /// Initialize a data store with the provided backing memory.
24    #[must_use]
25    pub fn init(memory: VirtualMemory<DefaultMemoryImpl>) -> Self {
26        Self(BTreeMap::init(memory))
27    }
28
29    /// Insert or replace one row by raw key.
30    pub(in crate::db) fn insert(&mut self, key: RawDataKey, row: CanonicalRow) -> Option<RawRow> {
31        self.0.insert(key, row.into_raw_row())
32    }
33
34    /// Insert one raw row directly for corruption-focused test setup only.
35    #[cfg(test)]
36    pub(crate) fn insert_raw_for_test(&mut self, key: RawDataKey, row: RawRow) -> Option<RawRow> {
37        self.0.insert(key, row)
38    }
39
40    /// Remove one row by raw key.
41    pub fn remove(&mut self, key: &RawDataKey) -> Option<RawRow> {
42        self.0.remove(key)
43    }
44
45    /// Load one row by raw key.
46    pub fn get(&self, key: &RawDataKey) -> Option<RawRow> {
47        self.0.get(key)
48    }
49
50    /// Clear all stored rows from the data store.
51    pub fn clear(&mut self) {
52        self.0.clear();
53    }
54
55    /// Sum of bytes used by all stored rows.
56    pub fn memory_bytes(&self) -> u64 {
57        // Report map footprint as key bytes + row bytes per entry.
58        self.iter()
59            .map(|entry| DataKey::STORED_SIZE_BYTES + entry.value().len() as u64)
60            .sum()
61    }
62}