userver: userver/utils/statistics/labels.hpp Source File
Loading...
Searching...
No Matches
labels.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utils/statistics/labels.hpp
4/// @brief Owning and non owning labels representations.
5
6#include <string>
7#include <string_view>
8#include <type_traits>
9
10#include <fmt/format.h>
11
12#include <userver/utils/assert.hpp>
13
14USERVER_NAMESPACE_BEGIN
15
16namespace utils::statistics {
17
18class Label;
19
20/// @ingroup userver_universal
21///
22/// @brief Non owning label name+value storage.
23class LabelView final {
24public:
25 LabelView() = delete;
26 LabelView(Label&& label) = delete;
27 explicit LabelView(const Label& label);
28 constexpr LabelView(std::string_view name, std::string_view value)
29 : name_(name),
30 value_(value)
31 {
32 UINVARIANT(!name_.empty(), "The label name must not be empty.");
33 }
34
35 template <class T, std::enable_if_t<std::is_arithmetic_v<T>>* = nullptr>
36 constexpr LabelView(std::string_view, T) {
37 static_assert(!sizeof(T), "Labels should not be arithmetic values, only strings!");
38 }
39
40 constexpr explicit operator bool() const { return !name_.empty(); }
41
42 constexpr std::string_view Name() const { return name_; }
43 constexpr std::string_view Value() const { return value_; }
44
45private:
46 std::string_view name_{};
47 std::string_view value_{};
48};
49
50bool operator<(const LabelView& x, const LabelView& y) noexcept;
51bool operator==(const LabelView& x, const LabelView& y) noexcept;
52bool operator!=(const LabelView& x, const LabelView& y) noexcept;
53
54/// @ingroup userver_universal
55///
56/// @brief Label name+value storage.
57class Label final {
58public:
59 Label() = default;
60 explicit Label(LabelView view);
61 Label(std::string name, std::string value);
62
63 template <class T, std::enable_if_t<std::is_arithmetic_v<T>>* = nullptr>
64 Label(std::string, T) {
65 static_assert(!sizeof(T), "Labels should not be arithmetic values, only strings!");
66 }
67
68 explicit operator bool() const { return !name_.empty(); }
69 explicit operator LabelView() const { return {name_, value_}; }
70
71 const std::string& Name() const { return name_; }
72 const std::string& Value() const& { return value_; }
73 std::string& Value() & { return value_; }
74 std::string&& Value() && { return std::move(value_); }
75
76private:
77 std::string name_;
78 std::string value_;
79};
80
81bool operator<(const Label& x, const Label& y) noexcept;
82bool operator==(const Label& x, const Label& y) noexcept;
83bool operator!=(const Label& x, const Label& y) noexcept;
84
85/// @ingroup userver_universal
86///
87/// @brief View over a continuous range of LabelView.
88class LabelsSpan final {
89public:
90 using iterator = const LabelView*;
91 using const_iterator = const LabelView*;
92
93 LabelsSpan() = default;
94 LabelsSpan(const LabelView* begin, const LabelView* end) noexcept;
95 LabelsSpan(std::initializer_list<LabelView> il) noexcept : LabelsSpan(il.begin(), il.end()) {}
96
97 template <
98 class Container,
99 std::enable_if_t<
100 std::is_same_v<
101 decltype(*(std::declval<const Container&>().data() + std::declval<const Container&>().size())),
102 const LabelView&>,
103 int> = 0>
104 /*implicit*/ LabelsSpan(const Container& cont) noexcept : LabelsSpan(cont.data(), cont.data() + cont.size()) {}
105
106 const LabelView* begin() const noexcept { return begin_; }
107 const LabelView* end() const noexcept { return end_; }
108 std::size_t size() const noexcept { return end_ - begin_; }
109 bool empty() const noexcept { return end_ == begin_; }
110
111private:
112 const LabelView* begin_{nullptr};
113 const LabelView* end_{nullptr};
114};
115
116} // namespace utils::statistics
117
118USERVER_NAMESPACE_END
119
120template <>
121struct fmt::formatter<USERVER_NAMESPACE::utils::statistics::LabelView> {
122 constexpr static auto parse(format_parse_context& ctx) { return ctx.begin(); }
123
124 template <typename FormatContext>
125 auto format(USERVER_NAMESPACE::utils::statistics::LabelView value, FormatContext& ctx) const {
126 return fmt::format_to(ctx.out(), "{}={}", value.Name(), value.Value());
127 }
128};
129
130template <>
131struct fmt::formatter<USERVER_NAMESPACE::utils::statistics::Label>
132 : public fmt::formatter<USERVER_NAMESPACE::utils::statistics::LabelView> {
133 template <typename FormatContext>
134 auto format(const USERVER_NAMESPACE::utils::statistics::Label& value, FormatContext& ctx) const {
135 return formatter<USERVER_NAMESPACE::utils::statistics::LabelView>::format(
136 USERVER_NAMESPACE::utils::statistics::LabelView{value},
137 ctx
138 );
139 }
140};
141
142template <>
143struct fmt::formatter<USERVER_NAMESPACE::utils::statistics::LabelsSpan> {
144 constexpr static auto parse(format_parse_context& ctx) { return ctx.begin(); }
145
146 fmt::format_context::iterator format(
147 USERVER_NAMESPACE::utils::statistics::LabelsSpan value,
148 fmt::format_context& ctx
149 ) const;
150};