leveldb/database/
filter_policy.rs1use crate::binding::{
7 leveldb_filterpolicy_create, leveldb_filterpolicy_create_bloom, leveldb_filterpolicy_destroy,
8 leveldb_filterpolicy_t,
9};
10use libc::{c_char, c_uchar, c_void};
11use std::ffi::CString;
12use std::os::raw::c_int;
13use std::slice;
14
15pub trait LevelDBFilterPolicy {
17 fn raw_ptr(&self) -> *mut leveldb_filterpolicy_t;
19}
20
21pub struct BloomFilterPolicy {
23 ptr: *mut leveldb_filterpolicy_t,
24}
25
26impl BloomFilterPolicy {
27 pub fn new(bits_per_key: i32) -> BloomFilterPolicy {
29 let ptr = unsafe { leveldb_filterpolicy_create_bloom(bits_per_key) };
30 BloomFilterPolicy { ptr }
31 }
32}
33
34impl LevelDBFilterPolicy for BloomFilterPolicy {
35 fn raw_ptr(&self) -> *mut leveldb_filterpolicy_t {
37 self.ptr
38 }
39}
40
41impl Drop for BloomFilterPolicy {
42 fn drop(&mut self) {
43 unsafe {
44 leveldb_filterpolicy_destroy(self.ptr);
45 }
46 }
47}
48
49pub trait FilterPolicy {
51 fn create_filter(&self, keys: &[&[u8]]) -> Vec<u8>;
53
54 fn key_may_match(&self, key: &[u8], filter: &[u8]) -> bool;
56
57 fn name(&self) -> &'static str;
59}
60
61pub struct CustomFilterPolicy<T: FilterPolicy> {
63 ptr: *mut leveldb_filterpolicy_t,
64 policy: T,
65}
66
67impl<T: FilterPolicy> CustomFilterPolicy<T> {
68 pub fn new(policy: T) -> Self {
70 let boxed_policy = Box::new(policy);
71 let state = Box::into_raw(boxed_policy) as *mut c_void;
72
73 extern "C" fn destructor<T: FilterPolicy>(state: *mut c_void) {
74 unsafe {
75 let _ = Box::from_raw(state as *mut T);
76 }
77 }
78
79 extern "C" fn create_filter<T: FilterPolicy>(
80 state: *mut c_void,
81 key_array: *const *const c_char,
82 key_length_array: *const usize,
83 num_keys: c_int,
84 filter_length: *mut usize,
85 ) -> *mut c_char {
86 unsafe {
87 let policy = &*(state as *const T);
88 let keys: Vec<&[u8]> = (0..num_keys as usize)
89 .map(|i| {
90 let key_ptr = *key_array.add(i);
91 let key_len = *key_length_array.add(i);
92 slice::from_raw_parts(key_ptr as *const u8, key_len)
93 })
94 .collect();
95
96 let filter_data = policy.create_filter(&keys);
97 *filter_length = filter_data.len();
98
99 let mut boxed_filter = filter_data.into_boxed_slice();
100 let ptr = boxed_filter.as_mut_ptr() as *mut c_char;
101 let _ = Box::into_raw(boxed_filter);
102 ptr
103 }
104 }
105
106 extern "C" fn key_may_match<T: FilterPolicy>(
107 state: *mut c_void,
108 key: *const c_char,
109 key_length: usize,
110 filter: *const c_char,
111 filter_length: usize,
112 ) -> c_uchar {
113 unsafe {
114 let policy = &*(state as *const T);
115 let key_slice = slice::from_raw_parts(key as *const u8, key_length);
116 let filter_slice = slice::from_raw_parts(filter as *const u8, filter_length);
117
118 policy.key_may_match(key_slice, filter_slice) as c_uchar
119 }
120 }
121
122 extern "C" fn name<T: FilterPolicy>(state: *mut c_void) -> *const c_char {
123 unsafe {
124 let policy = &*(state as *const T);
125 let name_str = policy.name();
126 let cstring = CString::new(name_str).unwrap();
127 cstring.into_raw()
128 }
129 }
130
131 let ptr = unsafe {
132 leveldb_filterpolicy_create(
133 state,
134 destructor::<T>,
135 create_filter::<T>,
136 key_may_match::<T>,
137 name::<T>,
138 )
139 };
140
141 let policy = unsafe { *Box::from_raw(state as *mut T) };
142
143 CustomFilterPolicy { ptr, policy }
144 }
145
146 pub fn policy(&self) -> &T {
148 &self.policy
149 }
150}
151
152impl<T: FilterPolicy> LevelDBFilterPolicy for CustomFilterPolicy<T> {
153 fn raw_ptr(&self) -> *mut leveldb_filterpolicy_t {
155 self.ptr
156 }
157}
158
159impl<T: FilterPolicy> Drop for CustomFilterPolicy<T> {
160 fn drop(&mut self) {
161 unsafe {
162 leveldb_filterpolicy_destroy(self.ptr);
163 }
164 }
165}