redis_module/
native_types.rs

1use std::cell::RefCell;
2use std::ffi::CString;
3use std::ptr;
4
5use crate::raw;
6
7pub struct RedisType {
8    name: &'static str,
9    version: i32,
10    type_methods: raw::RedisModuleTypeMethods,
11    pub raw_type: RefCell<*mut raw::RedisModuleType>,
12}
13
14// We want to be able to create static instances of this type,
15// which means we need to implement Sync.
16unsafe impl Sync for RedisType {}
17
18impl RedisType {
19    #[must_use]
20    pub const fn new(
21        name: &'static str,
22        version: i32,
23        type_methods: raw::RedisModuleTypeMethods,
24    ) -> Self {
25        Self {
26            name,
27            version,
28            type_methods,
29            raw_type: RefCell::new(ptr::null_mut()),
30        }
31    }
32
33    #[allow(clippy::not_unsafe_ptr_arg_deref)]
34    pub fn create_data_type(&self, ctx: *mut raw::RedisModuleCtx) -> Result<(), &str> {
35        if self.name.len() != 9 {
36            let msg = "Redis requires the length of native type names to be exactly 9 characters";
37            redis_log(ctx, format!("{msg}, name is: '{}'", self.name).as_str());
38            return Err(msg);
39        }
40
41        let type_name = CString::new(self.name).unwrap();
42
43        let redis_type = unsafe {
44            raw::RedisModule_CreateDataType.unwrap()(
45                ctx,
46                type_name.as_ptr(),
47                self.version, // Encoding version
48                &mut self.type_methods.clone(),
49            )
50        };
51
52        if redis_type.is_null() {
53            redis_log(ctx, "Error: created data type is null");
54            return Err("Error: created data type is null");
55        }
56
57        *self.raw_type.borrow_mut() = redis_type;
58
59        redis_log(
60            ctx,
61            format!("Created new data type '{}'", self.name).as_str(),
62        );
63
64        Ok(())
65    }
66}
67
68// TODO: Move to raw
69#[allow(clippy::not_unsafe_ptr_arg_deref)]
70pub fn redis_log(ctx: *mut raw::RedisModuleCtx, msg: &str) {
71    let level = CString::new("notice").unwrap(); // FIXME reuse this
72    let msg = CString::new(msg).unwrap();
73    unsafe {
74        raw::RedisModule_Log.unwrap()(ctx, level.as_ptr(), msg.as_ptr());
75    }
76}