use crate::index_ewah::Ewah;
use crate::index_stat::be32;
const VERSION_TEXT_TOKEN: u32 = 2;
const VERSION_TIMESTAMP: u32 = 1;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Fsmonitor {
pub token: Vec<u8>,
pub dirty: Vec<usize>,
}
pub fn read_fsmonitor(data: &[u8], entries: usize) -> Option<Fsmonitor> {
let version: u32 = be32(data, 0)?;
let (token, after): (Vec<u8>, usize) = if version == VERSION_TIMESTAMP {
let stamp: u64 = u64::from_be_bytes(data.get(4..12)?.try_into().ok()?);
(stamp.to_string().into_bytes(), 12)
} else if version == VERSION_TEXT_TOKEN {
let nul: usize = data.get(4..)?.iter().position(|byte| { return *byte == 0; })?;
(data[4..4 + nul].to_vec(), 4 + nul + 1)
} else {
return None;
};
let size: usize = be32(data, after)? as usize;
let bitmap_bytes: &[u8] = data.get(after + 4..after + 4 + size)?;
let (bitmap, used) = Ewah::read(bitmap_bytes, entries)?;
if used != size || after + 4 + size != data.len() {
return None;
}
return Some(Fsmonitor { token, dirty: bitmap.bits() });
}
pub fn write_fsmonitor(token: &[u8], dirty: &[usize]) -> Vec<u8> {
let mut out: Vec<u8> = Vec::new();
out.extend_from_slice(&VERSION_TEXT_TOKEN.to_be_bytes());
out.extend_from_slice(token);
out.push(0);
let mut bitmap: Vec<u8> = Vec::new();
Ewah::from_bits(dirty).serialize(&mut bitmap);
out.extend_from_slice(&(bitmap.len() as u32).to_be_bytes());
out.extend_from_slice(bitmap.as_slice());
return out;
}
#[cfg(test)]
#[path = "index_fsmonitor_tests.rs"]
mod tests;