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 <concepts>
7#include <optional>
8#include <string>
9#include <unordered_map>
10#include <unordered_set>
11#include <vector>
12
13#include <userver/formats/json/value.hpp>
14#include <userver/storages/redis/fwd.hpp>
15
16#include <userver/storages/redis/reply_types.hpp>
17
18USERVER_NAMESPACE_BEGIN
19
20namespace storages::redis {
21namespace impl {
22
23ReplyData&& ExtractData(ReplyPtr& reply);
24
25template <typename Result, typename ReplyType = Result>
26concept HasParseFunctionFromRedisReply = requires {
27 {
28 Result::Parse(std::declval<ReplyData>(), std::declval<const std::string&>())
29 } -> std::same_as<ReplyType>;
30};
31
32bool IsNil(const ReplyData& reply_data);
33
34void ExpectIsOk(const ReplyPtr& reply, const std::string& request_description);
35
36void ExpectArray(const ReplyData& reply_data, const std::string& request_description);
37
38const std::string& RequestDescription(const ReplyPtr& reply, const std::string& request_description);
39
40} // namespace impl
41
42/// An ADL helper that allows searching for `Parse` functions in namespace
43/// `storages::redis` additionally to the namespace of `Result`.
44template <typename Result, typename ReplyType = Result>
45struct To {};
46
47std::vector<std::string>
48ParseReplyDataArray(ReplyData&& array_data, const std::string& request_description, To<std::vector<std::string>>);
49
50std::
51 vector<std::optional<std::string>>
52 ParseReplyDataArray(ReplyData&& array_data, const std::string& request_description, To<std::vector<std::optional<std::string>>>);
53
54std::vector<std::pair<std::string, std::string>>
55ParseReplyDataArray(ReplyData&& array_data, const std::string& request_description, To<std::vector<std::pair<std::string, std::string>>>);
56
57std::vector<MemberScore>
58ParseReplyDataArray(ReplyData&& array_data, const std::string& request_description, To<std::vector<MemberScore>>);
59
60std::vector<GeoPoint>
61ParseReplyDataArray(ReplyData&& array_data, const std::string& request_description, To<std::vector<GeoPoint>>);
62
63std::
64 vector<std::optional<Point>>
65 ParseReplyDataArray(ReplyData&& array_data, const std::string& request_description, To<std::vector<std::optional<Point>>>);
66
67std::string Parse(ReplyData&& reply_data, const std::string& request_description, To<std::string>);
68
69double Parse(ReplyData&& reply_data, const std::string& request_description, To<double>);
70
71size_t Parse(ReplyData&& reply_data, const std::string& request_description, To<size_t>);
72
73bool Parse(ReplyData&& reply_data, const std::string& request_description, To<size_t, bool>);
74
75int64_t Parse(ReplyData&& reply_data, const std::string& request_description, To<int64_t>);
76
77std::chrono::system_clock::time_point
78Parse(ReplyData&& reply_data, const std::string& request_description, To<std::chrono::system_clock::time_point>);
79
80HsetReply Parse(ReplyData&& reply_data, const std::string& request_description, To<HsetReply>);
81
82PersistReply Parse(ReplyData&& reply_data, const std::string& request_description, To<PersistReply>);
83
84KeyType Parse(ReplyData&& reply_data, const std::string& request_description, To<KeyType>);
85
86void Parse(ReplyData&& reply_data, const std::string& request_description, To<StatusOk, void>);
87
88bool Parse(ReplyData&& reply_data, const std::string& request_description, To<std::optional<StatusOk>, bool>);
89
90void Parse(ReplyData&& reply_data, const std::string& request_description, To<StatusPong, void>);
91
92Point Parse(ReplyData&& reply_data, const std::string& request_description, To<Point>);
93
94SetReply Parse(ReplyData&& reply_data, const std::string& request_description, To<SetReply>);
95
96std::unordered_set<std::string>
97Parse(ReplyData&& reply_data, const std::string& request_description, To<std::unordered_set<std::string>>);
98
99std::unordered_map<std::string, std::string>
100Parse(ReplyData&& reply_data, const std::string& request_description, To<std::unordered_map<std::string, std::string>>);
101
102ReplyData Parse(ReplyData&& reply_data, const std::string& request_description, To<ReplyData>);
103
104formats::json::Value Parse(ReplyData&& reply_data, const std::string& request_description, To<formats::json::Value>);
105
106std::vector<std::optional<formats::json::Value>>
107ParseReplyDataArray(ReplyData&& array_data, const std::string& request_description, To<std::vector<std::optional<formats::json::Value>>>);
108
109template <typename Result, typename ReplyType = Result>
110requires impl::HasParseFunctionFromRedisReply<Result, ReplyType>
111ReplyType Parse(ReplyData&& reply_data, const std::string& request_description, To<Result, ReplyType>) {
112 return Result::Parse(std::move(reply_data), request_description);
113}
114
115template <typename T>
116std::vector<T> Parse(ReplyData&& reply_data, const std::string& request_description, To<std::vector<T>>) {
117 impl::ExpectArray(reply_data, request_description);
118 return ParseReplyDataArray(std::move(reply_data), request_description, To<std::vector<T>>{});
119}
120
121template <typename T>
122std::optional<T> Parse(ReplyData&& reply_data, const std::string& request_description, To<std::optional<T>>) {
123 if (impl::IsNil(reply_data)) {
124 return std::nullopt;
125 }
126 return Parse(std::move(reply_data), request_description, To<T>{});
127}
128
129namespace impl {
130
131template <typename Result, typename ReplyType = Result>
132ReplyType ParseReply(ReplyPtr reply, const std::string& request_description = {}) {
133 const auto& description = impl::RequestDescription(reply, request_description);
134 impl::ExpectIsOk(reply, description);
135 return Parse(impl::ExtractData(reply), description, To<Result, ReplyType>{}); // Customization point
136}
137
138} // namespace impl
139
140} // namespace storages::redis
141
142USERVER_NAMESPACE_END