Skip to content

Commit c9a62cb

Browse files
committed
More Command wrapper improvements
1 parent 3c89a00 commit c9a62cb

File tree

4 files changed

+155
-69
lines changed

4 files changed

+155
-69
lines changed

examples/hello.rs

Lines changed: 19 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -4,90 +4,43 @@ extern crate libc;
44

55
use libc::c_int;
66

7+
#[macro_use]
78
extern crate redismodule;
89

9-
use redismodule::raw;
1010
use redismodule::Context;
1111
use redismodule::{Command, RedisResult, RedisValue, RedisError};
1212

13-
const MODULE_NAME: &str = "hello";
14-
const MODULE_VERSION: u32 = 1;
15-
16-
1713
fn hello_mul(_: &Context, args: Vec<String>) -> RedisResult {
1814
if args.len() != 3 {
1915
return Err(RedisError::WrongArity);
2016
}
2117

22-
// TODO: Write generic RedisValue::parse method
23-
if let RedisValue::Integer(m1) = parse_integer(&args[1])? {
24-
if let RedisValue::Integer(m2) = parse_integer(&args[2])? {
25-
let result = m1 * m2;
18+
let m1 = parse_integer(&args[1])?;
19+
let m2 = parse_integer(&args[2])?;
2620

27-
return Ok(RedisValue::Array(
28-
vec![m1, m2, result]
29-
.into_iter()
30-
.map(|v| RedisValue::Integer(v))
31-
.collect()));
32-
}
33-
}
21+
let result = m1 * m2;
3422

35-
Err(RedisError::String("Something went wrong"))
23+
return Ok(RedisValue::Array(
24+
vec![m1, m2, result]
25+
.into_iter()
26+
.map(|v| RedisValue::Integer(v))
27+
.collect()));
3628
}
3729

3830
//////////////////////////////////////////////////////
3931

40-
#[no_mangle]
41-
#[allow(non_snake_case)]
42-
pub extern "C" fn RedisModule_OnLoad(
43-
ctx: *mut raw::RedisModuleCtx,
44-
_argv: *mut *mut raw::RedisModuleString,
45-
_argc: c_int,
46-
) -> c_int {
47-
unsafe {
48-
//////////////////
49-
50-
let module_name = MODULE_NAME;
51-
let module_version = MODULE_VERSION;
52-
53-
let commands = [
54-
Command::new("hello.mul", hello_mul, "write"),
55-
];
56-
57-
//////////////////
58-
59-
let module_name = CString::new(module_name).unwrap();
60-
let module_version = module_version as c_int;
61-
62-
if raw::Export_RedisModule_Init(
63-
ctx,
64-
module_name.as_ptr(),
65-
module_version,
66-
raw::REDISMODULE_APIVER_1 as c_int,
67-
) == raw::Status::Err as _ { return raw::Status::Err as _; }
32+
fn parse_integer(arg: &str) -> Result<i64, RedisError> {
33+
arg.parse::<i64>()
34+
.map_err(|_| RedisError::String("Couldn't parse as integer"))
35+
}
6836

69-
for command in &commands {
70-
let name = CString::new(command.name).unwrap();
71-
let flags = CString::new(command.flags).unwrap();
72-
let (firstkey, lastkey, keystep) = (1, 1, 1);
37+
//////////////////////////////////////////////////////
7338

74-
if raw::RedisModule_CreateCommand.unwrap()(
75-
ctx,
76-
name.as_ptr(),
77-
command.wrap_handler(),
78-
flags.as_ptr(),
79-
firstkey, lastkey, keystep,
80-
) == raw::Status::Err as _ { return raw::Status::Err as _; }
81-
}
39+
const MODULE_NAME: &str = "hello";
40+
const MODULE_VERSION: u32 = 1;
8241

83-
raw::Status::Ok as _
84-
}
85-
}
42+
redis_module!(MODULE_NAME, MODULE_VERSION, [
43+
Command::new("hello.mul", hello_mul, "write"),
44+
]);
8645

87-
fn parse_integer(arg: &str) -> RedisResult {
88-
arg.parse::<i64>()
89-
.map_err(|_| RedisError::String("Couldn't parse as integer"))
90-
.map(|v| RedisValue::Integer(v))
91-
//Error::generic(format!("Couldn't parse as integer: {}", arg).as_str()))
92-
}
9346

src/macros.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,45 @@ macro_rules! log_debug {
2121
}
2222
}
2323

