2
0
mirror of https://github.com/boostorg/redis.git synced 2026-01-19 04:42:09 +00:00

Merge pull request #63 from boostorg/62-let-the-implementation-call-adaptresp-automatically

async_exec accepts response now instead of adapter.
This commit is contained in:
Marcelo
2023-02-05 10:08:05 +01:00
committed by GitHub
38 changed files with 228 additions and 232 deletions

View File

@@ -15,7 +15,7 @@ concerned with only three library entities
[pipelines](https://redis.io/docs/manual/pipelining/).
* `boost::redis::request`: A container of Redis commands that supports
STL containers and user defined data types.
* `boost::redis::adapt()`: A function that adapts data structures to receive responses.
* `boost::redis::response`: Container of Redis responses.
In the next sections we will cover all those points in detail with
examples. The requirements for using Boost.Redis are
@@ -62,7 +62,7 @@ auto co_main() -> net::awaitable<void>
// The tuple elements will store the responses to each individual
// command. The responses to HELLO and QUIT are being ignored for
// simplicity.
response<ignore, std::map<std::string, std::string>, ignore> resp;
response<ignore_t, std::map<std::string, std::string>, ignore_t> resp;
// Executes the request. See below why we are using operator ||.
co_await (conn.async_run() || conn.async_exec(req, adapt(resp)));
@@ -364,11 +364,11 @@ have as many elements as the request has commands (exceptions below).
It is also necessary that each tuple element is capable of storing the
response to the command it refers to, otherwise an error will occur.
To ignore responses to individual commands in the request use the tag
`boost::redis::ignore`
`boost::redis::ignore_t`
```cpp
// Ignore the second and last responses.
response<std::string, boost::redis::ignore, std::string, boost::redis::ignore>
response<std::string, boost::redis::ignore_t, std::string, boost::redis::ignore_t>
```
The following table provides the resp3-types returned by some Redis
@@ -416,12 +416,12 @@ can be read in the tuple below
```cpp
response<
redis::ignore, // hello
int, // rpush
int, // hset
std::vector<T>, // lrange
std::map<U, V>, // hgetall
std::string // quit
redis::ignore_t, // hello
int, // rpush
int, // hset
std::vector<T>, // lrange
std::map<U, V>, // hgetall
std::string // quit
> resp;
```
@@ -515,10 +515,10 @@ using exec_resp_type =
>;
response<
boost::redis::ignore, // multi
boost::redis::ignore, // get
boost::redis::ignore, // lrange
boost::redis::ignore, // hgetall
boost::redis::ignore_t, // multi
boost::redis::ignore_t, // get
boost::redis::ignore_t, // lrange
boost::redis::ignore_t, // hgetall
exec_resp_type, // exec
> resp;
@@ -868,6 +868,8 @@ Acknowledgement to people that helped shape Boost.Redis
* Moves `boost::redis::resp3::request` to `boost::redis::request`.
* Adds new typedef `boost::redis::response` that should be used instead of `std::tuple`.
* Adds new typedef `boost::redis::generic_response` that should be used instead of `std::vector<resp3::node<std::string>>`.
* Renames `redis::ignore` to `redis::ignore_t`.
* Changes the signature from `async_exec` to receive a `redis::response` instead of an adapter.
### v1.4.0-1

View File

@@ -16,7 +16,6 @@ using namespace net::experimental::awaitable_operators;
using resolver = net::use_awaitable_t<>::as_default_on_t<net::ip::tcp::resolver>;
using timer_type = net::use_awaitable_t<>::as_default_on_t<net::steady_timer>;
using boost::redis::request;
using boost::redis::adapt;
using boost::redis::operation;
namespace
@@ -35,7 +34,7 @@ auto healthy_checker(std::shared_ptr<connection> conn) -> net::awaitable<void>
for (boost::system::error_code ec;;) {
timer.expires_after(std::chrono::seconds{1});
co_await (conn->async_exec(req, adapt()) || timer.async_wait(redir(ec)));
co_await (conn->async_exec(req) || timer.async_wait(redir(ec)));
if (!ec) {
co_return;

View File

@@ -11,7 +11,6 @@
namespace net = boost::asio;
namespace redis = boost::redis;
using redis::adapt;
using redis::operation;
using redis::request;
using redis::response;
@@ -39,7 +38,7 @@ auto main(int argc, char * argv[]) -> int
req.push("QUIT");
// The response.
response<redis::ignore, std::string, redis::ignore> resp;
response<redis::ignore_t, std::string, redis::ignore_t> resp;
net::io_context ioc;
@@ -75,7 +74,7 @@ auto main(int argc, char * argv[]) -> int
return log(ec, "on_connect: ");
conn.async_run(on_run);
conn.async_exec(req, adapt(resp), on_exec);
conn.async_exec(req, resp, on_exec);
};
// Resolve callback.

View File

@@ -16,17 +16,16 @@
namespace net = boost::asio;
namespace redis = boost::redis;
using redis::adapt;
using connection = redis::connection;
using boost::redis::request;
using boost::redis::response;
template <class Adapter>
auto exec(std::shared_ptr<connection> conn, request const& req, Adapter adapter)
template <class Response>
auto exec(std::shared_ptr<connection> conn, request const& req, Response& resp)
{
net::dispatch(
conn->get_executor(),
net::deferred([&]() { return conn->async_exec(req, adapter, net::deferred); }))
net::deferred([&]() { return conn->async_exec(req, resp, net::deferred); }))
(net::use_future).get();
}
@@ -67,10 +66,10 @@ auto main(int argc, char * argv[]) -> int
req.push("PING");
req.push("QUIT");
response<boost::redis::ignore, std::string, boost::redis::ignore> resp;
response<boost::redis::ignore_t, std::string, boost::redis::ignore_t> resp;
// Executes commands synchronously.
exec(conn, req, adapt(resp));
exec(conn, req, resp);
std::cout << "Response: " << std::get<1>(resp) << std::endl;

View File

@@ -18,7 +18,6 @@ namespace net = boost::asio;
using namespace net::experimental::awaitable_operators;
using stream_descriptor = net::use_awaitable_t<>::as_default_on_t<net::posix::stream_descriptor>;
using signal_set = net::use_awaitable_t<>::as_default_on_t<net::signal_set>;
using boost::redis::adapt;
using boost::redis::request;
using boost::redis::generic_response;
@@ -29,7 +28,7 @@ using boost::redis::generic_response;
auto receiver(std::shared_ptr<connection> conn) -> net::awaitable<void>
{
for (generic_response resp;;) {
co_await conn->async_receive(adapt(resp));
co_await conn->async_receive(resp);
std::cout << resp.at(1).value << " " << resp.at(2).value << " " << resp.at(3).value << std::endl;
resp.clear();
}

View File

@@ -16,7 +16,6 @@
namespace net = boost::asio;
namespace redis = boost::redis;
using namespace net::experimental::awaitable_operators;
using redis::adapt;
using boost::redis::request;
using boost::redis::response;
@@ -63,10 +62,10 @@ auto hgetall(std::shared_ptr<connection> conn) -> net::awaitable<void>
req.push("HGETALL", "hset-key");
// Responses as tuple elements.
response<redis::ignore, std::map<std::string, std::string>> resp;
response<redis::ignore_t, std::map<std::string, std::string>> resp;
// Executes the request and reads the response.
co_await conn->async_exec(req, adapt(resp));
co_await conn->async_exec(req, resp);
print(std::get<1>(resp));
}
@@ -82,14 +81,14 @@ auto transaction(std::shared_ptr<connection> conn) -> net::awaitable<void>
req.push("EXEC");
response<
redis::ignore, // hello
redis::ignore, // multi
redis::ignore, // lrange
redis::ignore, // hgetall
redis::ignore_t, // hello
redis::ignore_t, // multi
redis::ignore_t, // lrange
redis::ignore_t, // hgetall
response<std::optional<std::vector<int>>, std::optional<std::map<std::string, std::string>>> // exec
> resp;
co_await conn->async_exec(req, adapt(resp));
co_await conn->async_exec(req, resp);
print(std::get<0>(std::get<4>(resp)).value());
print(std::get<1>(std::get<4>(resp)).value());

View File

@@ -15,22 +15,20 @@ using namespace net::experimental::awaitable_operators;
using tcp_socket = net::use_awaitable_t<>::as_default_on_t<net::ip::tcp::socket>;
using tcp_acceptor = net::use_awaitable_t<>::as_default_on_t<net::ip::tcp::acceptor>;
using signal_set = net::use_awaitable_t<>::as_default_on_t<net::signal_set>;
using boost::redis::adapt;
using boost::redis::request;
using boost::redis::response;
auto echo_server_session(tcp_socket socket, std::shared_ptr<connection> conn) -> net::awaitable<void>
{
request req;
std::string resp;
response<std::string> resp;
for (std::string buffer;;) {
auto n = co_await net::async_read_until(socket, net::dynamic_buffer(buffer, 1024), "\n");
req.push("PING", buffer);
auto tmp = std::tie(resp);
co_await conn->async_exec(req, adapt(tmp));
co_await net::async_write(socket, net::buffer(resp));
resp.clear();
co_await conn->async_exec(req, resp);
co_await net::async_write(socket, net::buffer(std::get<0>(resp)));
std::get<0>(resp).clear();
req.clear();
buffer.erase(0, n);
}

View File

@@ -10,7 +10,6 @@
#include "common/common.hpp"
namespace net = boost::asio;
using boost::redis::adapt;
using boost::redis::operation;
using boost::redis::request;
using boost::redis::response;
@@ -35,7 +34,7 @@ auto ping(std::shared_ptr<connection> conn) -> net::awaitable<void>
req.push("PING", "Hello world");
response<std::string> resp;
co_await conn->async_exec(req, adapt(resp));
co_await conn->async_exec(req, resp);
std::cout << "PING: " << std::get<0>(resp) << std::endl;
}

View File

@@ -12,7 +12,6 @@
namespace net = boost::asio;
using namespace net::experimental::awaitable_operators;
using boost::redis::adapt;
using boost::redis::request;
using boost::redis::response;
@@ -24,11 +23,11 @@ auto co_main(std::string host, std::string port) -> net::awaitable<void>
req.push("PING", "Hello world");
req.push("QUIT");
response<boost::redis::ignore, std::string, boost::redis::ignore> resp;
response<boost::redis::ignore_t, std::string, boost::redis::ignore_t> resp;
auto conn = std::make_shared<connection>(co_await net::this_coro::executor);
co_await connect(conn, host, port);
co_await (conn->async_run() || conn->async_exec(req, adapt(resp)));
co_await (conn->async_run() || conn->async_exec(req, resp));
std::cout << "PING: " << std::get<1>(resp) << std::endl;
}

