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);
69 throw InvalidInputBufferSize{
71 "for an integral value type (expecting size 2, 4, or 8). Not an "
72 "integer was returned from query."};
78struct IntegralBinaryFormatter {
79 static constexpr std::size_t size =
sizeof(T);
80 using BySizeType =
typename IntegralType<size>::type;
84 explicit IntegralBinaryFormatter(T val) : value{val} {}
85 template <
typename Buffer>
86 void operator()(
const UserTypes&, Buffer& buf)
const {
87 buf.reserve(buf.size() + size);
88 auto tmp = boost::endian::native_to_big(
static_cast<BySizeType>(value));
89 const char* p =
reinterpret_cast<
char const*>(&tmp);
90 const char* e = p + size;
91 std::copy(p, e, std::back_inserter(buf));
95 template <
typename Iterator>
96 void operator()(Iterator buffer)
const {
97 auto tmp = boost::endian::native_to_big(
static_cast<BySizeType>(value));
98 const char* p =
reinterpret_cast<
char const*>(&tmp);
99 const char* e = p + size;
100 std::copy(p, e, buffer);
104#if defined(__x86_64__
) || defined(__aarch64__)
106using AltInteger = std::conditional_t<std::is_same_v<Bigint,
long>,
long long,
long>;
107static_assert(
sizeof(AltInteger) ==
sizeof(Bigint));
110using AltInteger = std::conditional_t<std::is_same_v<Integer,
int>,
long int,
int>;
111static_assert(
sizeof(AltInteger) ==
sizeof(Integer));
181 template <
typename Buffer>
191struct CppToSystemPg<Smallint> : PredefinedOid<PredefinedOids::kInt2> {};
193struct CppToSystemPg<Integer> : PredefinedOid<PredefinedOids::kInt4> {};
195struct CppToSystemPg<Bigint> : PredefinedOid<PredefinedOids::kInt8> {};
197struct CppToSystemPg<
bool> : PredefinedOid<PredefinedOids::kBoolean> {};