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<
decltype(std::declval<T&>(
 
   22    )(std::declval<
const FieldBuffer&>(), 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, 
const char* base_file);
 
   33    void RequireInstance() 
const;
 
   40template <
class Type, 
class Reader>
 
   41struct CheckForBufferReaderODR 
final {
 
   42    static inline ReadersRegistrator content{
typeid(Type), 
typeid(Reader), __BASE_FILE__};
 
   47class WritersRegistrator 
final {
 
   49    WritersRegistrator(std::type_index type, std::type_index formatter_type, 
const char* base_file);
 
   50    void RequireInstance() 
const;
 
   57template <
class Type, 
class Writer>
 
   58struct CheckForBufferWriterODR 
final {
 
   59    static inline WritersRegistrator content{
typeid(Type), 
typeid(Writer), __BASE_FILE__};
 
   70    using ValueType = std::decay_t<T>;
 
   71    traits::CheckParser<ValueType>();
 
   72    using BufferReader = 
typename traits::
IO<ValueType>::ParserType;
 
   74        !detail::ParserRequiresTypeCategories<BufferReader>::value,
 
   75        "Type parser requires knowledge about type categories" 
   77    if (
traits::kParserBufferCategory<BufferReader> != buffer.category) {
 
   79            compiler::GetTypeName<ValueType>(), 
traits::kTypeBufferCategory<ValueType>, buffer.category
 
   84    detail::CheckForBufferReaderODR<T, BufferReader>::content.RequireInstance();
 
   86    BufferReader{std::forward<T>(value)}(buffer);
 
 
   90void ReadBuffer(
const FieldBuffer& buffer, T&& value, 
const TypeBufferCategory& categories) {
 
   91    using ValueType = std::decay_t<T>;
 
   92    traits::CheckParser<ValueType>();
 
   93    using BufferReader = 
typename traits::
IO<ValueType>::ParserType;
 
   94    if (
traits::kParserBufferCategory<BufferReader> != buffer.category) {
 
   96            compiler::GetTypeName<ValueType>(), 
traits::kTypeBufferCategory<ValueType>, buffer.category
 
  101    detail::CheckForBufferReaderODR<T, BufferReader>::content.RequireInstance();
 
  104    if constexpr (detail::ParserRequiresTypeCategories<BufferReader>::value) {
 
  105        BufferReader{std::forward<T>(value)}(buffer, categories);
 
  107        BufferReader{std::forward<T>(value)}(buffer);
 
  112typename traits::
IO<T>::FormatterType BufferWriter(
const T& value) {
 
  113    using Formatter = 
typename traits::
IO<T>::FormatterType;
 
  115    detail::CheckForBufferWriterODR<T, Formatter>::content.RequireInstance();
 
  117    return Formatter(value);
 
  120template <
typename T, 
typename Buffer>
 
  121void WriteBuffer(
const UserTypes& types, Buffer& buffer, 
const T& value) {
 
  122    traits::CheckFormatter<T>();
 
  123    BufferWriter(value)(types, buffer);