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,
29 ReplyType,
30 utils::void_t<decltype(Result::Parse(std::declval<ReplyData>(), std::declval<const std::string&>()))>> {
31 static constexpr bool value = std::is_same<
32 decltype(Result::Parse(std::declval<ReplyData>(), std::declval<const std::string&>())),
33 ReplyType>::value;
34};
35
36bool IsNil(const ReplyData& reply_data);
37
38void ExpectIsOk(const ReplyPtr& reply, const std::string& request_description);
39
40void ExpectArray(const ReplyData& reply_data, const std::string& request_description);
41
42const std::string& RequestDescription(const ReplyPtr& reply, const std::string& request_description);
43
44} // namespace impl
45
46/// An ADL helper that allows searching for `Parse` functions in namespace
47/// `storages::redis` additionally to the namespace of `Result`.
48template <typename Result, typename ReplyType = Result>
49struct To {};
50
51std::vector<std::string>
52ParseReplyDataArray(ReplyData&& array_data, const std::string& request_description, To<std::vector<std::string>>);
53
54std::vector<std::optional<std::string>>
55ParseReplyDataArray(ReplyData&& array_data, const std::string& request_description, To<std::vector<std::optional<std::string>>>);
56
57std::vector<std::pair<std::string, std::string>>
58ParseReplyDataArray(ReplyData&& array_data, const std::string& request_description, To<std::vector<std::pair<std::string, std::string>>>);
59
60std::vector<MemberScore>
61ParseReplyDataArray(ReplyData&& array_data, const std::string& request_description, To<std::vector<MemberScore>>);
62
63std::vector<GeoPoint>
64ParseReplyDataArray(ReplyData&& array_data, const std::string& request_description, To<std::vector<GeoPoint>>);
65
66std::string Parse(ReplyData&& reply_data, const std::string& request_description, To<std::string>);
67
68double Parse(ReplyData&& reply_data, const std::string& request_description, To<double>);
69
70size_t Parse(ReplyData&& reply_data, const std::string& request_description, To<size_t>);
71
72bool Parse(ReplyData&& reply_data, const std::string& request_description, To<size_t, bool>);
73
74int64_t Parse(ReplyData&& reply_data, const std::string& request_description, To<int64_t>);
75
76std::chrono::system_clock::time_point
77Parse(ReplyData&& reply_data, const std::string& request_description, To<std::chrono::system_clock::time_point>);
78
79HsetReply Parse(ReplyData&& reply_data, const std::string& request_description, To<HsetReply>);
80
81PersistReply Parse(ReplyData&& reply_data, const std::string& request_description, To<PersistReply>);
82
83KeyType Parse(ReplyData&& reply_data, const std::string& request_description, To<KeyType>);
84
85void Parse(ReplyData&& reply_data, const std::string& request_description, To<StatusOk, void>);
86
87bool Parse(ReplyData&& reply_data, const std::string& request_description, To<std::optional<StatusOk>, bool>);
88
89void Parse(ReplyData&& reply_data, const std::string& request_description, To<StatusPong, void>);
90
91SetReply Parse(ReplyData&& reply_data, const std::string& request_description, To<SetReply>);
92
93std::unordered_set<std::string>
94Parse(ReplyData&& reply_data, const std::string& request_description, To<std::unordered_set<std::string>>);
95
96std::unordered_map<std::string, std::string>
97Parse(ReplyData&& reply_data, const std::string& request_description, To<std::unordered_map<std::string, std::string>>);
98
99ReplyData Parse(ReplyData&& reply_data, const std::string& request_description, To<ReplyData>);
100
101template <typename Result, typename ReplyType = Result>
102std::enable_if_t<impl::HasParseFunctionFromRedisReply<Result, ReplyType>::value, ReplyType>
103Parse(ReplyData&& reply_data, const std::string& request_description, To<Result, ReplyType>) {
104 return Result::Parse(std::move(reply_data), request_description);
105}
106
107template <typename T>
108std::vector<T> Parse(ReplyData&& reply_data, const std::string& request_description, To<std::vector<T>>) {
109 impl::ExpectArray(reply_data, request_description);
110 return ParseReplyDataArray(std::move(reply_data), request_description, To<std::vector<T>>{});
111}
112
113template <typename T>
114std::optional<T> Parse(ReplyData&& reply_data, const std::string& request_description, To<std::optional<T>>) {
115 if (impl::IsNil(reply_data)) return std::nullopt;
116 return Parse(std::move(reply_data), request_description, To<T>{});
117}
118
119template <typename Result, typename ReplyType = Result>
120ReplyType ParseReply(ReplyPtr reply, const std::string& request_description = {}) {
121 const auto& description = impl::RequestDescription(reply, request_description);
122 impl::ExpectIsOk(reply, description);
123 return Parse(impl::ExtractData(reply), description, To<Result, ReplyType>{});
124}
125
126} // namespace storages::redis
127
128USERVER_NAMESPACE_END