diff --git a/Makefile.am b/Makefile.am index 37525477..eef62f5d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -47,6 +47,11 @@ async_basic_SOURCES = $(top_srcdir)/examples/async_basic.cpp async_basic_CPPFLAGS = $(MY_CPPFLAGS) async_basic_LDADD = $(MY_LDADD) +noinst_PROGRAMS += hello +hello_SOURCES = $(top_srcdir)/examples/hello.cpp +hello_CPPFLAGS = $(MY_CPPFLAGS) +hello_LDADD = $(MY_LDADD) + noinst_PROGRAMS += test test_SOURCES = $(top_srcdir)/tests/general.cpp test_CPPFLAGS = $(MY_CPPFLAGS) diff --git a/examples/async_basic.cpp b/examples/async_basic.cpp index 44d3b3a5..fb9014d9 100644 --- a/examples/async_basic.cpp +++ b/examples/async_basic.cpp @@ -5,6 +5,8 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#include + #include using namespace aedis; diff --git a/examples/hello.cpp b/examples/hello.cpp new file mode 100644 index 00000000..79595c17 --- /dev/null +++ b/examples/hello.cpp @@ -0,0 +1,68 @@ +/* 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 + +#include + +/* A very simple example where we connect to redis and quit. + */ + +using namespace aedis; + +using tcp_socket = net::use_awaitable_t<>::as_default_on_t; + +void print_event(std::pair const& p) +{ + std::cout << "Event: " << p.first << "."; + + if (!std::empty(p.second)) + std::cout << " Key: " << p.second << "."; + + std::cout << std::endl; +} + +net::awaitable +example( + tcp_socket& socket, + std::queue& requests) +{ + requests.push({}); + requests.back().hello("3"); + + resp3::response resp; + resp3::consumer cs; + + for (;;) { + co_await cs.async_consume(socket, requests, resp); + auto const cmd = requests.front().ids.front().first; + auto const type = requests.front().ids.front().first; + + std::cout << cmd << "\n" << resp << std::endl; + + if (cmd == command::hello) { + prepare_next(requests); + requests.back().quit(); + } + + resp.clear(); + } +} + +int main() +{ + net::io_context ioc; + net::ip::tcp::resolver resolver{ioc}; + auto const res = resolver.resolve("127.0.0.1", "6379"); + + tcp_socket socket{ioc}; + net::connect(socket, res); + + std::queue requests; + co_spawn(ioc, example(socket, requests), net::detached); + ioc.run(); +} diff --git a/include/aedis/resp3/detail/response_adapter.hpp b/include/aedis/resp3/detail/response_adapter.hpp deleted file mode 100644 index edd07e46..00000000 --- a/include/aedis/resp3/detail/response_adapter.hpp +++ /dev/null @@ -1,48 +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 -#include - -namespace aedis { -namespace resp3 { -namespace detail { - -// This response type is able to deal with recursive redis responses -// as in a transaction for example. -class response_adapter: public response_adapter_base { -private: - std::vector* result_; - std::size_t depth_; - -public: - 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_; } - - 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; } -}; - -} // detail -} // resp3 -} // aedis diff --git a/include/aedis/resp3/detail/write.hpp b/include/aedis/resp3/detail/write.hpp index c7747149..eacf63e9 100644 --- a/include/aedis/resp3/detail/write.hpp +++ b/include/aedis/resp3/detail/write.hpp @@ -49,7 +49,7 @@ std::size_t write( return bytes_transferred; } -/** Asynchronously writes one or more requests on the stream. +/* Asynchronously writes one or more requests on the stream. */ template struct write_some_op { diff --git a/include/aedis/resp3/impl/node.ipp b/include/aedis/resp3/impl/node.ipp deleted file mode 100644 index fd775869..00000000 --- a/include/aedis/resp3/impl/node.ipp +++ /dev/null @@ -1,34 +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/. - */ - -#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; -}; - -std::ostream& operator<<(std::ostream& os, node const& o) -{ - std::string res; - res += o.depth; - res += '\t'; - res += to_string(o.data_type); - res += '\t'; - res += o.data; - os << res; - return os; -} - -} // resp3 -} // aedis - diff --git a/include/aedis/resp3/impl/response.ipp b/include/aedis/resp3/impl/response.ipp index 77d0ccfa..3e49c0cb 100644 --- a/include/aedis/resp3/impl/response.ipp +++ b/include/aedis/resp3/impl/response.ipp @@ -17,6 +17,26 @@ void response::clear() adapter_.clear(); } +bool operator==(response::node const& a, response::node const& b) +{ + return a.size == b.size + && a.depth == b.depth + && a.data_type == b.data_type + && a.data == b.data; +}; + +std::ostream& operator<<(std::ostream& os, response::node const& o) +{ + std::string res; + res += std::to_string(o.depth); + res += '\t'; + res += to_string(o.data_type); + res += '\t'; + res += o.data; + os << res; + return os; +} + std::ostream& operator<<(std::ostream& os, response const& r) { for (auto const& n : r.data_) diff --git a/include/aedis/resp3/node.hpp b/include/aedis/resp3/node.hpp deleted file mode 100644 index 9fc47c3e..00000000 --- a/include/aedis/resp3/node.hpp +++ /dev/null @@ -1,42 +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 { - -/** 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 comparison for a node. -bool operator==(node const& a, node const& b); - -/** Writes the text representation of node to the output stream. - * - * NOTE: Bonary data is not converted to text. - */ -std::ostream& operator<<(std::ostream& os, node const& o); - -} // resp3 -} // aedis diff --git a/include/aedis/resp3/response.hpp b/include/aedis/resp3/response.hpp index 8ea2ab82..a7923680 100644 --- a/include/aedis/resp3/response.hpp +++ b/include/aedis/resp3/response.hpp @@ -9,8 +9,7 @@ #include #include -#include -#include +#include namespace aedis { namespace resp3 { @@ -18,24 +17,68 @@ namespace resp3 { /// A pre-order-view of the response tree. class response { public: + /** 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; + }; + using storage_type = std::vector; -private: +public: + // This response type is able to deal with recursive redis responses + // as in a transaction for example. + class adapter: public response_adapter_base { + private: + storage_type* result_; + std::size_t depth_; + + public: + adapter(storage_type* p) + : result_{p} + , depth_{0} + { } + + void add_aggregate(type t, int n) override + { 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; } + }; + private: + friend std::ostream& operator<<(std::ostream& os, response const& r); storage_type data_; - detail::response_adapter adapter_{&data_}; + adapter adapter_{&data_}; + public: + /// Destructor virtual ~response() = default; /** Returns the response adapter suitable to construct this * response type from the wire format. Override this function for * your own response types. */ - virtual - response_adapter_base* + virtual adapter* select_adapter( resp3::type t, command cmd = command::unknown, @@ -62,6 +105,15 @@ public: auto get_type() const noexcept { return data_.front().data_type; } }; +/// Equality comparison for a node. +bool operator==(response::node const& a, response::node const& b); + +/** Writes the text representation of node to the output stream. + * + * NOTE: Bonary data is not converted to text. + */ +std::ostream& operator<<(std::ostream& os, response::node const& o); + /** Writes the text representation of the response to the output * stream the response to the output stream. */ diff --git a/include/aedis/src.hpp b/include/aedis/src.hpp index f58b7276..19c77948 100644 --- a/include/aedis/src.hpp +++ b/include/aedis/src.hpp @@ -9,6 +9,5 @@ #include #include #include -#include #include #include diff --git a/tests/general.cpp b/tests/general.cpp index a4c649ba..be088667 100644 --- a/tests/general.cpp +++ b/tests/general.cpp @@ -5,6 +5,8 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#include + #include #include @@ -35,7 +37,7 @@ using namespace aedis; using namespace aedis::resp3; resp3::response::storage_type array_buffer; -resp3::detail::response_adapter radapter{&array_buffer}; +resp3::response::adapter radapter{&array_buffer}; template void check_equal(T const& a, T const& b, std::string const& msg = "")