icydb_core/db/data/
store.rs1use crate::db::data::{CanonicalRow, DataKey, RawDataKey, RawRow};
7use canic_cdk::structures::{BTreeMap, DefaultMemoryImpl, btreemap::Iter, memory::VirtualMemory};
8#[cfg(feature = "diagnostics")]
9use std::cell::Cell;
10use std::ops::RangeBounds;
11
12#[cfg(feature = "diagnostics")]
13thread_local! {
14 static DATA_STORE_GET_CALL_COUNT: Cell<u64> = const { Cell::new(0) };
15}
16
17#[cfg(feature = "diagnostics")]
18fn record_data_store_get_call() {
19 DATA_STORE_GET_CALL_COUNT.with(|count| {
20 count.set(count.get().saturating_add(1));
21 });
22}
23
24pub struct DataStore {
34 map: BTreeMap<RawDataKey, RawRow, VirtualMemory<DefaultMemoryImpl>>,
35}
36
37impl DataStore {
38 #[must_use]
40 pub fn init(memory: VirtualMemory<DefaultMemoryImpl>) -> Self {
41 Self {
42 map: BTreeMap::init(memory),
43 }
44 }
45
46 pub(in crate::db) fn insert(&mut self, key: RawDataKey, row: CanonicalRow) -> Option<RawRow> {
48 self.map.insert(key, row.into_raw_row())
49 }
50
51 #[cfg(test)]
53 pub(crate) fn insert_raw_for_test(&mut self, key: RawDataKey, row: RawRow) -> Option<RawRow> {
54 self.map.insert(key, row)
55 }
56
57 pub fn remove(&mut self, key: &RawDataKey) -> Option<RawRow> {
59 self.map.remove(key)
60 }
61
62 pub fn get(&self, key: &RawDataKey) -> Option<RawRow> {
64 #[cfg(feature = "diagnostics")]
65 record_data_store_get_call();
66
67 self.map.get(key)
68 }
69
70 #[must_use]
72 pub fn contains(&self, key: &RawDataKey) -> bool {
73 self.map.contains_key(key)
74 }
75
76 pub fn clear(&mut self) {
78 self.map.clear();
79 }
80
81 #[must_use]
83 pub fn len(&self) -> u64 {
84 self.map.len()
85 }
86
87 #[must_use]
89 pub fn is_empty(&self) -> bool {
90 self.map.is_empty()
91 }
92
93 pub(in crate::db) fn entries(
95 &self,
96 ) -> Iter<'_, RawDataKey, RawRow, VirtualMemory<DefaultMemoryImpl>> {
97 self.map.iter()
98 }
99
100 pub(in crate::db) fn range(
102 &self,
103 key_range: impl RangeBounds<RawDataKey>,
104 ) -> Iter<'_, RawDataKey, RawRow, VirtualMemory<DefaultMemoryImpl>> {
105 self.map.range(key_range)
106 }
107
108 pub fn memory_bytes(&self) -> u64 {
110 self.entries()
112 .map(|entry| DataKey::STORED_SIZE_BYTES + entry.value().len() as u64)
113 .sum()
114 }
115
116 #[cfg(feature = "diagnostics")]
118 pub(in crate::db) fn current_get_call_count() -> u64 {
119 DATA_STORE_GET_CALL_COUNT.with(Cell::get)
120 }
121}