1use errors::RedisError;
2use redis::{PubSubArg, PubSubClientAsync, RedisClient, RedisClientAsync};
3use results::RedisResult;
4use std::collections::HashMap;
5use types::PubSubType;
6
7pub struct RedisCommand {
25 cmd: Vec<u8>,
26 cmd_nb: usize,
27}
28
29impl<'a> From<&'a mut RedisCommand> for &'a[u8] {
30 fn from(command: &mut RedisCommand) -> &[u8] {
31 &command.cmd[..]
32 }
33}
34
35impl<'a> From<&'a mut RedisCommand> for Vec<u8> {
36 fn from(command: &mut RedisCommand) -> Vec<u8> {
37 command.cmd.clone()
38 }
39}
40
41impl RedisCommand {
42 pub fn new() -> RedisCommand {
43 RedisCommand {
44 cmd: vec![],
45 cmd_nb: 0,
46 }
47 }
48
49 pub fn add_cmd<C>(&mut self, command: C) -> &mut RedisCommand where C: ToString {
51 self.cmd.extend(command.to_string().into_bytes());
52 self
53 }
54
55 pub fn add_arg<A>(&mut self, arg: A) -> &mut RedisCommand where A: ToString {
57 self.cmd.extend([32].iter().cloned());
58 self.cmd.extend(arg.to_string().into_bytes());
59 self
60 }
61
62 pub fn add_args<A>(&mut self, args: Vec<A>) -> &mut RedisCommand where A: ToString {
64 for arg in args {
65 self.cmd.extend([32].iter().cloned());
66 self.cmd.extend(arg.to_string().into_bytes());
67 }
68 self
69 }
70
71 pub fn add_arg_map<F: ToString>(&mut self, args: HashMap<String, F>) -> &mut RedisCommand {
73 for (arg, value) in args {
74 self.cmd.extend([32].iter().cloned());
75 self.cmd.extend(arg.to_string().into_bytes());
76 self.cmd.extend([32].iter().cloned());
77 self.cmd.extend(value.to_string().into_bytes());
78 }
79 self
80 }
81
82 pub fn add_binary_arg(&mut self, arg: &[u8]) -> &mut RedisCommand {
84 self.cmd.extend([32].iter().cloned());
85 self.cmd.extend(arg.iter().cloned());
86 self
87 }
88
89 pub fn end(&mut self) -> &mut RedisCommand {
91 self.cmd.extend([13, 10].iter().cloned());
92 self.cmd_nb += 1;
93 self
94 }
95
96 pub fn get_command_nb(&self) -> usize {
98 self.cmd_nb
99 }
100}
101
102macro_rules! generate_command_traits {
103 ($(
104 fn $func_name:ident$(<$($gen_id:ident: $gen_type:ident),*>)*($($arg_name:ident: $arg_type:ty),*) {
105 $($cmd:ident $bo:expr;)+
106 }
107 )*)
108 =>
109 (
110 pub trait CommandBuilder {
127 $(
128 fn $func_name$(<$($gen_id : $gen_type),*>)* (&mut self $(,$arg_name: $arg_type)*) -> &mut RedisCommand;
129 )*
130 }
131
132 impl CommandBuilder for RedisCommand{
133 $(
134 fn $func_name$(<$($gen_id : $gen_type),*>)* (&mut self $(,$arg_name: $arg_type)*) -> &mut RedisCommand {
135 $(self.$cmd($bo));*;
136 self.end()
137 }
138 )*
139 }
140
141 pub trait CommandSender {
160 $(
161 fn $func_name<R: From<RedisResult>, $($($gen_id : $gen_type),*)*> (&mut self $(,$arg_name: $arg_type)*) -> Result<R, RedisError>;
162 )*
163 }
164
165 impl CommandSender for RedisClient{
166 $(
167 fn $func_name<R: From<RedisResult>, $($($gen_id : $gen_type),*)*> (&mut self $(,$arg_name: $arg_type)*) -> Result<R, RedisError> {
168 let cmd = &mut RedisCommand::new();
169 cmd.$func_name($($arg_name),*);
170
171 let res = try!(self.exec_redis_command(cmd));
172 Ok(res.convert::<R>())
173 }
174 )*
175 }
176
177 pub trait CommandSenderAsync {
197 $(
198 fn $func_name<G: Fn(Result<RedisResult, RedisError>), $($($gen_id : $gen_type),*)*> (&mut self $(,$arg_name: $arg_type)*, callback: G)
199 -> Result<(), RedisError> where G: Send + 'static;
200 )*
201 }
202
203 impl CommandSenderAsync for RedisClientAsync{
204 $(
205 fn $func_name<G: Fn(Result<RedisResult, RedisError>), $($($gen_id : $gen_type),*)*> (&mut self $(,$arg_name: $arg_type)*, callback: G)
206 -> Result<(), RedisError> where G: Send + 'static
207 {
208 let cmd = &mut RedisCommand::new();
209 cmd.$func_name($($arg_name),*);
210
211 try!(self.exec_redis_command_async(cmd, callback));
212 Ok(())
213 }
214 )*
215 }
216
217 pub trait PubSubCommandAsync {
218 fn subscribe<C: ToString, G: Fn(Result<RedisResult, RedisError>), S: Fn(RedisResult)>(&mut self, channel: C, cmd_callback: G, callback: S)
219 -> Result<(), RedisError> where G: Send + 'static, S: Send + 'static;
220
221 fn psubscribe<C: ToString, G: Fn(Result<RedisResult, RedisError>), S: Fn(RedisResult)>(&mut self, channel: C, cmd_callback: G, callback: S)
222 -> Result<(), RedisError> where G: Send + 'static, S: Send + 'static;
223
224 fn publish<C: ToString, M: ToString, G: Fn(Result<RedisResult, RedisError>)>(&mut self, channel: C, message: M, cmd_callback: G)
225 -> Result<(), RedisError> where G: Send + 'static;
226 }
227
228 impl PubSubCommandAsync for PubSubClientAsync {
229 fn subscribe<C: ToString, G: Fn(Result<RedisResult, RedisError>), S: Fn(RedisResult)>(&mut self, channel: C, cmd_callback: G, callback: S)
230 -> Result<(), RedisError> where G: Send + 'static, S: Send + 'static
231 {
232 let channel_str: String = channel.to_string();
233 let cmd = &mut RedisCommand::new();
234 cmd.add_arg("SUBSCRIBE").add_arg(channel).end();
235
236 try!(self.exec_redis_command_async(cmd, cmd_callback, PubSubArg{
237 pubsub_type: PubSubType::Channel(channel_str),
238 callback: Some(Box::new(callback))
239 }));
240 Ok(())
241 }
242
243 fn psubscribe<C: ToString, G: Fn(Result<RedisResult, RedisError>), S: Fn(RedisResult)>(&mut self, channel: C, cmd_callback: G, callback: S)
244 -> Result<(), RedisError> where G: Send + 'static, S: Send + 'static
245 {
246 let channel_str: String = channel.to_string();
247 let cmd = &mut RedisCommand::new();
248 cmd.add_arg("PSUBSCRIBE").add_arg(channel).end();
249
250 try!(self.exec_redis_command_async(cmd, cmd_callback, PubSubArg{
251 pubsub_type: PubSubType::Pattern(channel_str),
252 callback: Some(Box::new(callback))
253 }));
254 Ok(())
255 }
256
257 fn publish<C: ToString, M: ToString, G: Fn(Result<RedisResult, RedisError>)>(&mut self, channel: C, message: M, cmd_callback: G)
258 -> Result<(), RedisError> where G: Send + 'static
259 {
260 let cmd = &mut RedisCommand::new();
261 cmd.add_arg("PUBLISH").add_arg(channel).add_arg(message).end();
262
263 try!(self.exec_redis_command_async(cmd, cmd_callback, PubSubArg{
264 pubsub_type: PubSubType::Simple,
265 callback: None
266 }));
267 Ok(())
268 }
269 }
270 )
271}
272
273generate_command_traits!{
274 fn append<K: ToString, V: ToString>(key: K, value: V) {
275 add_cmd("APPEND");
276 add_arg(key);
277 add_arg(value);
278 }
279
280 fn auth<P: ToString>(password: P) {
281 add_cmd("AUTH");
282 add_arg(password);
283 }
284
285 fn bgrewriteaof() {
286 add_cmd("BGREWRITEAOF");
287 }
288
289 fn bgsave() {
290 add_cmd("BGSAVE");
291 }
292
293 fn bitcount<K: ToString>(key: K) {
294 add_cmd("BITCOUNT");
295 add_arg(key);
296 }
297
298 fn bitcount_range<K: ToString>(key: K, start_range: i64, end_range: i64) {
299 add_cmd("BITCOUNT");
300 add_arg(key);
301 add_arg(start_range);
302 add_arg(end_range);
303 }
304
305 fn blpop<K: ToString>(key: K, timeout: u32) {
306 add_cmd("BLPOP");
307 add_arg(key);
308 add_arg(timeout);
309 }
310
311 fn mblpop<K: ToString>(keys: Vec<K>, timeout: u32) {
312 add_cmd("BLPOP");
313 add_args(keys);
314 add_arg(timeout);
315 }
316
317 fn brpop<K: ToString>(key: K, timeout: u32) {
318 add_cmd("BRPOP");
319 add_arg(key);
320 add_arg(timeout);
321 }
322
323 fn mbrpop<K: ToString>(keys: Vec<K>, timeout: u32) {
324 add_cmd("BRPOP");
325 add_args(keys);
326 add_arg(timeout);
327 }
328
329 fn brpoplpush<S: ToString, D: ToString>(source: S, dest: D, timeout: u32) {
330 add_cmd("BRPOPLPUSH");
331 add_arg(source);
332 add_arg(dest);
333 add_arg(timeout);
334 }
335
336 fn decr<K: ToString>(key: K) {
337 add_cmd("DECR");
338 add_arg(key);
339 }
340
341 fn decrby<K: ToString>(key: K, increment: i64) {
342 add_cmd("DECRBY");
343 add_arg(key);
344 add_arg(increment);
345 }
346
347 fn del<K: ToString>(key: K) {
348 add_cmd("DEL");
349 add_arg(key);
350 }
351
352 fn mdel<K: ToString>(keys: Vec<K>){
353 add_cmd("DEL");
354 add_args(keys);
355 }
356
357 fn discard() {
358 add_cmd("DISCARD");
359 }
360
361 fn echo<K: ToString>(msg: K) {
362 add_cmd("ECHO");
363 add_arg(msg);
364 }
365
366 fn exec() {
367 add_cmd("EXEC");
368 }
369
370 fn exists<K: ToString>(key: K) {
371 add_cmd("EXISTS");
372 add_arg(key);
373 }
374
375 fn mexists<K: ToString>(keys: Vec<K>){
376 add_cmd("EXISTS");
377 add_args(keys);
378 }
379
380 fn expire<K: ToString>(key: K, expiry: i64) {
381 add_cmd("EXPIRE");
382 add_arg(key);
383 add_arg(expiry);
384 }
385
386 fn expireat<K: ToString>(key: K, timestamp: i64) {
387 add_cmd("EXPIREAT");
388 add_arg(key);
389 add_arg(timestamp);
390 }
391
392 fn get<K: ToString>(key: K) {
393 add_cmd("GET");
394 add_arg(key);
395 }
396
397 fn getrange<K: ToString>(key: K, start_range: i64, end_range: i64) {
398 add_cmd("GETRANGE");
399 add_arg(key);
400 add_arg(start_range);
401 add_arg(end_range);
402 }
403
404 fn hdel<K: ToString, F: ToString>(key: K, field: F) {
405 add_cmd("HDEL");
406 add_arg(key);
407 add_arg(field);
408 }
409
410 fn hmdel<K: ToString, V: ToString>(key: K, fields: Vec<V>) {
411 add_cmd("HDEL");
412 add_arg(key);
413 add_args(fields);
414 }
415
416 fn hexists<K: ToString, F: ToString>(key: K, field: F) {
417 add_cmd("HEXISTS");
418 add_arg(key);
419 add_arg(field);
420 }
421
422 fn hget<K: ToString, F: ToString>(key: K, field: F) {
423 add_cmd("HGET");
424 add_arg(key);
425 add_arg(field);
426 }
427
428 fn hgetall<K: ToString>(key: K) {
429 add_cmd("HGETALL");
430 add_arg(key);
431 }
432
433 fn hincrby<K: ToString, F: ToString>(key: K, field: F, increment: i64) {
434 add_cmd("HINCRBY");
435 add_arg(key);
436 add_arg(field);
437 add_arg(increment);
438 }
439
440 fn hincrbyfloat<K: ToString, F: ToString>(key: K, field: F, increment: f64) {
441 add_cmd("HINCRBYBYFLOAT");
442 add_arg(key);
443 add_arg(field);
444 add_arg(increment);
445 }
446
447 fn hkeys<K: ToString>(key: K) {
448 add_cmd("HKEYS");
449 add_arg(key);
450 }
451
452 fn hlen<K: ToString>(key: K) {
453 add_cmd("HLEN");
454 add_arg(key);
455 }
456
457 fn hmget<K: ToString, F: ToString>(key: K, fields: Vec<F>) {
458 add_cmd("HMGET");
459 add_arg(key);
460 add_args(fields);
461 }
462
463 fn hmset<K: ToString>(key: K, fields: HashMap<String, K>) {
464 add_cmd("HMSET");
465 add_arg(key);
466 add_arg_map(fields);
467 }
468
469 fn hset<K: ToString, F: ToString, V: ToString>(key: K, field: F, value: V) {
470 add_cmd("HSET");
471 add_arg(key);
472 add_arg(field);
473 add_arg(value);
474 }
475
476 fn hstrlen<K: ToString, F: ToString>(key: K, field: F) {
477 add_cmd("HSTRLEN");
478 add_arg(key);
479 add_arg(field);
480 }
481
482 fn hsetnx<K: ToString, F: ToString, V: ToString>(key: K, field: F, value: V) {
483 add_cmd("HSETNX");
484 add_arg(key);
485 add_arg(field);
486 add_arg(value);
487 }
488
489 fn hvals<K: ToString>(key: K) {
490 add_cmd("HVALS");
491 add_arg(key);
492 }
493
494 fn lindex<K: ToString>(key: K, index: i32) {
495 add_cmd("LINDEX");
496 add_arg(key);
497 add_arg(index);
498 }
499
500 fn linsert_after<K: ToString, P: ToString, V: ToString>(key: K, pivot: P, value: V) {
501 add_cmd("LINSERT");
502 add_arg(key);
503 add_arg("AFTER");
504 add_arg(pivot);
505 add_arg(value);
506 }
507
508 fn linsert_before<K: ToString, P: ToString, V: ToString>(key: K, pivot: P, value: V) {
509 add_cmd("LINSERT");
510 add_arg(key);
511 add_arg("BEFORE");
512 add_arg(pivot);
513 add_arg(value);
514 }
515
516 fn llen<K: ToString>(key: K) {
517 add_cmd("LLEN");
518 add_arg(key);
519 }
520
521 fn lpop<K: ToString>(key: K) {
522 add_cmd("LPOP");
523 add_arg(key);
524 }
525
526 fn lpush<K: ToString, V: ToString>(key: K, value: V) {
527 add_cmd("LPUSH");
528 add_arg(key);
529 add_arg(value);
530 }
531
532 fn mlpush<K: ToString, V: ToString>(key: K, values: Vec<V>) {
533 add_cmd("LPUSH");
534 add_arg(key);
535 add_args(values);
536 }
537
538 fn lpushx<K: ToString, V: ToString>(key: K, value: V) {
539 add_cmd("LPUSHX");
540 add_arg(key);
541 add_arg(value);
542 }
543
544 fn lrange<K: ToString>(key: K, start: i32, end: i32) {
545 add_cmd("LRANGE");
546 add_arg(key);
547 add_arg(start);
548 add_arg(end);
549 }
550
551 fn lrem<K: ToString, V: ToString>(key: K, count: i32, value: V) {
552 add_cmd("LREM");
553 add_arg(key);
554 add_arg(count);
555 add_arg(value);
556 }
557
558 fn lset<K: ToString, V: ToString>(key: K, index: i32, value: V) {
559 add_cmd("LSET");
560 add_arg(key);
561 add_arg(index);
562 add_arg(value);
563 }
564
565 fn ltrim<K: ToString>(key: K, start: i32, end: i32) {
566 add_cmd("LTRIM");
567 add_arg(key);
568 add_arg(start);
569 add_arg(end);
570 }
571
572 fn multi() {
573 add_cmd("MULTI");
574 }
575
576 fn rename<K: ToString, N: ToString>(key: K, new_key: N) {
577 add_cmd("RENAME");
578 add_arg(key);
579 add_arg(new_key);
580 }
581
582 fn renamenx<K: ToString, N: ToString>(key: K, new_key: N) {
583 add_cmd("RENAMENX");
584 add_arg(key);
585 add_arg(new_key);
586 }
587
588 fn rpop<K: ToString>(key: K) {
589 add_cmd("RPOP");
590 add_arg(key);
591 }
592
593 fn rpoplpush<S: ToString, D: ToString>(source: S, dest: D) {
594 add_cmd("RPOPLPUSH");
595 add_arg(source);
596 add_arg(dest);
597 }
598
599 fn rpush<K: ToString, V: ToString>(key: K, value: V) {
600 add_cmd("RPUSH");
601 add_arg(key);
602 add_arg(value);
603 }
604
605 fn mrpush<K: ToString, V: ToString>(key: K, values: Vec<V>) {
606 add_cmd("RPUSH");
607 add_arg(key);
608 add_args(values);
609 }
610
611 fn rpushx<K: ToString, V: ToString>(key: K, value: V) {
612 add_cmd("RPUSHX");
613 add_arg(key);
614 add_arg(value);
615 }
616
617 fn sadd<K: ToString, M: ToString>(key: K, member: M) {
618 add_cmd("SADD");
619 add_arg(key);
620 add_arg(member);
621 }
622
623 fn msadd<K: ToString, M: ToString>(key: K, members: Vec<M>) {
624 add_cmd("SADD");
625 add_arg(key);
626 add_args(members);
627 }
628
629 fn sadd_binary<K: ToString>(key: K, member: &[u8]) {
630 add_cmd("SADD");
631 add_arg(key);
632 add_binary_arg(member);
633 }
634
635 fn scard<K: ToString>(key: K) {
636 add_cmd("SCARD");
637 add_arg(key);
638 }
639
640 fn select(db_index: i32){
641 add_cmd("SELECT");
642 add_arg(db_index);
643 }
644
645 fn set<K: ToString, V: ToString>(key: K, value: V) {
646 add_cmd("SET");
647 add_arg(key);
648 add_arg(value);
649 }
650
651 fn set_binary<K: ToString>(key: K, value: &[u8]) {
652 add_cmd("SET");
653 add_arg(key);
654 add_binary_arg(value);
655 }
656
657 fn setex<K: ToString, V: ToString>(key: K, value: V, expiry: i64) {
658 add_cmd("SET");
659 add_arg(key);
660 add_arg(value);
661 add_arg("EX");
662 add_arg(expiry);
663 }
664
665 fn psetex<K: ToString, V: ToString>(key: K, value: V, expiry: i64) {
666 add_cmd("SET");
667 add_arg(key);
668 add_arg(value);
669 add_arg("PX");
670 add_arg(expiry);
671 }
672
673 fn setnx<K: ToString, V: ToString>(key: K, value: V) {
674 add_cmd("SET");
675 add_arg(key);
676 add_arg(value);
677 add_arg("NX");
678 }
679
680 fn setxx<K: ToString, V: ToString>(key: K, value: V) {
681 add_cmd("SET");
682 add_arg(key);
683 add_arg(value);
684 add_arg("XX");
685 }
686
687 fn setex_nx<K: ToString, V: ToString>(key: K, value: V, expiry: i64) {
688 add_cmd("SET");
689 add_arg(key);
690 add_arg(value);
691 add_arg("EX");
692 add_arg(expiry);
693 add_arg("NX");
694 }
695
696 fn setex_xx<K: ToString, V: ToString>(key: K, value: V, expiry: i64) {
697 add_cmd("SET");
698 add_arg(key);
699 add_arg(value);
700 add_arg("EX");
701 add_arg(expiry);
702 add_arg("XX");
703 }
704
705 fn psetex_nx<K: ToString, V: ToString>(key: K, value: V, expiry: i64) {
706 add_cmd("SET");
707 add_arg(key);
708 add_arg(value);
709 add_arg("PX");
710 add_arg(expiry);
711 add_arg("NX");
712 }
713
714 fn psetex_xx<K: ToString, V: ToString>(key: K, value: V, expiry: i64) {
715 add_cmd("SET");
716 add_arg(key);
717 add_arg(value);
718 add_arg("PX");
719 add_arg(expiry);
720 add_arg("XX");
721 }
722
723 fn setbit<K: ToString>(key: K, offset: u32, bit: u8) {
724 add_cmd("SETBIT");
725 add_arg(key);
726 add_arg(offset);
727 add_arg(bit);
728 }
729
730 fn setrange<K: ToString, V: ToString>(key: K, offset: u32, value: V) {
731 add_cmd("SETRANGE");
732 add_arg(key);
733 add_arg(offset);
734 add_arg(value);
735 }
736
737 fn sismember<K: ToString, M: ToString>(key: K, member: M) {
738 add_cmd("SISMEMBER");
739 add_arg(key);
740 add_arg(member);
741 }
742
743 fn smembers<K: ToString>(key: K) {
744 add_cmd("SMEMBERS");
745 add_arg(key);
746 }
747
748 fn spop<K: ToString>(key: K) {
749 add_cmd("SPOP");
750 add_arg(key);
751 }
752
753 fn spop_count<K: ToString>(key: K, count: u32) {
754 add_cmd("SPOP");
755 add_arg(key);
756 add_arg(count);
757 }
758
759 fn srem<K: ToString, M: ToString>(key: K, member: M) {
760 add_cmd("SREM");
761 add_arg(key);
762 add_arg(member);
763 }
764
765 fn msrem<K: ToString, M: ToString>(key: K, members: Vec<M>) {
766 add_cmd("SREM");
767 add_arg(key);
768 add_args(members);
769 }
770
771 fn strlen<K: ToString>(key: K) {
772 add_cmd("STRLEN");
773 add_arg(key);
774 }
775
776 fn ttl<K: ToString>(key: K) {
777 add_cmd("TTL");
778 add_arg(key);
779 }
780
781 fn unwatch() {
782 add_cmd("UNWATCH");
783 }
784
785 fn watch<K: ToString>(key: K) {
786 add_cmd("WATCH");
787 add_arg(key);
788 }
789
790 fn mwatch<K: ToString>(keys: Vec<K>) {
791 add_cmd("WATCH");
792 add_args(keys);
793 }
794
795 fn zadd<K: ToString, V: ToString>(key: K, score: f64, member: V) {
796 add_cmd("ZADD");
797 add_arg(key);
798 add_arg(score);
799 add_arg(member);
800 }
801
802 fn zadd_binary<K: ToString>(key: K, score: f64, member: &[u8]) {
803 add_cmd("ZADD");
804 add_arg(key);
805 add_arg(score);
806 add_binary_arg(member);
807 }
808
809 fn zaddnx<K: ToString, V: ToString>(key: K, score: f64, member: V) {
810 add_cmd("ZADD");
811 add_arg(key);
812 add_arg("NX");
813 add_arg(score);
814 add_arg(member);
815 }
816
817 fn zaddxx<K: ToString, V: ToString>(key: K, score: f64, member: V) {
818 add_cmd("ZADD");
819 add_arg(key);
820 add_arg("XX");
821 add_arg(score);
822 add_arg(member);
823 }
824
825 fn zaddnx_ch<K: ToString, V: ToString>(key: K, score: f64, member: V) {
826 add_cmd("ZADD");
827 add_arg(key);
828 add_arg("NX");
829 add_arg("CH");
830 add_arg(score);
831 add_arg(member);
832 }
833
834 fn zaddxx_ch<K: ToString, V: ToString>(key: K, score: f64, member: V) {
835 add_cmd("ZADD");
836 add_arg(key);
837 add_arg("XX");
838 add_arg("CH");
839 add_arg(score);
840 add_arg(member);
841 }
842
843 fn zcard<K: ToString>(key: K) {
844 add_cmd("ZCARD");
845 add_arg(key);
846 }
847
848 fn zcount<K: ToString, S: ToString, E: ToString>(key: K, start_range: S, end_range: E) {
849 add_cmd("ZCOUNT");
850 add_arg(key);
851 add_arg(start_range);
852 add_arg(end_range);
853 }
854
855 fn zincrby<K: ToString, V: ToString>(key: K, increment: f64, member: V) {
856 add_cmd("ZINCRBY");
857 add_arg(key);
858 add_arg(increment);
859 add_arg(member);
860 }
861
862 fn zlexcount<K: ToString, S: ToString, E: ToString>(key: K, min: S, max: E) {
863 add_cmd("ZLEXCOUNT");
864 add_arg(key);
865 add_arg(min);
866 add_arg(max);
867 }
868
869 fn zrem<K: ToString, M: ToString>(key: K, member: M) {
870 add_cmd("ZREM");
871 add_arg(key);
872 add_arg(member);
873 }
874
875 fn mzrem<K: ToString, M: ToString>(key: K, members: Vec<M>) {
876 add_cmd("ZREM");
877 add_arg(key);
878 add_args(members);
879 }
880
881 fn zrange<K: ToString>(key: K, start_range: i64, end_range: i64) {
882 add_cmd("ZRANGE");
883 add_arg(key);
884 add_arg(start_range);
885 add_arg(end_range);
886 }
887
888 fn zrange_with_scores<K: ToString>(key: K, start_range: i64, end_range: i64) {
889 add_cmd("ZRANGE");
890 add_arg(key);
891 add_arg(start_range);
892 add_arg(end_range);
893 add_arg("WITHSCORES");
894 }
895
896 fn zrevrange<K: ToString>(key: K, start_range: i64, end_range: i64) {
897 add_cmd("ZREVRANGE");
898 add_arg(key);
899 add_arg(start_range);
900 add_arg(end_range);
901 }
902
903 fn zrevrange_with_scores<K: ToString>(key: K, start_range: i64, end_range: i64) {
904 add_cmd("ZREVRANGE");
905 add_arg(key);
906 add_arg(start_range);
907 add_arg(end_range);
908 add_arg("WITHSCORES");
909 }
910
911}
912