userver
C++ Async Framework
Loading...
Searching...
No Matches
yaml_config.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/yaml_config/yaml_config.hpp
4
/// @brief @copybrief yaml_config::YamlConfig
5
6
#
include
<
chrono
>
7
#
include
<
cstdint
>
8
#
include
<
optional
>
9
#
include
<
string
>
10
#
include
<
string_view
>
11
12
#
include
<
userver
/
formats
/
json_fwd
.
hpp
>
13
#
include
<
userver
/
formats
/
parse
/
common
.
hpp
>
14
#
include
<
userver
/
formats
/
parse
/
common_containers
.
hpp
>
15
#
include
<
userver
/
formats
/
yaml
/
value
.
hpp
>
16
17
#
include
<
userver
/
yaml_config
/
iterator
.
hpp
>
18
19
USERVER_NAMESPACE_BEGIN
20
21
/// Utilities to work with static YAML config
22
namespace
yaml_config
{
23
24
using
Exception =
formats
::
yaml
::
Exception
;
25
using
ParseException =
formats
::
yaml
::
ParseException
;
26
27
/// @ingroup userver_formats userver_universal
28
///
29
/// @brief Datatype that represents YAML with substituted variables
30
///
31
/// If YAML has value that starts with an `$`, then such value is treated as
32
/// a variable from `config_vars`. For example if `config_vars` contains
33
/// `variable: 42` and the YAML is following:
34
/// @snippet universal/src/yaml_config/yaml_config_test.cpp sample vars
35
/// Then the result of `yaml["some_element"]["some"].As<int>()` is `42`.
36
///
37
/// If YAML key ends on `#env` and the mode is YamlConfig::Mode::kEnvAllowed
38
/// or YamlConfig::Mode::kEnvAndFileAllowed,
39
/// then the value of the key is searched in
40
/// environment variables of the process and returned as a string value. For example:
41
/// @snippet universal/src/yaml_config/yaml_config_test.cpp sample env
42
///
43
/// If YAML key ends on `#file` and the mode is
44
/// YamlConfig::Mode::kEnvAndFileAllowed, then the value of the key is the
45
/// content of specified YAML parsed file. For example:
46
/// @snippet universal/src/yaml_config/yaml_config_test.cpp sample read_file
47
///
48
/// If YAML key ends on `#fallback`, then the value of the key is used as a
49
/// fallback for environment, file and `$` variables. For example for the
50
/// following YAML with YamlConfig::Mode::kEnvAndFileAllowed:
51
/// @snippet universal/src/yaml_config/yaml_config_test.cpp sample multiple
52
/// The result of `yaml["some_element"]["some"].As<int>()` is the value of
53
/// `variable` from `config_vars` if it exists; otherwise the value is the
54
/// contents of the environment variable `SOME_ENV_VARIABLE` if it exists;
55
/// otherwise the value is the content of the file with name `file.yaml`;
56
/// otherwise the value is `100500`, from the fallback.
57
///
58
/// Another example:
59
/// @snippet universal/src/yaml_config/yaml_config_test.cpp sample env fallback
60
/// With YamlConfig::Mode::kEnvAllowed the result of
61
/// `yaml["some_element"]["some"].As<int>()` is the value of `ENV_NAME`
62
/// environment variable if it exists; otherwise it is `5`.
63
///
64
/// @note `#env`, `#file` and `#fallback` also work for keys inside
65
/// `config_vars`.
66
///
67
/// @warning YamlConfig::Mode::kEnvAllowed or
68
/// YamlConfig::Mode::kEnvAndFileAllowed should be used only on configs that
69
/// come from trusted environments. Otherwise, an attacker could create a
70
/// config and read any of your environment variables of files, including
71
/// variables that contain passwords and other sensitive data.
72
class
YamlConfig
{
73
public
:
74
struct
IterTraits
{
75
using
value_type =
YamlConfig
;
76
using
reference =
const
YamlConfig
&;
77
using
pointer =
const
YamlConfig
*;
78
};
79
struct
DefaultConstructed
{};
80
81
enum
class
Mode
{
82
kSecure,
/// < secure mode, without reading environment variables or files
83
kEnvAllowed
,
/// < allows reading of environment variables
84
kEnvAndFileAllowed
,
/// < allows reading of environment variables and
85
/// files
86
};
87
88
using
const_iterator = Iterator<
IterTraits
>;
89
using
Exception =
yaml_config
::Exception;
90
using
ParseException =
yaml_config
::ParseException;
91
92
YamlConfig() =
default
;
93
YamlConfig(
const
YamlConfig
&) =
default
;
94
YamlConfig
& operator=(
const
YamlConfig
&) =
default
;
95
96
/// YamlConfig = config + config_vars
97
YamlConfig
(
formats
::
yaml
::Value yaml,
formats
::
yaml
::Value config_vars,
Mode
mode =
Mode
::kSecure);
98
99
/// @brief Access member by key for read.
100
/// @throw TypeMismatchException if value is not missing and is not object.
101
YamlConfig
operator
[](std::string_view key)
const
;
102
103
/// @brief Access member by index for read.
104
/// @throw TypeMismatchException if value is not missing and is not array.
105
YamlConfig
operator
[](size_t index)
const
;
106
107
/// @brief Returns array size or object members count.
108
/// @throw TypeMismatchException if not array or object value.
109
std::size_t
GetSize
()
const
;
110
111
/// @brief Returns true if *this holds nothing. When `IsMissing()` returns
112
/// `true` any attempt to get the actual value or iterate over *this will
113
/// throw MemberMissingException.
114
bool
IsMissing
()
const
noexcept
;
115
116
/// @brief Returns true if *this holds 'null'.
117
bool
IsNull
()
const
noexcept
;
118
119
/// @brief Returns true if *this is convertible to bool.
120
bool
IsBool
()
const
noexcept
;
121
122
/// @brief Returns true if *this is convertible to int.
123
bool
IsInt
()
const
noexcept
;
124
125
/// @brief Returns true if *this is convertible to int64_t.
126
bool
IsInt64
()
const
noexcept
;
127
128
/// @brief Returns true if *this is convertible to uint64_t.
129
bool
IsUInt64
()
const
noexcept
;
130
131
/// @brief Returns true if *this is convertible to double.
132
bool
IsDouble
()
const
noexcept
;
133
134
/// @brief Returns true if *this is convertible to std::string.
135
bool
IsString
()
const
noexcept
;
136
137
/// @brief Returns true if *this is an array (Type::kArray).
138
bool
IsArray
()
const
noexcept
;
139
140
/// @brief Returns true if *this is a map (Type::kObject).
141
bool
IsObject
()
const
noexcept
;
142
143
/// @throw MemberMissingException if `this->IsMissing()`.
144
void
CheckNotMissing
()
const
;
145
146
/// @throw MemberMissingException if `*this` is not an array.
147
void
CheckArray
()
const
;
148
149
/// @throw MemberMissingException if `*this` is not an array or Null.
150
void
CheckArrayOrNull
()
const
;
151
152
/// @throw TypeMismatchException if `*this` is not a map or Null.
153
void
CheckObjectOrNull
()
const
;
154
155
/// @throw TypeMismatchException if `*this` is not a map.
156
void
CheckObject
()
const
;
157
158
/// @throw TypeMismatchException if `*this` is not convertible to std::string.
159
void
CheckString
()
const
;
160
161
/// @throw TypeMismatchException if `*this` is not a map, array or Null.
162
void
CheckObjectOrArrayOrNull
()
const
;
163
164
/// @brief Returns value of *this converted to T.
165
/// @throw Anything derived from std::exception.
166
template
<
typename
T>
167
auto
As
()
const
;
168
169
/// @brief Returns value of *this converted to T or T(args) if
170
/// this->IsMissing().
171
/// @throw Anything derived from std::exception.
172
template
<
typename
T,
typename
First,
typename
... Rest>
173
auto
As
(First&& default_arg, Rest&&... more_default_args)
const
;
174
175
/// @brief Returns value of *this converted to T or T() if this->IsMissing().
176
/// @throw Anything derived from std::exception.
177
/// @note Use as `value.As<T>({})`
178
template
<
typename
T>
179
auto
As
(
DefaultConstructed
)
const
;
180
181
/// @brief Returns true if *this holds a `key`.
182
/// @throw Nothing.
183
bool
HasMember
(std::string_view key)
const
;
184
185
/// @brief Returns full path to this value.
186
std::string
GetPath
()
const
;
187
188
/// @brief Returns an iterator to the beginning of the held array or map.
189
/// @throw TypeMismatchException is the value of *this is not a map, array
190
/// or Null.
191
const_iterator
begin
()
const
;
192
193
/// @brief Returns an iterator to the end of the held array or map.
194
/// @throw TypeMismatchException is the value of *this is not a map, array
195
/// or Null.
196
const_iterator
end
()
const
;
197
198
/// @brief Get the plain Yaml without substitutions. It may contain raw references.
199
/// @deprecated Either use the current `YamlConfig` as a formats value, or use `.As<formats::json::Value>()`
200
/// to get the correct treatment for `$vars`, `#fallback`, `#env` and `#file`.
201
formats
::
yaml
::Value
GetRawYamlWithoutConfigVars
()
const
;
202
203
formats
::
yaml
::Value GetRawConfigVars()
const
;
204
205
private
:
206
formats
::
yaml
::Value yaml_;
207
formats
::
yaml
::Value config_vars_;
208
Mode
mode_{
Mode
::kSecure};
209
210
friend
bool
Parse(
const
YamlConfig
& value,
formats
::
parse
::
To
<
bool
>);
211
friend
int64_t Parse(
const
YamlConfig
& value,
formats
::
parse
::
To
<int64_t>);
212
friend
uint64_t Parse(
const
YamlConfig
& value,
formats
::
parse
::
To
<uint64_t>);
213
friend
double
Parse(
const
YamlConfig
& value,
formats
::
parse
::
To
<
double
>);
214
friend
std::string Parse(
const
YamlConfig
& value,
formats
::
parse
::
To
<std::string>);
215
friend
formats
::
yaml
::Value
Parse
(
const
YamlConfig
& value,
formats
::
parse
::
To
<
formats
::
yaml
::Value>);
216
};
217
218
using
Value =
YamlConfig
;
219
220
template
<
typename
T>
221
auto
YamlConfig
::
As
()
const
{
222
static_assert
(
223
formats
::
common
::impl::kHasParse<
YamlConfig
, T>,
224
"There is no `Parse(const yaml_config::YamlConfig&, "
225
"formats::parse::To<T>)`"
226
"in namespace of `T` or `formats::parse`. "
227
"Probably you forgot to include the "
228
"<userver/formats/parse/common_containers.hpp> or you "
229
"have not provided a `Parse` function overload."
230
);
231
232
return
Parse(*
this
,
formats
::
parse
::
To
<T>{});
233
}
234
235
bool
Parse(
const
YamlConfig
& value,
formats
::
parse
::
To
<
bool
>);
236
237
int64_t Parse(
const
YamlConfig
& value,
formats
::
parse
::
To
<int64_t>);
238
239
uint64_t Parse(
const
YamlConfig
& value,
formats
::
parse
::
To
<uint64_t>);
240
241
double
Parse(
const
YamlConfig
& value,
formats
::
parse
::
To
<
double
>);
242
243
std::string Parse(
const
YamlConfig
& value,
formats
::
parse
::
To
<std::string>);
244
245
template
<
typename
T,
typename
First,
typename
... Rest>
246
auto
YamlConfig
::
As
(First&& default_arg, Rest&&... more_default_args)
const
{
247
if
(
IsMissing
(
)
) {
248
// intended raw ctor call, sometimes casts
249
// NOLINTNEXTLINE(google-readability-casting)
250
return
decltype
(As<T>())(std::forward<First>(default_arg), std::forward<Rest>(more_default_args)...);
251
}
252
return
As<T>();
253
}
254
255
template
<
typename
T>
256
auto
YamlConfig
::
As
(
YamlConfig
::
DefaultConstructed
)
const
{
257
return
IsMissing
(
)
?
decltype
(As<T>())() : As<T>();
258
}
259
260
/// @brief Wrapper for handy python-like iteration over a map
261
///
262
/// @code
263
/// for (const auto& [name, value]: Items(map)) ...
264
/// @endcode
265
using
formats
::
common
::Items;
266
267
/// @brief Parses duration from string, understands suffixes: ms, s, m, h, d
268
/// @throws On invalid type, invalid string format, and if the duration is not a
269
/// whole amount of seconds
270
std::chrono::seconds
Parse
(
const
YamlConfig
& value,
formats
::
parse
::
To
<std::chrono::seconds>);
271
272
/// @brief Parses duration from string, understands suffixes: ms, s, m, h, d
273
/// @throws On invalid type and invalid string format
274
std::chrono::milliseconds
Parse
(
const
YamlConfig
& value,
formats
::
parse
::
To
<std::chrono::milliseconds>);
275
276
/// @brief Converts YAML to JSON
277
/// @throws yaml_config::YamlConfig::Exception if `value.IsMissing()`
278
formats
::
json
::
Value
Parse
(
const
YamlConfig
& value,
formats
::
parse
::
To
<
formats
::
json
::
Value
>);
279
280
/// @brief Converts YAML to YAML. Returns self
281
inline
YamlConfig
Parse
(
const
YamlConfig
& value,
formats
::
parse
::
To
<
YamlConfig
>) {
return
value; }
282
283
/// @brief Flattens a YamlConfig, applying all of its special syntax
284
/// @throws yaml_config::YamlConfig::Exception if `value.IsMissing()`
285
formats
::
yaml
::Value
Parse
(
const
YamlConfig
& value,
formats
::
parse
::
To
<
formats
::
yaml
::Value>);
286
287
}
// namespace yaml_config
288
289
USERVER_NAMESPACE_END
userver
yaml_config
yaml_config.hpp
Generated on Wed Jan 14 2026 19:58:45 for userver by
Doxygen
1.13.2