userver: userver/formats/parse/boost_variant.hpp Source File
Loading...
Searching...
No Matches
boost_variant.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/formats/parse/boost_variant.hpp
4/// @brief Ineffective but generic parser for boost::variant type
5///
6/// Parsing is performed for each of the N alternatives in variant, N-1
7/// exceptions is thrown and caught during the parsing.
8///
9/// @ingroup userver_universal userver_formats_parse
10
11#include <boost/variant/variant.hpp>
12
13#include <userver/compiler/demangle.hpp>
14#include <userver/formats/parse/variant.hpp>
15
16USERVER_NAMESPACE_BEGIN
17
18namespace formats::parse {
19
20namespace impl {
21template <class T, class Value, typename Result>
22void ParseBoostVariantSingle(const Value& value,
23 std::optional<Result>& result) {
24 if (result) {
25 std::type_index old_type = result->type();
26 try {
27 value.template As<T>();
28 } catch (const std::exception&) {
29 return;
30 }
31
32 ThrowVariantAmbiguousParse<typename Value::ParseException, Result, T>(
33 value.GetPath(), old_type);
34 } else {
35 // No result yet
36 try {
37 result = value.template As<T>();
38 } catch (const std::exception&) {
39 }
40 }
41}
42
43} // namespace impl
44
45template <class Value, typename... Types>
46boost::variant<Types...> Parse(const Value& value,
47 formats::parse::To<boost::variant<Types...>>) {
48 std::optional<boost::variant<Types...>> result;
49 (impl::ParseBoostVariantSingle<Types>(value, result), ...);
50
51 if (!result) {
52 ThrowVariantParseException<typename Value::ParseException,
53 boost::variant<Types...>>(value.GetPath());
54 }
55
56 return std::move(*result);
57}
58
59} // namespace formats::parse
60
61USERVER_NAMESPACE_END