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}