use crate::db::index::{IndexEntryValue, key::RawIndexStoreKey};
use candid::CandidType;
use ic_memory::stable_structures::{BTreeMap, DefaultMemoryImpl, memory_manager::VirtualMemory};
use serde::Deserialize;
#[derive(CandidType, Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq)]
pub enum IndexState {
Building,
#[default]
Ready,
Dropping,
}
impl IndexState {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::Building => "building",
Self::Ready => "ready",
Self::Dropping => "dropping",
}
}
}
pub struct IndexStore {
pub(super) map: BTreeMap<RawIndexStoreKey, IndexEntryValue, VirtualMemory<DefaultMemoryImpl>>,
generation: u64,
state: IndexState,
}
impl IndexStore {
#[must_use]
pub fn init(memory: VirtualMemory<DefaultMemoryImpl>) -> Self {
Self {
map: BTreeMap::init(memory),
generation: 0,
state: IndexState::Ready,
}
}
#[expect(clippy::redundant_closure_for_method_calls)]
pub(crate) fn entries(&self) -> Vec<(RawIndexStoreKey, IndexEntryValue)> {
self.map.iter().map(|entry| entry.into_pair()).collect()
}
pub(in crate::db) fn get(&self, key: &RawIndexStoreKey) -> Option<IndexEntryValue> {
self.map.get(key)
}
pub fn len(&self) -> u64 {
self.map.len()
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
#[must_use]
pub(in crate::db) const fn generation(&self) -> u64 {
self.generation
}
#[must_use]
pub(in crate::db) const fn state(&self) -> IndexState {
self.state
}
pub(in crate::db) const fn mark_building(&mut self) {
self.state = IndexState::Building;
}
pub(in crate::db) const fn mark_ready(&mut self) {
self.state = IndexState::Ready;
}
pub(in crate::db) const fn mark_dropping(&mut self) {
self.state = IndexState::Dropping;
}
pub(crate) fn insert(
&mut self,
key: RawIndexStoreKey,
entry: IndexEntryValue,
) -> Option<IndexEntryValue> {
let previous = self.map.insert(key, entry);
self.bump_generation();
previous
}
pub(crate) fn remove(&mut self, key: &RawIndexStoreKey) -> Option<IndexEntryValue> {
let previous = self.map.remove(key);
self.bump_generation();
previous
}
pub fn clear(&mut self) {
self.map.clear_new();
self.bump_generation();
}
pub fn memory_bytes(&self) -> u64 {
self.map
.iter()
.map(|entry| entry.key().as_bytes().len() as u64 + entry.value().len() as u64)
.sum()
}
const fn bump_generation(&mut self) {
self.generation = self.generation.saturating_add(1);
}
}