1 /*
2 * Hunt - A redis client library for D programming language.
3 *
4 * Copyright (C) 2018-2019 HuntLabs
5 *
6 * Website: https://www.huntlabs.net/
7 *
8 * Licensed under the Apache-2.0 License.
9 *
10 */
11
12 module hunt.redis.BinaryClient;
13
14 import hunt.redis.AbstractClient;
15 import hunt.redis.BitOP;
16 import hunt.redis.BitPosParams;
17 import hunt.redis.ListPosition;
18 import hunt.redis.GeoCoordinate;
19 import hunt.redis.GeoUnit;
20 import hunt.redis.Protocol;
21 import hunt.redis.ScanParams;
22 import hunt.redis.SortingParams;
23 import hunt.redis.ZParams;
24
25 // import hunt.redis.Protocol.Keyword;
26 import hunt.redis.params.ClientKillParams;
27 import hunt.redis.params.GeoRadiusParam;
28 import hunt.redis.params.MigrateParams;
29 import hunt.redis.params.SetParams;
30 import hunt.redis.params.ZAddParams;
31 import hunt.redis.params.ZIncrByParams;
32 import hunt.redis.util.SafeEncoder;
33
34 import hunt.collection.ArrayList;
35 import hunt.collection.List;
36 import hunt.collection.Map;
37
38 import std.conv;
39
40 alias Keyword = Protocol.Keyword;
41 alias Command = Protocol.Command;
42 alias toByteArray = Protocol.toByteArray;
43
44 class BinaryClient : AbstractClient {
45
46 private bool _isInMulti;
47
48 private string password;
49
50 private int db;
51
52 private bool _isInWatch;
53
54 this() {
55 super();
56 }
57
58 this(string host) {
59 super(host);
60 }
61
62 this(string host, int port) {
63 super(host, port);
64 }
65
66 this(string host, int port, bool ssl) {
67 super(host, port, ssl);
68 }
69
70 // this(string host, int port, bool ssl,
71 // SSLSocketFactory sslSocketFactory, SSLParameters sslParameters,
72 // HostnameVerifier hostnameVerifier) {
73 // super(host, port, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
74 // }
75
76 bool isInMulti() {
77 return _isInMulti;
78 }
79
80 bool isInWatch() {
81 return _isInWatch;
82 }
83
84 private const(ubyte)[][] joinParameters(const(ubyte)[] first, const(ubyte)[][] rest) {
85 const(ubyte)[][] result = new const(ubyte)[][rest.length + 1];
86 result[0] = first;
87 // System.arraycopy(rest, 0, result, 1, rest.length);
88 result[1 .. $] = rest[0 .. $];
89 return result;
90 }
91
92 private const(ubyte)[][] joinParameters(const(ubyte)[] first, const(ubyte)[] second, const(ubyte)[][] rest) {
93 const(ubyte)[][] result = new const(ubyte)[][rest.length + 2];
94 result[0] = first;
95 result[1] = second;
96 // System.arraycopy(rest, 0, result, 2, rest.length);
97 result[2 .. $] = rest[0 .. $];
98 return result;
99 }
100
101 void setPassword(string password) {
102 this.password = password;
103 }
104
105 void setDb(int db) {
106 this.db = db;
107 }
108
109 override
110 void connect() {
111 if (!isConnected()) {
112 super.connect();
113 if (password !is null) {
114 auth(password);
115 getStatusCodeReply();
116 }
117 if (db > 0) {
118 select(db);
119 getStatusCodeReply();
120 }
121 }
122 }
123
124 void ping() {
125 sendCommand(Command.PING);
126 }
127
128 void ping(const(ubyte)[] message) {
129 sendCommand(Command.PING, [message]);
130 }
131
132 void set(const(ubyte)[] key, const(ubyte)[] value) {
133 sendCommand(Command.SET, key, value);
134 }
135
136 void set(const(ubyte)[] key, const(ubyte)[] value, SetParams params) {
137 sendCommand(Command.SET, params.getByteParams(key, value));
138 }
139
140 void get(const(ubyte)[] key) {
141 sendCommand(Command.GET, key);
142 }
143
144 void quit() {
145 db = 0;
146 sendCommand(Command.QUIT);
147 }
148
149 void exists(const(ubyte)[][] keys...) {
150 sendCommand(Command.EXISTS, keys);
151 }
152
153 void del(const(ubyte)[][] keys...) {
154 sendCommand(Command.DEL, keys);
155 }
156
157 void unlink(const(ubyte)[][] keys...) {
158 sendCommand(Command.UNLINK, keys);
159 }
160
161 void type(const(ubyte)[] key) {
162 sendCommand(Command.TYPE, key);
163 }
164
165 void flushDB() {
166 sendCommand(Command.FLUSHDB);
167 }
168
169 void keys(const(ubyte)[] pattern) {
170 sendCommand(Command.KEYS, pattern);
171 }
172
173 void randomKey() {
174 sendCommand(Command.RANDOMKEY);
175 }
176
177 void rename(const(ubyte)[] oldkey, const(ubyte)[] newkey) {
178 sendCommand(Command.RENAME, oldkey, newkey);
179 }
180
181 void renamenx(const(ubyte)[] oldkey, const(ubyte)[] newkey) {
182 sendCommand(Command.RENAMENX, oldkey, newkey);
183 }
184
185 void dbSize() {
186 sendCommand(Command.DBSIZE);
187 }
188
189 void expire(const(ubyte)[] key, int seconds) {
190 sendCommand(Command.EXPIRE, key, toByteArray(seconds));
191 }
192
193 void expireAt(const(ubyte)[] key, long unixTime) {
194 sendCommand(Command.EXPIREAT, key, toByteArray(unixTime));
195 }
196
197 void ttl(const(ubyte)[] key) {
198 sendCommand(Command.TTL, key);
199 }
200
201 void touch(const(ubyte)[][] keys...) {
202 sendCommand(Command.TOUCH, keys);
203 }
204
205 void select(int index) {
206 sendCommand(Command.SELECT, toByteArray(index));
207 }
208
209 void swapDB(int index1, int index2) {
210 sendCommand(Command.SWAPDB, toByteArray(index1), toByteArray(index2));
211 }
212
213 void move(const(ubyte)[] key, int dbIndex) {
214 sendCommand(Command.MOVE, key, toByteArray(dbIndex));
215 }
216
217 void flushAll() {
218 sendCommand(Command.FLUSHALL);
219 }
220
221 void getSet(const(ubyte)[] key, const(ubyte)[] value) {
222 sendCommand(Command.GETSET, key, value);
223 }
224
225 void mget(const(ubyte)[][] keys...) {
226 sendCommand(Command.MGET, keys);
227 }
228
229 void setnx(const(ubyte)[] key, const(ubyte)[] value) {
230 sendCommand(Command.SETNX, key, value);
231 }
232
233 void setex(const(ubyte)[] key, int seconds, const(ubyte)[] value) {
234 sendCommand(Command.SETEX, key, toByteArray(seconds), value);
235 }
236
237 void mset(const(ubyte)[][] keysvalues...) {
238 sendCommand(Command.MSET, keysvalues);
239 }
240
241 void msetnx(const(ubyte)[][] keysvalues...) {
242 sendCommand(Command.MSETNX, keysvalues);
243 }
244
245 void decrBy(const(ubyte)[] key, long decrement) {
246 sendCommand(Command.DECRBY, key, toByteArray(decrement));
247 }
248
249 void decr(const(ubyte)[] key) {
250 sendCommand(Command.DECR, key);
251 }
252
253 void incrBy(const(ubyte)[] key, long increment) {
254 sendCommand(Command.INCRBY, key, toByteArray(increment));
255 }
256
257 void incrByFloat(const(ubyte)[] key, double increment) {
258 sendCommand(Command.INCRBYFLOAT, key, toByteArray(increment));
259 }
260
261 void incr(const(ubyte)[] key) {
262 sendCommand(Command.INCR, key);
263 }
264
265 void append(const(ubyte)[] key, const(ubyte)[] value) {
266 sendCommand(Command.APPEND, key, value);
267 }
268
269 void substr(const(ubyte)[] key, int start, int end) {
270 sendCommand(Command.SUBSTR, key, toByteArray(start), toByteArray(end));
271 }
272
273 void hset(const(ubyte)[] key, const(ubyte)[] field, const(ubyte)[] value) {
274 sendCommand(Command.HSET, key, field, value);
275 }
276
277 void hset(const(ubyte)[] key, Map!(const(ubyte)[], const(ubyte)[]) hash) {
278 const(ubyte)[][] params = new const(ubyte)[][1 + hash.size() * 2];
279
280 int index = 0;
281 params[index++] = key;
282 foreach (const(ubyte)[] k, const(ubyte)[] value; hash) {
283 params[index++] = k;
284 params[index++] = value;
285 }
286 sendCommand(Command.HSET, params);
287 }
288
289 void hget(const(ubyte)[] key, const(ubyte)[] field) {
290 sendCommand(Command.HGET, key, field);
291 }
292
293 void hsetnx(const(ubyte)[] key, const(ubyte)[] field, const(ubyte)[] value) {
294 sendCommand(Command.HSETNX, key, field, value);
295 }
296
297 void hmset(const(ubyte)[] key, Map!(const(ubyte)[], const(ubyte)[]) hash) {
298 List!(const(ubyte)[]) params = new ArrayList!(const(ubyte)[])();
299 params.add(key);
300
301 foreach(const(ubyte)[] k, const(ubyte)[] value ; hash) {
302 params.add(k);
303 params.add(value);
304 }
305 sendCommand(Command.HMSET, params.toArray());
306 }
307
308 void hmget(const(ubyte)[] key, const(ubyte)[][] fields...) {
309 sendCommand(Command.HMGET, joinParameters(key, fields));
310 }
311
312 void hincrBy(const(ubyte)[] key, const(ubyte)[] field, long value) {
313 sendCommand(Command.HINCRBY, key, field, toByteArray(value));
314 }
315
316 void hexists(const(ubyte)[] key, const(ubyte)[] field) {
317 sendCommand(Command.HEXISTS, key, field);
318 }
319
320 void hdel(const(ubyte)[] key, const(ubyte)[][] fields...) {
321 sendCommand(Command.HDEL, joinParameters(key, fields));
322 }
323
324 void hlen(const(ubyte)[] key) {
325 sendCommand(Command.HLEN, key);
326 }
327
328 void hkeys(const(ubyte)[] key) {
329 sendCommand(Command.HKEYS, key);
330 }
331
332 void hvals(const(ubyte)[] key) {
333 sendCommand(Command.HVALS, key);
334 }
335
336 void hgetAll(const(ubyte)[] key) {
337 sendCommand(Command.HGETALL, key);
338 }
339
340 void rpush(const(ubyte)[] key, const(ubyte)[][] strings...) {
341 sendCommand(Command.RPUSH, joinParameters(key, strings));
342 }
343
344 void lpush(const(ubyte)[] key, const(ubyte)[][] strings...) {
345 sendCommand(Command.LPUSH, joinParameters(key, strings));
346 }
347
348 void llen(const(ubyte)[] key) {
349 sendCommand(Command.LLEN, key);
350 }
351
352 void lrange(const(ubyte)[] key, long start, long stop) {
353 sendCommand(Command.LRANGE, key, toByteArray(start), toByteArray(stop));
354 }
355
356 void ltrim(const(ubyte)[] key, long start, long stop) {
357 sendCommand(Command.LTRIM, key, toByteArray(start), toByteArray(stop));
358 }
359
360 void lindex(const(ubyte)[] key, long index) {
361 sendCommand(Command.LINDEX, key, toByteArray(index));
362 }
363
364 void lset(const(ubyte)[] key, long index, const(ubyte)[] value) {
365 sendCommand(Command.LSET, key, toByteArray(index), value);
366 }
367
368 void lrem(const(ubyte)[] key, long count, const(ubyte)[] value) {
369 sendCommand(Command.LREM, key, toByteArray(count), value);
370 }
371
372 void lpop(const(ubyte)[] key) {
373 sendCommand(Command.LPOP, key);
374 }
375
376 void rpop(const(ubyte)[] key) {
377 sendCommand(Command.RPOP, key);
378 }
379
380 void rpoplpush(const(ubyte)[] srckey, const(ubyte)[] dstkey) {
381 sendCommand(Command.RPOPLPUSH, srckey, dstkey);
382 }
383
384 void sadd(const(ubyte)[] key, const(ubyte)[][] members...) {
385 sendCommand(Command.SADD, joinParameters(key, members));
386 }
387
388 void smembers(const(ubyte)[] key) {
389 sendCommand(Command.SMEMBERS, key);
390 }
391
392 void srem(const(ubyte)[] key, const(ubyte)[][] members...) {
393 sendCommand(Command.SREM, joinParameters(key, members));
394 }
395
396 void spop(const(ubyte)[] key) {
397 sendCommand(Command.SPOP, key);
398 }
399
400 void spop(const(ubyte)[] key, long count) {
401 sendCommand(Command.SPOP, key, toByteArray(count));
402 }
403
404 void smove(const(ubyte)[] srckey, const(ubyte)[] dstkey, const(ubyte)[] member) {
405 sendCommand(Command.SMOVE, srckey, dstkey, member);
406 }
407
408 void scard(const(ubyte)[] key) {
409 sendCommand(Command.SCARD, key);
410 }
411
412 void sismember(const(ubyte)[] key, const(ubyte)[] member) {
413 sendCommand(Command.SISMEMBER, key, member);
414 }
415
416 void sinter(const(ubyte)[][] keys...) {
417 sendCommand(Command.SINTER, keys);
418 }
419
420 void sinterstore(const(ubyte)[] dstkey, const(ubyte)[][] keys...) {
421 sendCommand(Command.SINTERSTORE, joinParameters(dstkey, keys));
422 }
423
424 void sunion(const(ubyte)[][] keys...) {
425 sendCommand(Command.SUNION, keys);
426 }
427
428 void sunionstore(const(ubyte)[] dstkey, const(ubyte)[][] keys...) {
429 sendCommand(Command.SUNIONSTORE, joinParameters(dstkey, keys));
430 }
431
432 void sdiff(const(ubyte)[][] keys...) {
433 sendCommand(Command.SDIFF, keys);
434 }
435
436 void sdiffstore(const(ubyte)[] dstkey, const(ubyte)[][] keys...) {
437 sendCommand(Command.SDIFFSTORE, joinParameters(dstkey, keys));
438 }
439
440 void srandmember(const(ubyte)[] key) {
441 sendCommand(Command.SRANDMEMBER, key);
442 }
443
444 void zadd(const(ubyte)[] key, double score, const(ubyte)[] member) {
445 sendCommand(Command.ZADD, key, toByteArray(score), member);
446 }
447
448 void zadd(const(ubyte)[] key, double score, const(ubyte)[] member,
449 ZAddParams params) {
450 sendCommand(Command.ZADD, params.getByteParams(key, toByteArray(score), member));
451 }
452
453 void zadd(const(ubyte)[] key, Map!(const(ubyte)[], double) scoreMembers) {
454 ArrayList!(const(ubyte)[]) args = new ArrayList!(const(ubyte)[])(scoreMembers.size() * 2 + 1);
455 args.add(key);
456 args.addAll(convertScoreMembersToByteArrays(scoreMembers));
457
458 const(ubyte)[][] argsArray = args.toArray();
459
460 sendCommand(Command.ZADD, argsArray);
461 }
462
463 void zadd(const(ubyte)[] key, Map!(const(ubyte)[], double) scoreMembers, ZAddParams params) {
464 ArrayList!(const(ubyte)[]) args = convertScoreMembersToByteArrays(scoreMembers);
465 const(ubyte)[][] argsArray = args.toArray();
466
467 sendCommand(Command.ZADD, params.getByteParams(key, argsArray));
468 }
469
470 void zrange(const(ubyte)[] key, long start, long stop) {
471 sendCommand(Command.ZRANGE, key, toByteArray(start), toByteArray(stop));
472 }
473
474 void zrem(const(ubyte)[] key, const(ubyte)[][] members...) {
475 sendCommand(Command.ZREM, joinParameters(key, members));
476 }
477
478 void zincrby(const(ubyte)[] key, double increment, const(ubyte)[] member) {
479 sendCommand(Command.ZINCRBY, key, toByteArray(increment), member);
480 }
481
482 void zincrby(const(ubyte)[] key, double increment, const(ubyte)[] member,
483 ZIncrByParams params) {
484 // Note that it actually calls ZADD with INCR option, so it requires Redis 3.0.2 or upper.
485 sendCommand(Command.ZADD, params.getByteParams(key, toByteArray(increment), member));
486 }
487
488 void zrank(const(ubyte)[] key, const(ubyte)[] member) {
489 sendCommand(Command.ZRANK, key, member);
490 }
491
492 void zrevrank(const(ubyte)[] key, const(ubyte)[] member) {
493 sendCommand(Command.ZREVRANK, key, member);
494 }
495
496 void zrevrange(const(ubyte)[] key, long start, long stop) {
497 sendCommand(Command.ZREVRANGE, key, toByteArray(start), toByteArray(stop));
498 }
499
500 void zrangeWithScores(const(ubyte)[] key, long start, long stop) {
501 sendCommand(Command.ZRANGE, key, toByteArray(start), toByteArray(stop), cast(const(ubyte)[])to!string(Keyword.WITHSCORES));
502 }
503
504 void zrevrangeWithScores(const(ubyte)[] key, long start, long stop) {
505 sendCommand(Command.ZREVRANGE, key, toByteArray(start), toByteArray(stop), cast(const(ubyte)[])to!string(Keyword.WITHSCORES));
506 }
507
508 void zcard(const(ubyte)[] key) {
509 sendCommand(Command.ZCARD, key);
510 }
511
512 void zscore(const(ubyte)[] key, const(ubyte)[] member) {
513 sendCommand(Command.ZSCORE, key, member);
514 }
515
516 void multi() {
517 sendCommand(Command.MULTI);
518 _isInMulti = true;
519 }
520
521 void discard() {
522 sendCommand(Command.DISCARD);
523 _isInMulti = false;
524 _isInWatch = false;
525 }
526
527 void exec() {
528 sendCommand(Command.EXEC);
529 _isInMulti = false;
530 _isInWatch = false;
531 }
532
533 void watch(const(ubyte)[][] keys...) {
534 sendCommand(Command.WATCH, keys);
535 _isInWatch = true;
536 }
537
538 void unwatch() {
539 sendCommand(Command.UNWATCH);
540 _isInWatch = false;
541 }
542
543 void sort(const(ubyte)[] key) {
544 sendCommand(Command.SORT, key);
545 }
546
547 void sort(const(ubyte)[] key, SortingParams sortingParameters) {
548 List!(const(ubyte)[]) args = new ArrayList!(const(ubyte)[])();
549 args.add(key);
550 args.addAll(sortingParameters.getParams());
551 sendCommand(Command.SORT, args.toArray());
552 }
553
554 void blpop(const(ubyte)[][] args) {
555 sendCommand(Command.BLPOP, args);
556 }
557
558 void blpop(int timeout, const(ubyte)[][] keys...) {
559 List!(const(ubyte)[]) args = new ArrayList!(const(ubyte)[])();
560 foreach(const(ubyte)[] arg ; keys) {
561 args.add(arg);
562 }
563 args.add(Protocol.toByteArray(timeout));
564 blpop(args.toArray());
565 }
566
567 void sort(const(ubyte)[] key, SortingParams sortingParameters, const(ubyte)[] dstkey) {
568 List!(const(ubyte)[]) args = new ArrayList!(const(ubyte)[])();
569 args.add(key);
570 args.addAll(sortingParameters.getParams());
571 args.add(cast(const(ubyte)[])to!string(Keyword.STORE));
572 args.add(dstkey);
573 sendCommand(Command.SORT, args.toArray());
574 }
575
576 void sort(const(ubyte)[] key, const(ubyte)[] dstkey) {
577 sendCommand(Command.SORT, key, cast(const(ubyte)[])to!string(Keyword.STORE), dstkey);
578 }
579
580 void brpop(const(ubyte)[][] args) {
581 sendCommand(Command.BRPOP, args);
582 }
583
584 void brpop(int timeout, const(ubyte)[][] keys...) {
585 List!(const(ubyte)[]) args = new ArrayList!(const(ubyte)[])();
586 foreach(const(ubyte)[] arg ; keys) {
587 args.add(arg);
588 }
589 args.add(Protocol.toByteArray(timeout));
590 brpop(args.toArray());
591 }
592
593 void auth(string password) {
594 import std.range;
595 if(password.empty) return;
596 setPassword(password);
597 sendCommand(Command.AUTH, password);
598 }
599
600 void subscribe(const(ubyte)[][] channels...) {
601 sendCommand(Command.SUBSCRIBE, channels);
602 }
603
604 void publish(const(ubyte)[] channel, const(ubyte)[] message) {
605 sendCommand(Command.PUBLISH, channel, message);
606 }
607
608 void unsubscribe() {
609 sendCommand(Command.UNSUBSCRIBE);
610 }
611
612 void unsubscribe(const(ubyte)[][] channels...) {
613 sendCommand(Command.UNSUBSCRIBE, channels);
614 }
615
616 void psubscribe(const(ubyte)[][] patterns...) {
617 sendCommand(Command.PSUBSCRIBE, patterns);
618 }
619
620 void punsubscribe() {
621 sendCommand(Command.PUNSUBSCRIBE);
622 }
623
624 void punsubscribe(const(ubyte)[][] patterns...) {
625 sendCommand(Command.PUNSUBSCRIBE, patterns);
626 }
627
628 void pubsub(const(ubyte)[][] args...) {
629 sendCommand(Command.PUBSUB, args);
630 }
631
632 void zcount(const(ubyte)[] key, double min, double max) {
633 sendCommand(Command.ZCOUNT, key, toByteArray(min), toByteArray(max));
634 }
635
636 void zcount(const(ubyte)[] key, const(ubyte)[] min, const(ubyte)[] max) {
637 sendCommand(Command.ZCOUNT, key, min, max);
638 }
639
640 void zrangeByScore(const(ubyte)[] key, double min, double max) {
641 sendCommand(Command.ZRANGEBYSCORE, key, toByteArray(min), toByteArray(max));
642 }
643
644 void zrangeByScore(const(ubyte)[] key, const(ubyte)[] min, const(ubyte)[] max) {
645 sendCommand(Command.ZRANGEBYSCORE, key, min, max);
646 }
647
648 void zrevrangeByScore(const(ubyte)[] key, double max, double min) {
649 sendCommand(Command.ZREVRANGEBYSCORE, key, toByteArray(max), toByteArray(min));
650 }
651
652 void zrevrangeByScore(const(ubyte)[] key, const(ubyte)[] max, const(ubyte)[] min) {
653 sendCommand(Command.ZREVRANGEBYSCORE, key, max, min);
654 }
655
656 void zrangeByScore(const(ubyte)[] key, double min, double max, int offset,
657 int count) {
658 sendCommand(Command.ZRANGEBYSCORE, key, toByteArray(min), toByteArray(max), cast(const(ubyte)[])to!string(Keyword.LIMIT), toByteArray(offset),
659 toByteArray(count));
660 }
661
662 void zrevrangeByScore(const(ubyte)[] key, double max, double min,
663 int offset, int count) {
664 sendCommand(Command.ZREVRANGEBYSCORE, key, toByteArray(max), toByteArray(min), cast(const(ubyte)[])to!string(Keyword.LIMIT), toByteArray(offset),
665 toByteArray(count));
666 }
667
668 void zrangeByScoreWithScores(const(ubyte)[] key, double min, double max) {
669 sendCommand(Command.ZRANGEBYSCORE, key, toByteArray(min), toByteArray(max), cast(const(ubyte)[])to!string(Keyword.WITHSCORES));
670 }
671
672 void zrevrangeByScoreWithScores(const(ubyte)[] key, double max, double min) {
673 sendCommand(Command.ZREVRANGEBYSCORE, key, toByteArray(max), toByteArray(min), cast(const(ubyte)[])to!string(Keyword.WITHSCORES));
674 }
675
676 void zrangeByScoreWithScores(const(ubyte)[] key, double min, double max,
677 int offset, int count) {
678 sendCommand(Command.ZRANGEBYSCORE, key, toByteArray(min), toByteArray(max), cast(const(ubyte)[])to!string(Keyword.LIMIT), toByteArray(offset),
679 toByteArray(count), cast(const(ubyte)[])to!string(Keyword.WITHSCORES));
680 }
681
682 void zrevrangeByScoreWithScores(const(ubyte)[] key, double max, double min,
683 int offset, int count) {
684 sendCommand(Command.ZREVRANGEBYSCORE, key, toByteArray(max), toByteArray(min), cast(const(ubyte)[])to!string(Keyword.LIMIT), toByteArray(offset),
685 toByteArray(count), cast(const(ubyte)[])to!string(Keyword.WITHSCORES));
686 }
687
688 void zrangeByScore(const(ubyte)[] key, const(ubyte)[] min, const(ubyte)[] max, int offset,
689 int count) {
690 sendCommand(Command.ZRANGEBYSCORE, key, min, max, cast(const(ubyte)[])to!string(Keyword.LIMIT), toByteArray(offset), toByteArray(count));
691 }
692
693 void zrevrangeByScore(const(ubyte)[] key, const(ubyte)[] max, const(ubyte)[] min,
694 int offset, int count) {
695 sendCommand(Command.ZREVRANGEBYSCORE, key, max, min, cast(const(ubyte)[])to!string(Keyword.LIMIT), toByteArray(offset), toByteArray(count));
696 }
697
698 void zrangeByScoreWithScores(const(ubyte)[] key, const(ubyte)[] min, const(ubyte)[] max) {
699 sendCommand(Command.ZRANGEBYSCORE, key, min, max, cast(const(ubyte)[])to!string(Keyword.WITHSCORES));
700 }
701
702 void zrevrangeByScoreWithScores(const(ubyte)[] key, const(ubyte)[] max, const(ubyte)[] min) {
703 sendCommand(Command.ZREVRANGEBYSCORE, key, max, min, cast(const(ubyte)[])to!string(Keyword.WITHSCORES));
704 }
705
706 void zrangeByScoreWithScores(const(ubyte)[] key, const(ubyte)[] min, const(ubyte)[] max,
707 int offset, int count) {
708 sendCommand(Command.ZRANGEBYSCORE, key, min, max, cast(const(ubyte)[])to!string(Keyword.LIMIT), toByteArray(offset), toByteArray(count),
709 cast(const(ubyte)[])to!string(Keyword.WITHSCORES));
710 }
711
712 void zrevrangeByScoreWithScores(const(ubyte)[] key, const(ubyte)[] max, const(ubyte)[] min,
713 int offset, int count) {
714 sendCommand(Command.ZREVRANGEBYSCORE, key, max, min, cast(const(ubyte)[])to!string(Keyword.LIMIT), toByteArray(offset),
715 toByteArray(count), cast(const(ubyte)[])to!string(Keyword.WITHSCORES));
716 }
717
718 void zremrangeByRank(const(ubyte)[] key, long start, long stop) {
719 sendCommand(Command.ZREMRANGEBYRANK, key, toByteArray(start), toByteArray(stop));
720 }
721
722 void zremrangeByScore(const(ubyte)[] key, double min, double max) {
723 sendCommand(Command.ZREMRANGEBYSCORE, key, toByteArray(min), toByteArray(max));
724 }
725
726 void zremrangeByScore(const(ubyte)[] key, const(ubyte)[] min, const(ubyte)[] max) {
727 sendCommand(Command.ZREMRANGEBYSCORE, key, min, max);
728 }
729
730 void zunionstore(const(ubyte)[] dstkey, const(ubyte)[][] sets...) {
731 sendCommand(Command.ZUNIONSTORE, joinParameters(dstkey, toByteArray(sets.length), sets));
732 }
733
734 void zunionstore(const(ubyte)[] dstkey, ZParams params, const(ubyte)[][] sets...) {
735 List!(const(ubyte)[]) args = new ArrayList!(const(ubyte)[])();
736 args.add(dstkey);
737 args.add(Protocol.toByteArray(sets.length));
738 foreach(const(ubyte)[] set ; sets) {
739 args.add(set);
740 }
741 args.addAll(params.getParams());
742 sendCommand(Command.ZUNIONSTORE, args.toArray());
743 }
744
745 void zinterstore(const(ubyte)[] dstkey, const(ubyte)[][] sets...) {
746 sendCommand(Command.ZINTERSTORE, joinParameters(dstkey, Protocol.toByteArray(sets.length), sets));
747 }
748
749 void zinterstore(const(ubyte)[] dstkey, ZParams params, const(ubyte)[][] sets...) {
750 List!(const(ubyte)[]) args = new ArrayList!(const(ubyte)[])();
751 args.add(dstkey);
752 args.add(Protocol.toByteArray(sets.length));
753 foreach(const(ubyte)[] set ; sets) {
754 args.add(set);
755 }
756 args.addAll(params.getParams());
757 sendCommand(Command.ZINTERSTORE, args.toArray());
758 }
759
760 void zlexcount(const(ubyte)[] key, const(ubyte)[] min, const(ubyte)[] max) {
761 sendCommand(Command.ZLEXCOUNT, key, min, max);
762 }
763
764 void zrangeByLex(const(ubyte)[] key, const(ubyte)[] min, const(ubyte)[] max) {
765 sendCommand(Command.ZRANGEBYLEX, key, min, max);
766 }
767
768 void zrangeByLex(const(ubyte)[] key, const(ubyte)[] min, const(ubyte)[] max, int offset,
769 int count) {
770 sendCommand(Command.ZRANGEBYLEX, key, min, max, cast(const(ubyte)[])to!string(Keyword.LIMIT), toByteArray(offset), toByteArray(count));
771 }
772
773 void zrevrangeByLex(const(ubyte)[] key, const(ubyte)[] max, const(ubyte)[] min) {
774 sendCommand(Command.ZREVRANGEBYLEX, key, max, min);
775 }
776
777 void zrevrangeByLex(const(ubyte)[] key, const(ubyte)[] max, const(ubyte)[] min,
778 int offset, int count) {
779 sendCommand(Command.ZREVRANGEBYLEX, key, max, min, cast(const(ubyte)[])to!string(Keyword.LIMIT), toByteArray(offset), toByteArray(count));
780 }
781
782 void zremrangeByLex(const(ubyte)[] key, const(ubyte)[] min, const(ubyte)[] max) {
783 sendCommand(Command.ZREMRANGEBYLEX, key, min, max);
784 }
785
786 void save() {
787 sendCommand(Command.SAVE);
788 }
789
790 void bgsave() {
791 sendCommand(Command.BGSAVE);
792 }
793
794 void bgrewriteaof() {
795 sendCommand(Command.BGREWRITEAOF);
796 }
797
798 void lastsave() {
799 sendCommand(Command.LASTSAVE);
800 }
801
802 void shutdown() {
803 sendCommand(Command.SHUTDOWN);
804 }
805
806 void info() {
807 sendCommand(Command.INFO);
808 }
809
810 void info(string section) {
811 sendCommand(Command.INFO, section);
812 }
813
814 void monitor() {
815 sendCommand(Command.MONITOR);
816 }
817
818 void slaveof(string host, int port) {
819 sendCommand(Command.SLAVEOF, host, port.to!string);
820 }
821
822 void slaveofNoOne() {
823 sendCommand(Command.SLAVEOF, cast(const(ubyte)[])to!string(Keyword.NO), cast(const(ubyte)[])to!string(Keyword.ONE));
824 }
825
826 void configGet(const(ubyte)[] pattern) {
827 sendCommand(Command.CONFIG, cast(const(ubyte)[])to!string(Keyword.GET), pattern);
828 }
829
830 void configSet(const(ubyte)[] parameter, const(ubyte)[] value) {
831 sendCommand(Command.CONFIG, cast(const(ubyte)[])to!string(Keyword.SET), parameter, value);
832 }
833
834 void strlen(const(ubyte)[] key) {
835 sendCommand(Command.STRLEN, key);
836 }
837
838 void sync() {
839 sendCommand(Command.SYNC);
840 }
841
842 void lpushx(const(ubyte)[] key, const(ubyte)[][] strings...) {
843 sendCommand(Command.LPUSHX, joinParameters(key, strings));
844 }
845
846 void persist(const(ubyte)[] key) {
847 sendCommand(Command.PERSIST, key);
848 }
849
850 void rpushx(const(ubyte)[] key, const(ubyte)[][] strings...) {
851 sendCommand(Command.RPUSHX, joinParameters(key, strings));
852 }
853
854 void echo(const(ubyte)[] strings) {
855 sendCommand(Command.ECHO, strings);
856 }
857
858 void linsert(const(ubyte)[] key, ListPosition where, const(ubyte)[] pivot,
859 const(ubyte)[] value) {
860 sendCommand(Command.LINSERT, key, cast(const(ubyte)[])to!string(where), pivot, value);
861 }
862
863 // void debug(DebugParams params) {
864 // sendCommand(Command.DEBUG, params.getCommand());
865 // }
866
867 void brpoplpush(const(ubyte)[] source, const(ubyte)[] destination, int timeout) {
868 sendCommand(Command.BRPOPLPUSH, source, destination, toByteArray(timeout));
869 }
870
871 void configResetStat() {
872 sendCommand(Command.CONFIG, cast(const(ubyte)[])to!string(Keyword.RESETSTAT));
873 }
874
875 void configRewrite() {
876 sendCommand(Command.CONFIG, cast(const(ubyte)[])to!string(Keyword.REWRITE));
877 }
878
879 void setbit(const(ubyte)[] key, long offset, const(ubyte)[] value) {
880 sendCommand(Command.SETBIT, key, toByteArray(offset), value);
881 }
882
883 void setbit(const(ubyte)[] key, long offset, bool value) {
884 sendCommand(Command.SETBIT, key, toByteArray(offset), toByteArray(value));
885 }
886
887 void getbit(const(ubyte)[] key, long offset) {
888 sendCommand(Command.GETBIT, key, toByteArray(offset));
889 }
890
891 void bitpos(const(ubyte)[] key, bool value, BitPosParams params) {
892 List!(const(ubyte)[]) args = new ArrayList!(const(ubyte)[])();
893 args.add(key);
894 args.add(toByteArray(value));
895 args.addAll(params.getParams());
896 sendCommand(Command.BITPOS, args.toArray());
897 }
898
899 void setrange(const(ubyte)[] key, long offset, const(ubyte)[] value) {
900 sendCommand(Command.SETRANGE, key, toByteArray(offset), value);
901 }
902
903 void getrange(const(ubyte)[] key, long startOffset, long endOffset) {
904 sendCommand(Command.GETRANGE, key, toByteArray(startOffset), toByteArray(endOffset));
905 }
906
907 int getDB() {
908 return db;
909 }
910
911 // override
912 // void disconnect() {
913 // db = 0;
914 // super.disconnect();
915 // }
916
917 override
918 void close() {
919 db = 0;
920 super.close();
921 }
922
923 void resetState() {
924 if (isInWatch()) {
925 unwatch();
926 getStatusCodeReply();
927 }
928 }
929
930 void eval(const(ubyte)[] script, const(ubyte)[] keyCount, const(ubyte)[][] params) {
931 sendCommand(Command.EVAL, joinParameters(script, keyCount, params));
932 }
933
934 void eval(const(ubyte)[] script, int keyCount, const(ubyte)[][] params...) {
935 sendCommand(Command.EVAL, joinParameters(script, toByteArray(keyCount), params));
936 }
937
938 void evalsha(const(ubyte)[] sha1, const(ubyte)[] keyCount, const(ubyte)[][] params...) {
939 sendCommand(Command.EVALSHA, joinParameters(sha1, keyCount, params));
940 }
941
942 void evalsha(const(ubyte)[] sha1, int keyCount, const(ubyte)[][] params...) {
943 sendCommand(Command.EVALSHA, joinParameters(sha1, toByteArray(keyCount), params));
944 }
945
946 void scriptFlush() {
947 sendCommand(Command.SCRIPT, cast(const(ubyte)[])to!string(Keyword.FLUSH));
948 }
949
950 void scriptExists(const(ubyte)[][] sha1...) {
951 sendCommand(Command.SCRIPT, joinParameters(cast(const(ubyte)[])to!string(Keyword.EXISTS), sha1));
952 }
953
954 void scriptLoad(const(ubyte)[] script) {
955 sendCommand(Command.SCRIPT, cast(const(ubyte)[])to!string(Keyword.LOAD), script);
956 }
957
958 void scriptKill() {
959 sendCommand(Command.SCRIPT, cast(const(ubyte)[])to!string(Keyword.KILL));
960 }
961
962 void slowlogGet() {
963 sendCommand(Command.SLOWLOG, cast(const(ubyte)[])to!string(Keyword.GET));
964 }
965
966 void slowlogGet(long entries) {
967 sendCommand(Command.SLOWLOG, cast(const(ubyte)[])to!string(Keyword.GET), toByteArray(entries));
968 }
969
970 void slowlogReset() {
971 sendCommand(Command.SLOWLOG, cast(const(ubyte)[])to!string(Keyword.RESET));
972 }
973
974 void slowlogLen() {
975 sendCommand(Command.SLOWLOG, cast(const(ubyte)[])to!string(Keyword.LEN));
976 }
977
978 void objectRefcount(const(ubyte)[] key) {
979 sendCommand(Command.OBJECT, cast(const(ubyte)[])to!string(Keyword.REFCOUNT), key);
980 }
981
982 void objectIdletime(const(ubyte)[] key) {
983 sendCommand(Command.OBJECT, cast(const(ubyte)[])to!string(Keyword.IDLETIME), key);
984 }
985
986 void objectEncoding(const(ubyte)[] key) {
987 sendCommand(Command.OBJECT, cast(const(ubyte)[])to!string(Keyword.ENCODING), key);
988 }
989
990 void bitcount(const(ubyte)[] key) {
991 sendCommand(Command.BITCOUNT, key);
992 }
993
994 void bitcount(const(ubyte)[] key, long start, long end) {
995 sendCommand(Command.BITCOUNT, key, toByteArray(start), toByteArray(end));
996 }
997
998 void bitop(BitOP op, const(ubyte)[] destKey, const(ubyte)[][] srcKeys...) {
999 sendCommand(Command.BITOP, joinParameters(cast(const(ubyte)[])to!string(op), destKey, srcKeys));
1000 }
1001
1002 void sentinel(const(ubyte)[][] args...) {
1003 sendCommand(Command.SENTINEL, args);
1004 }
1005
1006 void dump(const(ubyte)[] key) {
1007 sendCommand(Command.DUMP, key);
1008 }
1009
1010 void restore(const(ubyte)[] key, int ttl, const(ubyte)[] serializedValue) {
1011 sendCommand(Command.RESTORE, key, toByteArray(ttl), serializedValue);
1012 }
1013
1014 void restoreReplace(const(ubyte)[] key, int ttl, const(ubyte)[] serializedValue) {
1015 sendCommand(Command.RESTORE, key, toByteArray(ttl), serializedValue, cast(const(ubyte)[])to!string(Keyword.REPLACE));
1016 }
1017
1018 void pexpire(const(ubyte)[] key, long milliseconds) {
1019 sendCommand(Command.PEXPIRE, key, toByteArray(milliseconds));
1020 }
1021
1022 void pexpireAt(const(ubyte)[] key, long millisecondsTimestamp) {
1023 sendCommand(Command.PEXPIREAT, key, toByteArray(millisecondsTimestamp));
1024 }
1025
1026 void pttl(const(ubyte)[] key) {
1027 sendCommand(Command.PTTL, key);
1028 }
1029
1030 void psetex(const(ubyte)[] key, long milliseconds, const(ubyte)[] value) {
1031 sendCommand(Command.PSETEX, key, toByteArray(milliseconds), value);
1032 }
1033
1034 void srandmember(const(ubyte)[] key, int count) {
1035 sendCommand(Command.SRANDMEMBER, key, toByteArray(count));
1036 }
1037
1038 void memoryDoctor() {
1039 sendCommand(Command.MEMORY, cast(const(ubyte)[])to!string(Keyword.DOCTOR));
1040 }
1041
1042 void clientKill(const(ubyte)[] ipPort) {
1043 sendCommand(Command.CLIENT, cast(const(ubyte)[])to!string(Keyword.KILL), ipPort);
1044 }
1045
1046 void clientKill(string ip, int port) {
1047 sendCommand(Command.CLIENT, Keyword.KILL.to!string(), ip ~ ":" ~ port.to!string);
1048 }
1049
1050 void clientKill(ClientKillParams params) {
1051 sendCommand(Command.CLIENT, joinParameters(cast(const(ubyte)[])to!string(Keyword.KILL), params.getByteParams()));
1052 }
1053
1054 void clientGetname() {
1055 sendCommand(Command.CLIENT, cast(const(ubyte)[])to!string(Keyword.GETNAME));
1056 }
1057
1058 void clientList() {
1059 sendCommand(Command.CLIENT, cast(const(ubyte)[])to!string(Keyword.LIST));
1060 }
1061
1062 void clientSetname(const(ubyte)[] name) {
1063 sendCommand(Command.CLIENT, cast(const(ubyte)[])to!string(Keyword.SETNAME), name);
1064 }
1065
1066 void clientPause(long timeout) {
1067 sendCommand(Command.CLIENT, cast(const(ubyte)[])to!string(Keyword.PAUSE), toByteArray(timeout));
1068 }
1069
1070 void time() {
1071 sendCommand(Command.TIME);
1072 }
1073
1074 void migrate(string host, int port, const(ubyte)[] key, int destinationDb,
1075 int timeout) {
1076 sendCommand(Command.MIGRATE, SafeEncoder.encode(host), toByteArray(port), key,
1077 toByteArray(destinationDb), toByteArray(timeout));
1078 }
1079
1080 void migrate(string host, int port, int destinationDB,
1081 int timeout, MigrateParams params, const(ubyte)[][] keys...) {
1082 const(ubyte)[][] bparams = params.getByteParams();
1083 int len = cast(int)(5 + bparams.length + 1 + keys.length);
1084 const(ubyte)[][] args = new const(ubyte)[][len];
1085 int i = 0;
1086 args[i++] = SafeEncoder.encode(host);
1087 args[i++] = toByteArray(port);
1088 args[i++] = [];
1089 args[i++] = toByteArray(destinationDB);
1090 args[i++] = toByteArray(timeout);
1091 // System.arraycopy(bparams, 0, args, i, bparams.length);
1092 args[i .. i+bparams.length] = bparams[0 .. $];
1093 i += bparams.length;
1094 args[i++] = cast(const(ubyte)[])to!string(Keyword.KEYS);
1095 // System.arraycopy(keys, 0, args, i, keys.length);
1096 args[i .. i+keys.length] = keys[0 .. $];
1097 sendCommand(Command.MIGRATE, args);
1098 }
1099
1100 void hincrByFloat(const(ubyte)[] key, const(ubyte)[] field, double increment) {
1101 sendCommand(Command.HINCRBYFLOAT, key, field, toByteArray(increment));
1102 }
1103
1104 void scan(const(ubyte)[] cursor, ScanParams params) {
1105 List!(const(ubyte)[]) args = new ArrayList!(const(ubyte)[])();
1106 args.add(cursor);
1107 args.addAll(params.getParams());
1108 sendCommand(Command.SCAN, args.toArray());
1109 }
1110
1111 void hscan(const(ubyte)[] key, const(ubyte)[] cursor, ScanParams params) {
1112 List!(const(ubyte)[]) args = new ArrayList!(const(ubyte)[])();
1113 args.add(key);
1114 args.add(cursor);
1115 args.addAll(params.getParams());
1116 sendCommand(Command.HSCAN, args.toArray());
1117 }
1118
1119 void sscan(const(ubyte)[] key, const(ubyte)[] cursor, ScanParams params) {
1120 List!(const(ubyte)[]) args = new ArrayList!(const(ubyte)[])();
1121 args.add(key);
1122 args.add(cursor);
1123 args.addAll(params.getParams());
1124 sendCommand(Command.SSCAN, args.toArray());
1125 }
1126
1127 void zscan(const(ubyte)[] key, const(ubyte)[] cursor, ScanParams params) {
1128 List!(const(ubyte)[]) args = new ArrayList!(const(ubyte)[])();
1129 args.add(key);
1130 args.add(cursor);
1131 args.addAll(params.getParams());
1132 sendCommand(Command.ZSCAN, args.toArray());
1133 }
1134
1135 void waitReplicas(int replicas, long timeout) {
1136 sendCommand(Command.WAIT, toByteArray(replicas), toByteArray(timeout));
1137 }
1138
1139 void cluster(const(ubyte)[][] args...) {
1140 sendCommand(Command.CLUSTER, args);
1141 }
1142
1143 void asking() {
1144 sendCommand(Command.ASKING);
1145 }
1146
1147 void pfadd(const(ubyte)[] key, const(ubyte)[][] elements...) {
1148 sendCommand(Command.PFADD, joinParameters(key, elements));
1149 }
1150
1151 void pfcount(const(ubyte)[] key) {
1152 sendCommand(Command.PFCOUNT, key);
1153 }
1154
1155 void pfcount(const(ubyte)[][] keys...) {
1156 sendCommand(Command.PFCOUNT, keys);
1157 }
1158
1159 void pfmerge(const(ubyte)[] destkey, const(ubyte)[][] sourcekeys...) {
1160 sendCommand(Command.PFMERGE, joinParameters(destkey, sourcekeys));
1161 }
1162
1163 void readonly() {
1164 sendCommand(Command.READONLY);
1165 }
1166
1167 void geoadd(const(ubyte)[] key, double longitude, double latitude, const(ubyte)[] member) {
1168 sendCommand(Command.GEOADD, key, toByteArray(longitude), toByteArray(latitude), member);
1169 }
1170
1171 void geoadd(const(ubyte)[] key, Map!(const(ubyte)[], GeoCoordinate) memberCoordinateMap) {
1172 List!(const(ubyte)[]) args = new ArrayList!(const(ubyte)[])(memberCoordinateMap.size() * 3 + 1);
1173 args.add(key);
1174 args.addAll(convertGeoCoordinateMapToByteArrays(memberCoordinateMap));
1175
1176 const(ubyte)[][] argsArray = args.toArray();
1177
1178 sendCommand(Command.GEOADD, argsArray);
1179 }
1180
1181 void geodist(const(ubyte)[] key, const(ubyte)[] member1, const(ubyte)[] member2) {
1182 sendCommand(Command.GEODIST, key, member1, member2);
1183 }
1184
1185 void geodist(const(ubyte)[] key, const(ubyte)[] member1, const(ubyte)[] member2, GeoUnit unit) {
1186 sendCommand(Command.GEODIST, key, member1, member2, cast(const(ubyte)[])(unit.toString()));
1187 }
1188
1189 void geohash(const(ubyte)[] key, const(ubyte)[][] members...) {
1190 sendCommand(Command.GEOHASH, joinParameters(key, members));
1191 }
1192
1193 void geopos(const(ubyte)[] key, const(ubyte)[][] members) {
1194 sendCommand(Command.GEOPOS, joinParameters(key, members));
1195 }
1196
1197 void georadius(const(ubyte)[] key, double longitude, double latitude, double radius, GeoUnit unit) {
1198 sendCommand(Command.GEORADIUS, key, toByteArray(longitude), toByteArray(latitude), toByteArray(radius),
1199 cast(const(ubyte)[])(unit.toString()));
1200 }
1201
1202 void georadiusReadonly(const(ubyte)[] key, double longitude, double latitude, double radius, GeoUnit unit) {
1203 sendCommand(Command.GEORADIUS_RO, key, toByteArray(longitude), toByteArray(latitude), toByteArray(radius),
1204 cast(const(ubyte)[])(unit.toString()));
1205 }
1206
1207 void georadius(const(ubyte)[] key, double longitude, double latitude, double radius, GeoUnit unit,
1208 GeoRadiusParam param) {
1209 sendCommand(Command.GEORADIUS, param.getByteParams(key, toByteArray(longitude), toByteArray(latitude),
1210 toByteArray(radius), cast(const(ubyte)[])(unit.toString())));
1211 }
1212
1213 void georadiusReadonly(const(ubyte)[] key, double longitude, double latitude, double radius, GeoUnit unit,
1214 GeoRadiusParam param) {
1215 sendCommand(Command.GEORADIUS_RO, param.getByteParams(key, toByteArray(longitude), toByteArray(latitude),
1216 toByteArray(radius), cast(const(ubyte)[])(unit.toString())));
1217 }
1218
1219 void georadiusByMember(const(ubyte)[] key, const(ubyte)[] member, double radius, GeoUnit unit) {
1220 sendCommand(Command.GEORADIUSBYMEMBER, key, member, toByteArray(radius), cast(const(ubyte)[])(unit.toString()));
1221 }
1222
1223 void georadiusByMemberReadonly(const(ubyte)[] key, const(ubyte)[] member, double radius, GeoUnit unit) {
1224 sendCommand(Command.GEORADIUSBYMEMBER_RO, key, member, toByteArray(radius), cast(const(ubyte)[])(unit.toString()));
1225 }
1226
1227 void georadiusByMember(const(ubyte)[] key, const(ubyte)[] member, double radius, GeoUnit unit,
1228 GeoRadiusParam param) {
1229 sendCommand(Command.GEORADIUSBYMEMBER, param.getByteParams(key, member, toByteArray(radius), cast(const(ubyte)[])(unit.toString())));
1230 }
1231
1232 void georadiusByMemberReadonly(const(ubyte)[] key, const(ubyte)[] member, double radius, GeoUnit unit,
1233 GeoRadiusParam param) {
1234 sendCommand(Command.GEORADIUSBYMEMBER_RO, param.getByteParams(key, member, toByteArray(radius), cast(const(ubyte)[])(unit.toString())));
1235 }
1236
1237 void moduleLoad(const(ubyte)[] path) {
1238 sendCommand(Command.MODULE, cast(const(ubyte)[])to!string(Keyword.LOAD), path);
1239 }
1240
1241 void moduleList() {
1242 sendCommand(Command.MODULE, cast(const(ubyte)[])to!string(Keyword.LIST));
1243 }
1244
1245 void moduleUnload(const(ubyte)[] name) {
1246 sendCommand(Command.MODULE, cast(const(ubyte)[])to!string(Keyword.UNLOAD), name);
1247 }
1248
1249 private ArrayList!(const(ubyte)[]) convertScoreMembersToByteArrays(Map!(const(ubyte)[], double) scoreMembers) {
1250 ArrayList!(const(ubyte)[]) args = new ArrayList!(const(ubyte)[])(scoreMembers.size() * 2);
1251
1252 foreach(const(ubyte)[] key, double value ; scoreMembers) {
1253 args.add(toByteArray(value));
1254 args.add(key);
1255 }
1256
1257 return args;
1258 }
1259
1260 private List!(const(ubyte)[]) convertGeoCoordinateMapToByteArrays(
1261 Map!(const(ubyte)[], GeoCoordinate) memberCoordinateMap) {
1262 List!(const(ubyte)[]) args = new ArrayList!(const(ubyte)[])(memberCoordinateMap.size() * 3);
1263
1264 foreach(const(ubyte)[] key, GeoCoordinate coordinate ; memberCoordinateMap) {
1265 args.add(toByteArray(coordinate.getLongitude()));
1266 args.add(toByteArray(coordinate.getLatitude()));
1267 args.add(key);
1268 }
1269
1270 return args;
1271 }
1272
1273 void bitfield(const(ubyte)[] key, const(ubyte)[][] value...) {
1274 sendCommand(Command.BITFIELD, joinParameters(key, value));
1275 }
1276
1277 void hstrlen(const(ubyte)[] key, const(ubyte)[] field) {
1278 sendCommand(Command.HSTRLEN, key, field);
1279 }
1280
1281 void xadd(const(ubyte)[] key, const(ubyte)[] id, Map!(const(ubyte)[], const(ubyte)[]) hash, long maxLen, bool approximateLength) {
1282 int maxLexArgs = 0;
1283 if(maxLen < long.max) { // optional arguments
1284 if(approximateLength) {
1285 maxLexArgs = 3; // e.g. MAXLEN ~ 1000
1286 } else {
1287 maxLexArgs = 2; // e.g. MAXLEN 1000
1288 }
1289 }
1290
1291 const(ubyte)[][] params = new const(ubyte)[][2 + maxLexArgs + hash.size() * 2];
1292 int index = 0;
1293 params[index++] = key;
1294 if(maxLen < long.max) {
1295 params[index++] = cast(const(ubyte)[])to!string(Keyword.MAXLEN);
1296 if(approximateLength) {
1297 params[index++] = cast(const(ubyte)[])Protocol.BYTES_TILDE;
1298 }
1299 params[index++] = toByteArray(maxLen);
1300 }
1301
1302 params[index++] = id;
1303 foreach(const(ubyte)[] k, const(ubyte)[] value ; hash) {
1304 params[index++] = k;
1305 params[index++] = value;
1306 }
1307 sendCommand(Command.XADD, params);
1308 }
1309
1310 void xlen(const(ubyte)[] key) {
1311 sendCommand(Command.XLEN, key);
1312 }
1313
1314 void xrange(const(ubyte)[] key, const(ubyte)[] start, const(ubyte)[] end, long count) {
1315 sendCommand(Command.XRANGE, key, start, end, cast(const(ubyte)[])to!string(Keyword.COUNT), toByteArray(count));
1316 }
1317
1318 void xrevrange(const(ubyte)[] key, const(ubyte)[] end, const(ubyte)[] start, int count) {
1319 sendCommand(Command.XREVRANGE, key, end, start, cast(const(ubyte)[])to!string(Keyword.COUNT), toByteArray(count));
1320 }
1321
1322 void xread(int count, long block, Map!(const(ubyte)[], const(ubyte)[]) streams) {
1323 const(ubyte)[][] params = new const(ubyte)[][3 + streams.size() * 2 + (block > 0 ? 2 : 0)];
1324
1325 int streamsIndex = 0;
1326 params[streamsIndex++] = cast(const(ubyte)[])to!string(Keyword.COUNT);
1327 params[streamsIndex++] = toByteArray(count);
1328 if(block > 0) {
1329 params[streamsIndex++] = cast(const(ubyte)[])to!string(Keyword.BLOCK);
1330 params[streamsIndex++] = toByteArray(block);
1331 }
1332
1333 params[streamsIndex++] = cast(const(ubyte)[])to!string(Keyword.STREAMS);
1334 int idsIndex = streamsIndex + streams.size();
1335
1336 foreach(const(ubyte)[] key, const(ubyte)[] value; streams) {
1337 params[streamsIndex++] = key;
1338 params[idsIndex++] = value;
1339 }
1340
1341 sendCommand(Command.XREAD, params);
1342 }
1343
1344 void xack(const(ubyte)[] key, const(ubyte)[] group, const(ubyte)[][] ids...) {
1345 const(ubyte)[][] params = new const(ubyte)[][2 + ids.length];
1346 int index = 0;
1347 params[index++] = key;
1348 params[index++] = group;
1349 foreach(const(ubyte)[] id ; ids) {
1350 params[index++] = id;
1351 }
1352 sendCommand(Command.XACK, params);
1353 }
1354
1355 void xgroupCreate(const(ubyte)[] key, const(ubyte)[] groupname, const(ubyte)[] id, bool makeStream) {
1356 if(makeStream) {
1357 sendCommand(Command.XGROUP, cast(const(ubyte)[])to!string(Keyword.CREATE), key, groupname, id, cast(const(ubyte)[])to!string(Keyword.MKSTREAM));
1358 } else {
1359 sendCommand(Command.XGROUP, cast(const(ubyte)[])to!string(Keyword.CREATE), key, groupname, id);
1360 }
1361 }
1362
1363 void xgroupSetID(const(ubyte)[] key, const(ubyte)[] groupname, const(ubyte)[] id) {
1364 sendCommand(Command.XGROUP, cast(const(ubyte)[])to!string(Keyword.SETID), key, groupname, id);
1365 }
1366
1367 void xgroupDestroy(const(ubyte)[] key, const(ubyte)[] groupname) {
1368 sendCommand(Command.XGROUP, cast(const(ubyte)[])to!string(Keyword.DESTROY), key, groupname);
1369 }
1370
1371 void xgroupDelConsumer(const(ubyte)[] key, const(ubyte)[] groupname, const(ubyte)[] consumerName) {
1372 sendCommand(Command.XGROUP, cast(const(ubyte)[])to!string(Keyword.DELCONSUMER), key, groupname, consumerName);
1373 }
1374
1375 void xdel(const(ubyte)[] key, const(ubyte)[][] ids...) {
1376 const(ubyte)[][] params = new const(ubyte)[][1 + ids.length];
1377 int index = 0;
1378 params[index++] = key;
1379 foreach(const(ubyte)[] id ; ids) {
1380 params[index++] = id;
1381 }
1382 sendCommand(Command.XDEL, params);
1383 }
1384
1385 void xtrim(const(ubyte)[] key, long maxLen, bool approximateLength) {
1386 if(approximateLength) {
1387 sendCommand(Command.XTRIM, key, cast(const(ubyte)[])to!string(Keyword.MAXLEN), Protocol.BYTES_TILDE ,toByteArray(maxLen));
1388 } else {
1389 sendCommand(Command.XTRIM, key, cast(const(ubyte)[])to!string(Keyword.MAXLEN), toByteArray(maxLen));
1390 }
1391 }
1392
1393 void xreadGroup(const(ubyte)[] groupname, const(ubyte)[] consumer, int count,
1394 long block, bool noAck, Map!(const(ubyte)[], const(ubyte)[]) streams) {
1395
1396 int optional = 0;
1397 if(count>0) {
1398 optional += 2;
1399 }
1400 if(block > 0) {
1401 optional += 2;
1402 }
1403 if(noAck) {
1404 optional += 1;
1405 }
1406
1407
1408 const(ubyte)[][] params = new const(ubyte)[][4 + optional + streams.size() * 2];
1409
1410 int streamsIndex = 0;
1411 params[streamsIndex++] = cast(const(ubyte)[])to!string(Keyword.GROUP);
1412 params[streamsIndex++] = groupname;
1413 params[streamsIndex++] = consumer;
1414 if(count>0) {
1415 params[streamsIndex++] = cast(const(ubyte)[])to!string(Keyword.COUNT);
1416 params[streamsIndex++] = toByteArray(count);
1417 }
1418 if(block > 0) {
1419 params[streamsIndex++] = cast(const(ubyte)[])to!string(Keyword.BLOCK);
1420 params[streamsIndex++] = toByteArray(block);
1421 }
1422 if(noAck) {
1423 params[streamsIndex++] = cast(const(ubyte)[])to!string(Keyword.NOACK);
1424 }
1425 params[streamsIndex++] = cast(const(ubyte)[])to!string(Keyword.STREAMS);
1426
1427 int idsIndex = streamsIndex + streams.size();
1428 foreach(const(ubyte)[] key, const(ubyte)[] value ; streams) {
1429 params[streamsIndex++] = key;
1430 params[idsIndex++] = value;
1431 }
1432
1433 sendCommand(Command.XREADGROUP, params);
1434 }
1435
1436
1437 void xpending(const(ubyte)[] key, const(ubyte)[] groupname, const(ubyte)[] start,
1438 const(ubyte)[] end, int count, const(ubyte)[] consumername) {
1439 if(consumername is null) {
1440 sendCommand(Command.XPENDING, key, groupname, start, end, toByteArray(count));
1441 } else {
1442 sendCommand(Command.XPENDING, key, groupname, start, end, toByteArray(count), consumername);
1443 }
1444 }
1445
1446 void xclaim(const(ubyte)[] key, const(ubyte)[] groupname, const(ubyte)[] consumername, long minIdleTime,
1447 long newIdleTime, int retries, bool force, const(ubyte)[][] ids) {
1448
1449 ArrayList!(const(ubyte)[]) arguments = new ArrayList!(const(ubyte)[])(cast(int)(10 + ids.length));
1450
1451 arguments.add(key);
1452 arguments.add(groupname);
1453 arguments.add(consumername);
1454 arguments.add(toByteArray(minIdleTime));
1455
1456 foreach(const(ubyte)[] id ; ids) {
1457 arguments.add(id);
1458 }
1459 if(newIdleTime > 0) {
1460 arguments.add(cast(const(ubyte)[])to!string(Keyword.IDLE));
1461 arguments.add(toByteArray(newIdleTime));
1462 }
1463 if(retries > 0) {
1464 arguments.add(cast(const(ubyte)[])to!string(Keyword.RETRYCOUNT));
1465 arguments.add(toByteArray(retries));
1466 }
1467 if(force) {
1468 arguments.add(cast(const(ubyte)[])to!string(Keyword.FORCE));
1469 }
1470 sendCommand(Command.XCLAIM, arguments.toArray());
1471 }
1472
1473 }