View File

@@ -20,7 +20,6 @@ namespace net = boost::asio;
namespace redis = boost::redis;
using namespace net::experimental::awaitable_operators;
using resolver = net::use_awaitable_t<>::as_default_on_t<net::ip::tcp::resolver>;
using redis::adapt;
using connection = net::use_awaitable_t<>::as_default_on_t<redis::ssl::connection>;
using boost::redis::request;
using boost::redis::response;
@@ -38,7 +37,7 @@ net::awaitable<void> co_main(std::string, std::string)
req.push("PING");
req.push("QUIT");
response<redis::ignore, std::string, redis::ignore> resp;
response<redis::ignore_t, std::string, redis::ignore_t> resp;
// Resolve
auto ex = co_await net::this_coro::executor;
@@ -52,7 +51,7 @@ net::awaitable<void> co_main(std::string, std::string)
co_await net::async_connect(conn.lowest_layer(), endpoints);
co_await conn.next_layer().async_handshake(net::ssl::stream_base::client);
co_await (conn.async_run() || conn.async_exec(req, adapt(resp)));
co_await (conn.async_run() || conn.async_exec(req, resp));
std::cout << "Response: " << std::get<1>(resp) << std::endl;
}

View File

@@ -14,7 +14,6 @@
namespace net = boost::asio;
using namespace net::experimental::awaitable_operators;
using endpoints = net::ip::tcp::resolver::results_type;
using boost::redis::adapt;
using boost::redis::request;
using boost::redis::response;
@@ -37,11 +36,11 @@ auto resolve_master_address(std::vector<address> const& endpoints) -> net::await
auto conn = std::make_shared<connection>(co_await net::this_coro::executor);
response<std::optional<std::array<std::string, 2>>, boost::redis::ignore> addr;
response<std::optional<std::array<std::string, 2>>, boost::redis::ignore_t> addr;
for (auto ep : endpoints) {
boost::system::error_code ec;
co_await connect(conn, ep.host, ep.port);
co_await (conn->async_run() && conn->async_exec(req, adapt(addr), redir(ec)));
co_await (conn->async_run() && conn->async_exec(req, addr, redir(ec)));
conn->reset_stream();
if (std::get<0>(addr))
co_return address{std::get<0>(addr).value().at(0), std::get<0>(addr).value().at(1)};

View File

@@ -26,7 +26,6 @@ namespace net = boost::asio;
namespace redis = boost::redis;
using namespace net::experimental::awaitable_operators;
using namespace boost::json;
using redis::adapt;
using boost::redis::request;
using boost::redis::response;
@@ -99,12 +98,12 @@ net::awaitable<void> co_main(std::string host, std::string port)
req.push("SMEMBERS", "sadd-key"); // Retrieves
req.push("QUIT");
response<redis::ignore, int, std::set<user>, std::string> resp;
response<redis::ignore_t, int, std::set<user>, std::string> resp;
auto conn = std::make_shared<connection>(co_await net::this_coro::executor);
co_await connect(conn, host, port);
co_await (conn->async_run() || conn->async_exec(req, adapt(resp)));
co_await (conn->async_run() || conn->async_exec(req, resp));
for (auto const& e: std::get<2>(resp))
std::cout << e << "\n";

View File

@@ -14,7 +14,6 @@
namespace net = boost::asio;
using namespace net::experimental::awaitable_operators;
using steady_timer = net::use_awaitable_t<>::as_default_on_t<net::steady_timer>;
using boost::redis::adapt;
using boost::redis::request;
using boost::redis::generic_response;
@@ -38,7 +37,7 @@ using boost::redis::generic_response;
auto receiver(std::shared_ptr<connection> conn) -> net::awaitable<void>
{
for (generic_response resp;;) {
co_await conn->async_receive(adapt(resp));
co_await conn->async_receive(resp);
std::cout << resp.at(1).value << " " << resp.at(2).value << " " << resp.at(3).value << std::endl;
resp.clear();
}

View File

@@ -8,7 +8,6 @@
#define BOOST_REDIS_HPP
#include <boost/redis/error.hpp>
#include <boost/redis/adapt.hpp>
#include <boost/redis/connection.hpp>
#include <boost/redis/request.hpp>
#include <boost/redis/response.hpp>

View File

@@ -31,9 +31,9 @@ using adapter_t = typename detail::adapter_t<T>;
// Ignores all responses except for the response to ping.
std::string buffer;
resp3::read(socket, dynamic_buffer(buffer), adapt()); // hello
resp3::read(socket, dynamic_buffer(buffer), adapt(resp)); // ping
resp3::read(socket, dynamic_buffer(buffer, adapt())); // quit
resp3::read(socket, dynamic_buffer(buffer), adapt2()); // hello
resp3::read(socket, dynamic_buffer(buffer), adapt2(resp)); // ping
resp3::read(socket, dynamic_buffer(buffer, adapt2())); // quit
@endcode
*/
inline

View File

@@ -20,7 +20,7 @@
namespace boost::redis::adapter::detail {
using ignore = std::decay_t<decltype(std::ignore)>;
using ignore_t = std::decay_t<decltype(std::ignore)>;
/* Traits class for response objects.
*
@@ -34,8 +34,8 @@ struct response_traits {
};
template <>
struct response_traits<ignore> {
using response_type = ignore;
struct response_traits<ignore_t> {
using response_type = ignore_t;
using adapter_type = resp3::detail::ignore_response;
static auto adapt(response_type) noexcept { return adapter_type{}; }
};

View File

@@ -8,6 +8,7 @@
#define BOOST_REDIS_CONNECTION_HPP
#include <boost/redis/detail/connection_base.hpp>
#include <boost/redis/response.hpp>
#include <boost/asio/io_context.hpp>
#include <chrono>
@@ -112,7 +113,7 @@ public:
* automatically queued by the implementation.
*
* @param req Request object.
* @param adapter Response adapter.
* @param response Response object.
* @param token Asio completion token.
*
* For an example see cpp20_echo_server.cpp. The completion token must
@@ -126,14 +127,14 @@ public:
* bytes.
*/
template <
class Adapter = detail::response_traits<void>::adapter_type,
class Response = ignore_t,
class CompletionToken = asio::default_completion_token_t<executor_type>>
auto async_exec(
request const& req,
Adapter adapter = adapt(),
Response& response = ignore,
CompletionToken token = CompletionToken{})
{
return base_type::async_exec(req, adapter, std::move(token));
return base_type::async_exec(req, response, std::move(token));
}
/** @brief Receives server side pushes asynchronously.
@@ -142,7 +143,7 @@ public:
* loop. If a push arrives and there is no reader, the connection
* will hang.
*
* @param adapter The response adapter.
* @param response The response object.
* @param token The Asio completion token.
*
* For an example see cpp20_subscriber.cpp. The completion token must
@@ -156,13 +157,13 @@ public:
* bytes.
*/
template <
class Adapter = detail::response_traits<void>::adapter_type,
class Response = ignore_t,
class CompletionToken = asio::default_completion_token_t<executor_type>>
auto async_receive(
Adapter adapter = adapt(),
Response& response = ignore,
CompletionToken token = CompletionToken{})
{
return base_type::async_receive(adapter, std::move(token));
return base_type::async_receive(response, std::move(token));
}
/** @brief Cancel operations.

View File

@@ -4,8 +4,8 @@
* accompanying file LICENSE.txt)
*/
#ifndef BOOST_REDIS_ADAPT_HPP
#define BOOST_REDIS_ADAPT_HPP
#ifndef BOOST_REDIS_DETAIL_ADAPT_HPP
#define BOOST_REDIS_DETAIL_ADAPT_HPP
#include <boost/redis/resp3/node.hpp>
#include <boost/redis/response.hpp>
@@ -19,23 +19,7 @@
#include <string_view>
#include <variant>
namespace boost::redis {
/** @brief Tag used to ignore responses.
* @ingroup high-level-api
*
* For example
*
* @code
* response<boost::redis::ignore, std::string, boost::redis::ignore> resp;
* @endcode
*
* will cause only the second tuple type to be parsed, the others
* will be ignored.
*/
using ignore = adapter::detail::ignore;
namespace detail
namespace boost::redis::detail
{
class ignore_adapter {
@@ -112,11 +96,11 @@ template <class>
struct response_traits;
template <>
struct response_traits<void> {
struct response_traits<ignore_t> {
using response_type = void;
using adapter_type = detail::ignore_adapter;
static auto adapt() noexcept
static auto adapt(ignore_t&) noexcept
{ return detail::ignore_adapter{}; }
};
@@ -160,21 +144,7 @@ auto make_adapter_wrapper(Adapter adapter)
return wrapper{adapter};
}
} // detail
/** @brief Creates an adapter that ignores responses.
* @ingroup high-level-api
*
* This function can be used to create adapters that ignores
* responses.
*/
inline auto adapt() noexcept
{
return detail::response_traits<void>::adapt();
}
/** @brief Adapts a type to be used as a response.
* @ingroup high-level-api
*
* The type T must be either
*
@@ -187,11 +157,11 @@ inline auto adapt() noexcept
* @param t Tuple containing the responses.
*/
template<class T>
auto adapt(T& t) noexcept
auto boost_redis_adapt(T& t) noexcept
{
return detail::response_traits<T>::adapt(t);
}
} // boost::redis
} // boost::redis::detail
#endif // BOOST_REDIS_ADAPT_HPP
#endif // BOOST_REDIS_DETAIL_ADAPT_HPP

View File

@@ -7,7 +7,7 @@
#ifndef BOOST_REDIS_CONNECTION_BASE_HPP
#define BOOST_REDIS_CONNECTION_BASE_HPP
#include <boost/redis/adapt.hpp>
#include <boost/redis/detail/adapt.hpp>
#include <boost/redis/operation.hpp>
#include <boost/redis/request.hpp>
#include <boost/redis/detail/connection_ops.hpp>
@@ -128,20 +128,24 @@ public:
return ret;
}
template <class Adapter, class CompletionToken>
auto async_exec(request const& req, Adapter adapter, CompletionToken token)
template <class Response, class CompletionToken>
auto async_exec(request const& req, Response& resp, CompletionToken token)
{
using namespace boost::redis;
auto adapter = boost_redis_adapt(resp);
BOOST_ASSERT_MSG(req.size() <= adapter.get_supported_response_size(), "Request and response have incompatible sizes.");
return asio::async_compose
< CompletionToken
, void(system::error_code, std::size_t)
>(detail::exec_op<Derived, Adapter>{&derived(), &req, adapter}, token, writer_timer_);
>(detail::exec_op<Derived, decltype(adapter)>{&derived(), &req, adapter}, token, writer_timer_);
}
template <class Adapter, class CompletionToken>
auto async_receive(Adapter adapter, CompletionToken token)
template <class Response, class CompletionToken>
auto async_receive(Response& response, CompletionToken token)
{
using namespace boost::redis;
auto adapter = boost_redis_adapt(response);
auto f = detail::make_adapter_wrapper(adapter);
return asio::async_compose

View File

@@ -7,7 +7,7 @@
#ifndef BOOST_REDIS_CONNECTION_OPS_HPP
#define BOOST_REDIS_CONNECTION_OPS_HPP
#include <boost/redis/adapt.hpp>
#include <boost/redis/detail/adapt.hpp>
#include <boost/redis/error.hpp>
#include <boost/redis/resp3/type.hpp>
#include <boost/redis/resp3/detail/parser.hpp>

View File

@@ -0,0 +1,12 @@
/* Copyright (c) 2018-2022 Marcelo Zimbres Silva (mzimbres@gmail.com)
*
* Distributed under the Boost Software License, Version 1.0. (See
* accompanying file LICENSE.txt)
*/
#include <boost/redis/response.hpp>
namespace boost::redis
{
ignore_t ignore;
}

View File

@@ -16,31 +16,13 @@ namespace boost::redis::resp3 {
*
* RESP3 can contain recursive data structures: A map of sets of
* vector of etc. As it is parsed each element is passed to user
* callbacks (push parser), the `boost::redis::adapt` function. The signature of this
* callbacks (push parser). The signature of this
* callback is `f(resp3::node<std::string_view)`. This class is called a node
* because it can be seen as the element of the response tree. It
* is a template so that users can use it with owing strings e.g.
* `std::string` or `boost::static_string` etc. if they decide to use a node as
* response type, for example, to read a non-aggregate data-type use
* `std::string` or `boost::static_string` etc.
*
* ```cpp
* resp3::node<std::string> resp;
* co_await conn->async_exec(req, adapt(resp));
* ```
*
* for an aggregate use instead
*
* ```cpp
* std::vector<resp3::node<std::string>> resp; co_await
* conn->async_exec(req, adapt(resp));
* ```
*
* The vector will contain the
* [pre-order](https://en.wikipedia.org/wiki/Tree_traversal#Pre-order,_NLR)
* view of the response tree. Any Redis response can be received in
* an array of nodes as shown above.
*
* \tparam String A `std::string`-like type.
* @tparam String A `std::string`-like type.
*/
template <class String>
struct node {

View File

@@ -8,6 +8,7 @@
#define BOOST_REDIS_RESPONSE_HPP
#include <boost/redis/resp3/node.hpp>
#include <boost/redis/adapter/adapt.hpp>
#include <vector>
#include <string>
@@ -23,9 +24,39 @@ using response = std::tuple<Ts...>;
/** @brief A generic response to a request
* @ingroup high-level-api
*
* It contains the
* [pre-order](https://en.wikipedia.org/wiki/Tree_traversal#Pre-order,_NLR)
* view of the response tree. Any Redis response can be received in
* an array of nodes.
*/
using generic_response = std::vector<resp3::node<std::string>>;
/** @brief Type used to ignore responses.
* @ingroup high-level-api
*
* For example
*
* @code
* response<boost::redis::ignore_t, std::string, boost::redis::ignore_t> resp;
* @endcode
*
* will cause only the second tuple type to be parsed, the others
* will be ignored.
*/
using ignore_t = adapter::detail::ignore_t;
/** @brief Global ignore object.
* @ingroup high-level-api
*
* Can be used to ignore responses to a request
*
* @code
* conn->async_exec(req, ignore, ...);
* @endcode
*/
extern ignore_t ignore;
} // boost::redis::resp3
#endif // BOOST_REDIS_RESPONSE_HPP

View File

@@ -6,5 +6,6 @@
#include <boost/redis/impl/error.ipp>
#include <boost/redis/impl/request.ipp>
#include <boost/redis/impl/response.ipp>
#include <boost/redis/resp3/impl/type.ipp>
#include <boost/redis/resp3/detail/impl/parser.ipp>

View File

@@ -8,6 +8,7 @@
#define BOOST_REDIS_SSL_CONNECTION_HPP
#include <boost/redis/detail/connection_base.hpp>
#include <boost/redis/response.hpp>
#include <boost/asio/io_context.hpp>
#include <chrono>
@@ -93,14 +94,14 @@ public:
* See redis::connection::async_exec for more information.
*/
template <
class Adapter = redis::detail::response_traits<void>::adapter_type,
class Response = ignore_t,
class CompletionToken = asio::default_completion_token_t<executor_type>>
auto async_exec(
request const& req,
Adapter adapter = adapt(),
Response& response = ignore,
CompletionToken token = CompletionToken{})
{
return base_type::async_exec(req, adapter, std::move(token));
return base_type::async_exec(req, response, std::move(token));
}
/** @brief Receives server side pushes asynchronously.
@@ -108,13 +109,13 @@ public:
* See redis::connection::async_receive for detailed information.
*/
template <
class Adapter = redis::detail::response_traits<void>::adapter_type,
class Response = ignore_t,
class CompletionToken = asio::default_completion_token_t<executor_type>>
auto async_receive(
Adapter adapter = adapt(),
Response& response = ignore,
CompletionToken token = CompletionToken{})
{
return base_type::async_receive(adapter, std::move(token));
return base_type::async_receive(response, std::move(token));
}
/** @brief Cancel operations.

View File

@@ -18,15 +18,15 @@
namespace net = boost::asio;
using error_code = boost::system::error_code;
using boost::redis::operation;
using boost::redis::adapt;
using boost::redis::request;
using boost::redis::response;
using boost::redis::ignore;
auto push_consumer(std::shared_ptr<connection> conn, int expected) -> net::awaitable<void>
{
int c = 0;
for (;;) {
co_await conn->async_receive(adapt(), net::use_awaitable);
co_await conn->async_receive(ignore, net::use_awaitable);
if (++c == expected)
break;
}
@@ -34,7 +34,7 @@ auto push_consumer(std::shared_ptr<connection> conn, int expected) -> net::await
request req;
req.push("HELLO", 3);
req.push("QUIT");
co_await conn->async_exec(req, adapt());
co_await conn->async_exec(req, ignore);
}
auto echo_session(std::shared_ptr<connection> conn, std::string id, int n) -> net::awaitable<void>
@@ -42,7 +42,7 @@ auto echo_session(std::shared_ptr<connection> conn, std::string id, int n) -> ne
auto ex = co_await net::this_coro::executor;
request req;
response<boost::redis::ignore, std::string> resp;
response<boost::redis::ignore_t, std::string> resp;
for (auto i = 0; i < n; ++i) {
auto const msg = id + "/" + std::to_string(i);
@@ -51,7 +51,7 @@ auto echo_session(std::shared_ptr<connection> conn, std::string id, int n) -> ne
req.push("PING", msg);
req.push("SUBSCRIBE", "channel");
boost::system::error_code ec;
co_await conn->async_exec(req, adapt(resp), redir(ec));
co_await conn->async_exec(req, resp, redir(ec));
BOOST_CHECK_EQUAL(ec, boost::system::error_code{});
BOOST_CHECK_EQUAL(msg, std::get<1>(resp));
req.clear();

View File

@@ -22,9 +22,9 @@
namespace net = boost::asio;
using error_code = boost::system::error_code;
using connection = boost::redis::connection;
using boost::redis::adapt;
using boost::redis::request;
using boost::redis::response;
using boost::redis::ignore;
BOOST_AUTO_TEST_CASE(hello_priority)
{
@@ -55,21 +55,21 @@ BOOST_AUTO_TEST_CASE(hello_priority)
bool seen2 = false;
bool seen3 = false;
conn.async_exec(req1, adapt(), [&](auto ec, auto){
conn.async_exec(req1, ignore, [&](auto ec, auto){
std::cout << "bbb" << std::endl;
BOOST_TEST(!ec);
BOOST_TEST(!seen2);
BOOST_TEST(seen3);
seen1 = true;
});
conn.async_exec(req2, adapt(), [&](auto ec, auto){
conn.async_exec(req2, ignore, [&](auto ec, auto){
std::cout << "ccc" << std::endl;
BOOST_TEST(!ec);
BOOST_TEST(seen1);
BOOST_TEST(seen3);
seen2 = true;
});
conn.async_exec(req3, adapt(), [&](auto ec, auto){
conn.async_exec(req3, ignore, [&](auto ec, auto){
std::cout << "ddd" << std::endl;
BOOST_TEST(!ec);
BOOST_TEST(!seen1);
@@ -91,14 +91,14 @@ BOOST_AUTO_TEST_CASE(wrong_response_data_type)
req.push("QUIT");
// Wrong data type.
response<boost::redis::ignore, int> resp;
response<boost::redis::ignore_t, int> resp;
net::io_context ioc;
auto const endpoints = resolve();
connection conn{ioc};
net::connect(conn.next_layer(), endpoints);
conn.async_exec(req, adapt(resp), [](auto ec, auto){
conn.async_exec(req, resp, [](auto ec, auto){
BOOST_CHECK_EQUAL(ec, boost::redis::error::not_a_number);
});
conn.async_run([](auto ec){
@@ -117,7 +117,7 @@ BOOST_AUTO_TEST_CASE(cancel_request_if_not_connected)
net::io_context ioc;
auto conn = std::make_shared<connection>(ioc);
conn->async_exec(req, adapt(), [](auto ec, auto){
conn->async_exec(req, ignore, [](auto ec, auto){
BOOST_CHECK_EQUAL(ec, boost::redis::error::not_connected);
});

View File

@@ -25,9 +25,9 @@ namespace net = boost::asio;
using error_code = boost::system::error_code;
using namespace net::experimental::awaitable_operators;
using boost::redis::operation;
using boost::redis::adapt;
using boost::redis::request;
using boost::redis::response;
using boost::redis::ignore;
auto async_ignore_explicit_cancel_of_req_written() -> net::awaitable<void>
{
@@ -47,14 +47,14 @@ auto async_ignore_explicit_cancel_of_req_written() -> net::awaitable<void>
request req0;
req0.get_config().coalesce = false;
req0.push("HELLO", 3);
std::ignore = co_await conn->async_exec(req0, adapt(), net::use_awaitable);
std::ignore = co_await conn->async_exec(req0, ignore, net::use_awaitable);
request req1;
req1.get_config().coalesce = false;
req1.push("BLPOP", "any", 3);
// Should not be canceled.
conn->async_exec(req1, adapt(), [](auto ec, auto){
conn->async_exec(req1, ignore, [](auto ec, auto){
BOOST_TEST(!ec);
});
@@ -63,7 +63,7 @@ auto async_ignore_explicit_cancel_of_req_written() -> net::awaitable<void>
req2.push("PING", "second");
// Should be canceled.
conn->async_exec(req2, adapt(), [](auto ec, auto){
conn->async_exec(req2, ignore, [](auto ec, auto){
BOOST_CHECK_EQUAL(ec, net::error::basic_errors::operation_aborted);
});
@@ -79,7 +79,7 @@ auto async_ignore_explicit_cancel_of_req_written() -> net::awaitable<void>
// Test whether the connection remains usable after a call to
// cancel(exec).
co_await conn->async_exec(req3, adapt(), net::redirect_error(net::use_awaitable, ec1));
co_await conn->async_exec(req3, ignore, net::redirect_error(net::use_awaitable, ec1));
BOOST_TEST(!ec1);
}
@@ -100,7 +100,7 @@ auto ignore_implicit_cancel_of_req_written() -> net::awaitable<void>
request req0;
req0.get_config().coalesce = false;
req0.push("HELLO", 3);
std::ignore = co_await conn->async_exec(req0, adapt(), net::use_awaitable);
std::ignore = co_await conn->async_exec(req0, ignore, net::use_awaitable);
// Will be cancelled after it has been written but before the
// response arrives.
@@ -119,8 +119,8 @@ auto ignore_implicit_cancel_of_req_written() -> net::awaitable<void>
boost::system::error_code ec1, ec2, ec3;
co_await (
conn->async_exec(req1, adapt(), redir(ec1)) ||
conn->async_exec(req2, adapt(), redir(ec2)) ||
conn->async_exec(req1, ignore, redir(ec1)) ||
conn->async_exec(req2, ignore, redir(ec2)) ||
st.async_wait(redir(ec3))
);
@@ -149,8 +149,8 @@ auto cancel_of_req_written_on_run_canceled() -> net::awaitable<void>
boost::system::error_code ec0, ec1, ec2, ec3;
co_await (
conn->async_exec(req0, adapt(), redir(ec0)) &&
(conn->async_exec(req1, adapt(), redir(ec1)) ||
conn->async_exec(req0, ignore, redir(ec0)) &&
(conn->async_exec(req1, ignore, redir(ec1)) ||
conn->async_run(redir(ec2)) ||
st.async_wait(redir(ec3)))
);

View File

@@ -19,9 +19,9 @@
namespace net = boost::asio;
using error_code = boost::system::error_code;
using connection = boost::redis::connection;
using boost::redis::adapt;
using boost::redis::request;
using boost::redis::response;
using boost::redis::ignore;
BOOST_AUTO_TEST_CASE(request_retry_false)
{
@@ -58,15 +58,15 @@ BOOST_AUTO_TEST_CASE(request_retry_false)
auto const endpoints = resolve();
net::connect(conn.next_layer(), endpoints);
conn.async_exec(req0, adapt(), [](auto ec, auto){
conn.async_exec(req0, ignore, [](auto ec, auto){
BOOST_TEST(!ec);
});
conn.async_exec(req1, adapt(), [](auto ec, auto){
conn.async_exec(req1, ignore, [](auto ec, auto){
BOOST_CHECK_EQUAL(ec, boost::system::errc::errc_t::operation_canceled);
});
conn.async_exec(req2, adapt(), [](auto ec, auto){
conn.async_exec(req2, ignore, [](auto ec, auto){
BOOST_CHECK_EQUAL(ec, boost::system::errc::errc_t::operation_canceled);
});
@@ -117,17 +117,17 @@ BOOST_AUTO_TEST_CASE(request_retry_true)
auto const endpoints = resolve();
net::connect(conn.next_layer(), endpoints);
conn.async_exec(req0, adapt(), [](auto ec, auto){
conn.async_exec(req0, ignore, [](auto ec, auto){
BOOST_TEST(!ec);
});
conn.async_exec(req1, adapt(), [](auto ec, auto){
conn.async_exec(req1, ignore, [](auto ec, auto){
BOOST_CHECK_EQUAL(ec, boost::system::errc::errc_t::operation_canceled);
});
conn.async_exec(req2, adapt(), [&](auto ec, auto){
conn.async_exec(req2, ignore, [&](auto ec, auto){
BOOST_TEST(!ec);
conn.async_exec(req3, adapt(), [&](auto ec, auto){
conn.async_exec(req3, ignore, [&](auto ec, auto){
BOOST_TEST(!ec);
});
});

View File

@@ -20,13 +20,13 @@
namespace net = boost::asio;
namespace resp3 = boost::redis::resp3;
using boost::redis::adapt;
using boost::redis::operation;
using connection = boost::redis::connection;
using error_code = boost::system::error_code;
using net::experimental::as_tuple;
using boost::redis::request;
using boost::redis::response;
using boost::redis::ignore;
BOOST_AUTO_TEST_CASE(push_filtered_out)
{
@@ -41,12 +41,12 @@ BOOST_AUTO_TEST_CASE(push_filtered_out)
req.push("SUBSCRIBE", "channel");
req.push("QUIT");
response<boost::redis::ignore, std::string, std::string> resp;
conn.async_exec(req, adapt(resp), [](auto ec, auto){
response<boost::redis::ignore_t, std::string, std::string> resp;
conn.async_exec(req, resp, [](auto ec, auto){
BOOST_TEST(!ec);
});
conn.async_receive(adapt(), [](auto ec, auto){
conn.async_receive(ignore, [](auto ec, auto){
BOOST_TEST(!ec);
});
@@ -67,7 +67,7 @@ void receive_wrong_syntax(request const& req)
connection conn{ioc};
net::connect(conn.next_layer(), endpoints);
conn.async_exec(req, adapt(), [](auto ec, auto){
conn.async_exec(req, ignore, [](auto ec, auto){
BOOST_TEST(!ec);
});
@@ -75,7 +75,7 @@ void receive_wrong_syntax(request const& req)
BOOST_CHECK_EQUAL(ec, boost::asio::error::basic_errors::operation_aborted);
});
conn.async_receive(adapt(), [&](auto ec, auto){
conn.async_receive(ignore, [&](auto ec, auto){
BOOST_TEST(!ec);
conn.cancel(boost::redis::operation::run);
});
@@ -87,19 +87,22 @@ void receive_wrong_syntax(request const& req)
net::awaitable<void> push_consumer1(connection& conn, bool& push_received)
{
{
auto [ec, ev] = co_await conn.async_receive(adapt(), as_tuple(net::use_awaitable));
auto [ec, ev] = co_await conn.async_receive(ignore, as_tuple(net::use_awaitable));
BOOST_TEST(!ec);
}
{
auto [ec, ev] = co_await conn.async_receive(adapt(), as_tuple(net::use_awaitable));
auto [ec, ev] = co_await conn.async_receive(ignore, as_tuple(net::use_awaitable));
BOOST_CHECK_EQUAL(ec, net::experimental::channel_errc::channel_cancelled);
}
push_received = true;
}
struct adapter_error {
struct response_error_tag{};
response_error_tag error_tag_obj;
struct response_error_adapter {
void
operator()(
std::size_t, boost::redis::resp3::node<std::string_view> const&, boost::system::error_code& ec)
@@ -112,6 +115,11 @@ struct adapter_error {
{ return static_cast<std::size_t>(-1);}
};
auto boost_redis_adapt(response_error_tag&)
{
return response_error_adapter{};
}
BOOST_AUTO_TEST_CASE(test_push_adapter)
{
net::io_context ioc;
@@ -125,11 +133,11 @@ BOOST_AUTO_TEST_CASE(test_push_adapter)
req.push("SUBSCRIBE", "channel");
req.push("PING");
conn.async_receive(adapter_error{}, [](auto ec, auto) {
conn.async_receive(error_tag_obj, [](auto ec, auto) {
BOOST_CHECK_EQUAL(ec, boost::redis::error::incompatible_size);
});
conn.async_exec(req, adapt(), [](auto ec, auto){
conn.async_exec(req, ignore, [](auto ec, auto){
BOOST_CHECK_EQUAL(ec, net::experimental::error::channel_errors::channel_cancelled);
});
@@ -156,7 +164,7 @@ void test_push_is_received1(bool coalesce)
req.push("SUBSCRIBE", "channel");
req.push("QUIT");
conn.async_exec(req, adapt(), [](auto ec, auto){
conn.async_exec(req, ignore, [](auto ec, auto){
BOOST_TEST(!ec);
});
@@ -201,9 +209,9 @@ void test_push_is_received2(bool coalesce)
BOOST_TEST(!ec);
};
conn.async_exec(req1, adapt(), handler);
conn.async_exec(req2, adapt(), handler);
conn.async_exec(req3, adapt(), handler);
conn.async_exec(req1, ignore, handler);
conn.async_exec(req2, ignore, handler);
conn.async_exec(req3, ignore, handler);
conn.async_run([&](auto ec) {
BOOST_TEST(!ec);
@@ -224,7 +232,7 @@ void test_push_is_received2(bool coalesce)
net::awaitable<void> push_consumer3(connection& conn)
{
for (;;)
co_await conn.async_receive(adapt(), net::use_awaitable);
co_await conn.async_receive(ignore, net::use_awaitable);
}
// Test many subscribe requests.
@@ -252,18 +260,18 @@ void test_push_many_subscribes(bool coalesce)
connection conn{ioc};
net::connect(conn.next_layer(), endpoints);
conn.async_exec(req0, adapt(), handler);
conn.async_exec(req1, adapt(), handler);
conn.async_exec(req2, adapt(), handler);
conn.async_exec(req2, adapt(), handler);
conn.async_exec(req1, adapt(), handler);
conn.async_exec(req2, adapt(), handler);
conn.async_exec(req1, adapt(), handler);
conn.async_exec(req2, adapt(), handler);
conn.async_exec(req2, adapt(), handler);
conn.async_exec(req1, adapt(), handler);
conn.async_exec(req2, adapt(), handler);
conn.async_exec(req3, adapt(), handler);
conn.async_exec(req0, ignore, handler);
conn.async_exec(req1, ignore, handler);
conn.async_exec(req2, ignore, handler);
conn.async_exec(req2, ignore, handler);
conn.async_exec(req1, ignore, handler);
conn.async_exec(req2, ignore, handler);
conn.async_exec(req1, ignore, handler);
conn.async_exec(req2, ignore, handler);
conn.async_exec(req2, ignore, handler);
conn.async_exec(req1, ignore, handler);
conn.async_exec(req2, ignore, handler);
conn.async_exec(req3, ignore, handler);
conn.async_run([&](auto ec) {
BOOST_TEST(!ec);

View File

@@ -17,12 +17,12 @@
namespace net = boost::asio;
using boost::redis::adapt;
using connection = boost::redis::connection;
using error_code = boost::system::error_code;
using operation = boost::redis::operation;
using boost::redis::request;
using boost::redis::response;
using boost::redis::ignore;
// Test if quit causes async_run to exit.
BOOST_AUTO_TEST_CASE(test_quit_no_coalesce)
@@ -43,19 +43,19 @@ BOOST_AUTO_TEST_CASE(test_quit_no_coalesce)
req2.get_config().coalesce = false;
req2.push("QUIT");
conn.async_exec(req1, adapt(), [](auto ec, auto){
conn.async_exec(req1, ignore, [](auto ec, auto){
BOOST_TEST(!ec);
});
conn.async_exec(req2, adapt(), [](auto ec, auto) {
conn.async_exec(req2, ignore, [](auto ec, auto) {
BOOST_TEST(!ec);
});
conn.async_exec(req1, adapt(), [](auto ec, auto){
conn.async_exec(req1, ignore, [](auto ec, auto){
BOOST_CHECK_EQUAL(ec, boost::system::errc::errc_t::operation_canceled);
});
conn.async_exec(req1, adapt(), [](auto ec, auto){
conn.async_exec(req1, ignore, [](auto ec, auto){
BOOST_CHECK_EQUAL(ec, boost::system::errc::errc_t::operation_canceled);
});
conn.async_exec(req1, adapt(), [](auto ec, auto){
conn.async_exec(req1, ignore, [](auto ec, auto){
BOOST_CHECK_EQUAL(ec, boost::system::errc::errc_t::operation_canceled);
});
@@ -79,7 +79,7 @@ void test_quit2(bool coalesce)
net::connect(conn.next_layer(), endpoints);
conn.async_exec(req, adapt(), [](auto ec, auto) {
conn.async_exec(req, ignore, [](auto ec, auto) {
BOOST_TEST(!ec);
});

View File

@@ -17,12 +17,12 @@
namespace net = boost::asio;
using boost::redis::adapt;
using connection = boost::redis::connection;
using error_code = boost::system::error_code;
using operation = boost::redis::operation;
using boost::redis::request;
using boost::redis::response;
using boost::redis::ignore;
BOOST_AUTO_TEST_CASE(test_quit_coalesce)
{
@@ -37,16 +37,16 @@ BOOST_AUTO_TEST_CASE(test_quit_coalesce)
request req2{{false, true}};
req2.push("QUIT");
conn.async_exec(req1, adapt(), [](auto ec, auto){
conn.async_exec(req1, ignore, [](auto ec, auto){
BOOST_TEST(!ec);
});
conn.async_exec(req2, adapt(), [](auto ec, auto){
conn.async_exec(req2, ignore, [](auto ec, auto){
BOOST_TEST(!ec);
});
conn.async_exec(req1, adapt(), [](auto ec, auto){
conn.async_exec(req1, ignore, [](auto ec, auto){
BOOST_CHECK_EQUAL(ec, net::error::misc_errors::eof);
});
conn.async_exec(req1, adapt(), [](auto ec, auto){
conn.async_exec(req1, ignore, [](auto ec, auto){
BOOST_CHECK_EQUAL(ec, boost::system::errc::errc_t::operation_canceled);
});

View File

@@ -17,10 +17,10 @@
#include "../examples/common/common.hpp"
namespace net = boost::asio;
using boost::redis::adapt;
using error_code = boost::system::error_code;
using boost::redis::request;
using boost::redis::response;
using boost::redis::ignore;
#include <boost/asio/experimental/awaitable_operators.hpp>
using namespace boost::asio::experimental::awaitable_operators;
@@ -40,7 +40,7 @@ net::awaitable<void> test_reconnect_impl()
boost::system::error_code ec1, ec2;
net::connect(conn.next_layer(), endpoints);
co_await (
conn.async_exec(req, adapt(), net::redirect_error(net::use_awaitable, ec1)) &&
conn.async_exec(req, ignore, net::redirect_error(net::use_awaitable, ec1)) &&
conn.async_run(net::redirect_error(net::use_awaitable, ec2))
);
@@ -80,7 +80,7 @@ auto async_test_reconnect_timeout() -> net::awaitable<void>
co_await connect(conn, "127.0.0.1", "6379");
st.expires_after(std::chrono::seconds{1});
co_await (
conn->async_exec(req1, adapt(), redir(ec1)) ||
conn->async_exec(req1, ignore, redir(ec1)) ||
conn->async_run(redir(ec2)) ||
st.async_wait(redir(ec3))
);
@@ -99,7 +99,7 @@ auto async_test_reconnect_timeout() -> net::awaitable<void>
co_await connect(conn, "127.0.0.1", "6379");
st.expires_after(std::chrono::seconds{1});
co_await (
conn->async_exec(req1, adapt(), net::redirect_error(net::use_awaitable, ec1)) ||
conn->async_exec(req1, ignore, net::redirect_error(net::use_awaitable, ec1)) ||
conn->async_run(net::redirect_error(net::use_awaitable, ec2)) ||
st.async_wait(net::redirect_error(net::use_awaitable, ec3))
);

View File

@@ -20,12 +20,12 @@
namespace net = boost::asio;
using boost::redis::operation;
using boost::redis::adapt;
using connection = boost::redis::connection;
using error_code = boost::system::error_code;
using net::experimental::as_tuple;
using boost::redis::request;
using boost::redis::response;
using boost::redis::ignore;
#include <boost/asio/experimental/awaitable_operators.hpp>
using namespace net::experimental::awaitable_operators;
@@ -157,7 +157,7 @@ BOOST_AUTO_TEST_CASE(reset_before_run_completes)
req.push("HELLO", 3);
req.push("PING");
conn.async_exec(req, adapt(), [&](auto ec, auto){
conn.async_exec(req, ignore, [&](auto ec, auto){
BOOST_TEST(!ec);
conn.reset_stream();
});

View File

@@ -18,7 +18,6 @@
namespace net = boost::asio;
using boost::redis::adapt;
using connection = boost::redis::ssl::connection;
using boost::redis::request;
using boost::redis::response;
@@ -58,7 +57,7 @@ BOOST_AUTO_TEST_CASE(ping)
net::connect(conn.lowest_layer(), endpoints);
conn.next_layer().handshake(net::ssl::stream_base::client);
conn.async_exec(req, adapt(resp), [](auto ec, auto) {
conn.async_exec(req, resp, [](auto ec, auto) {
BOOST_TEST(!ec);
});

View File

@@ -14,7 +14,6 @@
namespace net = boost::asio;
using namespace net::experimental::awaitable_operators;
using steady_timer = net::use_awaitable_t<>::as_default_on_t<net::steady_timer>;
using boost::redis::adapt;
using boost::redis::request;
using boost::redis::response;
@@ -38,8 +37,7 @@ auto periodic_task(std::shared_ptr<connection> conn) -> net::awaitable<void>
request req;
req.push("GET", "mykey");
response<std::string> response;
auto [ec, u] = co_await conn->async_exec(req, adapt(response),
net::as_tuple(net::use_awaitable));
auto [ec, u] = co_await conn->async_exec(req, response, net::as_tuple(net::use_awaitable));
if (ec) {
std::cout << "Error: " << ec << std::endl;
} else {

View File

@@ -26,8 +26,8 @@
namespace std
{
auto operator==(boost::redis::ignore, boost::redis::ignore) noexcept {return true;}
auto operator!=(boost::redis::ignore, boost::redis::ignore) noexcept {return false;}
auto operator==(boost::redis::ignore_t, boost::redis::ignore_t) noexcept {return true;}
auto operator!=(boost::redis::ignore_t, boost::redis::ignore_t) noexcept {return false;}
}
namespace net = boost::asio;
@@ -449,7 +449,7 @@ std::vector<node_type> const attr_e1b
test(ex, make_expected(S09a, set_type{"apple", "one", "orange", "three", "two"})); \
test(ex, make_expected(S04d, response<uset_type>{set_e1c})); \
test(ex, make_expected(S09b, std::vector<node_type>{ {resp3::type::set, 0UL, 0UL, {}} })); \
test(ex, make_expected(S10a, boost::redis::ignore{}, boost::redis::error::resp3_simple_error)); \
test(ex, make_expected(S10a, boost::redis::ignore, boost::redis::error::resp3_simple_error)); \
test(ex, make_expected(S10a, node_type{resp3::type::simple_error, 1UL, 0UL, {"Error"}}, boost::redis::error::resp3_simple_error)); \
test(ex, make_expected(S10b, node_type{resp3::type::simple_error, 1UL, 0UL, {""}}, boost::redis::error::resp3_simple_error)); \
test(ex, make_expected(S03c, map_type{}));\
@@ -460,7 +460,7 @@ std::vector<node_type> const attr_e1b
test(ex, make_expected(S11e, double{0}, boost::redis::error::not_a_double));\
test(ex, make_expected(S12a, node_type{resp3::type::blob_error, 1UL, 0UL, {"SYNTAX invalid syntax"}}, boost::redis::error::resp3_blob_error));\
test(ex, make_expected(S12b, node_type{resp3::type::blob_error, 1UL, 0UL, {}}, boost::redis::error::resp3_blob_error));\
test(ex, make_expected(S12c, boost::redis::ignore{}, boost::redis::error::resp3_blob_error));\
test(ex, make_expected(S12c, boost::redis::ignore, boost::redis::error::resp3_blob_error));\
test(ex, make_expected(S13a, node_type{resp3::type::verbatim_string, 1UL, 0UL, {"txt:Some string"}}));\
test(ex, make_expected(S13b, node_type{resp3::type::verbatim_string, 1UL, 0UL, {}}));\
test(ex, make_expected(S14a, node_type{resp3::type::big_number, 1UL, 0UL, {"3492890328409238509324850943850943825024385"}}));\
@@ -630,7 +630,7 @@ BOOST_AUTO_TEST_CASE(type_convert)
BOOST_AUTO_TEST_CASE(adapter)
{
using boost::redis::adapt;
using boost::redis::detail::boost_redis_adapt;
using resp3::type;
boost::system::error_code ec;
@@ -639,7 +639,7 @@ BOOST_AUTO_TEST_CASE(adapter)
int b;
auto resp = std::tie(a, b, std::ignore);
auto f = adapt(resp);
auto f = boost_redis_adapt(resp);
f(0, resp3::node<std::string_view>{type::simple_string, 1, 0, "Hello"}, ec);
f(1, resp3::node<std::string_view>{type::number, 1, 0, "42"}, ec);

View File

@@ -10,7 +10,8 @@
#include <boost/test/included/unit_test.hpp>
#include <boost/redis/request.hpp>
#include <boost/redis/src.hpp>
#include <boost/redis/impl/request.ipp>
#include <boost/redis/resp3/impl/type.ipp>
using boost::redis::request;