1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use crocksdb_ffi::{self, DBSliceTransform};
use libc::{c_char, c_void, size_t};
use std::ffi::CString;
use std::slice;
pub trait SliceTransform {
fn transform<'a>(&mut self, key: &'a [u8]) -> &'a [u8];
fn in_domain(&mut self, key: &[u8]) -> bool;
fn in_range(&mut self, _: &[u8]) -> bool {
true
}
}
#[repr(C)]
pub struct SliceTransformProxy {
name: CString,
transform: Box<dyn SliceTransform>,
}
extern "C" fn name(transform: *mut c_void) -> *const c_char {
unsafe { (*(transform as *mut SliceTransformProxy)).name.as_ptr() }
}
extern "C" fn destructor(transform: *mut c_void) {
unsafe {
Box::from_raw(transform as *mut SliceTransformProxy);
}
}
extern "C" fn transform(
transform: *mut c_void,
key: *const u8,
key_len: size_t,
dest_len: *mut size_t,
) -> *const u8 {
unsafe {
let transform = &mut *(transform as *mut SliceTransformProxy);
let key = slice::from_raw_parts(key, key_len);
let prefix = transform.transform.transform(key);
*dest_len = prefix.len() as size_t;
prefix.as_ptr() as *const u8
}
}
extern "C" fn in_domain(transform: *mut c_void, key: *const u8, key_len: size_t) -> u8 {
unsafe {
let transform = &mut *(transform as *mut SliceTransformProxy);
let key = slice::from_raw_parts(key, key_len);
transform.transform.in_domain(key) as u8
}
}
extern "C" fn in_range(transform: *mut c_void, key: *const u8, key_len: size_t) -> u8 {
unsafe {
let transform = &mut *(transform as *mut SliceTransformProxy);
let key = slice::from_raw_parts(key, key_len);
transform.transform.in_range(key) as u8
}
}
pub unsafe fn new_slice_transform(
c_name: CString,
f: Box<dyn SliceTransform>,
) -> Result<*mut DBSliceTransform, String> {
let proxy = Box::into_raw(Box::new(SliceTransformProxy {
name: c_name,
transform: f,
}));
let transform = crocksdb_ffi::crocksdb_slicetransform_create(
proxy as *mut c_void,
destructor,
transform,
in_domain,
in_range,
name,
);
Ok(transform)
}