diff --git a/examples/async_basic.cpp b/examples/async_basic.cpp index b663d4ae..92ad69c0 100644 --- a/examples/async_basic.cpp +++ b/examples/async_basic.cpp @@ -9,14 +9,14 @@ using namespace aedis; -void print_event(resp3::type t, std::pair const& p) +void print_event(std::pair const& p) { std::cout << "Event: " << p.first << "."; if (!std::empty(p.second)) std::cout << " Key: " << p.second << "."; - std::cout << " Type: " << t << std::endl; + std::cout << std::endl; } net::awaitable @@ -31,15 +31,15 @@ example(net::ip::tcp::socket& socket, for (;;) { auto const t = co_await cs.async_consume(socket, requests, resp, net::use_awaitable); + std::cout << resp.array() << std::endl; if (t == resp3::type::push) { - std::cout << "Event: " << "(" << t << ")" << std::endl; continue; } auto const id = requests.front().ids.front(); - print_event(t, id); + print_event(id); switch (id.first) { case command::hello: { diff --git a/include/aedis/resp3/detail/array_adapter.hpp b/include/aedis/resp3/detail/array_adapter.hpp index ea2c1b73..ec78f6c8 100644 --- a/include/aedis/resp3/detail/array_adapter.hpp +++ b/include/aedis/resp3/detail/array_adapter.hpp @@ -8,6 +8,7 @@ #pragma once #include +#include #include namespace aedis { @@ -18,7 +19,7 @@ namespace detail { // as in a transaction for example. class array_adapter: public response_adapter_base { private: - array_type* result_; + response_impl* result_; std::size_t depth_; void add_aggregate(int n, type t) @@ -31,16 +32,16 @@ private: { result_->emplace_back(1, depth_, t, std::string{s}); } public: - array_adapter(array_type* p = nullptr) + array_adapter(response_impl* p = nullptr) : result_{p} , depth_{0} { } - void select_array(int n) override {add_aggregate(n, type::flat_array);} + void select_array(int n) override {add_aggregate(n, type::array);} void select_push(int n) override {add_aggregate(n, type::push);} void select_set(int n) override {add_aggregate(n, type::set);} void select_map(int n) override {add_aggregate(n, type::map);} - void select_attribute(int n) override {add_aggregate(n, type::flat_attribute);} + void select_attribute(int n) override {add_aggregate(n, type::attribute);} void on_simple_string(std::string_view s) override { add(s, type::simple_string); } void on_simple_error(std::string_view s) override { add(s, type::simple_error); } diff --git a/include/aedis/resp3/detail/basic_flat_array_adapter.hpp b/include/aedis/resp3/detail/basic_flat_array_adapter.hpp index aff69596..7c392d64 100644 --- a/include/aedis/resp3/detail/basic_flat_array_adapter.hpp +++ b/include/aedis/resp3/detail/basic_flat_array_adapter.hpp @@ -13,6 +13,9 @@ namespace aedis { namespace resp3 { namespace detail { +template +using basic_flat_array = std::vector; + template struct basic_flat_array_adapter : response_adapter_base { int i = 0; diff --git a/include/aedis/resp3/detail/boolean_adapter.hpp b/include/aedis/resp3/detail/boolean_adapter.hpp deleted file mode 100644 index ab69ccb1..00000000 --- a/include/aedis/resp3/detail/boolean_adapter.hpp +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (c) 2019 - 2021 Marcelo Zimbres Silva (mzimbres at gmail dot com) - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -#pragma once - -#include -#include - -namespace aedis { namespace resp3 { namespace detail { - -struct boolean_adapter : public response_adapter_base { - boolean_type* result = nullptr; - - boolean_adapter(boolean_type* p) : result(p) {} - - void on_bool(std::string_view s) override - { - assert(std::ssize(s) == 1); - *result = s[0] == 't'; - } -}; - -} // detail -} // resp3 -} // aedis diff --git a/include/aedis/resp3/detail/ignore_adapter.hpp b/include/aedis/resp3/detail/ignore_adapter.hpp deleted file mode 100644 index 761bf21f..00000000 --- a/include/aedis/resp3/detail/ignore_adapter.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (c) 2019 - 2021 Marcelo Zimbres Silva (mzimbres at gmail dot com) - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -#pragma once - -#include - -namespace aedis { namespace resp3 { namespace detail { - -struct ignore_adapter : response_adapter_base { - void on_simple_string(std::string_view s) override {} - void on_simple_error(std::string_view s) override {} - void on_number(std::string_view s) override {} - void on_double(std::string_view s) override {} - void on_null() override {} - void on_bool(std::string_view s) override {} - void on_big_number(std::string_view s) override {} - void on_verbatim_string(std::string_view s = {}) override {} - void on_blob_string(std::string_view s = {}) override {} - void on_blob_error(std::string_view s = {}) override {} - void on_streamed_string_part(std::string_view s = {}) override {} - void select_array(int n) override {} - void select_set(int n) override {} - void select_map(int n) override {} - void select_push(int n) override {} - void select_attribute(int n) override {} -}; - -} // detail -} // resp3 -} // aedis diff --git a/include/aedis/resp3/detail/number_adapter.hpp b/include/aedis/resp3/detail/number_adapter.hpp deleted file mode 100644 index 5f11ab73..00000000 --- a/include/aedis/resp3/detail/number_adapter.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright (c) 2019 - 2021 Marcelo Zimbres Silva (mzimbres at gmail dot com) - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -#pragma once - -#include -#include -#include - -namespace aedis { namespace resp3 { namespace detail { - -struct number_adapter : public response_adapter_base { - number_type* result = nullptr; - - number_adapter(number_type* p) : result(p) {} - - void on_number(std::string_view s) override - { from_string_view(s, *result); } -}; - -} // detail -} // resp3 -} // aedis diff --git a/include/aedis/resp3/impl/node.ipp b/include/aedis/resp3/impl/node.ipp new file mode 100644 index 00000000..bf95749a --- /dev/null +++ b/include/aedis/resp3/impl/node.ipp @@ -0,0 +1,40 @@ +/* Copyright (c) 2019 - 2021 Marcelo Zimbres Silva (mzimbres at gmail dot com) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include + +namespace aedis { namespace resp3 { + +bool operator==(node const& a, node const& b) +{ + return a.size == b.size + && a.depth == b.depth + && a.data_type == b.data_type + && a.data == b.data; +}; + +} // resp3 +} // aedis + +std::ostream& operator<<(std::ostream& os, aedis::resp3::node const& o) +{ + std::string res(3 * o.depth, ' '); + res += o.data; + res += "("; + res += to_string(o.data_type); + res += ")"; + os << res; + return os; +} + +std::ostream& operator<<(std::ostream& os, aedis::resp3::response_impl const& r) +{ + for (auto const& n : r) + os << n << "\n"; + + return os; +} diff --git a/include/aedis/resp3/impl/response.ipp b/include/aedis/resp3/impl/response.ipp index 3810afc5..32734095 100644 --- a/include/aedis/resp3/impl/response.ipp +++ b/include/aedis/resp3/impl/response.ipp @@ -11,41 +11,14 @@ namespace aedis { namespace resp3 { response_adapter_base* -response::select_adapter(type type, command cmd, std::string const&) +response::select_adapter( + type type, + command cmd, + std::string const&) { - if (cmd == command::exec) { - array_.resize(0); - array_adapter_.clear(); - return &array_adapter_; - } - - switch (type) { - case type::doublean: - case type::simple_string: - case type::blob_string: - case type::simple_error: - case type::blob_error: - case type::big_number: - case type::verbatim_string: - case type::streamed_string_part: - case type::set: - case type::map: - case type::push: - { - array_.resize(0); - array_adapter_.clear(); - return &array_adapter_; - } - case type::flat_attribute: return &flat_attribute_adapter_; - case type::flat_array: return &flat_array_adapter_; - case type::number: return &number_adapter_; - case type::boolean: return &boolean_adapter_; - case type::null: return &ignore_adapter_; - default: { - assert(false); - return nullptr; - } - } + array_.resize(0); + array_adapter_.clear(); + return &array_adapter_; } } // resp3 diff --git a/include/aedis/resp3/impl/type.ipp b/include/aedis/resp3/impl/type.ipp index 84dd4540..a9d8ccc7 100644 --- a/include/aedis/resp3/impl/type.ipp +++ b/include/aedis/resp3/impl/type.ipp @@ -9,15 +9,8 @@ #include -namespace aedis { namespace resp3 { - -bool operator==(node const& a, node const& b) -{ - return a.size == b.size - && a.depth == b.depth - && a.data_type == b.data_type - && a.data == b.data; -}; +namespace aedis { +namespace resp3 { #define EXPAND_TYPE_CASE(x) case resp3::type::x: return #x @@ -25,11 +18,10 @@ std::string to_string(type t) { switch (t) { EXPAND_TYPE_CASE(array); - EXPAND_TYPE_CASE(flat_array); EXPAND_TYPE_CASE(push); EXPAND_TYPE_CASE(set); EXPAND_TYPE_CASE(map); - EXPAND_TYPE_CASE(flat_attribute); + EXPAND_TYPE_CASE(attribute); EXPAND_TYPE_CASE(simple_string); EXPAND_TYPE_CASE(simple_error); EXPAND_TYPE_CASE(number); @@ -62,8 +54,8 @@ type to_type(char c) case '_': return type::null; case '>': return type::push; case '~': return type::set; - case '*': return type::flat_array; - case '|': return type::flat_attribute; + case '*': return type::array; + case '|': return type::attribute; case '%': return type::map; default: return type::invalid; } diff --git a/include/aedis/resp3/node.hpp b/include/aedis/resp3/node.hpp new file mode 100644 index 00000000..c46af045 --- /dev/null +++ b/include/aedis/resp3/node.hpp @@ -0,0 +1,42 @@ +/* Copyright (c) 2019 - 2021 Marcelo Zimbres Silva (mzimbres at gmail dot com) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include + +namespace aedis { namespace resp3 { + +/** Represents a node in the response tree. + */ +struct node { + /// The number of children node is parent of. + std::size_t size; + + /// The depth of this node in the response tree. + std::size_t depth; + + /// The RESP3 type of the data in this node. + type data_type; + + /// The data. For aggregate data types this is always empty. + std::string data; +}; + +/// Equality compare for a node +bool operator==(node const& a, node const& b); + +/// A pre-order-view of the response tree. +using response_impl = std::vector; + +} // resp3 +} // aedis + +std::ostream& operator<<(std::ostream& os, aedis::resp3::node const& o); +std::ostream& operator<<(std::ostream& os, aedis::resp3::response_impl const& r); diff --git a/include/aedis/resp3/response.hpp b/include/aedis/resp3/response.hpp index cb13d310..20f00362 100644 --- a/include/aedis/resp3/response.hpp +++ b/include/aedis/resp3/response.hpp @@ -9,34 +9,16 @@ #include #include -#include -#include +#include #include -#include -#include -#include namespace aedis { namespace resp3 { class response { private: - array_type array_; + response_impl array_; detail::array_adapter array_adapter_{&array_}; - flat_array_type flat_array_; - detail::basic_flat_array_adapter flat_array_adapter_{&flat_array_}; - - flat_array_type flat_attribute_; - detail::basic_flat_array_adapter flat_attribute_adapter_{&flat_attribute_}; - - boolean_type boolean_; - detail::boolean_adapter boolean_adapter_{&boolean_}; - - number_type number_; - detail::number_adapter number_adapter_{&number_}; - - detail::ignore_adapter ignore_adapter_; - public: virtual ~response() = default; @@ -49,15 +31,6 @@ public: auto const& array() const noexcept {return array_;} auto& array() noexcept {return array_;} - - auto const& flat_array() const noexcept {return flat_array_;} - auto& flat_array() noexcept {return flat_array_;} - - auto const& number() const noexcept {return number_;} - auto& number() noexcept {return number_;} - - auto const& boolean() const noexcept {return boolean_;} - auto& boolean() noexcept {return boolean_;} }; } // resp3 diff --git a/include/aedis/resp3/type.hpp b/include/aedis/resp3/type.hpp index 6e376ac5..3608d475 100644 --- a/include/aedis/resp3/type.hpp +++ b/include/aedis/resp3/type.hpp @@ -15,11 +15,10 @@ namespace aedis { namespace resp3 { enum class type { array -, flat_array , push , set , map -, flat_attribute +, attribute , simple_string , simple_error , number @@ -34,38 +33,9 @@ enum class type , invalid }; +std::string to_string(type t); type to_type(char c); -template -using basic_flat_array = std::vector; - -/// RESP3 flat array types. -using flat_array_type = basic_flat_array; -using flat_array_int_type = basic_flat_array; - -using number_type = long long int; -using boolean_type = bool; - -struct node { - /// The number of children node is parent of. - std::size_t size; - - /// The depth of this node in the response tree. - std::size_t depth; - - /// The RESP3 type of the data in this node. - type data_type; - - /// The data. For aggregate data types this is always empty. - std::string data; -}; - -/// Equality compare for a node -bool operator==(node const& a, node const& b); - -/// A pre-order-view of the response tree. -using array_type = std::vector; - } // resp3 } // aedis diff --git a/include/aedis/src.hpp b/include/aedis/src.hpp index abd022a9..c56c64cf 100644 --- a/include/aedis/src.hpp +++ b/include/aedis/src.hpp @@ -10,4 +10,5 @@ #include #include #include +#include #include diff --git a/tests/general.cpp b/tests/general.cpp index 9a41a242..07289157 100644 --- a/tests/general.cpp +++ b/tests/general.cpp @@ -9,6 +9,8 @@ #include "test_stream.hpp" +#include + // TODO: Use Beast test_stream and instantiate the test socket only // once. @@ -23,13 +25,14 @@ namespace aedis { namespace resp3 { using flat_array_adapter = detail::basic_flat_array_adapter; using flat_array_int_adapter = detail::basic_flat_array_adapter; +using flat_array_int_type = detail::basic_flat_array; } // resp3 } // aedis using namespace aedis; -resp3::array_type array_buffer; +resp3::response_impl array_buffer; resp3::detail::array_adapter array_adapter{&array_buffer}; template @@ -134,7 +137,7 @@ test_general(net::ip::tcp::resolver::results_type const& res) switch (push_counter) { case 0: { - resp3::array_type expected + resp3::response_impl expected { {3UL, 0UL, resp3::type::push, {}} , {1UL, 1UL, resp3::type::blob_string, {"subscribe"}} , {1UL, 1UL, resp3::type::blob_string, {"channel"}} @@ -145,7 +148,7 @@ test_general(net::ip::tcp::resolver::results_type const& res) } break; case 1: { - resp3::array_type expected + resp3::response_impl expected { {3UL, 0UL, resp3::type::push, {}} , {1UL, 1UL, resp3::type::blob_string, {"message"}} , {1UL, 1UL, resp3::type::blob_string, {"channel"}} @@ -170,130 +173,242 @@ test_general(net::ip::tcp::resolver::results_type const& res) } break; case command::multi: { - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; check_equal(resp.array(), expected, "multi"); } break; case command::ping: { - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::simple_string, {"QUEUED"}} }; check_equal(resp.array(), expected, "ping"); } break; case command::set: { - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; check_equal(resp.array(), expected, "set"); } break; case command::quit: { - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; check_equal(resp.array(), expected, "quit"); } break; case command::flushall: { - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; check_equal(resp.array(), expected, "flushall"); } break; case command::ltrim: { - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; check_equal(resp.array(), expected, "ltrim"); } break; - case command::append: check_equal(resp.number(), 4LL, "append"); break; - case command::hset: check_equal(resp.number(), 2LL, "hset"); break; - case command::rpush: check_equal(resp.number(), (resp3::number_type)std::size(filler.list_), "rpush (value)"); break; - case command::del: check_equal(resp.number(), 1LL, "del"); break; - case command::llen: check_equal(resp.number(), 6LL, "llen"); break; - case command::incr: check_equal(resp.number(), 1LL, "incr"); break; - case command::publish: check_equal(resp.number(), 1LL, "publish"); break; - case command::hincrby: check_equal(resp.number(), 10LL, "hincrby"); break; - case command::zadd: check_equal(resp.number(), 1LL, "zadd"); break; - case command::sadd: check_equal(resp.number(), 3LL, "sadd"); break; - case command::hdel: check_equal(resp.number(), 2LL, "hdel"); break; - case command::zremrangebyscore: check_equal(resp.number(), 1LL, "zremrangebyscore"); break; + case command::append: + { + resp3::response_impl expected + { {1UL, 0UL, resp3::type::number, {"4"}} }; + + check_equal(resp.array(), expected, "append"); + } break; + case command::hset: + { + resp3::response_impl expected + { {1UL, 0UL, resp3::type::number, {"2"}} }; + + check_equal(resp.array(), expected, "hset"); + } break; + case command::rpush: + { + auto const n = std::to_string(std::size(filler.list_)); + resp3::response_impl expected + { {1UL, 0UL, resp3::type::number, n} }; + + check_equal(resp.array(), expected, "rpush (value)"); + } break; + case command::del: + { + resp3::response_impl expected + { {1UL, 0UL, resp3::type::number, {"1"}} }; + + check_equal(resp.array(), expected, "del"); + } break; + case command::llen: + { + resp3::response_impl expected + { {1UL, 0UL, resp3::type::number, {"6"}} }; + + check_equal(resp.array(), expected, "llen"); + } break; + case command::incr: + { + resp3::response_impl expected + { {1UL, 0UL, resp3::type::number, {"1"}} }; + + check_equal(resp.array(), expected, "incr"); + } break; + case command::publish: + { + resp3::response_impl expected + { {1UL, 0UL, resp3::type::number, {"1"}} }; + + check_equal(resp.array(), expected, "publish"); + } break; + case command::hincrby: + { + resp3::response_impl expected + { {1UL, 0UL, resp3::type::number, {"10"}} }; + + check_equal(resp.array(), expected, "hincrby"); + } break; + case command::zadd: + { + resp3::response_impl expected + { {1UL, 0UL, resp3::type::number, {"1"}} }; + + check_equal(resp.array(), expected, "zadd"); + } break; + case command::sadd: + { + resp3::response_impl expected + { {1UL, 0UL, resp3::type::number, {"3"}} }; + + check_equal(resp.array(), expected, "sadd"); + } break; + case command::hdel: + { + resp3::response_impl expected + { {1UL, 0UL, resp3::type::number, {"2"}} }; + + check_equal(resp.array(), expected, "hdel"); + } break; + case command::zremrangebyscore: + { + resp3::response_impl expected + { {1UL, 0UL, resp3::type::number, {"1"}} }; + + check_equal(resp.array(), expected, "zremrangebyscore"); + } break; case command::get: { - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::blob_string, filler.set_} }; check_equal(resp.array(), expected, "get"); } break; case command::hget: { - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::blob_string, std::string{"value2"}} }; check_equal(resp.array(), expected, "hget"); } break; - case command::lrange: check_equal(resp.flat_array(), {"1", "2", "3", "4", "5", "6"}, "lrange"); break; - case command::hvals: check_equal(resp.flat_array(), {"value1", "value2"}, "hvals"); break; - case command::zrange: check_equal(resp.flat_array(), {"Marcelo"}, "hvals"); break; - case command::zrangebyscore: check_equal(resp.flat_array(), {"Marcelo"}, "zrangebyscore"); break; + case command::lrange: + { + static int c = 0; + + if (c == 0) { + resp3::response_impl expected + { {6UL, 0UL, resp3::type::array, {}} + , {1UL, 1UL, resp3::type::blob_string, {"1"}} + , {1UL, 1UL, resp3::type::blob_string, {"2"}} + , {1UL, 1UL, resp3::type::blob_string, {"3"}} + , {1UL, 1UL, resp3::type::blob_string, {"4"}} + , {1UL, 1UL, resp3::type::blob_string, {"5"}} + , {1UL, 1UL, resp3::type::blob_string, {"6"}} + }; + + check_equal(resp.array(), expected, "lrange "); + } else { + resp3::response_impl expected + { {1UL, 0UL, resp3::type::simple_string, {"QUEUED"}} }; + + check_equal(resp.array(), expected, "lrange (inside transaction)"); + } + + ++c; + } break; + case command::hvals: + { + resp3::response_impl expected + { {2UL, 0UL, resp3::type::array, {}} + , {1UL, 1UL, resp3::type::array, {"value1"}} + , {1UL, 1UL, resp3::type::array, {"value2"}} + }; + + check_equal(resp.array(), expected, "hvals"); + } break; + case command::zrange: + { + resp3::response_impl expected + { {1UL, 0UL, resp3::type::array, {}} + , {1UL, 1UL, resp3::type::blob_string, {"Marcelo"}} + }; + + check_equal(resp.array(), expected, "hvals"); + } break; + case command::zrangebyscore: + { + resp3::response_impl expected + { {1UL, 0UL, resp3::type::array, {}} + , {1UL, 1UL, resp3::type::blob_string, {"Marcelo"}} + }; + + check_equal(resp.array(), expected, "zrangebyscore"); + } break; case command::lpop: { switch (t) { case resp3::type::blob_string: { - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::blob_string, {"3"}} }; check_equal(resp.array(), expected, "lpop"); } break; - case resp3::type::flat_array: check_equal(resp.flat_array(), {"4", "5"}, "lpop"); break; - default: {std::cout << "Error." << std::endl;} + case resp3::type::array: + { + resp3::response_impl expected + { {2UL, 0UL, resp3::type::array, {}} + , {1UL, 1UL, resp3::type::array, {"4"}} + , {1UL, 1UL, resp3::type::array, {"5"}} + }; + + check_equal(resp.array(), {"4", "5"}, "lpop"); + } break; + default: + { + std::cout << "Error." << std::endl; + } } } break; case command::exec: { - check_equal_number(t, resp3::type::flat_array, "exec (type)"); - check_equal_number(std::size(resp.array()), 6lu, "exec size (description)"); + resp3::response_impl expected + { {3UL, 0UL, resp3::type::array, {}} + , {1UL, 1UL, resp3::type::simple_string, {"PONG"}} + , {2UL, 1UL, resp3::type::array, {}} + , {1UL, 2UL, resp3::type::blob_string, {"4"}} + , {1UL, 2UL, resp3::type::blob_string, {"5"}} + , {1UL, 1UL, resp3::type::simple_string, {"PONG"}} + }; - check_equal_number(resp.array().at(0).size, 3UL, "(0) transaction (size)"); - check_equal_number(resp.array().at(0).depth, 0UL, "(0) transaction (depth)"); - check_equal_number(resp.array().at(0).data_type, resp3::type::flat_array, "(0) transaction (type)"); - check_equal(resp.array().at(0).data, {}, "(0) transaction (value)"); - - check_equal_number(resp.array().at(1).size, 1UL, "(1) transaction (size)"); - check_equal_number(resp.array().at(1).depth, 1UL, "(1) transaction (depth)"); - check_equal_number(resp.array().at(1).data_type, resp3::type::simple_string, "(1) transaction (type)"); - check_equal(resp.array().at(1).data, {"PONG"}, "(1) transaction (value)"); - - check_equal_number(resp.array().at(2).size, 2UL, "(2) transaction (size)"); - check_equal_number(resp.array().at(2).depth, 1UL, "(2) transaction (depth)"); - check_equal_number(resp.array().at(2).data_type, resp3::type::flat_array, "(2) transaction (type)"); - check_equal(resp.array().at(2).data, {}, "(2) transaction (value)"); - - check_equal_number(resp.array().at(3).size, 1UL, "(3) transaction (size)"); - check_equal_number(resp.array().at(3).depth, 2UL, "(3) transaction (depth)"); - check_equal_number(resp.array().at(3).data_type, resp3::type::blob_string, "(3) transaction (type)"); - check_equal(resp.array().at(3).data, {"4"}, "(3) transaction (value)"); - - check_equal_number(resp.array().at(4).size, 1UL, "(4) transaction (size)"); - check_equal_number(resp.array().at(4).depth, 2UL, "(4) transaction (depth)"); - check_equal_number(resp.array().at(4).data_type, resp3::type::blob_string, "(4) transaction (type)"); - check_equal(resp.array().at(4).data, {"5"}, "(4) transaction (value)"); - - check_equal_number(resp.array().at(5).size, 1UL, "(5) transaction (size)"); - check_equal_number(resp.array().at(5).depth, 1UL, "(5) transaction (depth)"); - check_equal_number(resp.array().at(5).data_type, resp3::type::simple_string, "(5) transaction (type)"); - check_equal(resp.array().at(5).data, {"PONG"}, "(5) transaction (value)"); + check_equal(resp.array(), expected, "transaction"); } break; case command::hgetall: { - resp3::array_type expected + resp3::response_impl expected { { 4UL, 0UL, resp3::type::map, {}} , { 1UL, 1UL, resp3::type::blob_string, {"field1"}} , { 1UL, 1UL, resp3::type::blob_string, {"value1"}} @@ -304,7 +419,7 @@ test_general(net::ip::tcp::resolver::results_type const& res) } break; case command::smembers: { - resp3::array_type expected + resp3::response_impl expected { { 3UL, 0UL, resp3::type::set, {}} , { 1UL, 1UL, resp3::type::blob_string, {"1"}} , { 1UL, 1UL, resp3::type::blob_string, {"2"}} @@ -343,24 +458,27 @@ test_list(net::ip::tcp::resolver::results_type const& results) std::string buf; { // hello - resp3::detail::ignore_adapter res; - co_await async_read_one(socket, buf, res); + array_buffer.clear(); + array_adapter.clear(); + co_await async_read_one(socket, buf, array_adapter); } { // flushall array_buffer.clear(); array_adapter.clear(); co_await async_read_one(socket, buf, array_adapter); - resp3::array_type expected - { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; + resp3::response_impl expected + { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; check_equal(array_buffer, expected, "flushall"); } { // rpush - resp3::number_type buffer; - resp3::detail::number_adapter res{&buffer}; - co_await async_read_one(socket, buf, res); - check_equal(buffer, (long long int)6, "rpush"); + array_buffer.clear(); + array_adapter.clear(); + resp3::response_impl expected + { {1UL, 0UL, resp3::type::number, {"6"}} }; + co_await async_read_one(socket, buf, array_adapter); + check_equal(array_buffer, expected, "rpush"); } { // lrange @@ -380,7 +498,7 @@ test_list(net::ip::tcp::resolver::results_type const& results) { // ltrim array_buffer.clear(); array_adapter.clear(); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; co_await async_read_one(socket, buf, array_adapter); @@ -390,7 +508,7 @@ test_list(net::ip::tcp::resolver::results_type const& results) { // lpop. Why a blob string instead of a number? array_buffer.clear(); array_adapter.clear(); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::blob_string, {"3"}} }; co_await async_read_one(socket, buf, array_adapter); @@ -401,7 +519,7 @@ test_list(net::ip::tcp::resolver::results_type const& results) array_buffer.clear(); array_adapter.clear(); co_await async_read_one(socket, buf, array_adapter); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; check_equal(array_buffer, expected, "ltrim"); } @@ -438,16 +556,17 @@ test_set(net::ip::tcp::resolver::results_type const& results) std::string buf; { // hello, flushall - resp3::detail::ignore_adapter res; - co_await async_read_one(socket, buf, res); - co_await async_read_one(socket, buf, res); + array_buffer.clear(); + array_adapter.clear(); + co_await async_read_one(socket, buf, array_adapter); + co_await async_read_one(socket, buf, array_adapter); } { // set array_buffer.clear(); array_adapter.clear(); co_await async_read_one(socket, buf, array_adapter); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; check_equal(array_buffer, expected, "set1"); } @@ -455,7 +574,7 @@ test_set(net::ip::tcp::resolver::results_type const& results) { // get array_buffer.clear(); array_adapter.clear(); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::blob_string, test_bulk1} }; co_await async_read_one(socket, buf, array_adapter); @@ -466,7 +585,7 @@ test_set(net::ip::tcp::resolver::results_type const& results) array_buffer.clear(); array_adapter.clear(); co_await async_read_one(socket, buf, array_adapter); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; check_equal(array_buffer, expected, "ltrim"); } @@ -474,7 +593,7 @@ test_set(net::ip::tcp::resolver::results_type const& results) { // get array_buffer.clear(); array_adapter.clear(); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::blob_string, test_bulk2} }; co_await async_read_one(socket, buf, array_adapter); check_equal(array_buffer, expected, "get2"); @@ -484,7 +603,7 @@ test_set(net::ip::tcp::resolver::results_type const& results) array_buffer.clear(); array_adapter.clear(); co_await async_read_one(socket, buf, array_adapter); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; check_equal(array_buffer, expected, "set3"); } @@ -492,7 +611,7 @@ test_set(net::ip::tcp::resolver::results_type const& results) { // get array_buffer.clear(); array_adapter.clear(); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::blob_string, {}} }; co_await async_read_one(socket, buf, array_adapter); @@ -503,7 +622,7 @@ test_set(net::ip::tcp::resolver::results_type const& results) array_buffer.clear(); array_adapter.clear(); co_await async_read_one(socket, buf, array_adapter); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; check_equal(array_buffer, expected, "quit"); } @@ -527,7 +646,7 @@ net::awaitable test_simple_string() array_buffer.clear(); array_adapter.clear(); co_await async_read_one(ts, buf, array_adapter); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::simple_string, {"OK"}} }; check_equal(array_buffer, expected, "simple_string"); } @@ -539,7 +658,7 @@ net::awaitable test_simple_string() array_buffer.clear(); array_adapter.clear(); co_await async_read_one(ts, buf, array_adapter); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::simple_string, {}} }; check_equal(array_buffer, expected, "simple_string (empty)"); //check_equal(res.attribute.value, {}, "simple_string (empty attribute)"); @@ -567,28 +686,34 @@ net::awaitable test_number() { // int std::string cmd {":-3\r\n"}; test_tcp_socket ts {cmd}; - resp3::number_type buffer; - resp3::detail::number_adapter res{&buffer}; - co_await async_read_one(ts, buf, res); - check_equal(buffer, (long long int)-3, "number (int)"); + array_buffer.clear(); + array_adapter.clear(); + resp3::response_impl expected + { {1UL, 0UL, resp3::type::number, {"-3"}} }; + co_await async_read_one(ts, buf, array_adapter); + check_equal(array_buffer, expected, "number (int)"); } { // unsigned std::string cmd {":3\r\n"}; test_tcp_socket ts {cmd}; - resp3::number_type buffer; - resp3::detail::number_adapter res{&buffer}; - co_await async_read_one(ts, buf, res); - check_equal(buffer, (long long int)3, "number (unsigned)"); + array_buffer.clear(); + array_adapter.clear(); + resp3::response_impl expected + { {1UL, 0UL, resp3::type::number, {"3"}} }; + co_await async_read_one(ts, buf, array_adapter); + check_equal(array_buffer, expected, "number (unsigned)"); } { // std::size_t std::string cmd {":1111111\r\n"}; test_tcp_socket ts {cmd}; - resp3::number_type buffer; - resp3::detail::number_adapter res{&buffer}; - co_await async_read_one(ts, buf, res); - check_equal(buffer, (long long int)1111111, "number (std::size_t)"); + array_buffer.clear(); + array_adapter.clear(); + resp3::response_impl expected + { {1UL, 0UL, resp3::type::number, {"1111111"}} }; + co_await async_read_one(ts, buf, array_adapter); + check_equal(array_buffer, expected, "number (std::size_t)"); } } @@ -599,10 +724,16 @@ net::awaitable test_array() { // String 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}; - resp3::flat_array_type buffer; - resp3::flat_array_adapter res{&buffer}; - co_await async_read_one(ts, buf, res); - check_equal(buffer, {"one", "two", "three"}, "array (dynamic)"); + array_buffer.clear(); + array_adapter.clear(); + resp3::response_impl 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); + check_equal(array_buffer, expected, "array"); } { // int @@ -617,10 +748,12 @@ net::awaitable test_array() { std::string cmd {"*0\r\n"}; test_tcp_socket ts {cmd}; - resp3::flat_array_type buffer; - resp3::flat_array_adapter res{&buffer}; - co_await async_read_one(ts, buf, res); - check_equal(buffer, {}, "array (empty)"); + array_buffer.clear(); + array_adapter.clear(); + resp3::response_impl expected + { {0UL, 0UL, resp3::type::array, {}} }; + co_await async_read_one(ts, buf, array_adapter); + check_equal(array_buffer, expected, "array (empty)"); } } @@ -633,7 +766,7 @@ net::awaitable test_blob_string() test_tcp_socket ts {cmd}; array_buffer.clear(); array_adapter.clear(); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::blob_string, {"hh"}} }; co_await async_read_one(ts, buf, array_adapter); check_equal(array_buffer, expected, "blob_string"); @@ -644,7 +777,7 @@ net::awaitable test_blob_string() test_tcp_socket ts {cmd}; array_buffer.clear(); array_adapter.clear(); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::blob_string, {"hhaa\aaaa\raaaaa\r\naaaaaaaaaa"}} }; co_await async_read_one(ts, buf, array_adapter); check_equal(array_buffer, expected, "blob_string (with separator)"); @@ -655,7 +788,7 @@ net::awaitable test_blob_string() test_tcp_socket ts {cmd}; array_buffer.clear(); array_adapter.clear(); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::blob_string, {}} }; co_await async_read_one(ts, buf, array_adapter); check_equal(array_buffer, expected, "blob_string (size 0)"); @@ -671,7 +804,7 @@ net::awaitable test_simple_error() test_tcp_socket ts {cmd}; array_buffer.clear(); array_adapter.clear(); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::simple_error, {"Error"}} }; co_await async_read_one(ts, buf, array_adapter); check_equal(array_buffer, expected, "simple_error (message)"); @@ -687,9 +820,9 @@ net::awaitable test_floating_point() test_tcp_socket ts {cmd}; resp3::response resp; auto* adapter = resp.select_adapter(resp3::type::doublean); - co_await async_read_one(ts, buf, *adapter); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::doublean, {"1.23"}} }; + co_await async_read_one(ts, buf, *adapter); check_equal(resp.array(), expected, "double"); } @@ -699,7 +832,7 @@ net::awaitable test_floating_point() resp3::response resp; auto* adapter = resp.select_adapter(resp3::type::doublean); co_await async_read_one(ts, buf, *adapter); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::doublean, {"inf"}} }; check_equal(resp.array(), expected, "double (inf)"); } @@ -710,7 +843,7 @@ net::awaitable test_floating_point() resp3::response resp; auto* adapter = resp.select_adapter(resp3::type::doublean); co_await async_read_one(ts, buf, *adapter); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::doublean, {"-inf"}} }; check_equal(resp.array(), expected, "double (-inf)"); } @@ -724,19 +857,25 @@ net::awaitable test_boolean() { std::string cmd {"#f\r\n"}; test_tcp_socket ts {cmd}; - resp3::boolean_type buffer; - resp3::detail::boolean_adapter res{&buffer}; - co_await async_read_one(ts, buf, res); - check_equal(buffer, false, "bool (false)"); + resp3::response resp; + auto* adapter = resp.select_adapter(resp3::type::boolean); + resp3::response_impl expected + { {1UL, 0UL, resp3::type::boolean, {"f"}} }; + + co_await async_read_one(ts, buf, *adapter); + check_equal(resp.array(), expected, "bool (false)"); } { std::string cmd {"#t\r\n"}; test_tcp_socket ts {cmd}; - resp3::boolean_type buffer; - resp3::detail::boolean_adapter res{&buffer}; - co_await async_read_one(ts, buf, res); - check_equal(buffer, true, "bool (true)"); + resp3::response resp; + auto* adapter = resp.select_adapter(resp3::type::boolean); + resp3::response_impl expected + { {1UL, 0UL, resp3::type::boolean, {"t"}} }; + + co_await async_read_one(ts, buf, *adapter); + check_equal(resp.array(), expected, "bool (true)"); } } @@ -749,7 +888,7 @@ net::awaitable test_blob_error() test_tcp_socket ts {cmd}; array_buffer.clear(); array_adapter.clear(); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::blob_error, {"SYNTAX invalid syntax"}} }; co_await async_read_one(ts, buf, array_adapter); check_equal(array_buffer, expected, "blob_error (message)"); @@ -760,7 +899,7 @@ net::awaitable test_blob_error() test_tcp_socket ts {cmd}; array_buffer.clear(); array_adapter.clear(); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::blob_error, {}} }; co_await async_read_one(ts, buf, array_adapter); check_equal(array_buffer, expected, "blob_error (empty message)"); @@ -776,7 +915,7 @@ net::awaitable test_verbatim_string() test_tcp_socket ts {cmd}; array_buffer.clear(); array_adapter.clear(); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::verbatim_string, {"txt:Some string"}} }; co_await async_read_one(ts, buf, array_adapter); check_equal(array_buffer, expected, "verbatim_string"); @@ -788,7 +927,7 @@ net::awaitable test_verbatim_string() co_await async_read_one(ts, buf, array_adapter); array_buffer.clear(); array_adapter.clear(); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::verbatim_string, {}} }; check_equal(array_buffer, expected, "verbatim_string (empty)"); } @@ -803,7 +942,7 @@ net::awaitable test_set2() test_tcp_socket ts {cmd}; array_buffer.clear(); - resp3::array_type expected + resp3::response_impl expected { { 5UL, 0UL, resp3::type::set, {}} , { 1UL, 1UL, resp3::type::simple_string, {"orange"}} , { 1UL, 1UL, resp3::type::simple_string, {"apple"}} @@ -821,7 +960,7 @@ net::awaitable test_set2() test_tcp_socket ts {cmd}; array_buffer.clear(); - resp3::array_type expected + resp3::response_impl expected { { 0UL, 0UL, resp3::type::set, {}} }; @@ -841,7 +980,7 @@ net::awaitable test_map() array_adapter.clear(); co_await async_read_one(ts, buf, array_adapter); - resp3::array_type expected + resp3::response_impl expected { {14UL, 0UL, resp3::type::map, {}} , { 1UL, 1UL, resp3::type::blob_string, {"server"}} , { 1UL, 1UL, resp3::type::blob_string, {"redis"}} @@ -856,7 +995,7 @@ net::awaitable test_map() , { 1UL, 1UL, resp3::type::blob_string, {"role"}} , { 1UL, 1UL, resp3::type::blob_string, {"master"}} , { 1UL, 1UL, resp3::type::blob_string, {"modules"}} - , { 0UL, 1UL, resp3::type::flat_array, {}} + , { 0UL, 1UL, resp3::type::array, {}} }; check_equal(array_buffer, expected, "test map"); } @@ -867,7 +1006,7 @@ net::awaitable test_map() array_buffer.clear(); array_adapter.clear(); co_await async_read_one(ts, buf, array_adapter); - resp3::array_type expected + resp3::response_impl expected { {0UL, 0UL, resp3::type::map, {}} }; check_equal(array_buffer, expected, "test map (empty)"); } @@ -882,7 +1021,7 @@ net::awaitable test_streamed_string() test_tcp_socket ts {cmd}; array_buffer.clear(); array_adapter.clear(); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::streamed_string_part, {"Hello world"}} }; co_await resp3::async_read_one(ts, buf, array_adapter); check_equal(array_buffer, expected, "streamed string"); @@ -895,7 +1034,7 @@ net::awaitable test_streamed_string() auto* adapter = resp.select_adapter(resp3::type::streamed_string_part, command::unknown, {}); co_await resp3::async_read_one(ts, buf, *adapter); - resp3::array_type expected + resp3::response_impl expected { {1UL, 0UL, resp3::type::streamed_string_part, {}} }; check_equal(resp.array(), expected, "streamed string (empty)"); }