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