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:
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,
122 utils::StrongTypedefOps Ops,
123 typename Enable = std::enable_if_t<utils::IsStrongTypedefLoggable(Ops)>>
124 ValueBuilder operator[](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
199private:
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>
210ValueBuilder ValueBuilder::operator[](const utils::StrongTypedef<Tag, std::string, Ops>& name) {
211 return (*this)[name.GetUnderlying()];
212}
213
214template <typename T>
215Value ValueBuilder::DoSerialize(const T& t) {
216 static_assert(
217 formats::common::impl::kHasSerialize<Value, T>,
218 "There is no `Serialize(const T&, formats::serialize::To<bson::Value>)` "
219 "in namespace of `T` or `formats::serialize`. "
220 ""
221 "Probably you forgot to include the "
222 "<userver/formats/serialize/common_containers.hpp> or you "
223 "have not provided a `Serialize` function overload."
224 );
225
226 return Serialize(t, formats::serialize::To<Value>());
227}
228
229} // namespace formats::bson
230
231USERVER_NAMESPACE_END