Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:51:19

0001 /* Copyright (c) 2018-2023 Marcelo Zimbres Silva (mzimbres@gmail.com)
0002  *
0003  * Distributed under the Boost Software License, Version 1.0. (See
0004  * accompanying file LICENSE.txt)
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 /* Traits class for response objects.
0027  *
0028  * Provides traits for all supported response types i.e. all STL
0029  * containers and C++ buil-in types.
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 } // boost::redis::adapter::detail
0162 
0163 #endif // BOOST_REDIS_ADAPTER_RESPONSE_TRAITS_HPP