diff --git a/include/aedis/command.hpp b/include/aedis/command.hpp index bcfba2b4..c0ef9ab5 100644 --- a/include/aedis/command.hpp +++ b/include/aedis/command.hpp @@ -33,12 +33,14 @@ enum class command , bgrewriteaof /// https://redis.io/commands/bgsave , bgsave + /// Adds ping to the request, see https://redis.io/commands/bitcount , bitcount /// https://redis.io/commands/client_id , client_id /// https://redis.io/commands/del , del , exec + /// https://redis.io/commands/expire , expire /// https://redis.io/commands/flushall , flushall @@ -46,18 +48,23 @@ enum class command , get /// https://redis.io/commands/hello , hello + /// https://redis.io/commands/hget , hget /// https://redis.io/commands/hgetall , hgetall + /// https://redis.io/commands/hincrby , hincrby /// https://redis.io/commands/hkeys , hkeys /// https://redis.io/commands/hlen , hlen + /// https://redis.io/commands/hmget , hmget + /// https://redis.io/commands/hset , hset /// https://redis.io/commands/hvals , hvals + /// https://redis.io/commands/hdel , hdel , incr /// https://redis.io/commands/keys @@ -66,8 +73,11 @@ enum class command , llen /// https://redis.io/commands/lpop , lpop + /// https://redis.io/commands/lpush , lpush + /// https://redis.io/commands/lrange , lrange + /// https://redis.io/commands/ltrim , ltrim , multi , ping @@ -77,22 +87,28 @@ enum class command , quit /// https://redis.io/commands/role , role + /// Adds ping to the request, see https://redis.io/commands/rpush , rpush + /// https://redis.io/commands/sadd , sadd /// https://redis.io/commands/scard , scard , sdiff /// https://redis.io/commands/sentinel , sentinel + /// Adds ping to the request, see https://redis.io/commands/set , set /// https://redis.io/commands/smembers , smembers , subscribe /// https://redis.io/commands/unsubscribe , unsubscribe + /// https://redis.io/commands/zadd , zadd , zrange + /// https://redis.io/commands/zrangebyscore , zrangebyscore + /// https://redis.io/commands/zremrangebyscore , zremrangebyscore , unknown }; diff --git a/include/aedis/resp3/request.hpp b/include/aedis/resp3/request.hpp index 4d28406e..aa0ca784 100644 --- a/include/aedis/resp3/request.hpp +++ b/include/aedis/resp3/request.hpp @@ -61,22 +61,52 @@ public: elements.emplace(c, std::string{}); } - void push(command c, std::string_view param) + template + void push(command c, T const& p1) { detail::add_header(payload, 2); detail::add_bulk(payload, as_string(c)); - detail::add_bulk(payload, param); - elements.emplace(c, std::string{param}); + detail::add_bulk(payload, p1); + elements.emplace(c, std::string{p1}); } template - void push(command c, std::string_view p1, T const& p2) + void push(command c, std::string_view key, T const& p) { detail::add_header(payload, 3); detail::add_bulk(payload, as_string(c)); + detail::add_bulk(payload, key); + detail::add_bulk(payload, p); + elements.emplace(c, std::string{key}); + } + + template + void push(command c, std::string_view key, T1 const& p1, T2 const& p2) + { + detail::add_header(payload, 4); + detail::add_bulk(payload, as_string(c)); + detail::add_bulk(payload, key); detail::add_bulk(payload, p1); detail::add_bulk(payload, p2); - elements.emplace(c, std::string{p1}); + elements.emplace(c, std::string{key}); + } + + template + void push_range(command cmd, std::string_view key, ForwardIterator begin, ForwardIterator end) + { + // TODO: For hset find a way to assert the value type is a pair. + using value_type = typename std::iterator_traits::value_type; + + auto constexpr size = detail::value_type_size::size; + auto const distance = std::distance(begin, end); + detail::add_header(payload, 2 + size * distance); + detail::add_bulk(payload, as_string(cmd)); + detail::add_bulk(payload, key); + + for (; begin != end; ++begin) + detail::add_bulk(payload, *begin); + + elements.emplace(cmd, std::string{key}); } /// Adds subscribe to the request, see https://redis.io/commands/subscribe @@ -96,241 +126,6 @@ public: // The response to this command is a push type. detail::assemble(payload, "UNSUBSCRIBE", key); } - - /// Adds ping to the request, see https://redis.io/commands/bitcount - void bitcount(std::string_view key, int start = 0, int end = -1) - { - auto const start_str = std::to_string(start); - auto const end_str = std::to_string(end); - auto const param = {start_str, end_str}; - auto const keys = {key}; - - detail::assemble(payload, "BITCOUNT", keys, param); - elements.emplace(command::bitcount, std::string{key}); - } - - /// Adds ping to the request, see https://redis.io/commands/rpush - template - void rpush(std::string_view key, Iter begin, Iter end) - { - auto const keys = {key}; - detail::assemble(payload, "RPUSH", std::cbegin(keys), std::cend(keys), begin, end); - elements.emplace(command::rpush, std::string{key}); - } - - /// Adds ping to the request, see https://redis.io/commands/rpush - template - void rpush(std::string_view key, std::initializer_list v) - { - return rpush(key, std::cbegin(v), std::cend(v)); - } - - /// Adds ping to the request, see https://redis.io/commands/rpush - template - void rpush(std::string_view key, Range const& v) - { - using std::cbegin; - using std::cend; - rpush(key, cbegin(v), cend(v)); - } - - /// Adds ping to the request, see https://redis.io/commands/lpush - template - void lpush(std::string_view key, Iter begin, Iter end) - { - detail::assemble(payload, "LPUSH", {key}, begin, end); - elements.emplace(command::lpush, std::string{key}); - } - - /// Adds ping to the request, see https://redis.io/commands/set - void set(std::string_view key, - std::initializer_list args) - { - auto const keys = {key}; - detail::assemble(payload, "SET", std::cbegin(keys), std::cend(keys), std::cbegin(args), std::cend(args)); - elements.emplace(command::set, std::string{key}); - } - - // TODO: Find a way to assert the value type is a pair. - /// Adds ping to the request, see https://redis.io/commands/hset - template - void hset(std::string_view key, Range const& r) - { - //Note: Requires an std::pair as value type, otherwise gets - //error: ERR Protocol error: expected '$', got '*' - using std::cbegin; - using std::cend; - auto const keys = {key}; - detail::assemble(payload, "HSET", std::cbegin(keys), std::cend(keys), std::cbegin(r), std::cend(r)); - elements.emplace(command::hset, std::string{key}); - } - - /// Adds ping to the request, see https://redis.io/commands/hincrby - void hincrby(std::string_view key, std::string_view field, int by) - { - auto const by_str = std::to_string(by); - std::initializer_list par {field, by_str}; - auto const keys = {key}; - detail::assemble(payload, "HINCRBY", std::cbegin(keys), std::cend(keys), - std::cbegin(par), std::cend(par)); - elements.emplace(command::hincrby, std::string{key}); - } - - /// Adds ping to the request, see https://redis.io/commands/hget - void hget(std::string_view key, std::string_view field) - { - auto const par = {field}; - auto const keys = {key}; - detail::assemble(payload, "HGET", std::cbegin(keys), std::cend(keys), std::cbegin(par), std::cend(par)); - elements.emplace(command::hget, std::string{key}); - } - - /// Adds ping to the request, see https://redis.io/commands/hmget - void hmget( - std::string_view key, - std::initializer_list fields) - { - auto const keys = {key}; - detail::assemble( payload - , "HMGET" - , std::cbegin(keys), std::cend(keys) - , std::cbegin(fields) - , std::cend(fields)); - - elements.emplace(command::hmget, std::string{key}); - } - - /// Adds ping to the request, see https://redis.io/commands/hdel - void - hdel(std::string_view key, - std::initializer_list fields) - { - auto const keys = {key}; - detail::assemble( - payload, - "HDEL", - std::cbegin(keys), std::cend(keys), - std::cbegin(fields), - std::cend(fields)); - - elements.emplace(command::hdel, std::string{key}); - } - - /// Adds ping to the request, see https://redis.io/commands/expire - void expire(std::string_view key, int secs) - { - auto const str = std::to_string(secs); - std::initializer_list par {str}; - - auto const keys = {key}; - detail::assemble(payload, "EXPIRE", std::cbegin(keys), std::cend(keys), std::cbegin(par), std::cend(par)); - elements.emplace(command::expire, std::string{key}); - } - - /// Adds ping to the request, see https://redis.io/commands/zadd - void zadd(std::string_view key, int score, std::string_view value) - { - auto const score_str = std::to_string(score); - std::initializer_list par = {score_str, value}; - auto const keys = {key}; - detail::assemble(payload, "ZADD", std::cbegin(keys), std::cend(keys), std::cbegin(par), std::cend(par)); - elements.emplace(command::zadd, std::string{key}); - } - - /// Adds zadd to the request, see https://redis.io/commands/zadd - template - void zadd(std::initializer_list key, Range const& r) - { - detail::assemble(payload, "ZADD", key, std::cbegin(r), std::cend(r), 2); - elements.emplace(command::zadd, std::string{key}); - } - - /// Adds ping to the request, see https://redis.io/commands/zrange - void zrange(std::string_view key, int min = 0, int max = -1) - { - auto const min_str = std::to_string(min); - auto const max_str = std::to_string(max); - std::initializer_list par {min_str, max_str}; - - auto const keys = {key}; - detail::assemble(payload, "ZRANGE", std::cbegin(keys), std::cend(keys), std::cbegin(par), std::cend(par)); - elements.emplace(command::zrange, std::string{key}); - } - - /// Adds ping to the request, see https://redis.io/commands/zrangebyscore - void zrangebyscore(std::string_view key, int min, int max) - { - auto max_str = std::string {"inf"}; - if (max != -1) - max_str = std::to_string(max); - - auto const min_str = std::to_string(min); - auto par = {min_str , max_str}; - auto const keys = {key}; - detail::assemble(payload, "ZRANGEBYSCORE", std::cbegin(keys), std::cend(keys), std::cbegin(par), std::cend(par)); - elements.emplace(command::zrangebyscore, std::string{key}); - } - - /// Adds ping to the request, see https://redis.io/commands/zremrangebyscore - void - zremrangebyscore( - std::string_view key, - std::string_view min, - std::string_view max) - { - auto const par = {min, max}; - auto const keys = {key}; - detail::assemble(payload, "ZREMRANGEBYSCORE", std::cbegin(keys), std::cend(keys), std::cbegin(par), std::cend(par)); - elements.emplace(command::zremrangebyscore, std::string{key}); - } - - /// Adds ping to the request, see https://redis.io/commands/lrange - void lrange(std::string_view key, int min = 0, int max = -1) - { - auto const min_str = std::to_string(min); - auto const max_str = std::to_string(max); - std::initializer_list par {min_str, max_str}; - auto const keys = {key}; - detail::assemble(payload, "LRANGE", std::cbegin(keys), std::cend(keys), std::cbegin(par), std::cend(par)); - elements.emplace(command::lrange, std::string{key}); - } - - /// Adds ping to the request, see https://redis.io/commands/ltrim - void ltrim(std::string_view key, int min = 0, int max = -1) - { - auto const min_str = std::to_string(min); - auto const max_str = std::to_string(max); - std::initializer_list par {min_str, max_str}; - auto const keys = {key}; - detail::assemble(payload, "LTRIM", std::cbegin(keys), std::cend(keys), std::cbegin(par), std::cend(par)); - elements.emplace(command::ltrim, std::string{key}); - } - - /// Adds ping to the request, see https://redis.io/commands/sadd - template - void sadd(std::string_view key, Iter begin, Iter end) - { - auto const keys = {key}; - detail::assemble(payload, "SADD", std::cbegin(keys), std::cend(keys), begin, end); - elements.emplace(command::sadd, std::string{key}); - } - - /// Adds ping to the request, see https://redis.io/commands/sadd - template - void sadd(std::string_view key, Range const& r) - { - using std::cbegin; - using std::cend; - sadd(key, cbegin(r), cend(r)); - } - - /// Adds ping to the request, see https://redis.io/commands/scard - void scard(std::string_view key, std::initializer_list l) - { - auto const keys = {key}; - detail::assemble(payload, "SDIFF", std::cbegin(keys), std::cend(keys), std::cbegin(l), std::cend(l)); - elements.emplace(command::sdiff, std::string{key}); - } }; /** Prepares the back of a queue to receive further commands and diff --git a/tests/general.cpp b/tests/general.cpp index 5088c797..fcce0f87 100644 --- a/tests/general.cpp +++ b/tests/general.cpp @@ -66,13 +66,13 @@ struct test_general_fill { void operator()(resp3::request& p) const { p.push(command::flushall); - p.rpush("a", list_); + p.push_range(command::rpush, "a", std::cbegin(list_), std::cend(list_)); p.push(command::llen, "a"); - p.lrange("a"); - p.ltrim("a", 2, -2); + p.push(command::lrange, "a", 0, -1); + p.push(command::ltrim, "a", 2, -2); p.push(command::lpop, "a"); //p.lpop("a", 2); // Not working? - p.set("b", {set_}); + p.push(command::set, "b", set_); p.push(command::get, "b"); p.push(command::append, "b", "b"); p.push(command::del, "b"); @@ -85,7 +85,7 @@ struct test_general_fill { for (auto i = 0; i < 3; ++i) { p.push(command::multi); p.push(command::ping); - p.lrange("a"); + p.push(command::lrange, "a", 0, -1); p.push(command::ping); // TODO: It looks like we can't publish to a channel we // are already subscribed to from inside a transaction. @@ -98,18 +98,19 @@ struct test_general_fill { { {"field1", "value1"} , {"field2", "value2"}}; - p.hset("d", m1); - p.hget("d", "field2"); + p.push_range(command::hset, "d", std::cbegin(m1), std::cend(m1)); + p.push(command::hget, "d", "field2"); p.push(command::hgetall, "d"); - p.hdel("d", {"field1", "field2"}); - p.hincrby("e", "some-field", 10); + p.push(command::hdel, "d", "field1", "field2"); // TODO: Test as range too. + p.push(command::hincrby, "e", "some-field", 10); - p.zadd("f", 1, "Marcelo"); - p.zrange("f"); - p.zrangebyscore("f", 1, 1); - p.zremrangebyscore("f", "-inf", "+inf"); + p.push(command::zadd, "f", 1, "Marcelo"); + p.push(command::zrange, "f", 0, 1); + p.push(command::zrangebyscore, "f", 1, 1); + p.push(command::zremrangebyscore, "f", "-inf", "+inf"); - p.sadd("g", std::vector{1, 2, 3}); + auto const v = std::vector{1, 2, 3}; + p.push_range(command::sadd, "g", std::cbegin(v), std::cend(v)); p.push(command::smembers, "g"); p.push(command::quit); @@ -448,10 +449,10 @@ test_list(net::ip::tcp::resolver::results_type const& results) resp3::request p; p.push(command::hello, "3"); p.push(command::flushall); - p.rpush("a", list); - p.lrange("a"); - p.lrange("a", 2, -2); - p.ltrim("a", 2, -2); + p.push_range(command::rpush, "a", std::cbegin(list), std::cend(list)); + p.push(command::lrange, "a", 0, -1); + p.push(command::lrange, "a", 2, -2); + p.push(command::ltrim, "a", 2, -2); p.push(command::lpop, "a"); p.push(command::quit); @@ -549,11 +550,11 @@ test_set(net::ip::tcp::resolver::results_type const& results) resp3::request p; p.push(command::hello, "3"); p.push(command::flushall); - p.set("s", {test_bulk1}); + p.push(command::set, "s", test_bulk1); p.push(command::get, "s"); - p.set("s", {test_bulk2}); + p.push(command::set, "s", test_bulk2); p.push(command::get, "s"); - p.set("s", {""}); + p.push(command::set, "s", ""); p.push(command::get, "s"); p.push(command::quit);