5#include <unordered_set>
7#include <userver/formats/json/value.hpp>
8#include <userver/formats/parse/common_containers.hpp>
9#include <userver/formats/serialize/common_containers.hpp>
10#include <userver/utils/impl/transparent_hash.hpp>
11#include <userver/utils/internal_tag_fwd.hpp>
13USERVER_NAMESPACE_BEGIN
15namespace dynamic_config {
20 formats::
json::Value Get(std::string_view name)
const;
22 bool Has(std::string_view name)
const;
23 void Set(std::string name, formats::
json::Value);
24 void Parse(
const std::string& json,
bool empty_ok);
27 void MergeOrAssign(DocsMap&& source);
28 void MergeMissing(
const DocsMap& source);
30 std::unordered_set<std::string> GetNames()
const;
31 std::string AsJsonString()
const;
32 bool AreContentsEqual(
const DocsMap& other)
const;
38 void SetConfigsExpectedToBeUsed(
39 utils::impl::TransparentSet<std::string> configs,
utils::InternalTag);
41 const utils::impl::TransparentSet<std::string>& GetConfigsExpectedToBeUsed(
42 utils::InternalTag)
const;
46 utils::impl::TransparentMap<std::string, formats::json::Value> docs_;
47 mutable utils::impl::TransparentSet<std::string> configs_to_be_used_;
53 Value(
const std::string& name,
const DocsMap& docs_map)
54 : value_(docs_map.Get(name).As<T>()) {}
56 operator
const T&()
const {
return value_; }
58 const T& Get()
const {
return value_; }
59 const T* operator->()
const {
return &value_; }
65extern const std::string kValueDictDefaultName;
69[[noreturn]]
void ThrowNoValueException(std::string_view dict_name,
70 std::string_view key);
74template <
typename ValueType>
75class ValueDict
final {
77 using DictType = utils::impl::TransparentMap<std::string, ValueType>;
78 using const_iterator =
typename DictType::const_iterator;
79 using iterator = const_iterator;
80 using value_type =
typename DictType::value_type;
81 using key_type = std::string;
82 using mapped_type = ValueType;
84 ValueDict() =
default;
86 ValueDict(std::initializer_list<value_type> contents) : dict_(contents) {}
88 ValueDict(DictType dict) : dict_(std::move(dict)) {}
90 ValueDict(std::string name, DictType dict)
91 : name_(std::move(name)), dict_(std::move(dict)) {}
94 ValueDict(std::string name,
const DocsMap& docs_map)
95 : name_(std::move(name)),
96 dict_(docs_map.Get(name_).
template As<DictType>()) {}
98 bool HasDefaultValue()
const {
return HasValue(kValueDictDefaultName); }
100 bool HasValue(std::string_view key)
const {
101 return utils::impl::FindTransparent(dict_, key) != dict_.end();
104 const ValueType& GetDefaultValue()
const {
105 const auto it = dict_.find(kValueDictDefaultName);
106 if (it == dict_.end()) {
107 impl::ThrowNoValueException(name_, kValueDictDefaultName);
112 const ValueType& operator[](std::string_view key)
const {
113 auto it = utils::impl::FindTransparent(dict_, key);
114 if (it == dict_.end()) {
115 it = dict_.find(kValueDictDefaultName);
116 if (it == dict_.end()) {
117 impl::ThrowNoValueException(name_, key);
123 template <
typename StringType>
124 const ValueType& operator[](
const std::optional<StringType>& key)
const {
125 if (key)
return (*
this)[*key];
126 return GetDefaultValue();
129 const ValueType& Get(std::string_view key)
const {
return (*
this)[key]; }
131 template <
typename StringType>
132 const ValueType& Get(
const std::optional<StringType>& key)
const {
136 std::optional<ValueType> GetOptional(std::string_view key)
const {
137 auto it = utils::impl::FindTransparent(dict_, key);
138 if (it == dict_.end()) {
139 it = dict_.find(kValueDictDefaultName);
140 if (it == dict_.end())
return std::nullopt;
150 Set(kValueDictDefaultName, std::move(value));
156 template <
typename StringType>
157 void Set(StringType&& key, ValueType value) {
158 utils::impl::TransparentInsertOrAssign(dict_, std::forward<StringType>(key),
162 auto begin()
const {
return dict_.begin(); }
164 auto end()
const {
return dict_.end(); }
166 const std::string& GetName()
const {
return name_; }
168 bool operator==(
const ValueDict& r)
const {
return dict_ == r.dict_; }
170 bool operator!=(
const ValueDict& r)
const {
return !(*
this == r); }
178ValueDict<T> Parse(
const formats::
json::Value& value,
179 formats::
parse::
To<ValueDict<T>>) {
180 return ValueDict<T>{value.GetPath(),
181 value.As<
typename ValueDict<T>::DictType>()};