7#include <boost/endian/conversion.hpp>
11#include <userver/storages/postgres/exceptions.hpp>
12#include <userver/storages/postgres/io/buffer_io_base.hpp>
13#include <userver/storages/postgres/io/traits.hpp>
14#include <userver/storages/postgres/io/type_mapping.hpp>
16USERVER_NAMESPACE_BEGIN
22template <std::size_t Size>
26struct IntegralType<2> {
27 using type = Smallint;
31struct IntegralType<4> {
36struct IntegralType<8> {
40template <std::size_t Size>
41struct IntegralBySizeParser {
42 using IntType =
typename IntegralType<Size>::type;
43 constexpr static std::size_t size = Size;
45 static IntType ParseBuffer(
const FieldBuffer& buf) {
47 std::memcpy(&i, buf.buffer, size);
48 return boost::endian::big_to_native(i);
53struct IntegralBinaryParser : BufferParserBase<T> {
54 using BaseType = BufferParserBase<T>;
55 using BaseType::BaseType;
60 this->value = IntegralBySizeParser<2>::ParseBuffer(buf);
63 this->value = IntegralBySizeParser<4>::ParseBuffer(buf);
66 this->value = IntegralBySizeParser<8>::ParseBuffer(buf);
70 "Invalid buffer size {} "
71 "for an integral value type (expecting size 2, 4, or 8). Not an "
72 "integer was returned from query.",
80struct IntegralBinaryFormatter {
81 static constexpr std::size_t size =
sizeof(T);
82 using BySizeType =
typename IntegralType<size>::type;
86 explicit IntegralBinaryFormatter(T val) : value{val} {}
87 template <
typename Buffer>
88 void operator()(
const UserTypes&, Buffer& buf)
const {
89 buf.reserve(buf.size() + size);
90 auto tmp = boost::endian::native_to_big(
static_cast<BySizeType>(value));
91 const char* p =
reinterpret_cast<
char const*>(&tmp);
92 const char* e = p + size;
93 std::copy(p, e, std::back_inserter(buf));
97 template <
typename Iterator>
98 void operator()(Iterator buffer)
const {
99 auto tmp = boost::endian::native_to_big(
static_cast<BySizeType>(value));
100 const char* p =
reinterpret_cast<
char const*>(&tmp);
101 const char* e = p + size;
102 std::copy(p, e, buffer);
106#if defined(__x86_64__
) || defined(__aarch64__)
108using AltInteger = std::conditional_t<std::is_same_v<Bigint,
long>,
long long,
long>;
109static_assert(
sizeof(AltInteger) ==
sizeof(Bigint));
112using AltInteger = std::conditional_t<std::is_same_v<Integer,
int>,
long int,
int>;
113static_assert(
sizeof(AltInteger) ==
sizeof(Integer));
121struct BufferParser<Smallint> : detail::IntegralBinaryParser<Smallint> {
122 explicit BufferParser(Smallint& val) : IntegralBinaryParser(val) {}
126struct BufferFormatter<Smallint> : detail::IntegralBinaryFormatter<Smallint> {
127 explicit BufferFormatter(Smallint val) : IntegralBinaryFormatter(val) {}
134struct BufferParser<Integer> : detail::IntegralBinaryParser<Integer> {
135 explicit BufferParser(Integer& val) : IntegralBinaryParser(val) {}
139struct BufferFormatter<Integer> : detail::IntegralBinaryFormatter<Integer> {
140 explicit BufferFormatter(Integer val) : IntegralBinaryFormatter(val) {}
147struct BufferParser<Bigint> : detail::IntegralBinaryParser<Bigint> {
148 explicit BufferParser(Bigint& val) : IntegralBinaryParser(val) {}
152struct BufferFormatter<Bigint> : detail::IntegralBinaryFormatter<Bigint> {
153 explicit BufferFormatter(Bigint val) : IntegralBinaryFormatter(val) {}
158struct BufferParser<detail::AltInteger> : detail::IntegralBinaryParser<detail::AltInteger> {
159 explicit BufferParser(detail::AltInteger& val) : IntegralBinaryParser(val) {}
163struct BufferFormatter<detail::AltInteger> : detail::IntegralBinaryFormatter<detail::AltInteger> {
164 explicit BufferFormatter(detail::AltInteger val) : IntegralBinaryFormatter(val) {}
173struct BufferParser<
bool> {
175 explicit BufferParser(
bool& val) : value{val} {}
176 void operator()(
const FieldBuffer& buf);
180struct BufferFormatter<
bool> {
182 explicit BufferFormatter(
bool val) : value(val) {}
183 template <
typename Buffer>
184 void operator()(
const UserTypes&, Buffer& buf)
const {
185 buf.push_back(value ? 1 : 0);
193struct CppToSystemPg<Smallint> : PredefinedOid<PredefinedOids::kInt2> {};
195struct CppToSystemPg<Integer> : PredefinedOid<PredefinedOids::kInt4> {};
197struct CppToSystemPg<Bigint> : PredefinedOid<PredefinedOids::kInt8> {};
199struct CppToSystemPg<
bool> : PredefinedOid<PredefinedOids::kBoolean> {};
203struct CppToSystemPg<detail::AltInteger>
204 : PredefinedOid<
sizeof(detail::AltInteger) == 8 ? PredefinedOids::kInt8 : PredefinedOids::kInt4> {};