use crocksdb_ffi::{self, DBCompactionFilter};
use libc::{c_char, c_int, c_void, size_t};
use std::ffi::CString;
use std::slice;
pub trait CompactionFilter {
fn filter(&mut self, level: usize, key: &[u8], value: &[u8]) -> bool;
}
#[repr(C)]
pub struct CompactionFilterProxy {
name: CString,
filter: Box<CompactionFilter>,
}
extern "C" fn name(filter: *mut c_void) -> *const c_char {
unsafe { (*(filter as *mut CompactionFilterProxy)).name.as_ptr() }
}
extern "C" fn destructor(filter: *mut c_void) {
unsafe {
Box::from_raw(filter as *mut CompactionFilterProxy);
}
}
extern "C" fn filter(
filter: *mut c_void,
level: c_int,
key: *const u8,
key_len: size_t,
value: *const u8,
value_len: size_t,
_: *mut *mut u8,
_: *mut size_t,
value_changed: *mut bool,
) -> bool {
unsafe {
let filter = &mut *(filter as *mut CompactionFilterProxy);
let key = slice::from_raw_parts(key, key_len);
let value = slice::from_raw_parts(value, value_len);
*value_changed = false;
filter.filter.filter(level as usize, key, value)
}
}
pub struct CompactionFilterHandle {
pub inner: *mut DBCompactionFilter,
}
impl Drop for CompactionFilterHandle {
fn drop(&mut self) {
unsafe {
crocksdb_ffi::crocksdb_compactionfilter_destroy(self.inner);
}
}
}
pub unsafe fn new_compaction_filter(
c_name: CString,
ignore_snapshots: bool,
f: Box<CompactionFilter>,
) -> Result<CompactionFilterHandle, String> {
let proxy = Box::into_raw(Box::new(CompactionFilterProxy {
name: c_name,
filter: f,
}));
let filter = crocksdb_ffi::crocksdb_compactionfilter_create(
proxy as *mut c_void,
destructor,
filter,
name,
);
crocksdb_ffi::crocksdb_compactionfilter_set_ignore_snapshots(filter, ignore_snapshots);
Ok(CompactionFilterHandle { inner: filter })
}