rust_rocksdb/
merge_operator.rs1use libc::{self, c_char, c_int, c_void, size_t};
63use std::ffi::CString;
64use std::mem;
65use std::ptr;
66use std::slice;
67
68pub trait MergeFn:
69 Fn(&[u8], Option<&[u8]>, &MergeOperands) -> Option<Vec<u8>> + Send + Sync + 'static
70{
71}
72impl<F> MergeFn for F where
73 F: Fn(&[u8], Option<&[u8]>, &MergeOperands) -> Option<Vec<u8>> + Send + Sync + 'static
74{
75}
76
77pub struct MergeOperatorCallback<F: MergeFn, PF: MergeFn> {
78 pub name: CString,
79 pub full_merge_fn: F,
80 pub partial_merge_fn: PF,
81}
82
83pub unsafe extern "C" fn destructor_callback<F: MergeFn, PF: MergeFn>(raw_cb: *mut c_void) {
84 unsafe {
85 drop(Box::from_raw(raw_cb as *mut MergeOperatorCallback<F, PF>));
86 }
87}
88
89pub unsafe extern "C" fn delete_callback(
90 _raw_cb: *mut c_void,
91 value: *const c_char,
92 value_length: size_t,
93) {
94 unsafe {
95 if !value.is_null() {
96 drop(Box::from_raw(ptr::slice_from_raw_parts_mut(
98 value as *mut u8,
99 value_length,
100 )));
101 }
102 }
103}
104
105pub unsafe extern "C" fn name_callback<F: MergeFn, PF: MergeFn>(
106 raw_cb: *mut c_void,
107) -> *const c_char {
108 unsafe {
109 let cb = &mut *(raw_cb as *mut MergeOperatorCallback<F, PF>);
110 cb.name.as_ptr()
111 }
112}
113
114pub unsafe extern "C" fn full_merge_callback<F: MergeFn, PF: MergeFn>(
115 raw_cb: *mut c_void,
116 raw_key: *const c_char,
117 key_len: size_t,
118 existing_value: *const c_char,
119 existing_value_len: size_t,
120 operands_list: *const *const c_char,
121 operands_list_len: *const size_t,
122 num_operands: c_int,
123 success: *mut u8,
124 new_value_length: *mut size_t,
125) -> *mut c_char {
126 unsafe {
127 let cb = &mut *(raw_cb as *mut MergeOperatorCallback<F, PF>);
128 let operands = &MergeOperands::new(operands_list, operands_list_len, num_operands);
129 let key = slice::from_raw_parts(raw_key as *const u8, key_len);
130 let oldval = if existing_value.is_null() {
131 None
132 } else {
133 Some(slice::from_raw_parts(
134 existing_value as *const u8,
135 existing_value_len,
136 ))
137 };
138 (cb.full_merge_fn)(key, oldval, operands).map_or_else(
139 || {
140 *new_value_length = 0;
141 *success = 0_u8;
142 ptr::null_mut() as *mut c_char
143 },
144 |result| {
145 *new_value_length = result.len() as size_t;
146 *success = 1_u8;
147 Box::into_raw(result.into_boxed_slice()) as *mut c_char
148 },
149 )
150 }
151}
152
153pub unsafe extern "C" fn partial_merge_callback<F: MergeFn, PF: MergeFn>(
154 raw_cb: *mut c_void,
155 raw_key: *const c_char,
156 key_len: size_t,
157 operands_list: *const *const c_char,
158 operands_list_len: *const size_t,
159 num_operands: c_int,
160 success: *mut u8,
161 new_value_length: *mut size_t,
162) -> *mut c_char {
163 unsafe {
164 let cb = &mut *(raw_cb as *mut MergeOperatorCallback<F, PF>);
165 let operands = &MergeOperands::new(operands_list, operands_list_len, num_operands);
166 let key = slice::from_raw_parts(raw_key as *const u8, key_len);
167 (cb.partial_merge_fn)(key, None, operands).map_or_else(
168 || {
169 *new_value_length = 0;
170 *success = 0_u8;
171 ptr::null_mut::<c_char>()
172 },
173 |result| {
174 *new_value_length = result.len() as size_t;
175 *success = 1_u8;
176 Box::into_raw(result.into_boxed_slice()) as *mut c_char
177 },
178 )
179 }
180}
181
182pub struct MergeOperands {
183 operands_list: *const *const c_char,
184 operands_list_len: *const size_t,
185 num_operands: usize,
186}
187
188impl MergeOperands {
189 fn new(
190 operands_list: *const *const c_char,
191 operands_list_len: *const size_t,
192 num_operands: c_int,
193 ) -> MergeOperands {
194 assert!(num_operands >= 0);
195 MergeOperands {
196 operands_list,
197 operands_list_len,
198 num_operands: num_operands as usize,
199 }
200 }
201
202 pub fn len(&self) -> usize {
203 self.num_operands
204 }
205
206 pub fn is_empty(&self) -> bool {
207 self.num_operands == 0
208 }
209
210 pub fn iter(&'_ self) -> MergeOperandsIter<'_> {
211 MergeOperandsIter {
212 operands: self,
213 cursor: 0,
214 }
215 }
216
217 fn get_operand(&self, index: usize) -> Option<&[u8]> {
218 if index >= self.num_operands {
219 None
220 } else {
221 unsafe {
222 let base = self.operands_list as usize;
223 let base_len = self.operands_list_len as usize;
224 let spacing = mem::size_of::<*const *const u8>();
225 let spacing_len = mem::size_of::<*const size_t>();
226 let len_ptr = (base_len + (spacing_len * index)) as *const size_t;
227 let len = *len_ptr;
228 let ptr = base + (spacing * index);
229 Some(slice::from_raw_parts(*(ptr as *const *const u8), len))
230 }
231 }
232 }
233}
234
235pub struct MergeOperandsIter<'a> {
236 operands: &'a MergeOperands,
237 cursor: usize,
238}
239
240impl<'a> Iterator for MergeOperandsIter<'a> {
241 type Item = &'a [u8];
242
243 fn next(&mut self) -> Option<Self::Item> {
244 let operand = self.operands.get_operand(self.cursor)?;
245 self.cursor += 1;
246 Some(operand)
247 }
248
249 fn size_hint(&self) -> (usize, Option<usize>) {
250 let remaining = self.operands.num_operands - self.cursor;
251 (remaining, Some(remaining))
252 }
253}
254
255impl<'a> IntoIterator for &'a MergeOperands {
256 type Item = &'a [u8];
257 type IntoIter = MergeOperandsIter<'a>;
258
259 fn into_iter(self) -> Self::IntoIter {
260 Self::IntoIter {
261 operands: self,
262 cursor: 0,
263 }
264 }
265}