12#include <userver/formats/common/meta.hpp>
13#include <userver/formats/parse/to.hpp>
14#include <userver/utils/meta.hpp>
16namespace boost::uuids {
20USERVER_NAMESPACE_BEGIN
22namespace formats::
parse {
26template <
typename T,
class Value>
27inline T AsExtractor(
const Value& value) {
28 return value.
template As<T>();
31template <
typename T,
class Value>
32inline T ConvertToExtractor(
const Value& value) {
33 return value.
template ConvertTo<T>();
36template <
typename ArrayType,
class Value,
typename ExtractFunc>
37ArrayType ParseArray(
const Value& value, ExtractFunc&& extract_func) {
38 value.CheckArrayOrNull();
40 auto inserter = std::inserter(response, response.end());
42 for (
const auto& subitem : value) {
43 *inserter = extract_func(subitem);
50template <
typename ObjectType,
class Value,
typename ExtractFunc>
51ObjectType ParseObject(
const Value& value, ExtractFunc&& extract_func) {
52 value.CheckObjectOrNull();
55 for (
auto it = value.begin(); it != value.end(); ++it) {
56 result.emplace(it.GetName(), extract_func(*it));
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>,
68Parse(
const Value& value, To<T>) {
69 return impl::ParseArray<T>(
70 value, &impl::AsExtractor<meta::RangeValueType<T>, Value>);
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>);
80template <
typename T,
typename Value>
81std::optional<T> Parse(
const Value& value,
To<std::optional<T>>) {
82 if (value.IsMissing() || value.IsNull()) {
85 return value.
template As<T>();
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");
96template <
typename T,
typename Value>
97std::enable_if_t<meta::kIsRange<T> && !meta::kIsMap<T> &&
98 !std::is_same_v<T, boost::uuids::uuid>,
100Convert(
const Value& value, To<T>) {
101 if (value.IsMissing()) {
104 return impl::ParseArray<T>(
105 value, &impl::ConvertToExtractor<meta::RangeValueType<T>, Value>);
108template <
typename T,
typename Value>
109std::enable_if_t<meta::kIsMap<T>, T> Convert(
const Value& value, To<T>) {
110 if (value.IsMissing()) {
113 return impl::ParseObject<T>(
114 value, &impl::ConvertToExtractor<
typename T::mapped_type, Value>);
117template <
typename T,
typename Value>
118std::optional<T> Convert(
const Value& value,
To<std::optional<T>>) {
119 if (value.IsMissing() || value.IsNull()) {
122 return value.
template ConvertTo<T>();
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");