1 module collections; 2 3 import std.range, 4 std.algorithm, 5 tinyredis.redis, 6 tinyredis.parser; 7 8 /* 9 Implements InputRange, OutputRange. 10 11 Operations should be done on the server side as much as possible, to reflect the true state of 12 the collection on the server. 13 */ 14 class Set 15 { 16 private : 17 string name; 18 Redis conn; 19 20 //Loading members 21 uint ctr = 0; 22 int total = -1; 23 Response _members; 24 bool loaded; 25 26 public : 27 28 this(Redis conn, const(char[]) name) 29 { 30 this.conn = conn; 31 this.name = cast(string)name; 32 } 33 34 Response smembers() 35 { 36 return conn.send("SMEMBERS", name); 37 } 38 39 int scard() 40 { 41 return conn.send!(int)("SCARD", name); 42 } 43 44 bool srem(const(char[]) value) 45 { 46 return conn.send!(bool)("SREM", name, value); 47 } 48 49 // OutputRange 50 void put(const(char[]) value) 51 { 52 conn.send("SADD", name, value); 53 } 54 55 void put(const(char[])[] values) 56 { 57 foreach(value; values) 58 conn.send("SADD", name, value); 59 } 60 61 void opAssign(const(char[]) value) 62 { 63 conn.send("DEL", name); 64 put(value); 65 } 66 67 void opAssign(const(char[])[] values) 68 { 69 conn.send("DEL", name); 70 put(values); 71 } 72 73 void opOpAssign(string op)(const(char[]) value) 74 { 75 static if (op == "~") { 76 put(value); 77 } else static if (op == "-") 78 srem(value); 79 else 80 static assert(0, "Operator "~op~" not implemented"); 81 } 82 83 void opOpAssign(string op)(const(char[])[] values) 84 { 85 static if (op == "~") { 86 foreach(value; values) 87 put(value); 88 } else static if (op == "-") 89 foreach(value; values) 90 srem(value); 91 else 92 static assert(0, "Operator "~op~" not implemented"); 93 } 94 95 void reset() 96 { 97 total = scard(); 98 ctr = 0; 99 loaded = true; 100 } 101 102 // InputRange 103 Response front() 104 { 105 if(!loaded) 106 { 107 load(); 108 loaded = true; 109 } 110 111 return _members.values[ctr]; 112 } 113 114 void popFront() 115 { 116 if(ctr < _members.values.length) 117 ctr++; 118 } 119 120 bool empty() 121 { 122 if(total == -1) 123 total = scard(); 124 125 return !(ctr < total); 126 } 127 128 private void load() 129 { 130 _members = smembers(); 131 } 132 } 133 134 class SortedSet 135 { 136 137 } 138 139 class List{} 140 class Hash{} 141 142 unittest { 143 144 assert(isInputRange!(Set)); 145 assert(isOutputRange!(Set, string)); 146 147 auto conn = new Redis("localhost", 6379); 148 auto set = new Set(conn, "tinyRedisUnitTestSet"); 149 auto data = ["banana", "apple", "orange"]; 150 set = data; 151 set.put("grapes"); 152 assert(set.scard() == 4); 153 154 //opAssign resets the data 155 set = ["adil", "baig"]; 156 assert(set.scard() == 2); 157 set ~= "banana"; 158 set ~= "apple"; 159 set ~= ["orange", "mango"]; 160 assert(set.scard() == 6); 161 162 set = data; 163 foreach(s; set) 164 assert(!std.algorithm.find(data, cast(string)s).empty); 165 166 assert(set.empty()); 167 set.reset(); 168 assert(!set.empty()); 169 assert(set.scard() == 3); 170 }