6#include <userver/storages/postgres/exceptions.hpp>
7#include <userver/storages/postgres/io/traits.hpp>
15template <
typename Parser>
16concept ParserCallableWithCategories =
requires(Parser& p,
const FieldBuffer& fb,
const TypeBufferCategory& cats) {
20template <
typename ValueType>
22concept kParserRequiresTypeCategories = ParserCallableWithCategories<
typename traits::
IO<ValueType>::ParserType>;
26class ReadersRegistrator
final {
28 ReadersRegistrator(std::type_index type, std::type_index parser_type,
const char* base_file);
29 void RequireInstance()
const;
36template <
class Type,
class Reader>
37struct CheckForBufferReaderODR
final {
38 static inline ReadersRegistrator content{
typeid(Type),
typeid(Reader), __BASE_FILE__};
43class WritersRegistrator
final {
45 WritersRegistrator(std::type_index type, std::type_index formatter_type,
const char* base_file);
46 void RequireInstance()
const;
53template <
class Type,
class Writer>
54struct CheckForBufferWriterODR
final {
55 static inline WritersRegistrator content{
typeid(Type),
typeid(Writer), __BASE_FILE__};
66 using ValueType = std::remove_cvref_t<T>;
67 traits::CheckParser<ValueType>();
68 using BufferReader =
typename traits::
IO<ValueType>::ParserType;
70 !detail::ParserCallableWithCategories<BufferReader>,
71 "Type parser requires knowledge about type categories"
73 if (
traits::kParserBufferCategory<BufferReader> != buffer.category) {
76 traits::kTypeBufferCategory<ValueType>,
82 detail::CheckForBufferReaderODR<T, BufferReader>::content.RequireInstance();
84 BufferReader{std::forward<T>(value)}(buffer);
88void ReadBuffer(
const FieldBuffer& buffer, T&& value,
const TypeBufferCategory& categories) {
89 using ValueType = std::remove_cvref_t<T>;
90 traits::CheckParser<ValueType>();
91 using BufferReader =
typename traits::
IO<ValueType>::ParserType;
92 if (
traits::kParserBufferCategory<BufferReader> != buffer.category) {
95 traits::kTypeBufferCategory<ValueType>,
101 detail::CheckForBufferReaderODR<T, BufferReader>::content.RequireInstance();
104 if constexpr (detail::ParserCallableWithCategories<BufferReader>) {
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);