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
 
   23struct StrongTypedefTag;
 
   26namespace formats::
parse {
 
   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>
 
   69std::enable_if_t<common::kIsFormatValue<Value> && meta::kIsRange<T> &&
 
   71                     !std::is_same_v<T, boost::uuids::uuid> &&
 
   72                     !std::is_convertible_v<
 
   73                         T&, utils::impl::strong_typedef::StrongTypedefTag&>,
 
   75Parse(
const Value& value, To<T>) {
 
   76  return impl::ParseArray<T>(
 
   77      value, &impl::AsExtractor<meta::RangeValueType<T>, Value>);
 
   80template <
typename T, 
typename Value>
 
   81std::enable_if_t<common::kIsFormatValue<Value> && meta::kIsMap<T>, T> Parse(
 
   82    const Value& value, To<T>) {
 
   83  return impl::ParseObject<T>(
 
   84      value, &impl::AsExtractor<
typename T::mapped_type, Value>);
 
   87template <
typename T, 
typename Value>
 
   88std::optional<
decltype(Parse(std::declval<Value>(), 
To<T>{}))> Parse(
 
   89    const Value& value, 
To<std::optional<T>>) {
 
   90  if (value.IsMissing() || value.IsNull()) {
 
   93  return value.
template As<T>();
 
   97std::optional<std::nullptr_t> Parse(
const Value&,
 
   98                                    To<std::optional<std::nullptr_t>>) {
 
   99  static_assert(!
sizeof(Value),
 
  100                "optional<nullptr_t> is forbidden, check IsNull() instead");
 
  104template <
typename T, 
typename Value>
 
  105std::enable_if_t<meta::kIsRange<T> && !meta::kIsMap<T> &&
 
  106                     !std::is_same_v<T, boost::uuids::uuid> &&
 
  107                     !std::is_convertible_v<
 
  108                         T&, utils::impl::strong_typedef::StrongTypedefTag&>,
 
  110Convert(
const Value& value, To<T>) {
 
  111  if (value.IsMissing()) {
 
  114  return impl::ParseArray<T>(
 
  115      value, &impl::ConvertToExtractor<meta::RangeValueType<T>, Value>);
 
  118template <
typename T, 
typename Value>
 
  119std::enable_if_t<meta::kIsMap<T>, T> Convert(
const Value& value, To<T>) {
 
  120  if (value.IsMissing()) {
 
  123  return impl::ParseObject<T>(
 
  124      value, &impl::ConvertToExtractor<
typename T::mapped_type, Value>);
 
  127template <
typename T, 
typename Value>
 
  128std::optional<T> Convert(
const Value& value, 
To<std::optional<T>>) {
 
  129  if (value.IsMissing() || value.IsNull()) {
 
  132  return value.
template ConvertTo<T>();
 
  135template <
class Value>
 
  136std::optional<std::nullptr_t> Convert(
const Value&,
 
  137                                      To<std::optional<std::nullptr_t>>) {
 
  138  static_assert(!
sizeof(Value),
 
  139                "optional<nullptr_t> is forbidden, check IsNull() instead");