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 explicit ValueBuilder(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(std::string);
90 /* implicit */ ValueBuilder(std::string_view);
91 /* implicit */ ValueBuilder(const std::chrono::system_clock::time_point&);
92 /* implicit */ ValueBuilder(const Oid&);
93 /* implicit */ ValueBuilder(Binary);
94 /* implicit */ ValueBuilder(const Decimal128&);
95 /* implicit */ ValueBuilder(MinKey);
96 /* implicit */ ValueBuilder(MaxKey);
97 /* implicit */ ValueBuilder(const Timestamp&);
98 /// @}
99
100 /// Universal constructor using Serialize
101 template <typename T>
102 ValueBuilder(const T& t) : ValueBuilder(DoSerialize(t)) {}
103
104 /// @brief Transfers the `ValueBuilder` object
105 /// @see formats::common::TransferTag for the transfer semantics
106 ValueBuilder(common::TransferTag, ValueBuilder&&) noexcept;
107
108 /// @brief Retrieves or creates document field by name
109 /// @throws TypeMismatchException if value is not a document or `null`
110 ValueBuilder operator[](const std::string& name);
111
112 /// @brief Access member by key for modification.
113 /// @throw `TypeMismatchException` if not object or null value.
114 template <
115 typename Tag, utils::StrongTypedefOps Ops,
116 typename Enable = std::enable_if_t<utils::IsStrongTypedefLoggable(Ops)>>
118 const utils::StrongTypedef<Tag, std::string, Ops>& name);
119
120 /// @brief Retrieves array element by index
121 /// @throws TypeMismatchException if value is not an array or `null`
122 /// @throws OutOfBoundsException if index is invalid for the array
123 ValueBuilder operator[](uint32_t index);
124
125 /// @brief Remove key from object. If key is missing nothing happens.
126 /// @throw `TypeMismatchException` if value is not an object.
127 void Remove(const std::string& key);
128
129 /// @brief Returns an iterator to the first array element/document field
130 /// @throws TypeMismatchException if value is not a document, array or `null`
132
133 /// @brief Returns an iterator following the last array element/document field
134 /// @throws TypeMismatchException if value is not a document, array or `null`
136
137 /// @brief Returns whether the document/array is empty
138 /// @throws TypeMismatchException if value is not a document, array or `null`
139 /// @note Returns `true` for `null`.
140 bool IsEmpty() const;
141
142 /// @brief Returns true if *this holds a Null (Type::kNull).
143 bool IsNull() const noexcept;
144
145 /// @brief Returns true if *this is convertible to bool.
146 bool IsBool() const noexcept;
147
148 /// @brief Returns true if *this is convertible to int.
149 bool IsInt() const noexcept;
150
151 /// @brief Returns true if *this is convertible to int64_t.
152 bool IsInt64() const noexcept;
153
154 /// @brief Returns true if *this is convertible to uint64_t.
155 bool IsUInt64() const noexcept;
156
157 /// @brief Returns true if *this is convertible to double.
158 bool IsDouble() const noexcept;
159
160 /// @brief Returns true if *this is convertible to std::string.
161 bool IsString() const noexcept;
162
163 /// @brief Returns true if *this is an array (Type::kArray).
164 bool IsArray() const noexcept;
165
166 /// @brief Returns true if *this holds a document (BSON_TYPE_DOCUMENT).
167 bool IsObject() const noexcept;
168
169 /// @brief Returns the number of elements in a document/array
170 /// @throws TypeMismatchException if value is not a document, array or `null`
171 /// @note Returns 0 for `null`.
172 uint32_t GetSize() const;
173
174 /// @brief Checks whether the document has a field
175 /// @param name field name
176 /// @throws TypeMismatchExcepiton if value is not a document or `null`
177 bool HasMember(const std::string& name) const;
178
179 /// @brief Creates or resizes the array
180 /// @param size new size
181 /// @throws TypeMismatchException if value is not an array or `null`
182 void Resize(uint32_t size);
183
184 /// @brief Appends an element to the array, possibly creating one
185 /// @param elem element to append
186 /// @throws TypeMismatchException if value is not an array or `null`
187 void PushBack(ValueBuilder&& elem);
188
189 /// @brief Retrieves a compiled value from the builder.
190 /// After calling this method the builder is in unspecified state.
192
193 private:
194 void Assign(const impl::ValueImplPtr&);
195 void Assign(impl::ValueImplPtr&&);
196
197 template <typename T>
198 static Value DoSerialize(const T& t);
199
200 impl::ValueImplPtr impl_;
201};
202
203template <typename Tag, utils::StrongTypedefOps Ops, typename Enable>
205 const utils::StrongTypedef<Tag, std::string, Ops>& name) {
206 return (*this)[name.GetUnderlying()];
207}
208
209template <typename T>
210Value ValueBuilder::DoSerialize(const T& t) {
211 static_assert(
212 formats::common::impl::kHasSerialize<Value, T>,
213 "There is no `Serialize(const T&, formats::serialize::To<bson::Value>)` "
214 "in namespace of `T` or `formats::serialize`. "
215 ""
216 "Probably you forgot to include the "
217 "<userver/formats/serialize/common_containers.hpp> or you "
218 "have not provided a `Serialize` function overload.");
219
220 return Serialize(t, formats::serialize::To<Value>());
221}
222
223} // namespace formats::bson
224
225USERVER_NAMESPACE_END