userver: userver/formats/bson/value_builder.hpp Source File
Loading...
Searching...
No Matches
value_builder.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/formats/bson/value_builder.hpp
4/// @brief @copybrief formats::bson::ValueBuilder
5
6#include <chrono>
7#include <cstddef>
8#include <cstdint>
9#include <string>
10#include <string_view>
11
12#include <userver/formats/bson/document.hpp>
13#include <userver/formats/bson/iterator.hpp>
14#include <userver/formats/bson/types.hpp>
15#include <userver/formats/bson/value.hpp>
16#include <userver/formats/common/meta.hpp>
17#include <userver/formats/common/transfer_tag.hpp>
18#include <userver/formats/common/type.hpp>
19#include <userver/utils/strong_typedef.hpp>
20
21USERVER_NAMESPACE_BEGIN
22
23namespace formats::bson {
24
25// clang-format off
26
27/// @brief Builder for BSON.
28///
29/// Class provides methods for building BSON. For read only access to the
30/// existing BSON values use formats::bson::Value.
31///
32/// ## Example usage:
33///
34/// @snippet formats/bson/value_builder_test.cpp Sample formats::bson::ValueBuilder usage
35///
36/// ## Customization example:
37///
38/// @snippet formats/bson/value_builder_test.cpp Sample Customization formats::bson::ValueBuilder usage
39///
40/// @see @ref scripts/docs/en/userver/formats.md
41
42// clang-format on
43
45public:
46 using iterator = Iterator<ValueBuilder>;
47 using Type = formats::common::Type;
48
49 /// Constructs a `null` value (may be used as either document or array)
51
52 /// Constructs a value with the predefined type
54
55 /// @cond
56 /// Constructor from implementation, internal use only
57 explicit ValueBuilder(impl::ValueImplPtr);
58 /// @endcond
59
60 ValueBuilder(const ValueBuilder& other);
61 // NOLINTNEXTLINE(performance-noexcept-move-constructor)
62 ValueBuilder(ValueBuilder&& other);
63 ValueBuilder& operator=(const ValueBuilder& other);
64 // NOLINTNEXTLINE(performance-noexcept-move-constructor)
65 ValueBuilder& operator=(ValueBuilder&& other);
66
67 /// @{
68 /// Efficiently constructs a copy of an existing value
70 ValueBuilder(const Document&);
71 // NOLINTNEXTLINE(performance-noexcept-move-constructor)
72 ValueBuilder(Value&&);
73 // NOLINTNEXTLINE(performance-noexcept-move-constructor)
74 ValueBuilder(Document&&);
75 /// @}
76
77 /// @name Concrete type constructors
78 /// @{
79 /* implicit */ ValueBuilder(std::nullptr_t);
80 /* implicit */ ValueBuilder(bool);
81 /* implicit */ ValueBuilder(int);
82 /* implicit */ ValueBuilder(unsigned int);
83 /* implicit */ ValueBuilder(long);
84 /* implicit */ ValueBuilder(unsigned long);
85 /* implicit */ ValueBuilder(long long);
86 /* implicit */ ValueBuilder(unsigned long long);
87 /* implicit */ ValueBuilder(double);
88 /* implicit */ ValueBuilder(const char*);
89 /* implicit */ ValueBuilder(char*);
90 /* implicit */ ValueBuilder(std::string);
91 /* implicit */ ValueBuilder(std::string_view);
92 /* implicit */ ValueBuilder(const std::chrono::system_clock::time_point&);
93 /* implicit */ ValueBuilder(const Oid&);
94 /* implicit */ ValueBuilder(Binary);
95 /* implicit */ ValueBuilder(const Decimal128&);
96 /* implicit */ ValueBuilder(MinKey);
97 /* implicit */ ValueBuilder(MaxKey);
98 /* implicit */ ValueBuilder(const Timestamp&);
99 /// @}
100
101 /// Universal constructor using Serialize
102 template <typename T>
103 ValueBuilder(const T& t)
104 : ValueBuilder(DoSerialize(t))
105 {}
106
107 /// @brief Transfers the `ValueBuilder` object
108 /// @see formats::common::TransferTag for the transfer semantics
109 ValueBuilder(common::TransferTag, ValueBuilder&&) noexcept;
110
111 /// @brief Retrieves or creates document field by name
112 /// @throws TypeMismatchException if value is not a document or `null`
113 ValueBuilder operator[](const std::string& name);
114
115 /// @brief Emplaces new member w/o a check whether the key already exists.
116 /// @warning May create invalid BSON with duplicate key.
117 /// @throw `TypeMismatchException` if not object or null value.
118 void EmplaceNocheck(std::string_view key, ValueBuilder value);
119
120 /// @brief Access member by key for modification.
121 /// @throw `TypeMismatchException` if not object or null value.
122 template <
123 typename Tag,
124 utils::StrongTypedefOps Ops,
125 typename Enable = std::enable_if_t<utils::IsStrongTypedefLoggable(Ops)>>
126 ValueBuilder operator[](const utils::StrongTypedef<Tag, std::string, Ops>& name);
127
128 /// @brief Retrieves array element by index
129 /// @throws TypeMismatchException if value is not an array or `null`
130 /// @throws OutOfBoundsException if index is invalid for the array
131 ValueBuilder operator[](uint32_t index);
132
133 /// @brief Remove key from object. If key is missing nothing happens.
134 /// @throw `TypeMismatchException` if value is not an object.
135 void Remove(const std::string& key);
136
137 /// @brief Returns an iterator to the first array element/document field
138 /// @throws TypeMismatchException if value is not a document, array or `null`
139 iterator begin();
140
141 /// @brief Returns an iterator following the last array element/document field
142 /// @throws TypeMismatchException if value is not a document, array or `null`
143 iterator end();
144
145 /// @brief Returns whether the document/array is empty
146 /// @throws TypeMismatchException if value is not a document, array or `null`
147 /// @note Returns `true` for `null`.
148 bool IsEmpty() const;
149
150 /// @brief Returns true if *this holds a Null (Type::kNull).
151 bool IsNull() const noexcept;
152
153 /// @brief Returns true if *this is convertible to bool.
154 bool IsBool() const noexcept;
155
156 /// @brief Returns true if *this is convertible to int.
157 bool IsInt() const noexcept;
158
159 /// @brief Returns true if *this is convertible to int64_t.
160 bool IsInt64() const noexcept;
161
162 /// @brief Returns true if *this is convertible to uint64_t.
163 bool IsUInt64() const noexcept;
164
165 /// @brief Returns true if *this is convertible to double.
166 bool IsDouble() const noexcept;
167
168 /// @brief Returns true if *this is convertible to std::string.
169 bool IsString() const noexcept;
170
171 /// @brief Returns true if *this is an array (Type::kArray).
172 bool IsArray() const noexcept;
173
174 /// @brief Returns true if *this holds a document (BSON_TYPE_DOCUMENT).
175 bool IsObject() const noexcept;
176
177 /// @brief Returns the number of elements in a document/array
178 /// @throws TypeMismatchException if value is not a document, array or `null`
179 /// @note Returns 0 for `null`.
180 uint32_t GetSize() const;
181
182 /// @brief Checks whether the document has a field
183 /// @param name field name
184 /// @throws TypeMismatchExcepiton if value is not a document or `null`
185 bool HasMember(const std::string& name) const;
186
187 /// @brief Creates or resizes the array
188 /// @param size new size
189 /// @throws TypeMismatchException if value is not an array or `null`
190 void Resize(uint32_t size);
191
192 /// @brief Appends an element to the array, possibly creating one
193 /// @param elem element to append
194 /// @throws TypeMismatchException if value is not an array or `null`
195 void PushBack(ValueBuilder&& elem);
196
197 /// @brief Retrieves a compiled value from the builder.
198 /// After calling this method the builder is in unspecified state.
200
201private:
202 void Assign(const impl::ValueImplPtr&);
203 void Assign(impl::ValueImplPtr&&);
204
205 template <typename T>
206 static Value DoSerialize(const T& t);
207
208 impl::ValueImplPtr impl_;
209};
210
211template <typename Tag, utils::StrongTypedefOps Ops, typename Enable>
212ValueBuilder ValueBuilder::operator[](const utils::StrongTypedef<Tag, std::string, Ops>& name) {
213 return (*this)[name.GetUnderlying()];
214}
215
216template <typename T>
217Value ValueBuilder::DoSerialize(const T& t) {
218 static_assert(
219 formats::common::impl::kHasSerialize<Value, T>,
220 "There is no `Serialize(const T&, formats::serialize::To<bson::Value>)` "
221 "in namespace of `T` or `formats::serialize`. "
222 ""
223 "Probably you forgot to include the "
224 "<userver/formats/serialize/common_containers.hpp> or you "
225 "have not provided a `Serialize` function overload."
226 );
227
228 return Serialize(t, formats::serialize::To<Value>());
229}
230
231} // namespace formats::bson
232
233USERVER_NAMESPACE_END