Action Engine
Loading...
Searching...
No Matches
reply.h
1// Copyright 2025 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef ACTIONENGINE_REDIS_REPLY_H_
16#define ACTIONENGINE_REDIS_REPLY_H_
17
18#include <array>
19#include <cstdint>
20#include <string>
21#include <variant>
22#include <vector>
23
24#include <absl/container/flat_hash_map.h>
25#include <absl/log/check.h>
26#include <absl/status/statusor.h>
27#include <hiredis/hiredis.h>
28
29#include "actionengine/util/status_macros.h"
30
31namespace act::redis {
32
33enum class ReplyType {
34 Status = REDIS_REPLY_STATUS,
35 Error = REDIS_REPLY_ERROR,
36 Integer = REDIS_REPLY_INTEGER,
37 Nil = REDIS_REPLY_NIL,
38 String = REDIS_REPLY_STRING,
39 Array = REDIS_REPLY_ARRAY,
40 Bool = REDIS_REPLY_BOOL,
41 Double = REDIS_REPLY_DOUBLE,
42 Map = REDIS_REPLY_MAP,
43 Set = REDIS_REPLY_SET,
44 Push = REDIS_REPLY_PUSH,
45 Attr = REDIS_REPLY_ATTR,
46 BigNum = REDIS_REPLY_BIGNUM,
47 Verbatim = REDIS_REPLY_VERB,
48 Uninitialized = -1,
49};
50
51struct StatusReplyData;
52struct ErrorReplyData;
53struct IntegerReplyData;
54struct NilReplyData;
55struct StringReplyData;
56struct BoolReplyData;
57struct DoubleReplyData;
58struct PushReplyData;
59struct AttrReplyData;
60struct BigNumReplyData;
61struct VerbatimReplyData;
62struct ArrayReplyData;
63struct MapReplyData;
64struct SetReplyData;
65
66using ReplyData =
67 std::variant<StatusReplyData, ErrorReplyData, IntegerReplyData,
68 NilReplyData, StringReplyData, BoolReplyData, DoubleReplyData,
69 PushReplyData, AttrReplyData, BigNumReplyData,
70 VerbatimReplyData, ArrayReplyData, MapReplyData, SetReplyData>;
71
72struct NilReplyData {};
73
74struct StatusReplyData {
75 [[nodiscard]] std::string Consume() { return std::move(value); }
76
77 absl::Status AsAbslStatus() const { return {absl::StatusCode::kOk, value}; }
78
79 std::string value{};
80};
81
82struct ErrorReplyData {
83 [[nodiscard]] std::string Consume() { return std::move(value); }
84
85 absl::Status AsAbslStatus() const {
86 return {absl::StatusCode::kInternal, value};
87 }
88
89 std::string value{};
90};
91
92struct IntegerReplyData {
93 [[nodiscard]] int64_t Consume() const { return value; }
94
95 int64_t value{0};
96};
97
98struct StringReplyData {
99 [[nodiscard]] std::string Consume() { return std::move(value); }
100
101 std::string value{};
102};
103
104struct BoolReplyData {
105 [[nodiscard]] bool Consume() const { return value; }
106
107 bool value{false};
108};
109
110struct DoubleReplyData {
111 [[nodiscard]] double Consume() const { return value; }
112
113 double value{0.0};
114};
115
116struct BigNumReplyData {
117 [[nodiscard]] std::string Consume() { return std::move(value); }
118
119 std::string value{};
120};
121
122struct VerbatimReplyData {
123 [[nodiscard]] std::string Consume() { return std::move(value); }
124
125 std::array<char, 3> type{};
126 std::string value{};
127};
128
129struct AttrReplyData {
130 AttrReplyData() { CHECK(false) << "AttrReplyData is not implemented yet."; }
131};
132
133struct Reply;
134
135struct ArrayReplyData {
136 [[nodiscard]] std::vector<Reply> Consume();
137 [[nodiscard]] absl::flat_hash_map<std::string, Reply> ConsumeAsMapOrDie();
138
139 std::vector<Reply> values;
140};
141
142struct MapReplyData {
143 [[nodiscard]] absl::flat_hash_map<std::string, Reply> Consume();
144 absl::flat_hash_map<std::string, Reply> values;
145};
146
147struct SetReplyData {
148 [[nodiscard]] std::vector<Reply> Consume();
149
150 std::vector<Reply> values;
151};
152
153struct PushReplyData {
154 [[nodiscard]] std::vector<Reply> ConsumeValueArray();
155
156 std::string type{};
157 ArrayReplyData value_array;
158};
159
160struct Reply {
161 // Reply() = default;
162 // ~Reply() = default;
163
164 std::string ConsumeStringContentOrDie();
165 std::vector<Reply> ConsumeAsArrayOrDie();
166 absl::flat_hash_map<std::string, Reply> ConsumeAsMapOrDie();
167
168 absl::StatusOr<bool> ToBool() const;
169 absl::StatusOr<double> ToDouble() const;
170 absl::StatusOr<int64_t> ToInt() const;
171
172 [[nodiscard]] bool ToBoolOrDie() const {
173 auto status_or_value = ToBool();
174 CHECK_OK(status_or_value);
175 return *status_or_value;
176 }
177
178 [[nodiscard]] double ToDoubleOrDie() const {
179 auto status_or_value = ToDouble();
180 CHECK_OK(status_or_value);
181 return *status_or_value;
182 }
183
184 int64_t ToIntOrDie() const {
185 auto status_or_value = ToInt();
186 CHECK_OK(status_or_value);
187 return *status_or_value;
188 }
189
190 [[nodiscard]] bool IsString() const {
191 return type == ReplyType::String &&
192 std::holds_alternative<StringReplyData>(data);
193 }
194
195 [[nodiscard]] bool IsStatus() const {
196 return type == ReplyType::Status &&
197 std::holds_alternative<StatusReplyData>(data);
198 }
199
200 [[nodiscard]] bool IsError() const {
201 return type == ReplyType::Error &&
202 std::holds_alternative<ErrorReplyData>(data);
203 }
204
205 [[nodiscard]] bool IsNil() const {
206 return type == ReplyType::Nil && std::holds_alternative<NilReplyData>(data);
207 }
208
209 ReplyType type{ReplyType::Uninitialized};
210 ReplyData data{NilReplyData{}};
211};
212
213absl::Status GetStatusOrErrorFrom(const Reply& reply);
214
215} // namespace act::redis
216
217#endif // ACTIONENGINE_REDIS_REPLY_H_