Skip to main content

icydb_core/db/data/
store.rs

1use crate::db::data::{DataKey, RawDataKey, RawRow};
2use canic_cdk::structures::{BTreeMap, DefaultMemoryImpl, memory::VirtualMemory};
3use derive_more::Deref;
4
5///
6/// DataStore
7///
8/// Architectural Notes:
9///
10/// - DataStore is a thin persistence wrapper over a stable BTreeMap.
11/// - All key and row validation occurs *before* insertion:
12///     - RawDataKey is fixed-size and validated at decode.
13///     - RawRow is size-bounded at construction.
14/// - This layer does NOT enforce transactional or commit-phase discipline.
15///   Higher layers (commit/executor) are responsible for write coordination.
16/// - Mutation methods (insert/remove/clear) are intentionally explicit to
17///   allow future interception (metrics, invariants, atomic guards).
18/// - Read surface is exposed via Deref for ergonomic iteration, but this
19///   means DataStore is not a strict policy layer.
20///
21
22#[derive(Deref)]
23pub struct DataStore(BTreeMap<RawDataKey, RawRow, VirtualMemory<DefaultMemoryImpl>>);
24
25impl DataStore {
26    #[must_use]
27    /// Initialize a data store with the provided backing memory.
28    pub fn init(memory: VirtualMemory<DefaultMemoryImpl>) -> Self {
29        Self(BTreeMap::init(memory))
30    }
31
32    pub fn insert(&mut self, key: RawDataKey, row: RawRow) -> Option<RawRow> {
33        self.0.insert(key, row)
34    }
35
36    pub fn remove(&mut self, key: &RawDataKey) -> Option<RawRow> {
37        self.0.remove(key)
38    }
39
40    pub fn get(&self, key: &RawDataKey) -> Option<RawRow> {
41        self.0.get(key)
42    }
43
44    /// Clear all stored rows from the data store.
45    pub fn clear(&mut self) {
46        self.0.clear();
47    }
48
49    /// Sum of bytes used by all stored rows.
50    pub fn memory_bytes(&self) -> u64 {
51        self.iter()
52            .map(|entry| DataKey::STORED_SIZE_BYTES + entry.value().len() as u64)
53            .sum()
54    }
55}