File indexing completed on 2025-01-18 09:51:19
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_REDIS_ADAPTER_RESPONSE_TRAITS_HPP
0008 #define BOOST_REDIS_ADAPTER_RESPONSE_TRAITS_HPP
0009
0010 #include <boost/redis/error.hpp>
0011 #include <boost/redis/resp3/type.hpp>
0012 #include <boost/redis/ignore.hpp>
0013 #include <boost/redis/adapter/detail/adapters.hpp>
0014 #include <boost/redis/adapter/result.hpp>
0015 #include <boost/redis/adapter/ignore.hpp>
0016 #include <boost/mp11.hpp>
0017
0018 #include <vector>
0019 #include <tuple>
0020 #include <string_view>
0021 #include <variant>
0022
0023 namespace boost::redis::adapter::detail
0024 {
0025
0026
0027
0028
0029
0030
0031 template <class Result>
0032 struct result_traits {
0033 using adapter_type = adapter::detail::wrapper<typename std::decay<Result>::type>;
0034 static auto adapt(Result& r) noexcept { return adapter_type{&r}; }
0035 };
0036
0037 template <>
0038 struct result_traits<result<ignore_t>> {
0039 using response_type = result<ignore_t>;
0040 using adapter_type = ignore;
0041 static auto adapt(response_type) noexcept { return adapter_type{}; }
0042 };
0043
0044 template <>
0045 struct result_traits<ignore_t> {
0046 using response_type = ignore_t;
0047 using adapter_type = ignore;
0048 static auto adapt(response_type) noexcept { return adapter_type{}; }
0049 };
0050
0051 template <class T>
0052 struct result_traits<result<resp3::basic_node<T>>> {
0053 using response_type = result<resp3::basic_node<T>>;
0054 using adapter_type = adapter::detail::general_simple<response_type>;
0055 static auto adapt(response_type& v) noexcept { return adapter_type{&v}; }
0056 };
0057
0058 template <class String, class Allocator>
0059 struct result_traits<result<std::vector<resp3::basic_node<String>, Allocator>>> {
0060 using response_type = result<std::vector<resp3::basic_node<String>, Allocator>>;
0061 using adapter_type = adapter::detail::general_aggregate<response_type>;
0062 static auto adapt(response_type& v) noexcept { return adapter_type{&v}; }
0063 };
0064
0065 template <class T>
0066 using adapter_t = typename result_traits<std::decay_t<T>>::adapter_type;
0067
0068 template<class T>
0069 auto internal_adapt(T& t) noexcept
0070 { return result_traits<std::decay_t<T>>::adapt(t); }
0071
0072 template <std::size_t N>
0073 struct assigner {
0074 template <class T1, class T2>
0075 static void assign(T1& dest, T2& from)
0076 {
0077 dest[N].template emplace<N>(internal_adapt(std::get<N>(from)));
0078 assigner<N - 1>::assign(dest, from);
0079 }
0080 };
0081
0082 template <>
0083 struct assigner<0> {
0084 template <class T1, class T2>
0085 static void assign(T1& dest, T2& from)
0086 {
0087 dest[0].template emplace<0>(internal_adapt(std::get<0>(from)));
0088 }
0089 };
0090
0091 template <class Tuple>
0092 class static_aggregate_adapter;
0093
0094 template <class Tuple>
0095 class static_aggregate_adapter<result<Tuple>> {
0096 private:
0097 using adapters_array_type =
0098 std::array<
0099 mp11::mp_rename<
0100 mp11::mp_transform<
0101 adapter_t, Tuple>,
0102 std::variant>,
0103 std::tuple_size<Tuple>::value>;
0104
0105 std::size_t i_ = 0;
0106 std::size_t aggregate_size_ = 0;
0107 adapters_array_type adapters_;
0108 result<Tuple>* res_ = nullptr;
0109
0110 public:
0111 explicit static_aggregate_adapter(result<Tuple>* r = nullptr)
0112 {
0113 if (r) {
0114 res_ = r;
0115 detail::assigner<std::tuple_size<Tuple>::value - 1>::assign(adapters_, r->value());
0116 }
0117 }
0118
0119 template <class String>
0120 void count(resp3::basic_node<String> const& nd)
0121 {
0122 if (nd.depth == 1) {
0123 if (is_aggregate(nd.data_type))
0124 aggregate_size_ = element_multiplicity(nd.data_type) * nd.aggregate_size;
0125 else
0126 ++i_;
0127
0128 return;
0129 }
0130
0131 if (--aggregate_size_ == 0)
0132 ++i_;
0133 }
0134
0135 template <class String>
0136 void operator()(resp3::basic_node<String> const& nd, system::error_code& ec)
0137 {
0138 using std::visit;
0139
0140 if (nd.depth == 0) {
0141 auto const real_aggr_size = nd.aggregate_size * element_multiplicity(nd.data_type);
0142 if (real_aggr_size != std::tuple_size<Tuple>::value)
0143 ec = redis::error::incompatible_size;
0144
0145 return;
0146 }
0147
0148 visit([&](auto& arg){arg(nd, ec);}, adapters_[i_]);
0149 count(nd);
0150 }
0151 };
0152
0153 template <class... Ts>
0154 struct result_traits<result<std::tuple<Ts...>>>
0155 {
0156 using response_type = result<std::tuple<Ts...>>;
0157 using adapter_type = static_aggregate_adapter<response_type>;
0158 static auto adapt(response_type& r) noexcept { return adapter_type{&r}; }
0159 };
0160
0161 }
0162
0163 #endif