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