6#include <unordered_map> 
    7#include <unordered_set> 
   10#include <userver/engine/impl/context_accessor.hpp> 
   11#include <userver/storages/redis/exception.hpp> 
   12#include <userver/storages/redis/reply_types.hpp> 
   13#include <userver/storages/redis/request_data_base.hpp> 
   14#include <userver/storages/redis/scan_tag.hpp> 
   16USERVER_NAMESPACE_BEGIN
 
   20template <ScanTag scan_tag>
 
   23template <
typename Result, 
typename ReplyType = Result>
 
   24class [[nodiscard]] Request final {
 
   26  using Reply = ReplyType;
 
   28  explicit Request(std::unique_ptr<RequestDataBase<ReplyType>>&& impl)
 
   29      : impl_(std::move(impl)) {}
 
   31  void Wait() { impl_->Wait(); }
 
   33  void IgnoreResult() 
const {}
 
   35  ReplyType Get(
const std::string& request_description = {}) {
 
   36    return impl_->Get(request_description);
 
   41  engine::impl::ContextAccessor* TryGetContextAccessor() 
noexcept {
 
   42    return impl_->TryGetContextAccessor();
 
   46  template <
typename T1, 
typename T2>
 
   47  friend class RequestEval;
 
   49  template <
typename T1, 
typename T2>
 
   50  friend class RequestEvalSha;
 
   52  template <ScanTag scan_tag>
 
   53  friend class RequestScanData;
 
   56  ReplyPtr GetRaw() { 
return impl_->GetRaw(); }
 
   58  std::unique_ptr<RequestDataBase<ReplyType>> impl_;
 
   61template <ScanTag scan_tag>
 
   62class ScanRequest final {
 
   64  using ReplyElem = 
typename ScanReplyElem<scan_tag>::type;
 
   66  explicit ScanRequest(std::unique_ptr<RequestScanDataBase<scan_tag>>&& impl)
 
   67      : impl_(std::move(impl)) {}
 
   69  template <
typename T = std::vector<ReplyElem>>
 
   70  T GetAll(std::string request_description) {
 
   71    SetRequestDescription(std::move(request_description));
 
   75  template <
typename T = std::vector<ReplyElem>>
 
   77    return T{begin(), end()};
 
   80  void SetRequestDescription(std::string request_description) {
 
   81    impl_->SetRequestDescription(std::move(request_description));
 
   86    using iterator_category = std::input_iterator_tag;
 
   88    using value_type = ReplyElem;
 
   89    using reference = value_type&;
 
   90    using pointer = value_type*;
 
   92    explicit Iterator(ScanRequest* stream) : stream_(stream) {
 
   93      if (stream_ && !stream_->HasMore()) stream_ = 
nullptr;
 
   98      ReplyElemHolder(value_type reply_elem)
 
   99          : reply_elem_(std::move(reply_elem)) {}
 
  101      value_type& operator*() { 
return reply_elem_; }
 
  104      value_type reply_elem_;
 
  115      if (!stream_->HasMore()) stream_ = 
nullptr;
 
  119    reference operator*() { 
return stream_->Current(); }
 
  121    pointer operator->() { 
return &**
this; }
 
  123    bool operator==(
const Iterator& rhs) 
const {
 
  124      return stream_ == rhs.stream_;
 
  127    bool operator!=(
const Iterator& rhs) 
const { 
return !(*
this == rhs); }
 
  130    ScanRequest* stream_;
 
  138    using USERVER_NAMESPACE::redis::
Exception::Exception;
 
  142  ReplyElem& Current() { 
return impl_->Current(); }
 
  144  ReplyElem Get() { 
return impl_->Get(); }
 
  146  bool HasMore() { 
return !impl_->Eof(); }
 
  150  std::unique_ptr<RequestScanDataBase<scan_tag>> impl_;
 
  160using RequestExec = Request<ReplyData, 
void>;
 
  177using RequestHmset = Request<StatusOk, 
void>;
 
  178using RequestHscan = ScanRequest<ScanTag::kHscan>;
 
  191using RequestLtrim = Request<StatusOk, 
void>;
 
  193using RequestMset = Request<StatusOk, 
void>;
 
  196using RequestPing = Request<StatusPong, 
void>;
 
  199using RequestRename = Request<StatusOk, 
void>;
 
  204using RequestScan = ScanRequest<ScanTag::kScan>;
 
  206using RequestSet = Request<StatusOk, 
void>;
 
  207using RequestSetIfExist = Request<std::optional<StatusOk>, 
bool>;
 
  208using RequestSetIfNotExist = Request<std::optional<StatusOk>, 
bool>;
 
  210using RequestSetex = Request<StatusOk, 
void>;
 
  216using RequestSscan = ScanRequest<ScanTag::kSscan>;
 
  233using RequestZscan = ScanRequest<ScanTag::kZscan>;