7#include <userver/logging/log_extra.hpp> 
    8#include <userver/utils/assert.hpp> 
   10#include <userver/storages/redis/impl/base.hpp> 
   11#include <userver/storages/redis/reply_status.hpp> 
   15USERVER_NAMESPACE_BEGIN
 
   19class ReplyData 
final {
 
   21  using Array = std::vector<ReplyData>;
 
   33  class KeyValues 
final {
 
   35    class KeyValue 
final {
 
   37      KeyValue(
const Array& array, size_t index)
 
   38          : array_(array), index_(index) {}
 
   40      std::string Key() 
const { 
return array_[index_ * 2].GetString(); }
 
   41      std::string Value() 
const { 
return array_[index_ * 2 + 1].GetString(); }
 
   48    class KeyValueIt 
final {
 
   50      KeyValueIt(
const Array& array, size_t index)
 
   51          : array_(array), index_(index) {}
 
   52      KeyValueIt& operator++() {
 
   56      bool operator!=(
const KeyValueIt& r) 
const { 
return index_ != r.index_; }
 
   57      KeyValue operator*() 
const { 
return {array_, index_}; }
 
   64    explicit KeyValues(
const Array& array) : array_(array) {}
 
   66    KeyValueIt begin() 
const { 
return {array_, 0}; }
 
   67    KeyValueIt end() 
const { 
return {array_, size()}; }
 
   69    size_t size() 
const { 
return array_.size() / 2; }
 
   75  class MovableKeyValues 
final {
 
   77    class MovableKeyValue 
final {
 
   79      MovableKeyValue(ReplyData& key_data, ReplyData& value_data)
 
   80          : key_data_(key_data), value_data_(value_data) {}
 
   82      std::string& Key() { 
return key_data_.GetString(); }
 
   83      std::string& Value() { 
return value_data_.GetString(); }
 
   87      ReplyData& value_data_;
 
   90    class MovableKeyValueIt 
final {
 
   92      MovableKeyValueIt(Array& array, size_t index)
 
   93          : array_(array), index_(index) {}
 
   94      MovableKeyValueIt& operator++() {
 
   98      bool operator!=(
const MovableKeyValueIt& r) 
const {
 
   99        return index_ != r.index_;
 
  101      MovableKeyValue operator*() {
 
  102        return {array_[index_ * 2], array_[index_ * 2 + 1]};
 
  110    explicit MovableKeyValues(Array& array) : array_(array) {}
 
  112    MovableKeyValueIt begin() 
const { 
return {array_, 0}; }
 
  113    MovableKeyValueIt end() 
const { 
return {array_, size()}; }
 
  115    size_t size() 
const { 
return array_.size() / 2; }
 
  121  MovableKeyValues GetMovableKeyValues();
 
  123  ReplyData(
const redisReply* reply);
 
  124  ReplyData(Array&& array);
 
  125  ReplyData(std::string s);
 
  126  ReplyData(
int value);
 
  127  static ReplyData CreateError(std::string&& error_msg);
 
  128  static ReplyData CreateStatus(std::string&& status_msg);
 
  129  static ReplyData CreateNil();
 
  131  explicit operator 
bool() 
const { 
return type_ != Type::kNoReply; }
 
  133  Type GetType() 
const { 
return type_; }
 
  134  std::string GetTypeString() 
const;
 
  136  inline bool IsString() 
const { 
return type_ == Type::kString; }
 
  137  inline bool IsArray() 
const { 
return type_ == Type::kArray; }
 
  138  inline bool IsInt() 
const { 
return type_ == Type::kInteger; }
 
  139  inline bool IsNil() 
const { 
return type_ == Type::kNil; }
 
  140  inline bool IsStatus() 
const { 
return type_ == Type::kStatus; }
 
  141  inline bool IsError() 
const { 
return type_ == Type::kError; }
 
  142  bool IsUnusableInstanceError() 
const;
 
  143  bool IsReadonlyError() 
const;
 
  144  bool IsUnknownCommandError() 
const;
 
  146  bool IsErrorMoved() 
const {
 
  147    return IsError() && !string_.compare(0, 6, 
"MOVED ");
 
  150  bool IsErrorAsk() 
const {
 
  151    return IsError() && !string_.compare(0, 4, 
"ASK ");
 
  154  const std::string& GetString() 
const {
 
  159  std::string& GetString() {
 
  164  const Array& GetArray() 
const {
 
  174  int64_t GetInt() 
const {
 
  179  const std::string& GetStatus() 
const {
 
  184  std::string& GetStatus() {
 
  189  const std::string& GetError() 
const {
 
  194  std::string& GetError() {
 
  199  const ReplyData& operator[](size_t idx) 
const {
 
  201    return array_.at(idx);
 
  204  ReplyData& operator[](size_t idx) {
 
  206    return array_.at(idx);
 
  209  size_t GetSize() 
const;
 
  211  std::string ToDebugString() 
const;
 
  212  KeyValues GetKeyValues() 
const;
 
  213  static std::string TypeToString(Type type);
 
  215  void ExpectType(ReplyData::Type type,
 
  216                  const std::string& request_description = {}) 
const;
 
  218  void ExpectString(
const std::string& request_description = {}) 
const;
 
  219  void ExpectArray(
const std::string& request_description = {}) 
const;
 
  220  void ExpectInt(
const std::string& request_description = {}) 
const;
 
  221  void ExpectNil(
const std::string& request_description = {}) 
const;
 
  222  void ExpectStatus(
const std::string& request_description = {}) 
const;
 
  223  void ExpectStatusEqualTo(
const std::string& expected_status_str,
 
  224                           const std::string& request_description = {}) 
const;
 
  225  void ExpectError(
const std::string& request_description = {}) 
const;
 
  228  ReplyData() = 
default;
 
  230  [[noreturn]] 
void ThrowUnexpectedReplyType(
 
  231      ReplyData::Type expected, 
const std::string& request_description) 
const;
 
  233  Type type_ = Type::kNoReply;
 
  242  Reply(std::string cmd, redisReply* redis_reply, ReplyStatus status);
 
  243  Reply(std::string cmd, redisReply* redis_reply, ReplyStatus status,
 
  244        std::string status_string);
 
  245  Reply(std::string cmd, ReplyData&& data);
 
  252  std::string status_string;
 
  256  operator 
bool() 
const { 
return IsOk(); }
 
  259  bool IsLoggableError() 
const;
 
  260  bool IsUnusableInstanceError() 
const;
 
  261  bool IsReadonlyError() 
const;
 
  262  bool IsUnknownCommandError() 
const;
 
  263  const logging::LogExtra& GetLogExtra() 
const;
 
  264  void FillSpanTags(
tracing::Span& span) 
const;
 
  266  void ExpectIsOk(
const std::string& request_description = {}) 
const;
 
  267  void ExpectType(ReplyData::Type type,
 
  268                  const std::string& request_description = {}) 
const;
 
  270  void ExpectString(
const std::string& request_description = {}) 
const;
 
  271  void ExpectArray(
const std::string& request_description = {}) 
const;
 
  272  void ExpectInt(
const std::string& request_description = {}) 
const;
 
  273  void ExpectNil(
const std::string& request_description = {}) 
const;
 
  274  void ExpectStatus(
const std::string& request_description = {}) 
const;
 
  275  void ExpectStatusEqualTo(
const std::string& expected_status_str,
 
  276                           const std::string& request_description = {}) 
const;
 
  277  void ExpectError(
const std::string& request_description = {}) 
const;
 
  279  const std::string& GetRequestDescription(
 
  280      const std::string& request_description) 
const;