response_traits.hpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /* Copyright (c) 2018-2025 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. #ifndef BOOST_REDIS_ADAPTER_DETAIL_RESPONSE_TRAITS_HPP
  7. #define BOOST_REDIS_ADAPTER_DETAIL_RESPONSE_TRAITS_HPP
  8. #include <boost/redis/adapter/detail/result_traits.hpp>
  9. #include <boost/redis/ignore.hpp>
  10. #include <boost/redis/resp3/node.hpp>
  11. #include <boost/redis/response.hpp>
  12. #include <boost/mp11.hpp>
  13. #include <boost/system.hpp>
  14. #include <limits>
  15. #include <string_view>
  16. #include <tuple>
  17. #include <variant>
  18. namespace boost::redis::adapter::detail {
  19. template <class Response>
  20. class static_adapter {
  21. private:
  22. static constexpr auto size = std::tuple_size<Response>::value;
  23. using adapter_tuple = mp11::mp_transform<adapter_t, Response>;
  24. using variant_type = mp11::mp_rename<adapter_tuple, std::variant>;
  25. using adapters_array_type = std::array<variant_type, size>;
  26. adapters_array_type adapters_;
  27. std::size_t i_ = 0;
  28. public:
  29. explicit static_adapter(Response& r) { assigner<size - 1>::assign(adapters_, r); }
  30. void on_init()
  31. {
  32. using std::visit;
  33. visit(
  34. [&](auto& arg) {
  35. arg.on_init();
  36. },
  37. adapters_.at(i_));
  38. }
  39. void on_done()
  40. {
  41. using std::visit;
  42. visit(
  43. [&](auto& arg) {
  44. arg.on_done();
  45. },
  46. adapters_.at(i_));
  47. i_ += 1;
  48. }
  49. template <class String>
  50. void on_node(resp3::basic_node<String> const& nd, system::error_code& ec)
  51. {
  52. using std::visit;
  53. // I am usure whether this should be an error or an assertion.
  54. BOOST_ASSERT(i_ < adapters_.size());
  55. visit(
  56. [&](auto& arg) {
  57. arg.on_node(nd, ec);
  58. },
  59. adapters_.at(i_));
  60. }
  61. };
  62. template <class>
  63. struct response_traits;
  64. template <>
  65. struct response_traits<ignore_t> {
  66. using response_type = ignore_t;
  67. using adapter_type = ignore;
  68. static auto adapt(response_type&) noexcept { return ignore{}; }
  69. };
  70. template <>
  71. struct response_traits<result<ignore_t>> {
  72. using response_type = result<ignore_t>;
  73. using adapter_type = ignore;
  74. static auto adapt(response_type&) noexcept { return ignore{}; }
  75. };
  76. template <class String, class Allocator>
  77. struct response_traits<result<std::vector<resp3::basic_node<String>, Allocator>>> {
  78. using response_type = result<std::vector<resp3::basic_node<String>, Allocator>>;
  79. using adapter_type = general_aggregate<response_type>;
  80. static auto adapt(response_type& v) noexcept { return adapter_type{&v}; }
  81. };
  82. template <class... Ts>
  83. struct response_traits<response<Ts...>> {
  84. using response_type = response<Ts...>;
  85. using adapter_type = static_adapter<response_type>;
  86. static auto adapt(response_type& r) noexcept { return adapter_type{r}; }
  87. };
  88. } // namespace boost::redis::adapter::detail
  89. #endif // BOOST_REDIS_ADAPTER_DETAIL_RESPONSE_TRAITS_HPP