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