rocksdb/
slice_transform.rs1use std::ffi::CString;
16use std::slice;
17
18use libc::{c_char, c_uchar, c_void, size_t};
19
20use crate::{ffi, ffi_util::CStrLike};
21
22pub struct SliceTransform {
27 pub inner: *mut ffi::rocksdb_slicetransform_t,
28}
29
30impl SliceTransform {
37 pub fn create(
38 name: impl CStrLike,
39 transform_fn: TransformFn,
40 in_domain_fn: Option<InDomainFn>,
41 ) -> SliceTransform {
42 let cb = Box::into_raw(Box::new(TransformCallback {
43 name: name.into_c_string().unwrap(),
44 transform_fn,
45 in_domain_fn,
46 }));
47
48 let st = unsafe {
49 ffi::rocksdb_slicetransform_create(
50 cb as *mut c_void,
51 Some(slice_transform_destructor_callback),
52 Some(transform_callback),
53 Some(in_domain_callback),
54 None,
56 Some(slice_transform_name_callback),
57 )
58 };
59
60 SliceTransform { inner: st }
61 }
62
63 pub fn create_fixed_prefix(len: size_t) -> SliceTransform {
64 SliceTransform {
65 inner: unsafe { ffi::rocksdb_slicetransform_create_fixed_prefix(len) },
66 }
67 }
68
69 pub fn create_noop() -> SliceTransform {
70 SliceTransform {
71 inner: unsafe { ffi::rocksdb_slicetransform_create_noop() },
72 }
73 }
74}
75
76pub type TransformFn<'a> = fn(&'a [u8]) -> &'a [u8];
77pub type InDomainFn = fn(&[u8]) -> bool;
78
79pub struct TransformCallback<'a> {
80 pub name: CString,
81 pub transform_fn: TransformFn<'a>,
82 pub in_domain_fn: Option<InDomainFn>,
83}
84
85pub unsafe extern "C" fn slice_transform_destructor_callback(raw_cb: *mut c_void) {
86 drop(Box::from_raw(raw_cb as *mut TransformCallback));
87}
88
89pub unsafe extern "C" fn slice_transform_name_callback(raw_cb: *mut c_void) -> *const c_char {
90 let cb = &mut *(raw_cb as *mut TransformCallback);
91 cb.name.as_ptr()
92}
93
94pub unsafe extern "C" fn transform_callback(
95 raw_cb: *mut c_void,
96 raw_key: *const c_char,
97 key_len: size_t,
98 dst_length: *mut size_t,
99) -> *mut c_char {
100 let cb = &mut *(raw_cb as *mut TransformCallback);
101 let key = slice::from_raw_parts(raw_key as *const u8, key_len);
102 let prefix = (cb.transform_fn)(key);
103 *dst_length = prefix.len() as size_t;
104 prefix.as_ptr() as *mut c_char
105}
106
107pub unsafe extern "C" fn in_domain_callback(
108 raw_cb: *mut c_void,
109 raw_key: *const c_char,
110 key_len: size_t,
111) -> c_uchar {
112 let cb = &mut *(raw_cb as *mut TransformCallback);
113 let key = slice::from_raw_parts(raw_key as *const u8, key_len);
114 c_uchar::from(cb.in_domain_fn.map_or(true, |in_domain| in_domain(key)))
115}