7#include <boost/endian/conversion.hpp>
12#include <userver/storages/postgres/exceptions.hpp>
13#include <userver/storages/postgres/io/buffer_io_base.hpp>
14#include <userver/storages/postgres/io/traits.hpp>
15#include <userver/storages/postgres/io/type_mapping.hpp>
16#include <userver/utils/numeric_cast.hpp>
18USERVER_NAMESPACE_BEGIN
24template <std::size_t Size>
28struct IntegralType<2> {
29 using type = Smallint;
33struct IntegralType<4> {
38struct IntegralType<8> {
42template <std::size_t Size>
43struct IntegralBySizeParser {
44 using IntType =
typename IntegralType<Size>::type;
45 constexpr static std::size_t size = Size;
47 static IntType ParseBuffer(
const FieldBuffer& buf) {
49 std::memcpy(&i, buf.buffer, size);
50 return boost::endian::big_to_native(i);
54template <
typename To,
typename From>
55To NumericCast(From value) {
60struct IntegralBinaryParser : BufferParserBase<T> {
61 using BaseType = BufferParserBase<T>;
62 using BaseType::BaseType;
63 using ValueType =
typename BaseType::ValueType;
68 this->value = NumericCast<ValueType>(IntegralBySizeParser<2>::ParseBuffer(buf));
71 this->value = NumericCast<ValueType>(IntegralBySizeParser<4>::ParseBuffer(buf));
74 this->value = NumericCast<ValueType>(IntegralBySizeParser<8>::ParseBuffer(buf));
78 "Invalid buffer size {} "
79 "for an integral value type (expecting size 2, 4, or 8). Not an "
80 "integer was returned from query.",
88struct IntegralBinaryFormatter {
89 static constexpr std::size_t size =
sizeof(T);
90 using BySizeType =
typename IntegralType<size>::type;
94 explicit IntegralBinaryFormatter(T val)
97 template <
typename Buffer>
98 void operator()(
const UserTypes&, Buffer& buf)
const {
99 buf.reserve(buf.size() + size);
100 auto tmp = boost::endian::native_to_big(
static_cast<BySizeType>(value));
101 const char* p =
reinterpret_cast<
char const*>(&tmp);
102 const char* e = p + size;
103 std::copy(p, e, std::back_inserter(buf));
107 template <
typename Iterator>
108 void operator()(Iterator buffer)
const {
109 auto tmp = boost::endian::native_to_big(
static_cast<BySizeType>(value));
110 const char* p =
reinterpret_cast<
char const*>(&tmp);
111 const char* e = p + size;
112 std::copy(p, e, buffer);
116#if defined(__x86_64__
) || defined(__aarch64__)
118using AltInteger = std::conditional_t<std::is_same_v<Bigint,
long>,
long long,
long>;
119static_assert(
sizeof(AltInteger) ==
sizeof(Bigint));
122using AltInteger = std::conditional_t<std::is_same_v<Integer,
int>,
long int,
int>;
123static_assert(
sizeof(AltInteger) ==
sizeof(Integer));
131struct BufferParser<Smallint> : detail::IntegralBinaryParser<Smallint> {
132 explicit BufferParser(Smallint& val)
133 : IntegralBinaryParser(val)
138struct BufferFormatter<Smallint> : detail::IntegralBinaryFormatter<Smallint> {
139 explicit BufferFormatter(Smallint val)
140 : IntegralBinaryFormatter(val)
148struct BufferParser<Integer> : detail::IntegralBinaryParser<Integer> {
149 explicit BufferParser(Integer& val)
150 : IntegralBinaryParser(val)
155struct BufferFormatter<Integer> : detail::IntegralBinaryFormatter<Integer> {
156 explicit BufferFormatter(Integer val)
157 : IntegralBinaryFormatter(val)
165struct BufferParser<Bigint> : detail::IntegralBinaryParser<Bigint> {
166 explicit BufferParser(Bigint& val)
167 : IntegralBinaryParser(val)
172struct BufferFormatter<Bigint> : detail::IntegralBinaryFormatter<Bigint> {
173 explicit BufferFormatter(Bigint val)
174 : IntegralBinaryFormatter(val)
180struct BufferParser<detail::AltInteger> : detail::IntegralBinaryParser<detail::AltInteger> {
181 explicit BufferParser(detail::AltInteger& val)
182 : IntegralBinaryParser(val)
187struct BufferFormatter<detail::AltInteger> : detail::IntegralBinaryFormatter<detail::AltInteger> {
188 explicit BufferFormatter(detail::AltInteger val)
189 : IntegralBinaryFormatter(val)
199struct BufferParser<
bool> {
201 explicit BufferParser(
bool& val)
208struct BufferFormatter<
bool> {
210 explicit BufferFormatter(
bool val)
213 template <
typename Buffer>
214 void operator()(
const UserTypes&, Buffer& buf)
const {
215 buf.push_back(value ? 1 : 0);
233struct CppToSystemPg<detail::AltInteger>