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(in crate::db) fn insert_raw_for_test(
54 &mut self,
55 key: RawDataKey,
56 row: RawRow,
57 ) -> Option<RawRow> {
58 self.map.insert(key, row)
59 }
60
61 pub(in crate::db) fn remove(&mut self, key: &RawDataKey) -> Option<RawRow> {
63 self.map.remove(key)
64 }
65
66 pub(in crate::db) fn get(&self, key: &RawDataKey) -> Option<RawRow> {
68 #[cfg(feature = "diagnostics")]
69 record_data_store_get_call();
70
71 self.map.get(key)
72 }
73
74 #[must_use]
76 pub(in crate::db) fn contains(&self, key: &RawDataKey) -> bool {
77 self.map.contains_key(key)
78 }
79
80 #[cfg(test)]
82 pub(in crate::db) fn clear(&mut self) {
83 self.map.clear();
84 }
85
86 #[must_use]
88 pub(in crate::db) fn len(&self) -> u64 {
89 self.map.len()
90 }
91
92 #[must_use]
94 #[cfg(test)]
95 pub(in crate::db) fn is_empty(&self) -> bool {
96 self.map.is_empty()
97 }
98
99 pub(in crate::db) fn entries(
101 &self,
102 ) -> Iter<'_, RawDataKey, RawRow, VirtualMemory<DefaultMemoryImpl>> {
103 self.map.iter()
104 }
105
106 pub(in crate::db) fn range(
108 &self,
109 key_range: impl RangeBounds<RawDataKey>,
110 ) -> Iter<'_, RawDataKey, RawRow, VirtualMemory<DefaultMemoryImpl>> {
111 self.map.range(key_range)
112 }
113
114 pub(in crate::db) fn memory_bytes(&self) -> u64 {
116 self.entries()
118 .map(|entry| DataKey::STORED_SIZE_BYTES + entry.value().len() as u64)
119 .sum()
120 }
121
122 #[cfg(feature = "diagnostics")]
124 pub(in crate::db) fn current_get_call_count() -> u64 {
125 DATA_STORE_GET_CALL_COUNT.with(Cell::get)
126 }
127}