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) {
78 throw InvalidParserCategory(
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) {
95 throw InvalidParserCategory(
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);