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);