10#include <unordered_map>
13#include <userver/utils/meta.hpp>
15#include <userver/formats/common/meta.hpp>
17USERVER_NAMESPACE_BEGIN
20struct StrongTypedefTag;
30template <
typename... Types,
typename StringBuilder>
31void WriteToStream(
const std::variant<Types...>& value, StringBuilder& sw) {
32 return std::visit([&sw](
const auto& item) { WriteToStream(item, sw); },
37template <
typename T,
typename StringBuilder>
44 WriteToStream(*value, sw);
52template <
class T,
class StringBuilder>
53constexpr inline bool kIsSerializeAllowedInWriteToStream =
true;
56template <
typename T,
typename StringBuilder>
57void WriteToStreamArray(
const T& value, StringBuilder& sw) {
58 typename StringBuilder::ArrayGuard guard(sw);
59 for (
const auto& item : value) {
61 WriteToStream(
static_cast<
const meta::RangeValueType<T>&>(item), sw);
66template <
typename T,
typename StringBuilder>
67void WriteToStreamDict(
const T& value, StringBuilder& sw) {
68 typename StringBuilder::ObjectGuard guard(sw);
69 for (
const auto& [key, item] : value) {
71 WriteToStream(item, sw);
81template <
typename T,
typename StringBuilder>
86 using Value =
typename StringBuilder::Value;
88 if constexpr (meta::kIsMap<T>) {
89 impl::WriteToStreamDict(value, sw);
90 }
else if constexpr (meta::kIsRange<T>) {
91 static_assert(!meta::kIsRecursiveRange<T>,
92 "Trying to log a recursive range, which can be dangerous. "
93 "(boost::filesystem::path?) Please implement WriteToStream "
95 impl::WriteToStreamArray(value, sw);
96 }
else if constexpr (
common::impl::kHasSerialize<Value, T>) {
99 impl::kIsSerializeAllowedInWriteToStream<T, StringBuilder>,
100 "SAX serialization falls back to Serialize call, which is not "
101 "allowed. Please implement WriteToStream for your type");
102 sw.WriteValue(Serialize(value,
serialize::
To<Value>{}));
104 static_assert(!
sizeof(T),
105 "Please implement WriteToStream or Serialize for your type");