userver: userver/formats/bson/value_builder.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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
45 public:
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
53 ValueBuilder(formats::common::Type 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) : ValueBuilder(DoSerialize(t)) {}
104
105 /// @brief Transfers the `ValueBuilder` object
106 /// @see formats::common::TransferTag for the transfer semantics
107 ValueBuilder(common::TransferTag, ValueBuilder&&) noexcept;
108
109 /// @brief Retrieves or creates document field by name
110 /// @throws TypeMismatchException if value is not a document or `null`
111 ValueBuilder operator[](const std::string& name);
112
113 /// @brief Emplaces new member w/o a check whether the key already exists.
114 /// @warning May create invalid BSON with duplicate key.
115 /// @throw `TypeMismatchException` if not object or null value.
116 void EmplaceNocheck(std::string_view key, ValueBuilder value);
117
118 /// @brief Access member by key for modification.
119 /// @throw `TypeMismatchException` if not object or null value.
120 template <
121 typename Tag, utils::StrongTypedefOps Ops,
122 typename Enable = std::enable_if_t<utils::IsStrongTypedefLoggable(Ops)>>
124 const utils::StrongTypedef<Tag, std::string, Ops>& name);
125
126 /// @brief Retrieves array element by index
127 /// @throws TypeMismatchException if value is not an array or `null`
128 /// @throws OutOfBoundsException if index is invalid for the array
129 ValueBuilder operator[](uint32_t index);
130
131 /// @brief Remove key from object. If key is missing nothing happens.
132 /// @throw `TypeMismatchException` if value is not an object.
133 void Remove(const std::string& key);
134
135 /// @brief Returns an iterator to the first array element/document field
136 /// @throws TypeMismatchException if value is not a document, array or `null`
138
139 /// @brief Returns an iterator following the last array element/document field
140 /// @throws TypeMismatchException if value is not a document, array or `null`
142
143 /// @brief Returns whether the document/array is empty
144 /// @throws TypeMismatchException if value is not a document, array or `null`
145 /// @note Returns `true` for `null`.
146 bool IsEmpty() const;
147
148 /// @brief Returns true if *this holds a Null (Type::kNull).
149 bool IsNull() const noexcept;
150
151 /// @brief Returns true if *this is convertible to bool.
152 bool IsBool() const noexcept;
153
154 /// @brief Returns true if *this is convertible to int.
155 bool IsInt() const noexcept;
156
157 /// @brief Returns true if *this is convertible to int64_t.
158 bool IsInt64() const noexcept;
159
160 /// @brief Returns true if *this is convertible to uint64_t.
161 bool IsUInt64() const noexcept;
162
163 /// @brief Returns true if *this is convertible to double.
164 bool IsDouble() const noexcept;
165
166 /// @brief Returns true if *this is convertible to std::string.
167 bool IsString() const noexcept;
168
169 /// @brief Returns true if *this is an array (Type::kArray).
170 bool IsArray() const noexcept;
171
172 /// @brief Returns true if *this holds a document (BSON_TYPE_DOCUMENT).
173 bool IsObject() const noexcept;
174
175 /// @brief Returns the number of elements in a document/array
176 /// @throws TypeMismatchException if value is not a document, array or `null`
177 /// @note Returns 0 for `null`.
178 uint32_t GetSize() const;
179
180 /// @brief Checks whether the document has a field
181 /// @param name field name
182 /// @throws TypeMismatchExcepiton if value is not a document or `null`
183 bool HasMember(const std::string& name) const;
184
185 /// @brief Creates or resizes the array
186 /// @param size new size
187 /// @throws TypeMismatchException if value is not an array or `null`
188 void Resize(uint32_t size);
189
190 /// @brief Appends an element to the array, possibly creating one
191 /// @param elem element to append
192 /// @throws TypeMismatchException if value is not an array or `null`
193 void PushBack(ValueBuilder&& elem);
194
195 /// @brief Retrieves a compiled value from the builder.
196 /// After calling this method the builder is in unspecified state.
198
199 private:
200 void Assign(const impl::ValueImplPtr&);
201 void Assign(impl::ValueImplPtr&&);
202
203 template <typename T>
204 static Value DoSerialize(const T& t);
205
206 impl::ValueImplPtr impl_;
207};
208
209template <typename Tag, utils::StrongTypedefOps Ops, typename Enable>
211 const utils::StrongTypedef<Tag, std::string, Ops>& name) {
212 return (*this)[name.GetUnderlying()];
213}
214
215template <typename T>
216Value ValueBuilder::DoSerialize(const T& t) {
217 static_assert(
218 formats::common::impl::kHasSerialize<Value, T>,
219 "There is no `Serialize(const T&, formats::serialize::To<bson::Value>)` "
220 "in namespace of `T` or `formats::serialize`. "
221 ""
222 "Probably you forgot to include the "
223 "<userver/formats/serialize/common_containers.hpp> or you "
224 "have not provided a `Serialize` function overload.");
225
226 return Serialize(t, formats::serialize::To<Value>());
227}
228
229} // namespace formats::bson
230
231USERVER_NAMESPACE_END