rust_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 Some(slice_transform_name_callback),
55 )
56 };
57
58 SliceTransform { inner: st }
59 }
60
61 pub fn create_fixed_prefix(len: size_t) -> SliceTransform {
62 SliceTransform {
63 inner: unsafe { ffi::rocksdb_slicetransform_create_fixed_prefix(len) },
64 }
65 }
66
67 pub fn create_noop() -> SliceTransform {
68 SliceTransform {
69 inner: unsafe { ffi::rocksdb_slicetransform_create_noop() },
70 }
71 }
72}
73
74pub type TransformFn<'a> = fn(&'a [u8]) -> &'a [u8];
75pub type InDomainFn = fn(&[u8]) -> bool;
76
77pub struct TransformCallback<'a> {
78 pub name: CString,
79 pub transform_fn: TransformFn<'a>,
80 pub in_domain_fn: Option<InDomainFn>,
81}
82
83pub unsafe extern "C" fn slice_transform_destructor_callback(raw_cb: *mut c_void) {
84 unsafe {
85 drop(Box::from_raw(raw_cb as *mut TransformCallback));
86 }
87}
88
89pub unsafe extern "C" fn slice_transform_name_callback(raw_cb: *mut c_void) -> *const c_char {
90 unsafe {
91 let cb = &mut *(raw_cb as *mut TransformCallback);
92 cb.name.as_ptr()
93 }
94}
95
96pub unsafe extern "C" fn transform_callback(
97 raw_cb: *mut c_void,
98 raw_key: *const c_char,
99 key_len: size_t,
100 dst_length: *mut size_t,
101) -> *mut c_char {
102 unsafe {
103 let cb = &mut *(raw_cb as *mut TransformCallback);
104 let key = slice::from_raw_parts(raw_key as *const u8, key_len);
105 let prefix = (cb.transform_fn)(key);
106 *dst_length = prefix.len() as size_t;
107 prefix.as_ptr() as *mut c_char
108 }
109}
110
111pub unsafe extern "C" fn in_domain_callback(
112 raw_cb: *mut c_void,
113 raw_key: *const c_char,
114 key_len: size_t,
115) -> c_uchar {
116 unsafe {
117 let cb = &mut *(raw_cb as *mut TransformCallback);
118 let key = slice::from_raw_parts(raw_key as *const u8, key_len);
119 c_uchar::from(cb.in_domain_fn.is_none_or(|in_domain| in_domain(key)))
120 }
121}