Skip to content

Commit 672d102

Browse files
committed
Completed multi-command redis_module macro
1 parent 44cf681 commit 672d102

File tree

7 files changed

+80
-207
lines changed

7 files changed

+80
-207
lines changed

Cargo.toml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@ crate-type = ["cdylib"]
1616
name = "data_type"
1717
crate-type = ["cdylib"]
1818

19-
[[example]]
20-
name = "macro_games"
21-
crate-type = ["cdylib"]
22-
2319
[dependencies]
2420
bitflags = "1.0"
2521
libc = "0.2"

examples/data_type.rs

Lines changed: 8 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
//#[macro_use]
1+
#[macro_use]
22
extern crate redismodule;
33

44
use redismodule::{Context, RedisResult, NextArg};
55
use redismodule::native_types::RedisType;
6-
use redismodule::redismodule::RedisValue;
76

87
#[derive(Debug)]
98
struct MyType {
@@ -43,118 +42,21 @@ fn alloc_get(ctx: &Context, args: Vec<String>) -> RedisResult {
4342

4443
let key = ctx.open_key_writable(&key); // TODO: Use read-only key
4544

46-
match key.get_value::<MyType>(&MY_REDIS_TYPE)? {
47-
None => Ok(RedisValue::None),
45+
let value = match key.get_value::<MyType>(&MY_REDIS_TYPE)? {
46+
None => ().into(),
4847
Some(value) => {
4948
// TODO: Use the value
5049
let _ = value;
51-
Ok("some value".into())
50+
"some value".into()
5251
}
53-
}
54-
}
55-
56-
//////////////////////////////////////////////////////
57-
58-
macro_rules! redis_command {
59-
($ctx: expr, $command_name:expr, $command_handler:expr, $command_flags:expr) => {
60-
{
61-
let name = CString::new($command_name).unwrap();
62-
let flags = CString::new($command_flags).unwrap();
63-
let (firstkey, lastkey, keystep) = (1, 1, 1);
52+
};
6453

65-
/////////////////////
66-
extern fn do_command(
67-
ctx: *mut raw::RedisModuleCtx,
68-
argv: *mut *mut raw::RedisModuleString,
69-
argc: c_int,
70-
) -> c_int {
71-
let context = Context::new(ctx);
72-
73-
let args: Vec<String> = unsafe { slice::from_raw_parts(argv, argc as usize) }
74-
.into_iter()
75-
.map(|a| RedisString::from_ptr(*a).expect("UTF8 encoding error in handler args").to_string())
76-
.collect();
77-
78-
let response = $command_handler(&context, args);
79-
context.reply(response) as c_int
80-
}
81-
/////////////////////
82-
83-
if raw::RedisModule_CreateCommand.unwrap()(
84-
$ctx,
85-
name.as_ptr(),
86-
Some(do_command),
87-
flags.as_ptr(),
88-
firstkey, lastkey, keystep,
89-
) == raw::Status::Err as _ { return raw::Status::Err as _; }
90-
}
91-
}
54+
Ok(value)
9255
}
9356

57+
//////////////////////////////////////////////////////
9458

95-
macro_rules! redis_module2 {
96-
(
97-
name: $module_name:expr,
98-
version: $module_version:expr,
99-
data_types: [
100-
$($data_type:ident),* $(,)*
101-
],
102-
commands: [
103-
$([
104-
$name:expr,
105-
$command:ident,
106-
$flags:expr
107-
]),* $(,)*
108-
] $(,)*
109-
) => {
110-
use std::os::raw::c_int;
111-
use std::ffi::CString;
112-
use std::slice;
113-
114-
use redismodule::raw;
115-
use redismodule::RedisString;
116-
117-
#[no_mangle]
118-
#[allow(non_snake_case)]
119-
pub extern "C" fn RedisModule_OnLoad(
120-
ctx: *mut raw::RedisModuleCtx,
121-
_argv: *mut *mut raw::RedisModuleString,
122-
_argc: c_int,
123-
) -> c_int {
124-
unsafe {
125-
let module_name = CString::new($module_name).unwrap();
126-
let module_version = $module_version as c_int;
127-
128-
if raw::Export_RedisModule_Init(
129-
ctx,
130-
module_name.as_ptr(),
131-
module_version,
132-
raw::REDISMODULE_APIVER_1 as c_int,
133-
) == raw::Status::Err as _ { return raw::Status::Err as _; }
134-
135-
$(
136-
if (&$data_type).create_data_type(ctx).is_err() {
137-
return raw::Status::Err as _;
138-
}
139-
)*
140-
141-
if true {
142-
redismodule::alloc::use_redis_alloc();
143-
} else {
144-
eprintln!("*** NOT USING Redis allocator ***");
145-
}
146-
147-
$(
148-
redis_command!(ctx, $name, $command, $flags);
149-
)*
150-
151-
raw::Status::Ok as _
152-
}
153-
}
154-
}
155-
}
156-
157-
redis_module2!{
59+
redis_module!{
15860
name: "alloc",
15961
version: 1,
16062
data_types: [

examples/hello.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
extern crate redismodule;
33

44
use redismodule::{Context, RedisResult, RedisError, parse_integer};
5-
use redismodule::native_types::RedisType;
65

76
fn hello_mul(_: &Context, args: Vec<String>) -> RedisResult {
87
if args.len() < 2 {
@@ -25,19 +24,14 @@ fn hello_mul(_: &Context, args: Vec<String>) -> RedisResult {
2524

2625
//////////////////////////////////////////////////////
2726

28-
const MODULE_NAME: &str = "hello";
29-
const MODULE_VERSION: i32 = 1;
30-
31-
/*
3227
redis_module!{
33-
MODULE_NAME,
34-
MODULE_VERSION,
35-
[] as [RedisType; 0],
36-
[
37-
Command::new("hello.mul", hello_mul, "write"),
38-
]
28+
name: "hello",
29+
version: 1,
30+
data_types: [],
31+
commands: [
32+
["hello.mul", hello_mul, ""],
33+
],
3934
}
40-
*/
4135

4236
//////////////////////////////////////////////////////
4337

examples/macro_games.rs

Lines changed: 0 additions & 44 deletions
This file was deleted.

src/key.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,21 +117,21 @@ impl RedisKeyWritable {
117117
Ok(Some(read_key(self.key_inner)?))
118118
}
119119

120-
pub fn set_expire(&self, expire: time::Duration) -> Result<(), Error> {
120+
pub fn set_expire(&self, expire: time::Duration) -> RedisResult {
121121
match raw::set_expire(self.key_inner, expire.num_milliseconds()) {
122-
raw::Status::Ok => Ok(()),
122+
raw::Status::Ok => Ok("OK".into()),
123123

124124
// Error may occur if the key wasn't open for writing or is an
125125
// empty key.
126-
raw::Status::Err => Err(error!("Error while setting key expire")),
126+
raw::Status::Err => Err(RedisError::Str("Error while setting key expire")),
127127
}
128128
}
129129

130-
pub fn write(&self, val: &str) -> Result<(), Error> {
130+
pub fn write(&self, val: &str) -> RedisResult {
131131
let val_str = RedisString::create(self.ctx, val);
132132
match raw::string_set(self.key_inner, val_str.inner) {
133-
raw::Status::Ok => Ok(()),
134-
raw::Status::Err => Err(error!("Error while setting key")),
133+
raw::Status::Ok => Ok("OK".into()),
134+
raw::Status::Err => Err(RedisError::Str("Error while setting key")),
135135
}
136136
}
137137

src/macros.rs

Lines changed: 54 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,62 @@
1-
macro_rules! error {
2-
($message:expr) => {
3-
Error::generic($message)
4-
};
5-
($message:expr, $($arg:tt)*) => {
6-
Error::generic(format!($message, $($arg)+).as_str())
7-
}
8-
}
1+
#[macro_export]
2+
macro_rules! redis_command {
3+
($ctx: expr, $command_name:expr, $command_handler:expr, $command_flags:expr) => {
4+
{
5+
let name = CString::new($command_name).unwrap();
6+
let flags = CString::new($command_flags).unwrap();
7+
let (firstkey, lastkey, keystep) = (1, 1, 1);
98

10-
#[allow(unused_macros)]
11-
macro_rules! log_debug {
12-
($logger:expr, $target:expr) => {
13-
if cfg!(debug_assertions) {
14-
$logger.log_debug($target)
15-
}
16-
};
17-
($logger:expr, $target:expr, $($arg:tt)*) => {
18-
if cfg!(debug_assertions) {
19-
$logger.log_debug(format!($target, $($arg)+).as_str())
9+
/////////////////////
10+
extern fn do_command(
11+
ctx: *mut raw::RedisModuleCtx,
12+
argv: *mut *mut raw::RedisModuleString,
13+
argc: c_int,
14+
) -> c_int {
15+
let context = Context::new(ctx);
16+
17+
let args: Vec<String> = unsafe { slice::from_raw_parts(argv, argc as usize) }
18+
.into_iter()
19+
.map(|a| RedisString::from_ptr(*a).expect("UTF8 encoding error in handler args").to_string())
20+
.collect();
21+
22+
let response = $command_handler(&context, args);
23+
context.reply(response) as c_int
24+
}
25+
/////////////////////
26+
27+
if raw::RedisModule_CreateCommand.unwrap()(
28+
$ctx,
29+
name.as_ptr(),
30+
Some(do_command),
31+
flags.as_ptr(),
32+
firstkey, lastkey, keystep,
33+
) == raw::Status::Err as _ { return raw::Status::Err as _; }
2034
}
2135
}
2236
}
2337

2438
#[macro_export]
2539
macro_rules! redis_module {
26-
($module_name:expr, $module_version:expr, $data_types:expr, $commands:expr) => {
40+
(
41+
name: $module_name:expr,
42+
version: $module_version:expr,
43+
data_types: [
44+
$($data_type:ident),* $(,)*
45+
],
46+
commands: [
47+
$([
48+
$name:expr,
49+
$command:ident,
50+
$flags:expr
51+
]),* $(,)*
52+
] $(,)*
53+
) => {
2754
use std::os::raw::c_int;
2855
use std::ffi::CString;
56+
use std::slice;
2957

3058
use redismodule::raw;
59+
use redismodule::RedisString;
3160

3261
#[no_mangle]
3362
#[allow(non_snake_case)]
@@ -47,31 +76,21 @@ macro_rules! redis_module {
4776
raw::REDISMODULE_APIVER_1 as c_int,
4877
) == raw::Status::Err as _ { return raw::Status::Err as _; }
4978

50-
for data_type in &$data_types {
51-
if data_type.create_data_type(ctx).is_err() {
79+
$(
80+
if (&$data_type).create_data_type(ctx).is_err() {
5281
return raw::Status::Err as _;
5382
}
54-
}
83+
)*
5584

5685
if true {
5786
redismodule::alloc::use_redis_alloc();
5887
} else {
5988
eprintln!("*** NOT USING Redis allocator ***");
6089
}
6190

62-
for command in &$commands {
63-
let name = CString::new(command.name).unwrap();
64-
let flags = CString::new(command.flags).unwrap();
65-
let (firstkey, lastkey, keystep) = (1, 1, 1);
66-
67-
if raw::RedisModule_CreateCommand.unwrap()(
68-
ctx,
69-
name.as_ptr(),
70-
command.wrap_handler(),
71-
flags.as_ptr(),
72-
firstkey, lastkey, keystep,
73-
) == raw::Status::Err as _ { return raw::Status::Err as _; }
74-
}
91+
$(
92+
redis_command!(ctx, $name, $command, $flags);
93+
)*
7594

7695
raw::Status::Ok as _
7796
}

src/redismodule.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ impl From<i64> for RedisValue {
2727
}
2828
}
2929

30+
impl From<()> for RedisValue {
31+
fn from(_: ()) -> Self {
32+
RedisValue::None
33+
}
34+
}
35+
3036
impl From<String> for RedisValue {
3137
fn from(s: String) -> Self {
3238
RedisValue::String(s)

0 commit comments

Comments
 (0)