9#include <userver/formats/json/value.hpp>
10#include <userver/formats/parse/common_containers.hpp>
11#include <userver/formats/serialize/common_containers.hpp>
12#include <userver/utils/impl/transparent_hash.hpp>
14USERVER_NAMESPACE_BEGIN
23[[noreturn]]
void ThrowNoValueException(std::string_view dict_name,
24 std::string_view key);
42template <
typename ValueType>
43class DefaultDict final {
45 using DictType = utils::impl::TransparentMap<std::string, ValueType>;
46 using const_iterator =
typename DictType::const_iterator;
47 using iterator = const_iterator;
48 using value_type =
typename DictType::value_type;
49 using key_type = std::string;
50 using mapped_type = ValueType;
52 std::initializer_list<std::pair<std::string_view, ValueType>>;
54 DefaultDict() =
default;
56 DefaultDict(init_list contents) : dict_(contents.begin(), contents.end()) {}
58 DefaultDict(DictType dict) : dict_(std::move(dict)) {}
60 DefaultDict(std::string name, init_list contents)
61 : name_(std::move(name)), dict_(contents.begin(), contents.end()) {}
63 DefaultDict(std::string name, DictType dict)
64 : name_(std::move(name)), dict_(std::move(dict)) {}
69 return HasValue(kDefaultDictDefaultName);
73 bool HasValue(std::string_view key)
const noexcept {
74 return utils::impl::FindTransparent(dict_, key) != dict_.end();
81 utils::impl::FindTransparent(dict_, kDefaultDictDefaultName);
82 if (it == dict_.end()) {
83 impl::ThrowNoValueException(name_, kDefaultDictDefaultName);
91 const ValueType&
operator[](std::string_view key)
const {
92 auto it = utils::impl::FindTransparent(dict_, key);
93 if (it == dict_.end()) {
94 it = utils::impl::FindTransparent(dict_, kDefaultDictDefaultName);
95 if (it == dict_.end()) {
96 impl::ThrowNoValueException(name_, key);
103 template <
typename StringType>
104 const ValueType&
operator[](
const std::optional<StringType>& key)
const {
109 const ValueType& Get(std::string_view key)
const {
return (*
this)[key]; }
112 template <
typename StringType>
113 const ValueType&
Get(
const std::optional<StringType>& key)
const {
120 std::optional<ValueType>
GetOptional(std::string_view key)
const {
121 auto it = utils::impl::FindTransparent(dict_, key);
122 if (it == dict_.end()) {
123 it = utils::impl::FindTransparent(dict_, kDefaultDictDefaultName);
124 if (it == dict_.end())
return std::nullopt;
135 Set(kDefaultDictDefaultName, std::move(value));
142 template <
typename StringType>
143 void Set(StringType&& key, ValueType value) {
144 utils::impl::TransparentInsertOrAssign(dict_, std::forward<StringType>(key),
148 auto begin()
const noexcept {
return dict_.begin(); }
150 auto end()
const noexcept {
return dict_.end(); }
152 const std::string& GetName()
const noexcept {
return name_; }
154 bool operator==(
const DefaultDict& r)
const noexcept {
155 return dict_ == r.dict_;
158 bool operator!=(
const DefaultDict& r)
const noexcept {
return !(*
this == r); }
165template <
typename Value,
typename T>
166std::enable_if_t<formats::common::kIsFormatValue<Value>, DefaultDict<T>> Parse(
167 const Value& value, formats::parse::To<DefaultDict<T>>) {
168 return DefaultDict<T>{value.GetPath(),
169 value.
template As<
typename DefaultDict<T>::DictType>()};