13#include <userver/formats/common/meta.hpp>
14#include <userver/formats/parse/to.hpp>
15#include <userver/utils/meta.hpp>
17namespace boost::uuids {
21USERVER_NAMESPACE_BEGIN
23namespace utils::
impl::strong_typedef {
24struct StrongTypedefTag;
31template <
typename T,
class Value>
32inline T AsExtractor(
const Value& value) {
33 return value.
template As<T>();
36template <
typename T,
class Value>
37inline T ConvertToExtractor(
const Value& value) {
38 return value.
template ConvertTo<T>();
41template <
typename ArrayType,
class Value,
typename ExtractFunc>
42ArrayType ParseArray(
const Value& value, ExtractFunc extract_func) {
43 value.CheckArrayOrNull();
45 auto inserter = std::inserter(response, response.end());
47 for (
const auto& subitem : value) {
48 *inserter = extract_func(subitem);
55template <
typename ObjectType,
class Value,
typename ExtractFunc>
56ObjectType ParseObject(
const Value& value, ExtractFunc extract_func) {
57 using KeyType =
typename ObjectType::key_type;
59 value.CheckObjectOrNull();
62 for (
auto it = value.begin(); it != value.end(); ++it) {
63 if constexpr (std::is_constructible_v<KeyType, std::string>) {
64 result.emplace(it.GetName(), extract_func(*it));
66 result.emplace(Parse(std::string_view(it.GetName()),
To<KeyType>{}), extract_func(*it));
75template <
typename T,
typename Value>
77 common::kIsFormatValue<Value> && meta::kIsRange<T> && !meta::kIsMap<T> && !std::is_same_v<T, boost::uuids::uuid> &&
78 !std::is_convertible_v<T&, utils::
impl::strong_typedef::StrongTypedefTag&>,
80Parse(
const Value& value,
To<T>) {
81 return impl::ParseArray<T>(value, &impl::AsExtractor<meta::RangeValueType<T>, Value>);
84template <
typename T,
typename Value>
85std::enable_if_t<
common::kIsFormatValue<Value> && meta::kIsMap<T>, T> Parse(
const Value& value,
To<T>) {
86 return impl::ParseObject<T>(value, &impl::AsExtractor<
typename T::mapped_type, Value>);
89template <
typename T,
typename Value>
90std::optional<
decltype(Parse(std::declval<Value>(),
To<T>{}))> Parse(
const Value& value,
To<std::optional<T>>) {
91 if (value.IsMissing() || value.IsNull()) {
94 return value.
template As<T>();
98std::optional<std::nullptr_t> Parse(
const Value&,
To<std::optional<std::nullptr_t>>) {
99 static_assert(!
sizeof(Value),
"optional<nullptr_t> is forbidden, check IsNull() instead");
103template <
typename T,
typename Value>
105 meta::kIsRange<T> && !meta::kIsMap<T> && !std::is_same_v<T, boost::uuids::uuid> &&
106 !std::is_convertible_v<T&, utils::
impl::strong_typedef::StrongTypedefTag&>,
108Convert(
const Value& value,
To<T>) {
109 if (value.IsMissing()) {
112 return impl::ParseArray<T>(value, &impl::ConvertToExtractor<meta::RangeValueType<T>, Value>);
115template <
typename T,
typename Value>
116std::enable_if_t<meta::kIsMap<T>, T> Convert(
const Value& value,
To<T>) {
117 if (value.IsMissing()) {
120 return impl::ParseObject<T>(value, &impl::ConvertToExtractor<
typename T::mapped_type, Value>);
123template <
typename T,
typename Value>
124std::optional<T> Convert(
const Value& value,
To<std::optional<T>>) {
125 if (value.IsMissing() || value.IsNull()) {
128 return value.
template ConvertTo<T>();
131template <
class Value>
132std::optional<std::nullptr_t> Convert(
const Value&,
To<std::optional<std::nullptr_t>>) {
133 static_assert(!
sizeof(Value),
"optional<nullptr_t> is forbidden, check IsNull() instead");