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/// Helper function for writing binary data
61template <typename ByteContainer>
62detail::ByteaRefWrapper<const ByteContainer&> Bytea(
63 const ByteContainer& bytes) {
64 return {bytes};
65}
66
67/// Helper function for reading binary data
68template <typename ByteContainer>
69detail::ByteaRefWrapper<ByteContainer&> Bytea(ByteContainer& bytes) {
70 return {bytes};
71}
72
73/// Wrapper for binary data container
74template <typename ByteContainer>
77
78 static_assert(
80 "This C++ type cannot be used with PostgreSQL `bytea` data type");
81
82 ByteContainer bytes;
83};
84
85namespace io {
86
87template <typename ByteContainer>
88struct BufferParser<
95 using BaseType::BaseType;
97
98 void operator()(const FieldBuffer& buffer) {
99 if constexpr (std::is_same<typename ByteaType::BytesType,
100 std::string_view>{}) {
101 this->value.bytes = std::string_view{
102 reinterpret_cast<const char*>(buffer.buffer), buffer.length};
103 } else {
106 this->value.bytes.begin());
107 }
108 }
109};
110
111template <typename ByteContainer>
116 using BaseType =
118 using BaseType::BaseType;
119
120 void operator()(const FieldBuffer& buffer) {
122 }
123};
124
125template <typename ByteContainer>
126struct BufferFormatter<
133 using BaseType::BaseType;
134
135 template <typename Buffer>
136 void operator()(const UserTypes&, Buffer& buf) const {
137 buf.reserve(buf.size() + this->value.bytes.size());
138 buf.insert(buf.end(), this->value.bytes.begin(), this->value.bytes.end());
139 }
140};
141
142template <typename ByteContainer>
147 using BaseType =
149 using BaseType::BaseType;
150
151 template <typename Buffer>
152 void operator()(const UserTypes& types, Buffer& buffer) const {
154 }
155};
156
157template <typename ByteContainer>
158struct CppToSystemPg<postgres::detail::ByteaRefWrapper<ByteContainer>>
159 : PredefinedOid<PredefinedOids::kBytea> {};
160template <typename ByteContainer>
161struct CppToSystemPg<postgres::ByteaWrapper<ByteContainer>>
162 : PredefinedOid<PredefinedOids::kBytea> {};
163
164} // namespace io
165} // namespace storages::postgres
166
167USERVER_NAMESPACE_END