Я создаю модуль Redis в Rust.Я нашел несколько хороших примеров, но я застрял при работе с интерфейсом C-функции, которая должна принимать переменные аргументы.
В Redis Module C SDK есть функция с именем RedisModule_Call
, которая принимает несколько конкретных аргументов, а затем n
аргументы, представляющие команду Redis.Из документации Redis Module SDK (на языке C): первые три аргумента
RedisModuleCallReply *reply;
reply = RedisModule_Call(ctx,"INCR","sc",argv[1],"10");
RedisModule_Call
являются конкретными, но остальные представляют команды Redis, которые могут легко иметь сотни аргументов.
В Rust я следую шаблонам в Redis-Cell , который является модулем Redis, реализованным (успешно) в Rust.Модуль фантастический, но имеет очень ограниченный способ решения этой конкретной проблемы.По сути, он принимает до трех аргументов в несколько грубой форме:
pub fn call(&self, command: &str, args: &[&str]) -> Result<Reply, CellError> {
// ... code ...
let raw_reply = match args.len() {
1 => raw::call1::call(/* ... */),
2 => raw::call2::call(/* ... */),
// ...
Эти call1
и call2
функции являются практически просто заглушками, которые обрабатывают различные длины аргументов:
pub mod call2 {
use redis::raw;
pub fn call(
ctx: *mut raw::RedisModuleCtx,
cmdname: *const u8,
fmt: *const u8,
arg0: *mut raw::RedisModuleString,
arg1: *mut raw::RedisModuleString,
) -> *mut raw::RedisModuleCallReply {
unsafe { RedisModule_Call(ctx, cmdname, fmt, arg0, arg1) }
}
#[allow(improper_ctypes)]
extern "C" {
pub static RedisModule_Call: extern "C" fn(
ctx: *mut raw::RedisModuleCtx,
cmdname: *const u8,
fmt: *const u8,
arg0: *mut raw::RedisModuleString,
arg1: *mut raw::RedisModuleString,
) -> *mut raw::RedisModuleCallReply;
}
}
Мне нужно иметь возможность передавать n
аргументы, при этом n
определяется во время выполнения, поэтому этот метод жесткого кодирования не практичен.Я знаю, что Rust имеет ограниченную поддержку функций с переменными значениями, и я немного читал о RFC 2137, но я не уверен, что это применимо.
Я ищу способ применить вектор аргумента к концу RedisModule_Call
или что-то вроде синтаксиса расширения для аргументов.Я относительно новичок в Rust, но я искал и искал, и я не могу найти какой-либо способ поцарапать этот зуд в Rust.
Чтобы уточнить - я могу передать аргументы в RedisModule_Call
(которыйэто не проблема, но я не могу найти синтаксический способ передать переменное число аргументов в Rust в функцию C.Я пытаюсь сделать что-то вроде этого:
impl Redis {
pub fn call(&self, command: &str, args: &[&str]) -> Result<Reply, CellError> {
/* ... */
unsafe { RedisModule_Call(ctx, cmdname, fmt, ...args) }
/* ... */
Где ...args
- это какая-то черная магия, которая позволяет аргументам представлять 1 аргумент или 100, что эквивалентно RedisModule_Call(ctx, cmdname, fmt, args[0], args[1] /* ... and so on */)
.