redis_module_ext/data_type/
io.rs

1use std::borrow::Borrow;
2use std::hash::Hasher;
3use std::ptr::NonNull;
4use std::str::Utf8Error;
5
6use redis_module::{RedisBuffer, RedisError, RedisResult, RedisString, raw};
7
8use crate::data_type::methods::CStrConv;
9use crate::prelude::IoLoggingExt;
10
11pub struct RdbSaveIo {
12    ptr: NonNull<raw::RedisModuleIO>,
13}
14
15impl RdbSaveIo {
16    /// # Safety
17    ///
18    /// 1. The ptr must be valid and from redis.
19    /// 2. The ptr must be for a RDBSave Operation.
20    pub unsafe fn new(ptr: NonNull<raw::RedisModuleIO>) -> Self {
21        Self { ptr }
22    }
23
24    pub fn ptr(&self) -> NonNull<raw::RedisModuleIO> {
25        self.ptr
26    }
27
28    pub fn save_double(&mut self, value: f64) {
29        raw::save_double(self.ptr.as_ptr(), value);
30    }
31
32    pub fn save_float(&mut self, value: f32) {
33        raw::save_float(self.ptr.as_ptr(), value);
34    }
35
36    pub fn save_redis_string(&mut self, string: impl Borrow<RedisString>) {
37        raw::save_redis_string(self.ptr.as_ptr(), string.borrow());
38    }
39
40    pub fn save_signed(&mut self, value: i64) {
41        raw::save_signed(self.ptr.as_ptr(), value);
42    }
43
44    pub fn save_unsigned(&mut self, value: u64) {
45        raw::save_unsigned(self.ptr.as_ptr(), value);
46    }
47
48    pub fn save_slice(&mut self, value: impl AsRef<[u8]>) {
49        raw::save_slice(self.ptr.as_ptr(), value.as_ref());
50    }
51
52    pub fn save_str(&mut self, value: impl AsRef<str>) {
53        raw::save_string(self.ptr.as_ptr(), value.as_ref());
54    }
55}
56
57impl IoLoggingExt for RdbSaveIo {
58    fn log(&mut self, level: redis_module::logging::RedisLogLevel, message: impl AsRef<str>) {
59        redis_module::logging::log_io_error(self.ptr.as_ptr(), level, message.as_ref());
60    }
61}
62
63pub struct RdbLoadIo {
64    ptr: NonNull<raw::RedisModuleIO>,
65}
66
67impl RdbLoadIo {
68    /// # Safety
69    ///
70    /// 1. The ptr must be valid and from redis.
71    /// 2. The ptr must be for a RDBLoad Operation.
72    pub unsafe fn new(ptr: NonNull<raw::RedisModuleIO>) -> Self {
73        Self { ptr }
74    }
75
76    pub fn ptr(&self) -> NonNull<raw::RedisModuleIO> {
77        self.ptr
78    }
79
80    pub fn load_double(&mut self) -> RedisResult<f64> {
81        raw::load_double(self.ptr.as_ptr()).map_err(|err| redis_module::RedisError::String(err.to_string()))
82    }
83
84    pub fn load_float(&mut self) -> RedisResult<f32> {
85        raw::load_float(self.ptr.as_ptr()).map_err(|err| redis_module::RedisError::String(err.to_string()))
86    }
87
88    pub fn load_string(&mut self) -> RedisResult<RedisString> {
89        raw::load_string(self.ptr.as_ptr()).map_err(|err| redis_module::RedisError::String(err.to_string()))
90    }
91
92    pub fn load_string_buffer(&mut self) -> RedisResult<RedisBuffer> {
93        raw::load_string_buffer(self.ptr.as_ptr()).map_err(|err| redis_module::RedisError::String(err.to_string()))
94    }
95
96    pub fn load_unsigned(&mut self) -> RedisResult<u64> {
97        raw::load_unsigned(self.ptr.as_ptr()).map_err(|err| redis_module::RedisError::String(err.to_string()))
98    }
99
100    pub fn load_signed(&mut self) -> RedisResult<i64> {
101        raw::load_signed(self.ptr.as_ptr()).map_err(|err| redis_module::RedisError::String(err.to_string()))
102    }
103
104    pub fn log(&mut self, level: redis_module::logging::RedisLogLevel, message: impl AsRef<str>) {
105        redis_module::logging::log_io_error(self.ptr.as_ptr(), level, message.as_ref());
106    }
107
108    pub fn log_warning(&mut self, message: impl AsRef<str>) {
109        self.log(redis_module::logging::RedisLogLevel::Warning, message)
110    }
111
112    pub fn log_debug(&mut self, message: impl AsRef<str>) {
113        self.log(redis_module::logging::RedisLogLevel::Debug, message)
114    }
115
116    pub fn log_notice(&mut self, message: impl AsRef<str>) {
117        self.log(redis_module::logging::RedisLogLevel::Notice, message)
118    }
119
120    pub fn log_verbose(&mut self, message: impl AsRef<str>) {
121        self.log(redis_module::logging::RedisLogLevel::Verbose, message)
122    }
123}
124
125impl IoLoggingExt for RdbLoadIo {
126    fn log(&mut self, level: redis_module::logging::RedisLogLevel, message: impl AsRef<str>) {
127        redis_module::logging::log_io_error(self.ptr.as_ptr(), level, message.as_ref());
128    }
129}
130
131pub struct AofRewriteIo {
132    ptr: NonNull<raw::RedisModuleIO>,
133}
134
135#[must_use = "Does nothing unless `EmitAofCommandBuilder::dispatch` is called"]
136pub struct EmitAofCommandBuilder<'a, C> {
137    io: &'a mut AofRewriteIo,
138    cmd: C,
139    args: Vec<RedisString>,
140}
141
142impl<C> EmitAofCommandBuilder<'_, C> {
143    pub fn arg(mut self, arg: impl AsRef<[u8]>) -> Self {
144        self.args
145            .push(RedisString::create_from_slice(std::ptr::null_mut(), arg.as_ref()));
146        self
147    }
148
149    pub fn args(mut self, args: impl IntoIterator<Item = impl AsRef<[u8]>>) -> Self {
150        self.args.extend(
151            args.into_iter()
152                .map(|arg| RedisString::create_from_slice(std::ptr::null_mut(), arg.as_ref())),
153        );
154        self
155    }
156
157    pub fn dispatch(mut self) -> RedisResult<()>
158    where
159        C: CStrConv,
160    {
161        let command = unsafe { raw::RedisModule_EmitAOF }.ok_or(RedisError::Str("missing emit aof"))?;
162
163        let cmd = self.cmd.into_cstr().ok_or(RedisError::Str("invalid command name"))?;
164        let cmd = cmd.borrow();
165
166        unsafe {
167            command(
168                self.io.ptr.as_ptr(),
169                cmd.as_ptr(),
170                c"v".as_ptr(),
171                self.args.as_mut_ptr(),
172                self.args.len(),
173            )
174        };
175        Ok(())
176    }
177}
178
179impl AofRewriteIo {
180    /// # Safety
181    ///
182    /// 1. The ptr must be valid and from redis.
183    /// 2. The ptr must be for a AofRewrite Operation.
184    pub unsafe fn new(ptr: NonNull<raw::RedisModuleIO>) -> Self {
185        Self { ptr }
186    }
187
188    pub fn emit_command<C>(&mut self, cmd: C) -> EmitAofCommandBuilder<'_, C> {
189        EmitAofCommandBuilder {
190            io: self,
191            cmd,
192            args: Vec::new(),
193        }
194    }
195
196    pub fn log(&mut self, level: redis_module::logging::RedisLogLevel, message: impl AsRef<str>) {
197        redis_module::logging::log_io_error(self.ptr.as_ptr(), level, message.as_ref());
198    }
199
200    pub fn log_warning(&mut self, message: impl AsRef<str>) {
201        self.log(redis_module::logging::RedisLogLevel::Warning, message)
202    }
203
204    pub fn log_debug(&mut self, message: impl AsRef<str>) {
205        self.log(redis_module::logging::RedisLogLevel::Debug, message)
206    }
207
208    pub fn log_notice(&mut self, message: impl AsRef<str>) {
209        self.log(redis_module::logging::RedisLogLevel::Notice, message)
210    }
211
212    pub fn log_verbose(&mut self, message: impl AsRef<str>) {
213        self.log(redis_module::logging::RedisLogLevel::Verbose, message)
214    }
215}
216
217impl IoLoggingExt for AofRewriteIo {
218    fn log(&mut self, level: redis_module::logging::RedisLogLevel, message: impl AsRef<str>) {
219        redis_module::logging::log_io_error(self.ptr.as_ptr(), level, message.as_ref());
220    }
221}
222
223pub struct RedisModuleDigest {
224    ptr: NonNull<raw::RedisModuleDigest>,
225}
226
227impl RedisModuleDigest {
228    /// # Safety
229    ///
230    /// 1. The ptr must be valid and from redis.
231    /// 2. The ptr must be for a ModuleDigest Operation.
232    pub unsafe fn new(ptr: NonNull<raw::RedisModuleDigest>) -> Self {
233        Self { ptr }
234    }
235
236    pub fn ptr(&self) -> NonNull<raw::RedisModuleDigest> {
237        self.ptr
238    }
239
240    pub fn add_str(&mut self, value: impl AsRef<str>) {
241        self.add_bytes(value.as_ref().as_bytes());
242    }
243
244    pub fn add_bytes(&mut self, value: impl AsRef<[u8]>) {
245        let value = value.as_ref();
246        let add_str_buffer = unsafe { raw::RedisModule_DigestAddStringBuffer }.unwrap();
247        unsafe { add_str_buffer(self.ptr.as_ptr(), value.as_ptr().cast(), value.len()) }
248    }
249
250    pub fn add_u64(&mut self, value: u64) {
251        self.add_i64(value as i64);
252    }
253
254    pub fn add_i64(&mut self, value: i64) {
255        let add_long_long = unsafe { raw::RedisModule_DigestAddLongLong }.unwrap();
256        unsafe { add_long_long(self.ptr.as_ptr(), value) }
257    }
258
259    pub fn end_sequence(&mut self) {
260        let add_end_seq = unsafe { raw::RedisModule_DigestEndSequence }.unwrap();
261        unsafe { add_end_seq(self.ptr.as_ptr()) }
262    }
263
264    pub fn key(&mut self) -> Result<&str, Utf8Error> {
265        let get_key = unsafe { raw::RedisModule_GetKeyNameFromDigest }.unwrap();
266        RedisString::from_ptr(unsafe { get_key(self.ptr.as_ptr()) })
267    }
268
269    pub fn database(&mut self) -> i32 {
270        let get_db = unsafe { raw::RedisModule_GetDbIdFromDigest }.unwrap();
271        unsafe { get_db(self.ptr.as_ptr()) }
272    }
273
274    pub fn add(&mut self, hash: impl std::hash::Hash) {
275        let mut hasher = std::hash::DefaultHasher::new();
276        hash.hash(&mut hasher);
277        self.add_u64(hasher.finish());
278    }
279}
280
281pub struct RedisModuleKeyOptCtx {
282    ptr: NonNull<raw::RedisModuleKeyOptCtx>,
283}
284
285impl RedisModuleKeyOptCtx {
286    /// # Safety
287    ///
288    /// 1. The ptr must be valid and from redis.
289    /// 2. The ptr must be for a RedisKeyOpt Operation.
290    pub unsafe fn new(ptr: NonNull<raw::RedisModuleKeyOptCtx>) -> Self {
291        Self { ptr }
292    }
293
294    pub fn ptr(&self) -> NonNull<raw::RedisModuleKeyOptCtx> {
295        self.ptr
296    }
297
298    pub fn key(&mut self) -> Result<&str, Utf8Error> {
299        let get_key = unsafe { raw::RedisModule_GetKeyNameFromOptCtx }.unwrap();
300        RedisString::from_ptr(unsafe { get_key(self.ptr.as_ptr()) })
301    }
302
303    pub fn to_key(&mut self) -> Result<&str, Utf8Error> {
304        let get_key = unsafe { raw::RedisModule_GetToKeyNameFromOptCtx }.unwrap();
305        RedisString::from_ptr(unsafe { get_key(self.ptr.as_ptr()) })
306    }
307
308    pub fn database(&mut self) -> i32 {
309        let get_db = unsafe { raw::RedisModule_GetDbIdFromOptCtx }.unwrap();
310        unsafe { get_db(self.ptr.as_ptr()) }
311    }
312
313    pub fn to_database(&mut self) -> i32 {
314        let get_db = unsafe { raw::RedisModule_GetToDbIdFromOptCtx }.unwrap();
315        unsafe { get_db(self.ptr.as_ptr()) }
316    }
317}