#[cfg(feature = "encryption")]
use std::path::Path;
use crate::codec::Codec;
use crate::error::{DbError, DbResult};
pub(crate) const POISON: u64 = 0xDEAD_BEEF_DEAD_BEEF;
#[derive(Clone, Default)]
pub(crate) struct PoisonCodec;
impl Codec<u64> for PoisonCodec {
fn encode_to(&self, value: &u64, buf: &mut Vec<u8>) -> DbResult<()> {
buf.clear();
buf.extend_from_slice(&value.to_le_bytes());
Ok(())
}
fn decode_from(&self, bytes: &[u8]) -> DbResult<u64> {
let arr: [u8; 8] = bytes
.try_into()
.map_err(|_| DbError::CorruptedEntry { offset: 0 })?;
let v = u64::from_le_bytes(arr);
if v == POISON {
return Err(DbError::CorruptedEntry { offset: 0 });
}
Ok(v)
}
fn size(&self, _value: &u64) -> usize {
8
}
}
#[cfg(feature = "encryption")]
pub(crate) fn big_value(fill: u8) -> Vec<u8> {
vec![fill; 16 * 1024]
}
#[cfg(feature = "encryption")]
pub(crate) fn corrupt_tags(shard_dir: &Path) {
let mut found = false;
for entry in std::fs::read_dir(shard_dir).expect("read shard dir") {
let path = entry.expect("dir entry").path();
if path.extension().and_then(|e| e.to_str()) == Some("tags") {
let mut bytes = std::fs::read(&path).expect("read tags file");
if bytes.is_empty() {
continue;
}
for b in bytes.iter_mut() {
*b ^= 0xFF;
}
std::fs::write(&path, &bytes).expect("write tags file");
found = true;
}
}
assert!(found, "no non-empty .tags file found in {shard_dir:?}");
}