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, std::optional<Result>& result) {
23 if (result) {
24 std::type_index old_type = result->type();
25 try {
26 value.template As<T>();
27 } catch (const std::exception&) {
28 return;
29 }
30
31 ThrowVariantAmbiguousParse<typename Value::ParseException, Result, T>(value.GetPath(), old_type);
32 } else {
33 // No result yet
34 try {
35 result = value.template As<T>();
36 } catch (const std::exception&) {
37 }
38 }
39}
40
41} // namespace impl
42
43template <class Value, typename... Types>
44boost::variant<Types...> Parse(const Value& value, formats::parse::To<boost::variant<Types...>>) {
45 std::optional<boost::variant<Types...>> result;
46 (impl::ParseBoostVariantSingle<Types>(value, result), ...);
47
48 if (!result) {
49 ThrowVariantParseException<typename Value::ParseException, boost::variant<Types...>>(value.GetPath());
50 }
51
52 return std::move(*result);
53}
54
55} // namespace formats::parse
56
57USERVER_NAMESPACE_END