22#include <userver/utils/constexpr_indices.hpp>
23#include <userver/utils/lazy_prvalue.hpp>
24#include <userver/utils/meta.hpp>
25#include <userver/utils/strong_typedef.hpp>
27#include <userver/dump/common.hpp>
28#include <userver/dump/meta.hpp>
29#include <userver/dump/meta_containers.hpp>
30#include <userver/dump/operations.hpp>
37template <
typename L,
typename R,
typename AP1,
typename AP2,
typename AP3>
42namespace multi_index {
44template <
typename Value,
typename IndexSpecifierList,
typename Allocator>
45class multi_index_container;
50using multi_index::multi_index_container;
55USERVER_NAMESPACE_BEGIN
61template <
typename L,
typename R,
typename... Args>
62using BoostBimap = boost::bimap<L, R, Args...>;
64template <
typename L,
typename R,
typename... Args>
65using BoostBimapLeftKey =
typename BoostBimap<L, R, Args...>::left_key_type;
67template <
typename L,
typename R,
typename... Args>
68using BoostBimapRightKey =
typename BoostBimap<L, R, Args...>::right_key_type;
71auto ReadLazyPrvalue(
Reader& reader) {
72 return utils::LazyPrvalue([&reader] {
return reader.Read<T>(); });
75[[noreturn]]
void ThrowInvalidVariantIndex(
const std::type_info& type, std::size_t index);
77template <
typename VariantType>
78VariantType ReadVariant(
Reader& reader, std::size_t index) {
79 static constexpr auto kVariantSize = std::variant_size_v<VariantType>;
80 std::optional<VariantType> result;
82 utils::WithConstexprIndex<kVariantSize>(index, [&](
auto index_constant) {
83 static constexpr auto kIndex =
decltype(index_constant)::value;
84 using Alternative = std::variant_alternative_t<kIndex, VariantType>;
86 result.emplace(std::in_place_index<kIndex>, reader.Read<Alternative>());
89 return std::move(*result);
96requires(IsContainer<T> && kIsWritable<meta::RangeValueType<T>>)
98 writer.Write(std::size(value));
99 for (
const auto& item : value) {
101 writer.Write(
static_cast<
const meta::RangeValueType<T>&>(item));
107requires(IsContainer<T> && kIsReadable<meta::RangeValueType<T>>)
111 if constexpr (meta::kIsReservable<T>) {
112 result.reserve(size);
114 for (std::size_t i = 0; i < size; ++i) {
115 dump::Insert(result, reader.Read<meta::RangeValueType<T>>());
121template <
typename T,
typename U>
122requires(kIsWritable<T> && kIsWritable<U>)
124 writer.Write(value.first);
125 writer.Write(value.second);
129template <
typename T,
typename U>
130requires(kIsReadable<T> && kIsReadable<U>)
132 return {reader.Read<T>(), reader.Read<U>()};
137requires kIsWritable<T>
139 writer.Write(value.has_value());
141 writer.Write(*value);
147requires kIsReadable<T>
152 return impl::ReadLazyPrvalue<T>(reader);
156template <
typename... Args>
157requires(
true && ... && kIsWritable<Args>)
159 writer.Write(value.index());
160 std::visit([&writer](
const auto& inner) { writer.Write(inner); }, value);
164template <
typename... Args>
165requires(
true && ... && (std::is_move_constructible_v<Args> && kIsReadable<Args>))
168 if (index >=
sizeof...(Args)) {
169 impl::ThrowInvalidVariantIndex(
typeid(std::variant<Args...>), index);
171 return impl::ReadVariant<std::variant<Args...>>(reader, index);
177requires kIsReadable<T>
179 return Read(reader,
To<T>{});
183template <
typename Tag,
typename T,
utils::StrongTypedefOps Ops>
184requires kIsWritable<T>
186 writer.Write(object.GetUnderlying());
190template <
typename Tag,
typename T,
utils::StrongTypedefOps Ops>
191requires kIsReadable<T>
193 return utils::StrongTypedef<Tag, T, Ops>{reader.Read<T>()};
198requires kIsWritable<T>
200 writer
.Write(static_cast<
bool>(ptr)
);
208requires kIsReadable<T>
213 return std::make_unique<T>(impl::ReadLazyPrvalue<T>(reader));
220requires kIsWritable<T>
222 writer
.Write(static_cast<
bool>(ptr)
);
232requires kIsReadable<T>
237 return std::make_shared<T>(impl::ReadLazyPrvalue<T>(reader));
241template <
typename L,
typename R,
typename... Args>
242requires(kIsWritable<impl::BoostBimapLeftKey<L, R, Args...>> && kIsWritable<impl::BoostBimapRightKey<L, R, Args...>>)
243void Write(
Writer& writer,
const boost::bimap<L, R, Args...>& map) {
244 writer.Write(map.size());
246 for (
const auto& [left, right] : map) {
253template <
typename L,
typename R,
typename... Args>
254requires(kIsReadable<impl::BoostBimapLeftKey<L, R, Args...>> && kIsReadable<impl::BoostBimapRightKey<L, R, Args...>>)
255boost::bimap<L, R, Args...>
Read(
Reader& reader,
To<boost::bimap<L, R, Args...>>) {
256 using BoostBimap = impl::BoostBimap<L, R, Args...>;
258 using BoostBimapLeftKey = impl::BoostBimapLeftKey<L, R, Args...>;
259 using BoostBimapRightKey = impl::BoostBimapRightKey<L, R, Args...>;
261 using BoostBimapSizeType =
typename BoostBimap::size_type;
266 const auto size = reader.Read<BoostBimapSizeType>();
267 for (BoostBimapSizeType i = 0; i < size; ++i) {
270 reader.Read<BoostBimapLeftKey>(),
271 reader.Read<BoostBimapRightKey>(),
279template <
typename T,
typename Index,
typename Alloc>
280requires kIsWritable<T>
281void Write(
Writer& writer,
const boost::multi_index_container<T, Index, Alloc>& container) {
282 writer.Write(container.
template get<0>().size());
283 for (
auto& item : container.
template get<0>()) {
289template <
typename T,
typename Index,
typename Alloc>
290requires kIsReadable<T>
291boost::multi_index_container<T, Index, Alloc>
Read(
Reader& reader,
To<boost::multi_index_container<T, Index, Alloc>>) {
293 boost::multi_index_container<T, Index, Alloc> container;
296 if constexpr (meta::kIsReservable<boost::multi_index_container<T, Index, Alloc>>) {
297 container.reserve(size);
300 for (std::size_t i = 0; i < size; ++i) {
301 container.insert(reader.Read<T>());