redis_module_ext/data_type/
io.rs1use 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 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 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 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 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 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}