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 utils::impl::strong_typedef {
23struct StrongTypedefTag;
30template <
typename T,
class Value>
31inline T AsExtractor(
const Value& value) {
32 return value.
template As<T>();
35template <
typename T,
class Value>
36inline T ConvertToExtractor(
const Value& value) {
37 return value.
template ConvertTo<T>();
40template <
typename ArrayType,
class Value,
typename ExtractFunc>
41ArrayType ParseArray(
const Value& value, ExtractFunc&& extract_func) {
42 value.CheckArrayOrNull();
44 auto inserter = std::inserter(response, response.end());
46 for (
const auto& subitem : value) {
47 *inserter = extract_func(subitem);
54template <
typename ObjectType,
class Value,
typename ExtractFunc>
55ObjectType ParseObject(
const Value& value, ExtractFunc&& extract_func) {
56 value.CheckObjectOrNull();
59 for (
auto it = value.begin(); it != value.end(); ++it) {
60 result.emplace(it.GetName(), extract_func(*it));
68template <
typename T,
typename Value>
70 common::kIsFormatValue<Value> && meta::kIsRange<T> && !meta::kIsMap<T> && !std::is_same_v<T, boost::uuids::uuid> &&
71 !std::is_convertible_v<T&, utils::impl::strong_typedef::StrongTypedefTag&>,
73Parse(
const Value& value, To<T>) {
74 return impl::ParseArray<T>(value, &impl::AsExtractor<meta::RangeValueType<T>, Value>);
77template <
typename T,
typename Value>
78std::enable_if_t<common::kIsFormatValue<Value> && meta::kIsMap<T>, T> Parse(
const Value& value, To<T>) {
79 return impl::ParseObject<T>(value, &impl::AsExtractor<
typename T::mapped_type, Value>);
82template <
typename T,
typename Value>
83std::optional<
decltype(Parse(std::declval<Value>(),
To<T>{}))> Parse(
const Value& value,
To<std::optional<T>>) {
84 if (value.IsMissing() || value.IsNull()) {
87 return value.
template As<T>();
91std::optional<std::nullptr_t> Parse(
const Value&,
To<std::optional<std::nullptr_t>>) {
92 static_assert(!
sizeof(Value),
"optional<nullptr_t> is forbidden, check IsNull() instead");
96template <
typename T,
typename Value>
98 meta::kIsRange<T> && !meta::kIsMap<T> && !std::is_same_v<T, boost::uuids::uuid> &&
99 !std::is_convertible_v<T&, utils::impl::strong_typedef::StrongTypedefTag&>,
101Convert(
const Value& value, To<T>) {
102 if (value.IsMissing()) {
105 return impl::ParseArray<T>(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>(value, &impl::ConvertToExtractor<
typename T::mapped_type, Value>);
116template <
typename T,
typename Value>
117std::optional<T> Convert(
const Value& value,
To<std::optional<T>>) {
118 if (value.IsMissing() || value.IsNull()) {
121 return value.
template ConvertTo<T>();
124template <
class Value>
125std::optional<std::nullptr_t> Convert(
const Value&,
To<std::optional<std::nullptr_t>>) {
126 static_assert(!
sizeof(Value),
"optional<nullptr_t> is forbidden, check IsNull() instead");