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<
21 USERVER_NAMESPACE::utils::void_t<
22 decltype(std::declval<T&>()(std::declval<
const FieldBuffer&>(), std::declval<
const TypeBufferCategory&>()))>>
27 kParserRequiresTypeCategories = ParserRequiresTypeCategories<
typename traits::IO<T>::ParserType>::value;
31class ReadersRegistrator
final {
33 ReadersRegistrator(std::type_index type, std::type_index parser_type,
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), __BASE_FILE__};
48class WritersRegistrator
final {
50 WritersRegistrator(std::type_index type, std::type_index formatter_type,
const char* base_file);
51 void RequireInstance()
const;
58template <
class Type,
class Writer>
59struct CheckForBufferWriterODR
final {
60 static inline WritersRegistrator content{
typeid(Type),
typeid(Writer), __BASE_FILE__};
71 using ValueType = std::decay_t<T>;
72 traits::CheckParser<ValueType>();
73 using BufferReader =
typename traits::
IO<ValueType>::ParserType;
75 !detail::ParserRequiresTypeCategories<BufferReader>::value,
76 "Type parser requires knowledge about type categories"
78 if (
traits::kParserBufferCategory<BufferReader> != buffer.category) {
81 traits::kTypeBufferCategory<ValueType>,
87 detail::CheckForBufferReaderODR<T, BufferReader>::content.RequireInstance();
89 BufferReader{std::forward<T>(value)}(buffer);
93void ReadBuffer(
const FieldBuffer& buffer, T&& value,
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) {
100 traits::kTypeBufferCategory<ValueType>,
106 detail::CheckForBufferReaderODR<T, BufferReader>::content.RequireInstance();
109 if constexpr (detail::ParserRequiresTypeCategories<BufferReader>::value) {
110 BufferReader{std::forward<T>(value)}(buffer, categories);
112 BufferReader{std::forward<T>(value)}(buffer);
117typename traits::
IO<T>::FormatterType BufferWriter(
const T& value) {
118 using Formatter =
typename traits::
IO<T>::FormatterType;
120 detail::CheckForBufferWriterODR<T, Formatter>::content.RequireInstance();
122 return Formatter(value);
125template <
typename T,
typename Buffer>
126void WriteBuffer(
const UserTypes& types, Buffer& buffer,
const T& value) {
127 traits::CheckFormatter<T>();
128 BufferWriter(value)(types, buffer);