diff --git a/examples/async_basic.cpp b/examples/async_basic.cpp index b19661a7..d636088a 100644 --- a/examples/async_basic.cpp +++ b/examples/async_basic.cpp @@ -30,12 +30,12 @@ example(net::ip::tcp::socket& socket, resp3::consumer cs; for (;;) { - auto const t = co_await cs.async_consume(socket, requests, resp, net::use_awaitable); + resp.clear(); + co_await cs.async_consume(socket, requests, resp, net::use_awaitable); std::cout << resp << std::endl; - if (t == resp3::type::push) { + if (resp.get_type() == resp3::type::push) continue; - } auto const id = requests.front().ids.front(); diff --git a/include/aedis/resp3/detail/adapter_utils.hpp b/include/aedis/resp3/detail/adapter_utils.hpp index f021621a..8b11d3e5 100644 --- a/include/aedis/resp3/detail/adapter_utils.hpp +++ b/include/aedis/resp3/detail/adapter_utils.hpp @@ -11,7 +11,9 @@ #include #include -namespace aedis { namespace resp3 { namespace detail { +namespace aedis { +namespace resp3 { +namespace detail { template typename std::enable_if::value, void>::type diff --git a/include/aedis/resp3/detail/basic_flat_array_adapter.hpp b/include/aedis/resp3/detail/basic_flat_array_adapter.hpp index 22b86904..34b74cb3 100644 --- a/include/aedis/resp3/detail/basic_flat_array_adapter.hpp +++ b/include/aedis/resp3/detail/basic_flat_array_adapter.hpp @@ -11,7 +11,9 @@ #include #include -namespace aedis { namespace resp3 { namespace detail { +namespace aedis { +namespace resp3 { +namespace detail { template using basic_flat_array = std::vector; diff --git a/include/aedis/resp3/detail/array_adapter.hpp b/include/aedis/resp3/detail/response_adapter.hpp similarity index 78% rename from include/aedis/resp3/detail/array_adapter.hpp rename to include/aedis/resp3/detail/response_adapter.hpp index e69a2ab6..edd07e46 100644 --- a/include/aedis/resp3/detail/array_adapter.hpp +++ b/include/aedis/resp3/detail/response_adapter.hpp @@ -19,28 +19,28 @@ namespace detail { // This response type is able to deal with recursive redis responses // as in a transaction for example. -class array_adapter: public response_adapter_base { +class response_adapter: public response_adapter_base { private: std::vector* result_; std::size_t depth_; public: - array_adapter(std::vector* p = nullptr) + response_adapter(std::vector* p) : result_{p} , depth_{0} { } void add_aggregate(type t, int n) override - { - result_->emplace_back(n, depth_, t, std::string{}); - ++depth_; - } + { result_->emplace_back(n, depth_, t, std::string{}); ++depth_; } void add(type t, std::string_view s = {}) override { result_->emplace_back(1, depth_, t, std::string{s}); } - void pop() override { --depth_; } - void clear() { depth_ = 0; } + void pop() override + { --depth_; } + + void clear() + { depth_ = 0; } }; } // detail diff --git a/include/aedis/resp3/impl/response.ipp b/include/aedis/resp3/impl/response.ipp index 41fbfec1..77d0ccfa 100644 --- a/include/aedis/resp3/impl/response.ipp +++ b/include/aedis/resp3/impl/response.ipp @@ -11,15 +11,10 @@ namespace aedis { namespace resp3 { -response_adapter_base* -response::select_adapter( - type type, - command cmd, - std::string const&) +void response::clear() { data_.resize(0); - array_adapter_.clear(); - return &array_adapter_; + adapter_.clear(); } std::ostream& operator<<(std::ostream& os, response const& r) diff --git a/include/aedis/resp3/request.hpp b/include/aedis/resp3/request.hpp index 8afacb96..7b0dbf95 100644 --- a/include/aedis/resp3/request.hpp +++ b/include/aedis/resp3/request.hpp @@ -19,7 +19,8 @@ #include -namespace aedis { namespace resp3 { +namespace aedis { +namespace resp3 { // TODO: Move to detail. void add_bulk(std::string& to, std::string_view param); @@ -127,9 +128,6 @@ public: auto size() const noexcept { return std::size(ids); } - auto payload_size() const noexcept - { return std::size(payload); } - bool empty() const noexcept { return std::empty(payload); }; @@ -299,14 +297,14 @@ public: /// Adds ping to the request, see https://redis.io/commands/rpush template - void rpush( std::string_view key, std::initializer_list v) + 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) + void rpush(std::string_view key, Range const& v) { using std::cbegin; using std::cend; diff --git a/include/aedis/resp3/response.hpp b/include/aedis/resp3/response.hpp index 4c966569..8ea2ab82 100644 --- a/include/aedis/resp3/response.hpp +++ b/include/aedis/resp3/response.hpp @@ -10,9 +10,10 @@ #include #include #include -#include +#include -namespace aedis { namespace resp3 { +namespace aedis { +namespace resp3 { /// A pre-order-view of the response tree. class response { @@ -24,7 +25,7 @@ private: std::ostream& operator<<(std::ostream& os, response const& r); storage_type data_; - detail::array_adapter array_adapter_{&data_}; + detail::response_adapter adapter_{&data_}; public: virtual ~response() = default; @@ -36,12 +37,29 @@ public: virtual response_adapter_base* select_adapter( - resp3::type type, + resp3::type t, command cmd = command::unknown, - std::string const& key = ""); + std::string const& key = "") + { return &adapter_; } + auto const& raw() const noexcept {return data_;} auto& raw() noexcept {return data_;} + + /** Clears the internal buffers but does not release already aquired + * memory. This function is usually called before reading a new + * response. + */ + void clear(); + + /// Returns true if the response is empty. + auto empty() const noexcept { return std::empty(data_);} + + /** Returns the RESP3 type of the response. + * + * Expects a non-empty response. + */ + auto get_type() const noexcept { return data_.front().data_type; } }; /** Writes the text representation of the response to the output diff --git a/include/aedis/resp3/response_adapter_base.hpp b/include/aedis/resp3/response_adapter_base.hpp index 02a43523..c29af5d9 100644 --- a/include/aedis/resp3/response_adapter_base.hpp +++ b/include/aedis/resp3/response_adapter_base.hpp @@ -42,7 +42,7 @@ struct response_adapter_base { virtual void add(type t, std::string_view s = {}) {} /** Called from the parser everytime a new RESP3 aggregate data - * type is received, those are + * type is received, those are * * array * push diff --git a/tests/general.cpp b/tests/general.cpp index ca7f3c8d..4233b826 100644 --- a/tests/general.cpp +++ b/tests/general.cpp @@ -33,7 +33,7 @@ using flat_array_int_type = detail::basic_flat_array; using namespace aedis; resp3::response::storage_type array_buffer; -resp3::detail::array_adapter array_adapter{&array_buffer}; +resp3::detail::response_adapter radapter{&array_buffer}; template void check_equal(T const& a, T const& b, std::string const& msg = "") @@ -130,6 +130,7 @@ test_general(net::ip::tcp::resolver::results_type const& res) int push_counter = 0; for (;;) { + resp.clear(); auto const t = co_await cs.async_consume(socket, requests, resp, net::use_awaitable); @@ -459,14 +460,14 @@ test_list(net::ip::tcp::resolver::results_type const& results) { // hello array_buffer.clear(); - array_adapter.clear(); - co_await async_read_one(socket, buf, array_adapter); + radapter.clear(); + co_await async_read_one(socket, buf, radapter); } { // flushall array_buffer.clear(); - array_adapter.clear(); - co_await async_read_one(socket, buf, array_adapter); + radapter.clear(); + co_await async_read_one(socket, buf, radapter); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; check_equal(array_buffer, expected, "flushall"); @@ -474,10 +475,10 @@ test_list(net::ip::tcp::resolver::results_type const& results) { // rpush array_buffer.clear(); - array_adapter.clear(); + radapter.clear(); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::number, {"6"}} }; - co_await async_read_one(socket, buf, array_adapter); + co_await async_read_one(socket, buf, radapter); check_equal(array_buffer, expected, "rpush"); } @@ -497,28 +498,28 @@ test_list(net::ip::tcp::resolver::results_type const& results) { // ltrim array_buffer.clear(); - array_adapter.clear(); + radapter.clear(); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; - co_await async_read_one(socket, buf, array_adapter); + co_await async_read_one(socket, buf, radapter); check_equal(array_buffer, expected, "ltrim"); } { // lpop. Why a blob string instead of a number? array_buffer.clear(); - array_adapter.clear(); + radapter.clear(); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::blob_string, {"3"}} }; - co_await async_read_one(socket, buf, array_adapter); + co_await async_read_one(socket, buf, radapter); check_equal(array_buffer, expected, "lpop"); } { // quit array_buffer.clear(); - array_adapter.clear(); - co_await async_read_one(socket, buf, array_adapter); + radapter.clear(); + co_await async_read_one(socket, buf, radapter); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; check_equal(array_buffer, expected, "ltrim"); @@ -558,15 +559,15 @@ test_set(net::ip::tcp::resolver::results_type const& results) std::string buf; { // hello, flushall array_buffer.clear(); - array_adapter.clear(); - co_await async_read_one(socket, buf, array_adapter); - co_await async_read_one(socket, buf, array_adapter); + radapter.clear(); + co_await async_read_one(socket, buf, radapter); + co_await async_read_one(socket, buf, radapter); } { // set array_buffer.clear(); - array_adapter.clear(); - co_await async_read_one(socket, buf, array_adapter); + radapter.clear(); + co_await async_read_one(socket, buf, radapter); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; check_equal(array_buffer, expected, "set1"); @@ -574,18 +575,18 @@ test_set(net::ip::tcp::resolver::results_type const& results) { // get array_buffer.clear(); - array_adapter.clear(); + radapter.clear(); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::blob_string, test_bulk1} }; - co_await async_read_one(socket, buf, array_adapter); + co_await async_read_one(socket, buf, radapter); check_equal(array_buffer, expected, "get1"); } { // set array_buffer.clear(); - array_adapter.clear(); - co_await async_read_one(socket, buf, array_adapter); + radapter.clear(); + co_await async_read_one(socket, buf, radapter); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; check_equal(array_buffer, expected, "ltrim"); @@ -593,17 +594,17 @@ test_set(net::ip::tcp::resolver::results_type const& results) { // get array_buffer.clear(); - array_adapter.clear(); + radapter.clear(); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::blob_string, test_bulk2} }; - co_await async_read_one(socket, buf, array_adapter); + co_await async_read_one(socket, buf, radapter); check_equal(array_buffer, expected, "get2"); } { // set array_buffer.clear(); - array_adapter.clear(); - co_await async_read_one(socket, buf, array_adapter); + radapter.clear(); + co_await async_read_one(socket, buf, radapter); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; check_equal(array_buffer, expected, "set3"); @@ -611,18 +612,18 @@ test_set(net::ip::tcp::resolver::results_type const& results) { // get array_buffer.clear(); - array_adapter.clear(); + radapter.clear(); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::blob_string, {}} }; - co_await async_read_one(socket, buf, array_adapter); + co_await async_read_one(socket, buf, radapter); check_equal(array_buffer, expected, "get3"); } { // quit array_buffer.clear(); - array_adapter.clear(); - co_await async_read_one(socket, buf, array_adapter); + radapter.clear(); + co_await async_read_one(socket, buf, radapter); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; check_equal(array_buffer, expected, "quit"); @@ -645,8 +646,8 @@ net::awaitable test_simple_string() std::string cmd {"+OK\r\n"}; test_tcp_socket ts {cmd}; array_buffer.clear(); - array_adapter.clear(); - co_await async_read_one(ts, buf, array_adapter); + radapter.clear(); + co_await async_read_one(ts, buf, radapter); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; check_equal(array_buffer, expected, "simple_string"); @@ -657,8 +658,8 @@ net::awaitable test_simple_string() std::string cmd {"+\r\n"}; test_tcp_socket ts {cmd}; array_buffer.clear(); - array_adapter.clear(); - co_await async_read_one(ts, buf, array_adapter); + radapter.clear(); + co_await async_read_one(ts, buf, radapter); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::simple_string, {}} }; check_equal(array_buffer, expected, "simple_string (empty)"); @@ -688,10 +689,10 @@ net::awaitable test_number() std::string cmd {":-3\r\n"}; test_tcp_socket ts {cmd}; array_buffer.clear(); - array_adapter.clear(); + radapter.clear(); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::number, {"-3"}} }; - co_await async_read_one(ts, buf, array_adapter); + co_await async_read_one(ts, buf, radapter); check_equal(array_buffer, expected, "number (int)"); } @@ -699,10 +700,10 @@ net::awaitable test_number() std::string cmd {":3\r\n"}; test_tcp_socket ts {cmd}; array_buffer.clear(); - array_adapter.clear(); + radapter.clear(); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::number, {"3"}} }; - co_await async_read_one(ts, buf, array_adapter); + co_await async_read_one(ts, buf, radapter); check_equal(array_buffer, expected, "number (unsigned)"); } @@ -710,10 +711,10 @@ net::awaitable test_number() std::string cmd {":1111111\r\n"}; test_tcp_socket ts {cmd}; array_buffer.clear(); - array_adapter.clear(); + radapter.clear(); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::number, {"1111111"}} }; - co_await async_read_one(ts, buf, array_adapter); + co_await async_read_one(ts, buf, radapter); check_equal(array_buffer, expected, "number (std::size_t)"); } } @@ -726,14 +727,14 @@ net::awaitable test_array() std::string cmd {"*3\r\n$3\r\none\r\n$3\r\ntwo\r\n$5\r\nthree\r\n"}; test_tcp_socket ts {cmd}; array_buffer.clear(); - array_adapter.clear(); + radapter.clear(); resp3::response::storage_type expected { {3UL, 0UL, resp3::type::array, {}} , {1UL, 1UL, resp3::type::blob_string, {"one"}} , {1UL, 1UL, resp3::type::blob_string, {"two"}} , {1UL, 1UL, resp3::type::blob_string, {"three"}} }; - co_await async_read_one(ts, buf, array_adapter); + co_await async_read_one(ts, buf, radapter); check_equal(array_buffer, expected, "array"); } @@ -750,10 +751,10 @@ net::awaitable test_array() std::string cmd {"*0\r\n"}; test_tcp_socket ts {cmd}; array_buffer.clear(); - array_adapter.clear(); + radapter.clear(); resp3::response::storage_type expected { {0UL, 0UL, resp3::type::array, {}} }; - co_await async_read_one(ts, buf, array_adapter); + co_await async_read_one(ts, buf, radapter); check_equal(array_buffer, expected, "array (empty)"); } } @@ -766,10 +767,10 @@ net::awaitable test_blob_string() std::string cmd {"$2\r\nhh\r\n"}; test_tcp_socket ts {cmd}; array_buffer.clear(); - array_adapter.clear(); + radapter.clear(); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::blob_string, {"hh"}} }; - co_await async_read_one(ts, buf, array_adapter); + co_await async_read_one(ts, buf, radapter); check_equal(array_buffer, expected, "blob_string"); } @@ -777,10 +778,10 @@ net::awaitable test_blob_string() std::string cmd {"$26\r\nhhaa\aaaa\raaaaa\r\naaaaaaaaaa\r\n"}; test_tcp_socket ts {cmd}; array_buffer.clear(); - array_adapter.clear(); + radapter.clear(); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::blob_string, {"hhaa\aaaa\raaaaa\r\naaaaaaaaaa"}} }; - co_await async_read_one(ts, buf, array_adapter); + co_await async_read_one(ts, buf, radapter); check_equal(array_buffer, expected, "blob_string (with separator)"); } @@ -788,10 +789,10 @@ net::awaitable test_blob_string() std::string cmd {"$0\r\n\r\n"}; test_tcp_socket ts {cmd}; array_buffer.clear(); - array_adapter.clear(); + radapter.clear(); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::blob_string, {}} }; - co_await async_read_one(ts, buf, array_adapter); + co_await async_read_one(ts, buf, radapter); check_equal(array_buffer, expected, "blob_string (size 0)"); } } @@ -804,10 +805,10 @@ net::awaitable test_simple_error() std::string cmd {"-Error\r\n"}; test_tcp_socket ts {cmd}; array_buffer.clear(); - array_adapter.clear(); + radapter.clear(); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::simple_error, {"Error"}} }; - co_await async_read_one(ts, buf, array_adapter); + co_await async_read_one(ts, buf, radapter); check_equal(array_buffer, expected, "simple_error (message)"); } } @@ -888,10 +889,10 @@ net::awaitable test_blob_error() std::string cmd {"!21\r\nSYNTAX invalid syntax\r\n"}; test_tcp_socket ts {cmd}; array_buffer.clear(); - array_adapter.clear(); + radapter.clear(); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::blob_error, {"SYNTAX invalid syntax"}} }; - co_await async_read_one(ts, buf, array_adapter); + co_await async_read_one(ts, buf, radapter); check_equal(array_buffer, expected, "blob_error (message)"); } @@ -899,10 +900,11 @@ net::awaitable test_blob_error() std::string cmd {"!0\r\n\r\n"}; test_tcp_socket ts {cmd}; array_buffer.clear(); - array_adapter.clear(); + radapter.clear(); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::blob_error, {}} }; - co_await async_read_one(ts, buf, array_adapter); + + co_await async_read_one(ts, buf, radapter); check_equal(array_buffer, expected, "blob_error (empty message)"); } } @@ -915,19 +917,19 @@ net::awaitable test_verbatim_string() std::string cmd {"=15\r\ntxt:Some string\r\n"}; test_tcp_socket ts {cmd}; array_buffer.clear(); - array_adapter.clear(); + radapter.clear(); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::verbatim_string, {"txt:Some string"}} }; - co_await async_read_one(ts, buf, array_adapter); + co_await async_read_one(ts, buf, radapter); check_equal(array_buffer, expected, "verbatim_string"); } { std::string cmd {"=0\r\n\r\n"}; test_tcp_socket ts {cmd}; - co_await async_read_one(ts, buf, array_adapter); array_buffer.clear(); - array_adapter.clear(); + radapter.clear(); + co_await async_read_one(ts, buf, radapter); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::verbatim_string, {}} }; check_equal(array_buffer, expected, "verbatim_string (empty)"); @@ -952,7 +954,7 @@ net::awaitable test_set2() , { 1UL, 1UL, resp3::type::simple_string, {"three"}} }; - co_await async_read_one(ts, buf, array_adapter); + co_await async_read_one(ts, buf, radapter); check_equal(array_buffer, expected, "test set (1)"); } @@ -965,7 +967,7 @@ net::awaitable test_set2() { { 0UL, 0UL, resp3::type::set, {}} }; - co_await async_read_one(ts, buf, array_adapter); + co_await async_read_one(ts, buf, radapter); check_equal(array_buffer, expected, "test set (2)"); } } @@ -978,8 +980,8 @@ net::awaitable test_map() std::string cmd {"%7\r\n$6\r\nserver\r\n$5\r\nredis\r\n$7\r\nversion\r\n$5\r\n6.0.9\r\n$5\r\nproto\r\n:3\r\n$2\r\nid\r\n:203\r\n$4\r\nmode\r\n$10\r\nstandalone\r\n$4\r\nrole\r\n$6\r\nmaster\r\n$7\r\nmodules\r\n*0\r\n"}; test_tcp_socket ts {cmd}; array_buffer.clear(); - array_adapter.clear(); - co_await async_read_one(ts, buf, array_adapter); + radapter.clear(); + co_await async_read_one(ts, buf, radapter); resp3::response::storage_type expected { {14UL, 0UL, resp3::type::map, {}} @@ -1005,8 +1007,8 @@ net::awaitable test_map() std::string cmd {"%0\r\n"}; test_tcp_socket ts {cmd}; array_buffer.clear(); - array_adapter.clear(); - co_await async_read_one(ts, buf, array_adapter); + radapter.clear(); + co_await async_read_one(ts, buf, radapter); resp3::response::storage_type expected { {0UL, 0UL, resp3::type::map, {}} }; check_equal(array_buffer, expected, "test map (empty)"); @@ -1021,10 +1023,10 @@ net::awaitable test_streamed_string() std::string cmd {"$?\r\n;4\r\nHell\r\n;5\r\no wor\r\n;1\r\nd\r\n;0\r\n"}; test_tcp_socket ts {cmd}; array_buffer.clear(); - array_adapter.clear(); + radapter.clear(); resp3::response::storage_type expected { {1UL, 0UL, resp3::type::streamed_string_part, {"Hello world"}} }; - co_await resp3::async_read_one(ts, buf, array_adapter); + co_await resp3::async_read_one(ts, buf, radapter); check_equal(array_buffer, expected, "streamed string"); } @@ -1047,7 +1049,7 @@ net::awaitable offline() //{ // std::string cmd {"|1\r\n+key-popularity\r\n%2\r\n$1\r\na\r\n,0.1923\r\n$1\r\nb\r\n,0.0012\r\n"}; // test_tcp_socket ts {cmd}; - // resp3::flat_array_adapter res; + // resp3::flat_radapter res; // co_await async_read_one(ts, buf, res); // check_equal(res.result, {"key-popularity", "a", "0.1923", "b", "0.0012"}, "attribute"); //} @@ -1055,7 +1057,7 @@ net::awaitable offline() //{ // std::string cmd {">4\r\n+pubsub\r\n+message\r\n+foo\r\n+bar\r\n"}; // test_tcp_socket ts {cmd}; - // resp3::flat_array_adapter res; + // resp3::flat_radapter res; // co_await async_read_one(ts, buf, res); // check_equal(res.result, {"pubsub", "message", "foo", "bar"}, "push type"); //} @@ -1063,7 +1065,7 @@ net::awaitable offline() //{ // std::string cmd {">0\r\n"}; // test_tcp_socket ts {cmd}; - // resp3::flat_array_adapter res; + // resp3::flat_radapter res; // co_await async_read_one(ts, buf, res); // check_equal(res.result, {}, "push type (empty)"); //}