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
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