redis_module/context/
keys_cursor.rs

1use crate::context::Context;
2use crate::key::RedisKey;
3use crate::raw;
4use crate::redismodule::RedisString;
5use std::ffi::c_void;
6use std::ptr::NonNull;
7
8pub struct KeysCursor {
9    inner_cursor: *mut raw::RedisModuleScanCursor,
10}
11
12extern "C" fn scan_callback<C: FnMut(&Context, RedisString, Option<&RedisKey>)>(
13    ctx: *mut raw::RedisModuleCtx,
14    key_name: *mut raw::RedisModuleString,
15    key: *mut raw::RedisModuleKey,
16    private_data: *mut ::std::os::raw::c_void,
17) {
18    let context = Context::new(ctx);
19    let key_name = RedisString::new(NonNull::new(ctx), key_name);
20    let redis_key = if key.is_null() {
21        None
22    } else {
23        Some(RedisKey::from_raw_parts(ctx, key))
24    };
25    let callback = unsafe { &mut *(private_data.cast::<C>()) };
26    callback(&context, key_name, redis_key.as_ref());
27
28    // we are not the owner of the key, so we must take the underline *mut raw::RedisModuleKey so it will not be freed.
29    redis_key.map(|v| v.take());
30}
31
32impl KeysCursor {
33    pub fn new() -> Self {
34        let inner_cursor = unsafe { raw::RedisModule_ScanCursorCreate.unwrap()() };
35        Self { inner_cursor }
36    }
37
38    pub fn scan<F: FnMut(&Context, RedisString, Option<&RedisKey>)>(
39        &self,
40        ctx: &Context,
41        callback: &F,
42    ) -> bool {
43        let res = unsafe {
44            raw::RedisModule_Scan.unwrap()(
45                ctx.ctx,
46                self.inner_cursor,
47                Some(scan_callback::<F>),
48                callback as *const F as *mut c_void,
49            )
50        };
51        res != 0
52    }
53
54    pub fn restart(&self) {
55        unsafe { raw::RedisModule_ScanCursorRestart.unwrap()(self.inner_cursor) };
56    }
57}
58
59impl Default for KeysCursor {
60    fn default() -> Self {
61        Self::new()
62    }
63}
64
65impl Drop for KeysCursor {
66    fn drop(&mut self) {
67        unsafe { raw::RedisModule_ScanCursorDestroy.unwrap()(self.inner_cursor) };
68    }
69}