userver: userver/formats/parse/common_containers.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
common_containers.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/formats/parse/common_containers.hpp
4/// @brief Parsers and converters for Standard Library containers and
5/// std::optional
6///
7/// @ingroup userver_universal userver_formats_parse
8
9#include <optional>
10#include <type_traits>
11
12#include <userver/formats/common/meta.hpp>
13#include <userver/formats/parse/to.hpp>
14#include <userver/utils/meta.hpp>
15
16namespace boost::uuids {
17struct uuid;
18}
19
20USERVER_NAMESPACE_BEGIN
21
22namespace formats::parse {
23
24namespace impl {
25
26template <typename T, class Value>
27inline T AsExtractor(const Value& value) {
28 return value.template As<T>();
29}
30
31template <typename T, class Value>
32inline T ConvertToExtractor(const Value& value) {
33 return value.template ConvertTo<T>();
34}
35
36template <typename ArrayType, class Value, typename ExtractFunc>
37ArrayType ParseArray(const Value& value, ExtractFunc&& extract_func) {
38 value.CheckArrayOrNull();
39 ArrayType response;
40 auto inserter = std::inserter(response, response.end());
41
42 for (const auto& subitem : value) {
43 *inserter = extract_func(subitem);
44 ++inserter;
45 }
46
47 return response;
48}
49
50template <typename ObjectType, class Value, typename ExtractFunc>
51ObjectType ParseObject(const Value& value, ExtractFunc&& extract_func) {
52 value.CheckObjectOrNull();
53 ObjectType result;
54
55 for (auto it = value.begin(); it != value.end(); ++it) {
56 result.emplace(it.GetName(), extract_func(*it));
57 }
58
59 return result;
60}
61
62} // namespace impl
63
64template <typename T, typename Value>
65std::enable_if_t<common::kIsFormatValue<Value> && meta::kIsRange<T> &&
66 !meta::kIsMap<T> && !std::is_same_v<T, boost::uuids::uuid>,
67 T>
68Parse(const Value& value, To<T>) {
69 return impl::ParseArray<T>(
70 value, &impl::AsExtractor<meta::RangeValueType<T>, Value>);
71}
72
73template <typename T, typename Value>
74std::enable_if_t<common::kIsFormatValue<Value> && meta::kIsMap<T>, T> Parse(
75 const Value& value, To<T>) {
76 return impl::ParseObject<T>(
77 value, &impl::AsExtractor<typename T::mapped_type, Value>);
78}
79
80template <typename T, typename Value>
81std::optional<T> Parse(const Value& value, To<std::optional<T>>) {
82 if (value.IsMissing() || value.IsNull()) {
83 return std::nullopt;
84 }
85 return value.template As<T>();
86}
87
88template <class Value>
89std::optional<std::nullptr_t> Parse(const Value&,
90 To<std::optional<std::nullptr_t>>) {
91 static_assert(!sizeof(Value),
92 "optional<nullptr_t> is forbidden, check IsNull() instead");
93 return nullptr;
94}
95
96template <typename T, typename Value>
97std::enable_if_t<meta::kIsRange<T> && !meta::kIsMap<T> &&
98 !std::is_same_v<T, boost::uuids::uuid>,
99 T>
100Convert(const Value& value, To<T>) {
101 if (value.IsMissing()) {
102 return {};
103 }
104 return impl::ParseArray<T>(
105 value, &impl::ConvertToExtractor<meta::RangeValueType<T>, Value>);
106}
107
108template <typename T, typename Value>
109std::enable_if_t<meta::kIsMap<T>, T> Convert(const Value& value, To<T>) {
110 if (value.IsMissing()) {
111 return {};
112 }
113 return impl::ParseObject<T>(
114 value, &impl::ConvertToExtractor<typename T::mapped_type, Value>);
115}
116
117template <typename T, typename Value>
118std::optional<T> Convert(const Value& value, To<std::optional<T>>) {
119 if (value.IsMissing() || value.IsNull()) {
120 return std::nullopt;
121 }
122 return value.template ConvertTo<T>();
123}
124
125template <class Value>
126std::optional<std::nullptr_t> Convert(const Value&,
127 To<std::optional<std::nullptr_t>>) {
128 static_assert(!sizeof(Value),
129 "optional<nullptr_t> is forbidden, check IsNull() instead");
130 return nullptr;
131}
132
133} // namespace formats::parse
134
135USERVER_NAMESPACE_END