userver: userver/storages/redis/parse_reply.hpp Source File
Loading...
Searching...
No Matches
parse_reply.hpp
1#pragma once
2
3#include <optional>
4#include <string>
5#include <unordered_map>
6#include <unordered_set>
7#include <vector>
8
9#include <userver/storages/redis/impl/types.hpp>
10#include <userver/utils/void_t.hpp>
11
12#include <userver/storages/redis/reply_types.hpp>
13
14USERVER_NAMESPACE_BEGIN
15
16namespace storages::redis {
17namespace impl {
18
19ReplyData&& ExtractData(ReplyPtr& reply);
20
21template <typename Result, typename ReplyType, typename = utils::void_t<>>
22struct HasParseFunctionFromRedisReply {
23 static constexpr bool value = false;
24};
25
26template <typename Result, typename ReplyType>
27struct HasParseFunctionFromRedisReply<
28 Result, ReplyType,
29 utils::void_t<decltype(Result::Parse(
30 std::declval<ReplyData>(), std::declval<const std::string&>()))>> {
31 static constexpr bool value =
32 std::is_same<decltype(Result::Parse(std::declval<ReplyData>(),
33 std::declval<const std::string&>())),
34 ReplyType>::value;
35};
36
37bool IsNil(const ReplyData& reply_data);
38
39void ExpectIsOk(const ReplyPtr& reply, const std::string& request_description);
40
41void ExpectArray(const ReplyData& reply_data,
42 const std::string& request_description);
43
44const std::string& RequestDescription(const ReplyPtr& reply,
45 const std::string& request_description);
46
47} // namespace impl
48
49/// An ADL helper that allows searching for `Parse` functions in namespace
50/// `storages::redis` additionally to the namespace of `Result`.
51template <typename Result, typename ReplyType = Result>
52struct To {};
53
54std::vector<std::string> ParseReplyDataArray(
55 ReplyData&& array_data, const std::string& request_description,
56 To<std::vector<std::string>>);
57
58std::vector<std::optional<std::string>> ParseReplyDataArray(
59 ReplyData&& array_data, const std::string& request_description,
60 To<std::vector<std::optional<std::string>>>);
61
62std::vector<std::pair<std::string, std::string>> ParseReplyDataArray(
63 ReplyData&& array_data, const std::string& request_description,
64 To<std::vector<std::pair<std::string, std::string>>>);
65
66std::vector<MemberScore> ParseReplyDataArray(
67 ReplyData&& array_data, const std::string& request_description,
68 To<std::vector<MemberScore>>);
69
70std::vector<GeoPoint> ParseReplyDataArray(
71 ReplyData&& array_data, const std::string& request_description,
72 To<std::vector<GeoPoint>>);
73
74std::string Parse(ReplyData&& reply_data,
75 const std::string& request_description, To<std::string>);
76
77double Parse(ReplyData&& reply_data, const std::string& request_description,
78 To<double>);
79
80size_t Parse(ReplyData&& reply_data, const std::string& request_description,
81 To<size_t>);
82
83bool Parse(ReplyData&& reply_data, const std::string& request_description,
84 To<size_t, bool>);
85
86int64_t Parse(ReplyData&& reply_data, const std::string& request_description,
87 To<int64_t>);
88
89std::chrono::system_clock::time_point Parse(
90 ReplyData&& reply_data, const std::string& request_description,
91 To<std::chrono::system_clock::time_point>);
92
93HsetReply Parse(ReplyData&& reply_data, const std::string& request_description,
94 To<HsetReply>);
95
96PersistReply Parse(ReplyData&& reply_data,
97 const std::string& request_description, To<PersistReply>);
98
99KeyType Parse(ReplyData&& reply_data, const std::string& request_description,
100 To<KeyType>);
101
102void Parse(ReplyData&& reply_data, const std::string& request_description,
103 To<StatusOk, void>);
104
105bool Parse(ReplyData&& reply_data, const std::string& request_description,
106 To<std::optional<StatusOk>, bool>);
107
108void Parse(ReplyData&& reply_data, const std::string& request_description,
109 To<StatusPong, void>);
110
111SetReply Parse(ReplyData&& reply_data, const std::string& request_description,
112 To<SetReply>);
113
114std::unordered_set<std::string> Parse(ReplyData&& reply_data,
115 const std::string& request_description,
116 To<std::unordered_set<std::string>>);
117
118std::unordered_map<std::string, std::string> Parse(
119 ReplyData&& reply_data, const std::string& request_description,
120 To<std::unordered_map<std::string, std::string>>);
121
122ReplyData Parse(ReplyData&& reply_data, const std::string& request_description,
123 To<ReplyData>);
124
125template <typename Result, typename ReplyType = Result>
126std::enable_if_t<impl::HasParseFunctionFromRedisReply<Result, ReplyType>::value,
127 ReplyType>
128Parse(ReplyData&& reply_data, const std::string& request_description,
129 To<Result, ReplyType>) {
130 return Result::Parse(std::move(reply_data), request_description);
131}
132
133template <typename T>
134std::vector<T> Parse(ReplyData&& reply_data,
135 const std::string& request_description,
136 To<std::vector<T>>) {
137 impl::ExpectArray(reply_data, request_description);
138 return ParseReplyDataArray(std::move(reply_data), request_description,
139 To<std::vector<T>>{});
140}
141
142template <typename T>
143std::optional<T> Parse(ReplyData&& reply_data,
144 const std::string& request_description,
145 To<std::optional<T>>) {
146 if (impl::IsNil(reply_data)) return std::nullopt;
147 return Parse(std::move(reply_data), request_description, To<T>{});
148}
149
150template <typename Result, typename ReplyType = Result>
151ReplyType ParseReply(ReplyPtr reply,
152 const std::string& request_description = {}) {
153 const auto& description =
154 impl::RequestDescription(reply, request_description);
155 impl::ExpectIsOk(reply, description);
156 return Parse(impl::ExtractData(reply), description, To<Result, ReplyType>{});
157}
158
159} // namespace storages::redis
160
161USERVER_NAMESPACE_END