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);