6#include <userver/storages/postgres/exceptions.hpp>
7#include <userver/storages/postgres/io/traits.hpp>
15template <
typename T,
typename Enable = USERVER_NAMESPACE::utils::void_t<>>
16struct ParserRequiresTypeCategories : std::false_type {};
19struct ParserRequiresTypeCategories<
20 T, USERVER_NAMESPACE::utils::void_t<
decltype(std::declval<T&>()(
21 std::declval<
const FieldBuffer&>(),
22 std::declval<
const TypeBufferCategory&>()))>> : std::true_type {};
25inline constexpr bool kParserRequiresTypeCategories =
26 ParserRequiresTypeCategories<
typename traits::IO<T>::ParserType>::value;
30class ReadersRegistrator
final {
32 ReadersRegistrator(std::type_index type, std::type_index parser_type,
33 const char* base_file);
34 void RequireInstance()
const;
41template <
class Type,
class Reader>
42struct CheckForBufferReaderODR
final {
43 static inline ReadersRegistrator content{
typeid(Type),
typeid(Reader),
49class WritersRegistrator
final {
51 WritersRegistrator(std::type_index type, std::type_index formatter_type,
52 const char* base_file);
53 void RequireInstance()
const;
60template <
class Type,
class Writer>
61struct CheckForBufferWriterODR
final {
62 static inline WritersRegistrator content{
typeid(Type),
typeid(Writer),
74 using ValueType = std::decay_t<T>;
75 traits::CheckParser<ValueType>();
76 using BufferReader =
typename traits::IO<ValueType>::ParserType;
77 static_assert(!detail::ParserRequiresTypeCategories<BufferReader>::value,
78 "Type parser requires knowledge about type categories");
79 if (traits::kParserBufferCategory<BufferReader> != buffer.category) {
80 throw InvalidParserCategory(compiler::GetTypeName<ValueType>(),
81 traits::kTypeBufferCategory<ValueType>,
86 detail::CheckForBufferReaderODR<T, BufferReader>::content.RequireInstance();
88 BufferReader{std::forward<T>(value)}(buffer);
92void ReadBuffer(
const FieldBuffer& buffer, T&& value,
93 const TypeBufferCategory& categories) {
94 using ValueType = std::decay_t<T>;
95 traits::CheckParser<ValueType>();
96 using BufferReader =
typename traits::IO<ValueType>::ParserType;
97 if (traits::kParserBufferCategory<BufferReader> != buffer.category) {
98 throw InvalidParserCategory(compiler::GetTypeName<ValueType>(),
99 traits::kTypeBufferCategory<ValueType>,
104 detail::CheckForBufferReaderODR<T, BufferReader>::content.RequireInstance();
107 if constexpr (detail::ParserRequiresTypeCategories<BufferReader>::value) {
108 BufferReader{std::forward<T>(value)}(buffer, categories);
110 BufferReader{std::forward<T>(value)}(buffer);
115typename traits::
IO<T>::FormatterType BufferWriter(
const T& value) {
116 using Formatter =
typename traits::
IO<T>::FormatterType;
118 detail::CheckForBufferWriterODR<T, Formatter>::content.RequireInstance();
120 return Formatter(value);
123template <
typename T,
typename Buffer>
124void WriteBuffer(
const UserTypes& types, Buffer& buffer,
const T& value) {
125 traits::CheckFormatter<T>();
126 BufferWriter(value)(types, buffer);