26class ReplyData
final {
28 using Array = std::vector<ReplyData>;
40 class MovableKeyValues
final {
44 View(ReplyData& key_data, ReplyData& value_data)
noexcept : key_data_(key_data), value_data_(value_data) {}
46 std::string& Key()
noexcept {
return key_data_.GetString(); }
47 std::string& Value()
noexcept {
return value_data_.GetString(); }
51 ReplyData& value_data_;
54 class Iterator
final {
56 using iterator_category = std::input_iterator_tag;
57 using difference_type = std::ptrdiff_t;
58 using value_type = View;
59 using reference = View;
62 constexpr Iterator(Array& array, std::size_t index)
noexcept : array_(&array), index_(index) {}
64 Iterator& operator++()
noexcept {
69 Iterator operator++(
int)
noexcept {
75 bool operator==(
const Iterator& r)
const noexcept {
return index_ == r.index_; }
76 bool operator!=(
const Iterator& r)
const noexcept {
return index_ != r.index_; }
78 View operator*()
const noexcept {
return {(*array_)[index_ * 2], (*array_)[index_ * 2 + 1]}; }
85 explicit MovableKeyValues(Array& array)
noexcept : array_(array) {}
87 Iterator begin()
const noexcept {
return {array_, 0}; }
88 Iterator end()
const noexcept {
return {array_, size()}; }
90 std::size_t size()
const noexcept {
return array_.size() / 2; }
96 MovableKeyValues GetMovableKeyValues();
98 ReplyData(
const redisReply* reply);
99 ReplyData(Array&& array);
100 ReplyData(std::string s);
101 ReplyData(
int value);
102 static ReplyData CreateError(std::string&& error_msg);
103 static ReplyData CreateStatus(std::string&& status_msg);
104 static ReplyData CreateNil();
106 explicit operator
bool()
const noexcept {
return GetType() != Type::kNoReply; }
108 Type GetType()
const noexcept {
109 UASSERT(!data_.valueless_by_exception());
110 return Type(data_.index());
112 std::string GetTypeString()
const;
114 inline bool IsString()
const noexcept {
return GetType() == Type::kString; }
115 inline bool IsArray()
const noexcept {
return GetType() == Type::kArray; }
116 inline bool IsInt()
const noexcept {
return GetType() == Type::kInteger; }
117 inline bool IsNil()
const noexcept {
return GetType() == Type::kNil; }
118 inline bool IsStatus()
const noexcept {
return GetType() == Type::kStatus; }
119 inline bool IsError()
const noexcept {
return GetType() == Type::kError; }
120 bool IsUnusableInstanceError()
const;
121 bool IsReadonlyError()
const;
122 bool IsUnknownCommandError()
const;
124 bool IsErrorMoved()
const {
return IsError() && !GetError().compare(0, 6,
"MOVED "); }
126 bool IsErrorAsk()
const {
return IsError() && !GetError().compare(0, 4,
"ASK "); }
128 bool IsErrorClusterdown()
const {
return IsError() && !GetError().compare(0, 12,
"CLUSTERDOWN "); }
130 const std::string& GetString()
const {
132 return std::get_if<String>(&data_)->GetUnderlying();
135 std::string& GetString() {
137 return std::get_if<String>(&data_)->GetUnderlying();
140 const Array& GetArray()
const {
142 return *std::get_if<Array>(&data_);
147 return *std::get_if<Array>(&data_);
150 std::int64_t GetInt()
const {
152 return *std::get_if<Integer>(&data_);
155 const std::string& GetStatus()
const {
157 return std::get_if<Status>(&data_)->GetUnderlying();
160 std::string& GetStatus() {
162 return std::get_if<Status>(&data_)->GetUnderlying();
165 const std::string& GetError()
const {
167 return std::get_if<Error>(&data_)->GetUnderlying();
170 std::string& GetError() {
172 return std::get_if<Error>(&data_)->GetUnderlying();
175 std::size_t GetSize()
const noexcept;
177 std::string ToDebugString()
const;
178 static std::string TypeToString(Type type);
180 void ExpectType(ReplyData::Type type,
const std::string& request_description = {})
const;
182 void ExpectString(
const std::string& request_description = {})
const;
183 void ExpectArray(
const std::string& request_description = {})
const;
184 void ExpectInt(
const std::string& request_description = {})
const;
185 void ExpectNil(
const std::string& request_description = {})
const;
186 void ExpectStatus(
const std::string& request_description = {})
const;
187 void ExpectStatusEqualTo(
const std::string& expected_status_str,
const std::string& request_description = {})
const;
188 void ExpectError(
const std::string& request_description = {})
const;
191 ReplyData() =
default;
193 [[noreturn]]
void ThrowUnexpectedReplyType(ReplyData::Type expected,
const std::string& request_description)
const;
196 using String = utils::StrongTypedef<
class StringTag, std::string>;
197 using Integer = std::int64_t;
199 using Status = utils::StrongTypedef<
class StatusTag, std::string>;
200 using Error = utils::StrongTypedef<
class ErrorTag, std::string>;
203 std::variant<NoReply, String, Array, Integer, Nil, Status, Error> data_{};
213 const std::string cmd;
219 DeadlinePropagationMeta deadline_propagation_meta;
222 operator
bool()
const {
return IsOk(); }
224 std::string_view GetStatusString()
const {
225 return (!IsOk() && data.IsError() ? data.GetError() : std::string_view{});
229 bool IsLoggableError()
const;
230 bool IsUnusableInstanceError()
const;
231 bool IsReadonlyError()
const;
232 bool IsUnknownCommandError()
const;
233 const logging::LogExtra& GetLogExtra()
const;
234 void FillSpanTags(
tracing::Span& span)
const;
236 void ExpectIsOk(
const std::string& request_description = {})
const;
238 const std::string& GetRequestDescription(
const std::string& request_description)
const;