24class ReplyData
final {
26 using Array = std::vector<ReplyData>;
38 class MovableKeyValues
final {
42 View(ReplyData& key_data, ReplyData& value_data)
noexcept : key_data_(key_data), value_data_(value_data) {}
44 std::string& Key()
noexcept {
return key_data_.GetString(); }
45 std::string& Value()
noexcept {
return value_data_.GetString(); }
49 ReplyData& value_data_;
52 class Iterator
final {
54 constexpr Iterator(Array& array, std::size_t index)
noexcept : array_(array), index_(index) {}
55 Iterator& operator++()
noexcept {
59 bool operator!=(
const Iterator& r)
const noexcept {
return index_ != r.index_; }
60 View operator*()
noexcept {
return {array_[index_ * 2], array_[index_ * 2 + 1]}; }
67 explicit MovableKeyValues(Array& array)
noexcept : array_(array) {}
69 Iterator begin()
const noexcept {
return {array_, 0}; }
70 Iterator end()
const noexcept {
return {array_, size()}; }
72 std::size_t size()
const noexcept {
return array_.size() / 2; }
78 MovableKeyValues GetMovableKeyValues();
80 ReplyData(
const redisReply* reply);
81 ReplyData(Array&& array);
82 ReplyData(std::string s);
84 static ReplyData CreateError(std::string&& error_msg);
85 static ReplyData CreateStatus(std::string&& status_msg);
86 static ReplyData CreateNil();
88 explicit operator
bool()
const noexcept {
return GetType() != Type::kNoReply; }
90 Type GetType()
const noexcept {
91 UASSERT(!data_.valueless_by_exception());
92 return Type(data_.index());
94 std::string GetTypeString()
const;
96 inline bool IsString()
const noexcept {
return GetType() == Type::kString; }
97 inline bool IsArray()
const noexcept {
return GetType() == Type::kArray; }
98 inline bool IsInt()
const noexcept {
return GetType() == Type::kInteger; }
99 inline bool IsNil()
const noexcept {
return GetType() == Type::kNil; }
100 inline bool IsStatus()
const noexcept {
return GetType() == Type::kStatus; }
101 inline bool IsError()
const noexcept {
return GetType() == Type::kError; }
102 bool IsUnusableInstanceError()
const;
103 bool IsReadonlyError()
const;
104 bool IsUnknownCommandError()
const;
106 bool IsErrorMoved()
const {
return IsError() && !GetError().compare(0, 6,
"MOVED "); }
108 bool IsErrorAsk()
const {
return IsError() && !GetError().compare(0, 4,
"ASK "); }
110 bool IsErrorClusterdown()
const {
return IsError() && !GetError().compare(0, 12,
"CLUSTERDOWN "); }
112 const std::string& GetString()
const {
114 return std::get_if<String>(&data_)->GetUnderlying();
117 std::string& GetString() {
119 return std::get_if<String>(&data_)->GetUnderlying();
122 const Array& GetArray()
const {
124 return *std::get_if<Array>(&data_);
129 return *std::get_if<Array>(&data_);
132 std::int64_t GetInt()
const {
134 return *std::get_if<Integer>(&data_);
137 const std::string& GetStatus()
const {
139 return std::get_if<Status>(&data_)->GetUnderlying();
142 std::string& GetStatus() {
144 return std::get_if<Status>(&data_)->GetUnderlying();
147 const std::string& GetError()
const {
149 return std::get_if<Error>(&data_)->GetUnderlying();
152 std::string& GetError() {
154 return std::get_if<Error>(&data_)->GetUnderlying();
157 std::size_t GetSize()
const noexcept;
159 std::string ToDebugString()
const;
160 static std::string TypeToString(Type type);
162 void ExpectType(ReplyData::Type type,
const std::string& request_description = {})
const;
164 void ExpectString(
const std::string& request_description = {})
const;
165 void ExpectArray(
const std::string& request_description = {})
const;
166 void ExpectInt(
const std::string& request_description = {})
const;
167 void ExpectNil(
const std::string& request_description = {})
const;
168 void ExpectStatus(
const std::string& request_description = {})
const;
169 void ExpectStatusEqualTo(
const std::string& expected_status_str,
const std::string& request_description = {})
const;
170 void ExpectError(
const std::string& request_description = {})
const;
173 ReplyData() =
default;
175 [[noreturn]]
void ThrowUnexpectedReplyType(ReplyData::Type expected,
const std::string& request_description)
const;
178 using String = utils::StrongTypedef<
class StringTag, std::string>;
179 using Integer = std::int64_t;
181 using Status = utils::StrongTypedef<
class StatusTag, std::string>;
182 using Error = utils::StrongTypedef<
class ErrorTag, std::string>;
185 std::variant<NoReply, String, Array, Integer, Nil, Status, Error> data_{};
195 const std::string cmd;
199 logging::LogExtra log_extra;
201 operator
bool()
const {
return IsOk(); }
203 std::string_view GetStatusString()
const {
204 return (!IsOk() && data.IsError() ? data.GetError() : std::string_view{});
208 bool IsLoggableError()
const;
209 bool IsUnusableInstanceError()
const;
210 bool IsReadonlyError()
const;
211 bool IsUnknownCommandError()
const;
212 const logging::LogExtra& GetLogExtra()
const;
213 void FillSpanTags(
tracing::Span& span)
const;
215 void ExpectIsOk(
const std::string& request_description = {})
const;
217 const std::string& GetRequestDescription(
const std::string& request_description)
const;