15#include <userver/compiler/demangle.hpp> 
   16#include <userver/formats/parse/to.hpp> 
   18USERVER_NAMESPACE_BEGIN
 
   20namespace formats::
parse {
 
   22template <
typename ParseException, 
typename Variant, 
typename TypeA>
 
   23[[noreturn]] 
void ThrowVariantAmbiguousParse(
const std::string& path,
 
   24                                             std::type_index type_b) {
 
   27      "' is ambiguous, it is parseable into multiple variants of '" +
 
   28      compiler::GetTypeName<Variant>() + 
"', at least '" +
 
   29      compiler::GetTypeName<TypeA>() + 
"' and '" +
 
   33template <
class ParseException, 
typename Variant>
 
   34[[noreturn]] 
void ThrowVariantParseException(
const std::string& path) {
 
   35  throw ParseException(
"Value of '" + path + 
"' cannot be parsed as " +
 
   40template <
class T, 
class Value, 
typename Result>
 
   41void ParseVariantSingle(
const Value& value, std::optional<Result>& result) {
 
   43    const auto old_type = std::visit(
 
   44        [](
const auto& v) -> std::type_index { 
return typeid(v); }, *result);
 
   46      value.
template As<T>();
 
   47    } 
catch (
const std::exception&) {
 
   51    ThrowVariantAmbiguousParse<
typename Value::ParseException, Result, T>(
 
   52        value.GetPath(), old_type);
 
   56      result = value.
template As<T>();
 
   57    } 
catch (
const std::exception&) {
 
   64template <
class Value, 
typename... Types>
 
   65std::variant<Types...> Parse(
const Value& value,
 
   66                             formats::
parse::
To<std::variant<Types...>>) {
 
   67  std::optional<std::variant<Types...>> result;
 
   68  (impl::ParseVariantSingle<Types>(value, result), ...);
 
   71    ThrowVariantParseException<
typename Value::ParseException,
 
   72                               std::variant<Types...>>(value.GetPath());
 
   75  return std::move(*result);