#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum DeleteStrategy {
CopyOnWrite,
MergeOnRead,
Adaptive {
purge_threshold_percent: u8,
},
}
impl DeleteStrategy {
#[must_use]
pub const fn default_adaptive() -> Self {
Self::Adaptive {
purge_threshold_percent: 5,
}
}
#[must_use]
pub const fn writes_bitmap(self) -> bool {
matches!(self, Self::MergeOnRead | Self::Adaptive { .. })
}
#[must_use]
const fn has_valid_threshold(self) -> bool {
match self {
Self::Adaptive {
purge_threshold_percent,
} => purge_threshold_percent <= 100,
Self::CopyOnWrite | Self::MergeOnRead => true,
}
}
}
impl Default for DeleteStrategy {
fn default() -> Self {
Self::default_adaptive()
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct DeleteStrategyPolicy(Vec<DeleteStrategy>);
impl core::ops::Deref for DeleteStrategyPolicy {
type Target = [DeleteStrategy];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DeleteStrategyPolicy {
#[must_use]
pub fn get(&self, level: usize) -> DeleteStrategy {
self.0
.get(level)
.copied()
.unwrap_or_else(|| self.0.last().copied().unwrap_or_default())
}
#[must_use]
pub fn all(strategy: DeleteStrategy) -> Self {
assert!(
strategy.has_valid_threshold(),
"adaptive purge threshold must be in 0..=100"
);
Self(vec![strategy])
}
#[must_use]
pub fn new(policy: impl Into<Vec<DeleteStrategy>>) -> Self {
let policy = policy.into();
assert!(
!policy.is_empty(),
"delete strategy policy may not be empty"
);
assert!(policy.len() <= 255, "delete strategy policy is too large");
assert!(
policy
.iter()
.copied()
.all(DeleteStrategy::has_valid_threshold),
"adaptive purge threshold must be in 0..=100"
);
Self(policy)
}
}
impl Default for DeleteStrategyPolicy {
fn default() -> Self {
Self::all(DeleteStrategy::default())
}
}
#[cfg(test)]
mod tests;