userver: userver/storages/postgres/io/optional.hpp Source File
Loading...
Searching...
No Matches
optional.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/postgres/io/optional.hpp
4/// @brief Optional values I/O support
5/// @ingroup userver_postgres_parse_and_format
6
7#include <optional>
8
9#include <userver/utils/assert.hpp>
10#include <userver/utils/optional_ref.hpp>
11
12#include <userver/storages/postgres/io/buffer_io.hpp>
13#include <userver/storages/postgres/io/buffer_io_base.hpp>
14#include <userver/storages/postgres/io/nullable_traits.hpp>
15#include <userver/storages/postgres/io/traits.hpp>
16
17#include <boost/optional/optional_fwd.hpp>
18
19USERVER_NAMESPACE_BEGIN
20
21namespace storages::postgres::io {
22
23namespace detail {
24
25template <template <typename> class Optional, typename T,
26 bool Categories = false>
27struct OptionalValueParser : BufferParserBase<Optional<T>> {
28 using BaseType = BufferParserBase<Optional<T>>;
29 using ValueParser = typename traits::IO<T>::ParserType;
30
31 using BaseType::BaseType;
32
33 void operator()(const FieldBuffer& buffer) {
34 T val;
35 ValueParser{val}(buffer);
36 this->value = std::move(val);
37 }
38};
39
40template <template <typename> class Optional, typename T>
41struct OptionalValueParser<Optional, T, true> : BufferParserBase<Optional<T>> {
42 using BaseType = BufferParserBase<Optional<T>>;
43 using ValueParser = typename traits::IO<T>::ParserType;
44
45 using BaseType::BaseType;
46
47 void operator()(const FieldBuffer& buffer,
48 const TypeBufferCategory& categories) {
49 T val;
50 ValueParser{val}(buffer, categories);
51 this->value = std::move(val);
52 }
53};
54
55template <template <typename> class Optional, typename T>
56struct OptionalValueFormatter : BufferFormatterBase<Optional<T>> {
57 using BaseType = BufferFormatterBase<Optional<T>>;
58 using ValueFormatter = typename traits::IO<T>::FormatterType;
59
60 using BaseType::BaseType;
61
62 template <typename Buffer>
63 void operator()(const UserTypes& types, Buffer& buffer) const {
64 if (this->value) {
65 ValueFormatter{*this->value}(types, buffer);
66 }
67 }
68};
69
70} // namespace detail
71
72/// Parser specialization for boost::optional
73template <typename T>
77 using BaseType =
80 using BaseType::BaseType;
81};
82
83/// Formatter specialization for boost::optional
84template <typename T>
89 using BaseType::BaseType;
90};
91
92/// Parser specialization for std::optional
93template <typename T>
97 using BaseType =
100 using BaseType::BaseType;
101};
102
103/// Formatter specialization for std::optional
104template <typename T>
109 using BaseType::BaseType;
110};
111
112/// Formatter specialization for utils::OptionalRef
113template <typename T>
114struct BufferFormatter<USERVER_NAMESPACE::utils::OptionalRef<T>,
116 : detail::OptionalValueFormatter<USERVER_NAMESPACE::utils::OptionalRef, T> {
117 using BaseType =
118 detail::OptionalValueFormatter<USERVER_NAMESPACE::utils::OptionalRef, T>;
119 using BaseType::BaseType;
120};
121
122/// Pg mapping specialization for boost::optional
123template <typename T>
125 : CppToPg<T> {};
126
127/// Pg mapping specialization for std::optional
128template <typename T>
130 : CppToPg<T> {};
131
132/// Pg mapping specialization for USERVER_NAMESPACE::utils::OptionalRef
133template <typename T>
134struct CppToPg<USERVER_NAMESPACE::utils::OptionalRef<T>,
136
137namespace traits {
138
139/// Nullability traits for boost::optional
140template <typename T>
141struct IsNullable<boost::optional<T>> : std::true_type {};
142
143template <typename T>
144struct GetSetNull<boost::optional<T>> {
145 using ValueType = boost::optional<T>;
146 inline static bool IsNull(const ValueType& v) { return !v; }
147 inline static void SetNull(ValueType& v) { v = ValueType{}; }
148 inline static void SetDefault(ValueType& v) { v.emplace(); }
149};
150
151template <typename T>
153template <typename T>
155
156template <typename T>
158 : ParserBufferCategory<typename traits::IO<T>::ParserType> {};
159
160/// Nullability traits for std::optional
161template <typename T>
162struct IsNullable<std::optional<T>> : std::true_type {};
163
164template <typename T>
165struct GetSetNull<std::optional<T>> {
166 using ValueType = std::optional<T>;
167 inline static bool IsNull(const ValueType& v) { return !v; }
168 inline static void SetNull(ValueType& v) { v = std::nullopt; }
169 inline static void SetDefault(ValueType& v) { v.emplace(); }
170};
171
172template <typename T>
174template <typename T>
176
177template <typename T>
179 : ParserBufferCategory<typename traits::IO<T>::ParserType> {};
180
181/// Nullability traits for USERVER_NAMESPACE::utils::OptionalRef
182template <typename T>
183struct IsNullable<USERVER_NAMESPACE::utils::OptionalRef<T>> : std::true_type {};
184
185template <typename T>
186struct GetSetNull<USERVER_NAMESPACE::utils::OptionalRef<T>> {
187 using ValueType = USERVER_NAMESPACE::utils::OptionalRef<T>;
188 inline static bool IsNull(const ValueType& v) { return !v; }
189 inline static void SetNull(ValueType&) {
190 static_assert(!sizeof(T), "SetNull not enabled for utils::OptionalRef");
191 }
192 inline static void SetDefault(ValueType&) {
193 static_assert(!sizeof(T), "SetDefault not enabled for utils::OptionalRef");
194 }
195};
196
197template <typename T>
198struct IsMappedToPg<USERVER_NAMESPACE::utils::OptionalRef<T>>
199 : IsMappedToPg<T> {};
200template <typename T>
201struct IsSpecialMapping<USERVER_NAMESPACE::utils::OptionalRef<T>>
202 : IsMappedToPg<T> {};
203
204} // namespace traits
205
206} // namespace storages::postgres::io
207
208USERVER_NAMESPACE_END