24+
#[macro_export]
25+
macro_rules! redis_module (
26+
($module_name:expr, $module_version:expr, $commands:expr) => (
27+
use redismodule::raw;
28+
29+
#[no_mangle]
30+
#[allow(non_snake_case)]
31+
pub extern "C" fn RedisModule_OnLoad(
32+
ctx: *mut raw::RedisModuleCtx,
33+
_argv: *mut *mut raw::RedisModuleString,
34+
_argc: c_int,
35+
) -> c_int {
36+
unsafe {
37+
let module_name = CString::new($module_name).unwrap();
38+
let module_version = $module_version as c_int;
39+
40+
if raw::Export_RedisModule_Init(
41+
ctx,
42+
module_name.as_ptr(),
43+
module_version,
44+
raw::REDISMODULE_APIVER_1 as c_int,
45+
) == raw::Status::Err as _ { return raw::Status::Err as _; }
46+
47+
for command in &$commands {
48+
let name = CString::new(command.name).unwrap();
49+
let flags = CString::new(command.flags).unwrap();
50+
let (firstkey, lastkey, keystep) = (1, 1, 1);
51+
52+
if raw::RedisModule_CreateCommand.unwrap()(
53+
ctx,
54+
name.as_ptr(),
55+
command.wrap_handler(),
56+
flags.as_ptr(),
57+
firstkey, lastkey, keystep,
58+
) == raw::Status::Err as _ { return raw::Status::Err as _; }
59+
}
60+
61+
raw::Status::Ok as _
62+
}
63+
}
64+
)
65+
);

src/redismodule.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ use std::slice;
22
use std::str;
33
use std::ffi::CString;
44

5-
use crate::raw;
5+
pub type RedisResult = Result<RedisValue, RedisError>;
66

7-
pub type RedisResult = ::std::result::Result<RedisValue, RedisError>;
7+
use crate::raw;
88

99
#[derive(Debug)]
1010
pub enum RedisError {
@@ -35,7 +35,6 @@ impl RedisString {
3535
RedisString { ctx, inner }
3636
}
3737

38-
3938
pub fn from_ptr<'a>(ptr: *mut raw::RedisModuleString) -> Result<&'a str, str::Utf8Error> {
4039
let mut len: libc::size_t = 0;
4140
let bytes = unsafe { raw::RedisModule_StringPtrLen.unwrap()(ptr, &mut len) };

unused/hello_no_macros.rs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
use std::ffi::CString;
2+
3+
extern crate libc;
4+
5+
use libc::c_int;
6+
7+
extern crate redismodule;
8+
9+
use redismodule::raw;
10+
use redismodule::Context;
11+
use redismodule::{Command, RedisResult, RedisValue, RedisError};
12+
13+
const MODULE_NAME: &str = "hello";
14+
const MODULE_VERSION: u32 = 1;
15+
16+
17+
fn hello_mul(_: &Context, args: Vec<String>) -> RedisResult {
18+
if args.len() != 3 {
19+
return Err(RedisError::WrongArity);
20+
}
21+
22+
// TODO: Write generic RedisValue::parse method
23+
if let RedisValue::Integer(m1) = parse_integer(&args[1])? {
24+
if let RedisValue::Integer(m2) = parse_integer(&args[2])? {
25+
let result = m1 * m2;
26+
27+
return Ok(RedisValue::Array(
28+
vec![m1, m2, result]
29+
.into_iter()
30+
.map(|v| RedisValue::Integer(v))
31+
.collect()));
32+
}
33+
}
34+
35+
Err(RedisError::String("Something went wrong"))
36+
}
37+
38+
//////////////////////////////////////////////////////
39+
40+
#[no_mangle]
41+
#[allow(non_snake_case)]
42+
pub extern "C" fn RedisModule_OnLoad(
43+
ctx: *mut raw::RedisModuleCtx,
44+
_argv: *mut *mut raw::RedisModuleString,
45+
_argc: c_int,
46+
) -> c_int {
47+
unsafe {
48+
//////////////////
49+
50+
let module_name = MODULE_NAME;
51+
let module_version = MODULE_VERSION;
52+
53+
let commands = [
54+
Command::new("hello.mul", hello_mul, "write"),
55+
];
56+
57+
//////////////////
58+
59+
let module_name = CString::new(module_name).unwrap();
60+
let module_version = module_version as c_int;
61+
62+
if raw::Export_RedisModule_Init(
63+
ctx,
64+
module_name.as_ptr(),
65+
module_version,
66+
raw::REDISMODULE_APIVER_1 as c_int,
67+
) == raw::Status::Err as _ { return raw::Status::Err as _; }
68+
69+
for command in &commands {
70+
let name = CString::new(command.name).unwrap();
71+
let flags = CString::new(command.flags).unwrap();
72+
let (firstkey, lastkey, keystep) = (1, 1, 1);
73+
74+
if raw::RedisModule_CreateCommand.unwrap()(
75+
ctx,
76+
name.as_ptr(),
77+
command.wrap_handler(),
78+
flags.as_ptr(),
79+
firstkey, lastkey, keystep,
80+
) == raw::Status::Err as _ { return raw::Status::Err as _; }
81+
}
82+
83+
raw::Status::Ok as _
84+
}
85+
}
86+
87+
fn parse_integer(arg: &str) -> RedisResult {
88+
arg.parse::<i64>()
89+
.map_err(|_| RedisError::String("Couldn't parse as integer"))
90+
.map(|v| RedisValue::Integer(v))
91+
//Error::generic(format!("Couldn't parse as integer: {}", arg).as_str()))
92+
}

0 commit comments

Comments
 (0)