userver: userver/storages/postgres/io/bytea.hpp Source File
Loading...
Searching...
No Matches
bytea.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/postgres/io/bytea.hpp
4/// @brief storages::postgres::Bytea I/O support
5/// @ingroup userver_postgres_parse_and_format
6
7#include <string>
8#include <string_view>
9#include <vector>
10
11#include <userver/storages/postgres/exceptions.hpp>
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/type_mapping.hpp>
15
16USERVER_NAMESPACE_BEGIN
17
18namespace storages::postgres {
19
20namespace io::traits {
21
22template <typename T>
23struct IsByteaCompatible : std::false_type {};
24
25template <>
26struct IsByteaCompatible<std::string> : std::true_type {};
27template <>
29template <typename... VectorArgs>
30struct IsByteaCompatible<std::vector<char, VectorArgs...>> : std::true_type {};
31template <typename... VectorArgs>
32struct IsByteaCompatible<std::vector<unsigned char, VectorArgs...>>
33 : std::true_type {};
34
35template <typename T>
36inline constexpr bool kIsByteaCompatible = IsByteaCompatible<T>::value;
37
38template <typename T>
40
41} // namespace io::traits
42
43namespace detail {
44
45template <typename ByteContainerRef>
46struct ByteaRefWrapper {
47 static_assert(std::is_reference<ByteContainerRef>::value,
48 "The container must be passed by reference");
49
50 using BytesType = std::decay_t<ByteContainerRef>;
51 static_assert(
52 io::traits::kIsByteaCompatible<BytesType>,
53 "This C++ type cannot be used with PostgreSQL `bytea` data type");
54
55 ByteContainerRef bytes;
56};
57
58} // namespace detail
59
60// clang-format off
61/// Helper function for reading binary data
62///
63/// Example usage:
64/// @snippet postgresql/src/storages/postgres/tests/bytea_pgtest.cpp bytea_simple
65/// @snippet postgresql/src/storages/postgres/tests/bytea_pgtest.cpp bytea_string
66/// @snippet postgresql/src/storages/postgres/tests/bytea_pgtest.cpp bytea_vector
67// clang-format on
68
69template <typename ByteContainer>
70detail::ByteaRefWrapper<const ByteContainer&> Bytea(
71 const ByteContainer& bytes) {
72 return {bytes};
73}
74
75// clang-format off
76/// Helper function for reading binary data
77///
78/// Example usage:
79/// @snippet postgresql/src/storages/postgres/tests/bytea_pgtest.cpp bytea_simple
80/// @snippet postgresql/src/storages/postgres/tests/bytea_pgtest.cpp bytea_string
81/// @snippet postgresql/src/storages/postgres/tests/bytea_pgtest.cpp bytea_vector
82// clang-format on
83
84template <typename ByteContainer>
85detail::ByteaRefWrapper<ByteContainer&> Bytea(ByteContainer& bytes) {
86 return {bytes};
87}
88
89/// Wrapper for binary data container
90template <typename ByteContainer>
93
94 static_assert(
96 "This C++ type cannot be used with PostgreSQL `bytea` data type");
97
98 ByteContainer bytes;
99};
100
101namespace io {
102
103template <typename ByteContainer>
104struct BufferParser<
111 using BaseType::BaseType;
113
114 void operator()(const FieldBuffer& buffer) {
115 if constexpr (std::is_same<typename ByteaType::BytesType,
116 std::string_view>{}) {
117 this->value.bytes = std::string_view{
118 reinterpret_cast<const char*>(buffer.buffer), buffer.length};
119 } else {
122 this->value.bytes.begin());
123 }
124 }
125};
126
127template <typename ByteContainer>
132 using BaseType =
134 using BaseType::BaseType;
135
136 void operator()(const FieldBuffer& buffer) {
138 }
139};
140
141template <typename ByteContainer>
142struct BufferFormatter<
149 using BaseType::BaseType;
150
151 template <typename Buffer>
152 void operator()(const UserTypes&, Buffer& buf) const {
153 buf.reserve(buf.size() + this->value.bytes.size());
154 buf.insert(buf.end(), this->value.bytes.begin(), this->value.bytes.end());
155 }
156};
157
158template <typename ByteContainer>
163 using BaseType =
165 using BaseType::BaseType;
166
167 template <typename Buffer>
168 void operator()(const UserTypes& types, Buffer& buffer) const {
170 }
171};
172
173template <typename ByteContainer>
174struct CppToSystemPg<postgres::detail::ByteaRefWrapper<ByteContainer>>
175 : PredefinedOid<PredefinedOids::kBytea> {};
176template <typename ByteContainer>
177struct CppToSystemPg<postgres::ByteaWrapper<ByteContainer>>
178 : PredefinedOid<PredefinedOids::kBytea> {};
179
180} // namespace io
181} // namespace storages::postgres
182
183USERVER_NAMESPACE_END