#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
pub use crate::table::filter::BloomConstructionPolicy;
#[derive(Copy, Debug, Clone, PartialEq)]
pub enum FilterPolicyEntry {
None,
Bloom(BloomConstructionPolicy),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FilterAdvisor {
budget_bytes: u64,
bits_per_key: Vec<u8>,
window_probes: u64,
}
impl FilterAdvisor {
const DEFAULT_BITS_PER_KEY: [u8; 6] = [6, 8, 10, 12, 14, 16];
const DEFAULT_WINDOW_PROBES: u64 = 1 << 20;
#[must_use]
pub fn new(budget_bytes: u64) -> Self {
Self {
budget_bytes,
bits_per_key: Self::DEFAULT_BITS_PER_KEY.to_vec(),
window_probes: Self::DEFAULT_WINDOW_PROBES,
}
}
#[must_use]
pub fn with_window_probes(mut self, probes: u64) -> Self {
assert!(probes > 0, "a probe window holds at least one probe");
self.window_probes = probes;
self
}
#[must_use]
pub fn window_probes(&self) -> u64 {
self.window_probes
}
#[must_use]
pub fn with_bits_per_key(mut self, bits_per_key: impl Into<Vec<u8>>) -> Self {
let mut bits_per_key = bits_per_key.into();
assert!(
!bits_per_key.is_empty(),
"a filter advisor needs at least one width"
);
assert!(
bits_per_key.iter().all(|bits| (1..=64).contains(bits)),
"filter widths must lie in 1..=64 bits per key",
);
bits_per_key.sort_unstable();
bits_per_key.dedup();
self.bits_per_key = bits_per_key;
self
}
#[must_use]
pub fn budget_bytes(&self) -> u64 {
self.budget_bytes
}
#[must_use]
pub fn bits_per_key(&self) -> &[u8] {
&self.bits_per_key
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct FilterPolicy(Vec<FilterPolicyEntry>);
impl core::ops::Deref for FilterPolicy {
type Target = [FilterPolicyEntry];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl FilterPolicy {
pub(crate) fn get(&self, level: usize) -> FilterPolicyEntry {
#[expect(clippy::expect_used, reason = "policy is expected not to be empty")]
self.0
.get(level)
.copied()
.unwrap_or_else(|| self.last().copied().expect("policy should not be empty"))
}
#[must_use]
pub fn disabled() -> Self {
Self::all(FilterPolicyEntry::None)
}
#[must_use]
pub fn all(c: FilterPolicyEntry) -> Self {
Self(vec![c])
}
#[must_use]
pub fn new(policy: impl Into<Vec<FilterPolicyEntry>>) -> Self {
let policy = policy.into();
assert!(!policy.is_empty(), "compression policy may not be empty");
assert!(policy.len() <= 255, "compression policy is too large");
Self(policy)
}
}