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>
15#include <userver/utils/numeric_cast.hpp>
17USERVER_NAMESPACE_BEGIN
23template <std::size_t Size>
27struct IntegralType<2> {
28 using type = Smallint;
32struct IntegralType<4> {
37struct IntegralType<8> {
41template <std::size_t Size>
42struct IntegralBySizeParser {
43 using IntType =
typename IntegralType<Size>::type;
44 constexpr static std::size_t size = Size;
46 static IntType ParseBuffer(
const FieldBuffer& buf) {
48 std::memcpy(&i, buf.buffer, size);
49 return boost::endian::big_to_native(i);
53template <
typename To,
typename From>
54To NumericCast(From value) {
59struct IntegralBinaryParser : BufferParserBase<T> {
60 using BaseType = BufferParserBase<T>;
61 using BaseType::BaseType;
62 using ValueType =
typename BaseType::ValueType;
67 this->value = NumericCast<ValueType>(IntegralBySizeParser<2>::ParseBuffer(buf));
70 this->value = NumericCast<ValueType>(IntegralBySizeParser<4>::ParseBuffer(buf));
73 this->value = NumericCast<ValueType>(IntegralBySizeParser<8>::ParseBuffer(buf));
77 "Invalid buffer size {} "
78 "for an integral value type (expecting size 2, 4, or 8). Not an "
79 "integer was returned from query.",
87struct IntegralBinaryFormatter {
88 static constexpr std::size_t size =
sizeof(T);
89 using BySizeType =
typename IntegralType<size>::type;
93 explicit IntegralBinaryFormatter(T val)
96 template <
typename Buffer>
97 void operator()(
const UserTypes&, Buffer& buf)
const {
98 buf.reserve(buf.size() + size);
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, std::back_inserter(buf));
106 template <
typename Iterator>
107 void operator()(Iterator buffer)
const {
108 auto tmp = boost::endian::native_to_big(
static_cast<BySizeType>(value));
109 const char* p =
reinterpret_cast<
char const*>(&tmp);
110 const char* e = p + size;
111 std::copy(p, e, buffer);
115#if defined(__x86_64__
) || defined(__aarch64__)
117using AltInteger = std::conditional_t<std::is_same_v<Bigint,
long>,
long long,
long>;
118static_assert(
sizeof(AltInteger) ==
sizeof(Bigint));
121using AltInteger = std::conditional_t<std::is_same_v<Integer,
int>,
long int,
int>;
122static_assert(
sizeof(AltInteger) ==
sizeof(Integer));
130struct BufferParser<Smallint> : detail::IntegralBinaryParser<Smallint> {
131 explicit BufferParser(Smallint& val)
132 : IntegralBinaryParser(val)
137struct BufferFormatter<Smallint> : detail::IntegralBinaryFormatter<Smallint> {
138 explicit BufferFormatter(Smallint val)
139 : IntegralBinaryFormatter(val)
147struct BufferParser<Integer> : detail::IntegralBinaryParser<Integer> {
148 explicit BufferParser(Integer& val)
149 : IntegralBinaryParser(val)
154struct BufferFormatter<Integer> : detail::IntegralBinaryFormatter<Integer> {
155 explicit BufferFormatter(Integer val)
156 : IntegralBinaryFormatter(val)
164struct BufferParser<Bigint> : detail::IntegralBinaryParser<Bigint> {
165 explicit BufferParser(Bigint& val)
166 : IntegralBinaryParser(val)
171struct BufferFormatter<Bigint> : detail::IntegralBinaryFormatter<Bigint> {
172 explicit BufferFormatter(Bigint val)
173 : IntegralBinaryFormatter(val)
179struct BufferParser<detail::AltInteger> : detail::IntegralBinaryParser<detail::AltInteger> {
180 explicit BufferParser(detail::AltInteger& val)
181 : IntegralBinaryParser(val)
186struct BufferFormatter<detail::AltInteger> : detail::IntegralBinaryFormatter<detail::AltInteger> {
187 explicit BufferFormatter(detail::AltInteger val)
188 : IntegralBinaryFormatter(val)
198struct BufferParser<
bool> {
200 explicit BufferParser(
bool& val)
207struct BufferFormatter<
bool> {
209 explicit BufferFormatter(
bool val)
212 template <
typename Buffer>
213 void operator()(
const UserTypes&, Buffer& buf)
const {
214 buf.push_back(value ? 1 : 0);
232struct CppToSystemPg<detail::AltInteger>