Loading...
Searching...
No Matches
response_traits.hpp
1/* Copyright (c) 2018-2024 Marcelo Zimbres Silva (mzimbres@gmail.com)
2 *
3 * Distributed under the Boost Software License, Version 1.0. (See
4 * accompanying file LICENSE.txt)
5 */
6
7#ifndef BOOST_REDIS_ADAPTER_DETAIL_RESPONSE_TRAITS_HPP
8#define BOOST_REDIS_ADAPTER_DETAIL_RESPONSE_TRAITS_HPP
9
10#include <boost/redis/adapter/detail/result_traits.hpp>
11#include <boost/redis/resp3/node.hpp>
12#include <boost/redis/response.hpp>
13
14#include <boost/mp11.hpp>
15#include <boost/system.hpp>
16
17#include <limits>
18#include <string_view>
19#include <tuple>
20#include <variant>
21
22namespace boost::redis::adapter::detail {
23
24class ignore_adapter {
25public:
26 template <class String>
27 void operator()(std::size_t, resp3::basic_node<String> const& nd, system::error_code& ec)
28 {
29 switch (nd.data_type) {
33 default: ;
34 }
35 }
36
37 [[nodiscard]]
38 auto get_supported_response_size() const noexcept
39 {
40 return static_cast<std::size_t>(-1);
41 }
42};
43
44template <class Response>
45class static_adapter {
46private:
47 static constexpr auto size = std::tuple_size<Response>::value;
48 using adapter_tuple = mp11::mp_transform<adapter_t, Response>;
49 using variant_type = mp11::mp_rename<adapter_tuple, std::variant>;
50 using adapters_array_type = std::array<variant_type, size>;
51
52 adapters_array_type adapters_;
53
54public:
55 explicit static_adapter(Response& r) { assigner<size - 1>::assign(adapters_, r); }
56
57 [[nodiscard]]
58 auto get_supported_response_size() const noexcept
59 {
60 return size;
61 }
62
63 template <class String>
64 void operator()(std::size_t i, resp3::basic_node<String> const& nd, system::error_code& ec)
65 {
66 using std::visit;
67 // I am usure whether this should be an error or an assertion.
68 BOOST_ASSERT(i < adapters_.size());
69 visit(
70 [&](auto& arg) {
71 arg(nd, ec);
72 },
73 adapters_.at(i));
74 }
75};
76
77template <class Vector>
78class vector_adapter {
79private:
80 using adapter_type = typename result_traits<Vector>::adapter_type;
81 adapter_type adapter_;
82
83public:
84 explicit vector_adapter(Vector& v)
85 : adapter_{internal_adapt(v)}
86 { }
87
88 [[nodiscard]]
89 auto get_supported_response_size() const noexcept
90 {
91 return static_cast<std::size_t>(-1);
92 }
93
94 template <class String>
95 void operator()(std::size_t, resp3::basic_node<String> const& nd, system::error_code& ec)
96 {
97 adapter_(nd, ec);
98 }
99};
100
101template <class>
102struct response_traits;
103
104template <>
105struct response_traits<ignore_t> {
106 using response_type = ignore_t;
107 using adapter_type = detail::ignore_adapter;
108
109 static auto adapt(response_type&) noexcept { return detail::ignore_adapter{}; }
110};
111
112template <>
113struct response_traits<result<ignore_t>> {
114 using response_type = result<ignore_t>;
115 using adapter_type = detail::ignore_adapter;
116
117 static auto adapt(response_type&) noexcept { return detail::ignore_adapter{}; }
118};
119
120template <class String, class Allocator>
121struct response_traits<result<std::vector<resp3::basic_node<String>, Allocator>>> {
122 using response_type = result<std::vector<resp3::basic_node<String>, Allocator>>;
123 using adapter_type = vector_adapter<response_type>;
124
125 static auto adapt(response_type& v) noexcept { return adapter_type{v}; }
126};
127
128template <class... Ts>
129struct response_traits<response<Ts...>> {
130 using response_type = response<Ts...>;
131 using adapter_type = static_adapter<response_type>;
132
133 static auto adapt(response_type& r) noexcept { return adapter_type{r}; }
134};
135
136template <class Adapter>
137class wrapper {
138public:
139 explicit wrapper(Adapter adapter)
140 : adapter_{adapter}
141 { }
142
143 template <class String>
144 void operator()(resp3::basic_node<String> const& nd, system::error_code& ec)
145 {
146 return adapter_(0, nd, ec);
147 }
148
149 [[nodiscard]]
150 auto get_supported_response_size() const noexcept
151 {
152 return adapter_.get_supported_response_size();
153 }
154
155private:
156 Adapter adapter_;
157};
158
159template <class Adapter>
160auto make_adapter_wrapper(Adapter adapter)
161{
162 return wrapper{adapter};
163}
164
165} // namespace boost::redis::adapter::detail
166
167#endif // BOOST_REDIS_ADAPTER_DETAIL_RESPONSE_TRAITS_HPP
system::result< Value, error > result
Stores response to individual Redis commands.
Definition result.hpp:54
std::decay_t< decltype(std::ignore)> ignore_t
Type used to ignore responses.
Definition ignore.hpp:30
std::tuple< adapter::result< Ts >... > response
Response with compile-time size.
Definition response.hpp:25
@ resp3_blob_error
Got RESP3 blob_error.
@ resp3_null
Got RESP3 null.
@ resp3_simple_error
Got RESP3 simple error.