use crate::keyspace::config::{DecodeConfig, EncodeConfig};
use byteorder::{ReadBytesExt, WriteBytesExt};
impl EncodeConfig for crate::config::FilterPolicy {
fn encode(&self) -> crate::Slice {
let mut v = vec![];
#[expect(clippy::cast_possible_truncation)]
#[expect(clippy::expect_used)]
v.write_u8(self.len() as u8)
.expect("cannot fail writing into a vec");
for item in self.iter() {
match item {
crate::config::FilterPolicyEntry::None => {
v.write_u8(0).expect("cannot fail writing into a vec");
}
crate::config::FilterPolicyEntry::Bloom(bloom) => {
v.write_u8(1).expect("cannot fail writing into a vec");
match bloom {
crate::config::BloomConstructionPolicy::BitsPerKey(bits) => {
v.write_u8(0).expect("cannot fail writing into a vec");
v.write_f32::<byteorder::LittleEndian>(*bits)
.expect("cannot fail writing into a vec");
}
crate::config::BloomConstructionPolicy::FalsePositiveRate(fpr) => {
v.write_u8(1).expect("cannot fail writing into a vec");
v.write_f32::<byteorder::LittleEndian>(*fpr)
.expect("cannot fail writing into a vec");
}
}
}
}
}
v.into()
}
}
impl DecodeConfig for crate::config::FilterPolicy {
fn decode(mut bytes: &[u8]) -> crate::Result<Self> {
let len = bytes.read_u8()?;
let mut v = vec![];
for _ in 0..len {
let tag = bytes.read_u8()?;
match tag {
0 => {
v.push(crate::config::FilterPolicyEntry::None);
}
1 => {
let policy_type = bytes.read_u8()?;
let policy = match policy_type {
0 => {
let bits = bytes.read_f32::<byteorder::LittleEndian>()?;
crate::config::FilterPolicyEntry::Bloom(
crate::config::BloomConstructionPolicy::BitsPerKey(bits),
)
}
1 => {
let value = bytes.read_f32::<byteorder::LittleEndian>()?;
crate::config::FilterPolicyEntry::Bloom(
crate::config::BloomConstructionPolicy::FalsePositiveRate(value),
)
}
_ => {
panic!("unknown bloom filter policy type: {policy_type}");
}
};
v.push(policy);
}
_ => {
panic!("unknown filter policy tag: {tag}");
}
}
}
Ok(Self::new(v))
}
}
#[cfg(test)]
mod tests {
use super::*;
use test_log::test;
#[test]
fn roundtrip_filter_policy() -> crate::Result<()> {
let policy = crate::config::FilterPolicy::new([
crate::config::FilterPolicyEntry::Bloom(
crate::config::BloomConstructionPolicy::BitsPerKey(10.0),
),
crate::config::FilterPolicyEntry::Bloom(
crate::config::BloomConstructionPolicy::FalsePositiveRate(0.01),
),
crate::config::FilterPolicyEntry::None,
]);
let encoded = policy.encode();
let decoded = crate::config::FilterPolicy::decode(&encoded)?;
assert_eq!(policy, decoded);
Ok(())
}
}