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 drop(unsafe { Box::from_raw(raw_cb as *mut TransformCallback) });
85}
86
87pub unsafe extern "C" fn slice_transform_name_callback(raw_cb: *mut c_void) -> *const c_char {
88 let cb = unsafe { &mut *(raw_cb as *mut TransformCallback) };
89 cb.name.as_ptr()
90}
91
92pub unsafe extern "C" fn transform_callback(
93 raw_cb: *mut c_void,
94 raw_key: *const c_char,
95 key_len: size_t,
96 dst_length: *mut size_t,
97) -> *mut c_char {
98 let cb = unsafe { &mut *(raw_cb as *mut TransformCallback) };
99 let key = unsafe { slice::from_raw_parts(raw_key.cast::<u8>(), key_len) };
100 let prefix = (cb.transform_fn)(key);
101 unsafe { *dst_length = prefix.len() as size_t };
102 prefix.as_ptr().cast::<c_char>().cast_mut()
103}
104
105pub unsafe extern "C" fn in_domain_callback(
106 raw_cb: *mut c_void,
107 raw_key: *const c_char,
108 key_len: size_t,
109) -> c_uchar {
110 let cb = unsafe { &mut *(raw_cb as *mut TransformCallback) };
111 let key = unsafe { slice::from_raw_parts(raw_key.cast::<u8>(), key_len) };
112 c_uchar::from(cb.in_domain_fn.is_none_or(|in_domain| in_domain(key)))
113}