1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use crc16::key_hash_slot;
use redis::{Cmd, Connection, ToRedisArgs, FromRedisValue, RedisResult};
pub struct ClusterCmd {
cmd: Cmd,
args: Vec<Vec<u8>>,
}
impl ClusterCmd {
pub fn new() -> ClusterCmd {
ClusterCmd {
cmd: Cmd::new(),
args: Vec::new(),
}
}
pub fn arg<T: ToRedisArgs>(&mut self, arg: T) -> &mut ClusterCmd {
for item in arg.to_redis_args().into_iter() {
self.args.push(item);
}
self.cmd.arg(arg);
self
}
pub fn query<T: FromRedisValue>(&self, conn: &Connection) -> RedisResult<T> {
self.cmd.query(conn)
}
pub fn slot(&self) -> Option<u16> {
slot_for_command(&self.args)
}
}
fn slot_for_command(args: &Vec<Vec<u8>>) -> Option<u16> {
if args.len() > 1 {
Some(key_hash_slot(args[1].as_slice()))
} else {
None
}
}
pub fn slot_for_packed_command(cmd: &[u8]) -> Option<u16> {
let args = unpack_command(cmd);
slot_for_command(&args)
}
fn unpack_command(cmd: &[u8]) -> Vec<Vec<u8>> {
let mut arg: Vec<u8> = Vec::new();
let mut args: Vec<Vec<u8>> = Vec::new();
let mut iter = cmd.iter().skip(2).peekable();
'outer: loop {
let b = *iter.next().unwrap();
if b == 13 && iter.peek().unwrap() == &&10 {
if arg.len() > 0 {
args.push(arg.clone());
arg.clear();
}
iter.next();
match iter.next() {
Some(_) => (),
None => break 'outer,
};
'inner: loop {
let b = *iter.next().unwrap();
if b == 13 && iter.peek().unwrap() == &&10 {
iter.next();
break 'inner;
}
}
} else {
arg.push(b);
}
}
args
}