Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:04:21

0001 /* Copyright (c) 2018-2024 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 = 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    // Tuple element we are currently on.
0106    std::size_t i_ = 0;
0107 
0108    // Nested aggregate element counter.
0109    std::size_t aggregate_size_ = 0;
0110 
0111    adapters_array_type adapters_;
0112    result<Tuple>* res_ = nullptr;
0113 
0114 public:
0115    explicit static_aggregate_adapter(result<Tuple>* r = nullptr)
0116    {
0117       if (r) {
0118          res_ = r;
0119          detail::assigner<std::tuple_size<Tuple>::value - 1>::assign(adapters_, r->value());
0120       }
0121    }
0122 
0123    template <class String>
0124    void count(resp3::basic_node<String> const& elem)
0125    {
0126       if (elem.depth == 1 && is_aggregate(elem.data_type)) {
0127          aggregate_size_ = element_multiplicity(elem.data_type) * elem.aggregate_size;
0128       }
0129 
0130       if (aggregate_size_ == 0) {
0131          i_ += 1;
0132       } else {
0133          aggregate_size_ -= 1;
0134       }
0135    }
0136 
0137    template <class String>
0138    void operator()(resp3::basic_node<String> const& elem, system::error_code& ec)
0139    {
0140       using std::visit;
0141 
0142       if (elem.depth == 0) {
0143          auto const multiplicity = element_multiplicity(elem.data_type);
0144          auto const real_aggr_size = elem.aggregate_size * multiplicity;
0145          if (real_aggr_size != std::tuple_size<Tuple>::value)
0146             ec = redis::error::incompatible_size;
0147 
0148          return;
0149       }
0150 
0151       visit([&](auto& arg){arg(elem, ec);}, adapters_[i_]);
0152       count(elem);
0153    }
0154 };
0155 
0156 template <class... Ts>
0157 struct result_traits<result<std::tuple<Ts...>>>
0158 {
0159    using response_type = result<std::tuple<Ts...>>;
0160    using adapter_type = static_aggregate_adapter<response_type>;
0161    static auto adapt(response_type& r) noexcept { return adapter_type{&r}; }
0162 };
0163 
0164 } // boost::redis::adapter::detail
0165 
0166 #endif // BOOST_REDIS_ADAPTER_RESPONSE_TRAITS_HPP