userver: userver/storages/postgres/io/field_buffer.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
field_buffer.hpp
1#pragma once
2
3#include <userver/storages/postgres/exceptions.hpp>
4#include <userver/storages/postgres/io/buffer_io.hpp>
5#include <userver/storages/postgres/io/integral_types.hpp>
6#include <userver/storages/postgres/io/nullable_traits.hpp>
7
8USERVER_NAMESPACE_BEGIN
9
10namespace storages::postgres::io {
11
12inline constexpr FieldBuffer FieldBuffer::GetSubBuffer(
13 std::size_t offset, std::size_t size, BufferCategory cat) const {
14 const auto* new_buffer_start = buffer + offset;
15 if (offset > length) {
16 throw InvalidInputBufferSize(
17 length, ". Offset requested " + std::to_string(offset));
18 }
19 size = size == npos ? length - offset : size;
20 if (offset + size > length) {
21 throw InvalidInputBufferSize(
22 size, ". Buffer remaininig size is " + std::to_string(length - offset));
23 }
25 cat = category;
26 }
27 return {is_null, cat, size, new_buffer_start};
28}
29
30template <typename T>
31std::size_t FieldBuffer::Read(T&& value, BufferCategory cat, std::size_t len) {
32 io::ReadBuffer(GetSubBuffer(0, len, cat), std::forward<T>(value));
33 length -= len;
34 buffer += len;
35 return len;
36}
37
38template <typename T>
39std::size_t FieldBuffer::Read(T&& value, const TypeBufferCategory& categories,
40 std::size_t len, BufferCategory cat) {
41 io::ReadBuffer(GetSubBuffer(0, len, cat), std::forward<T>(value), categories);
42 length -= len;
43 buffer += len;
44 return len;
45}
46
47template <typename T>
48std::size_t FieldBuffer::ReadRaw(T&& value,
49 const TypeBufferCategory& categories,
50 BufferCategory cat) {
51 using ValueType = std::decay_t<T>;
52 Integer field_length{0};
53 auto consumed = Read(field_length, BufferCategory::kPlainBuffer);
54 if (field_length == kPgNullBufferSize) {
55 // NULL value
56 traits::GetSetNull<ValueType>::SetNull(std::forward<T>(value));
57 return consumed;
58 } else if (field_length < 0) {
59 // invalid length value
60 throw InvalidInputBufferSize(0, "Negative buffer size value");
61 } else if (field_length == 0) {
62 traits::GetSetNull<ValueType>::SetDefault(std::forward<T>(value));
63 return consumed;
64 } else {
65 return consumed + Read(value, categories, field_length, cat);
66 }
67}
68
69template <typename T>
70std::size_t ReadRawBinary(FieldBuffer buffer, T& value,
71 const TypeBufferCategory& categories) {
72 return buffer.ReadRaw(value, categories);
73}
74
75namespace detail {
76
77template <typename T, typename Buffer,
78 typename Enable = USERVER_NAMESPACE::utils::void_t<>>
79struct FormatterAcceptsReplacementOid : std::false_type {};
80
81template <typename T, typename Buffer>
82struct FormatterAcceptsReplacementOid<
83 T, Buffer,
84 USERVER_NAMESPACE::utils::void_t<decltype(std::declval<T&>()(
85 std::declval<const UserTypes&>(), std::declval<Buffer&>(),
86 std::declval<Oid>()))>> : std::true_type {};
87
88} // namespace detail
89
90template <typename T, typename Buffer>
91void WriteRawBinary(const UserTypes& types, Buffer& buffer, const T& value,
92 [[maybe_unused]] Oid replace_oid = kInvalidOid) {
93 traits::CheckFormatter<T>();
94 static constexpr auto size_len = sizeof(Integer);
95 if (traits::GetSetNull<T>::IsNull(value)) {
96 io::WriteBuffer(types, buffer, kPgNullBufferSize);
97 } else {
98 using BufferFormatter = typename traits::IO<T>::FormatterType;
99 using AcceptsReplacementOid =
100 detail::FormatterAcceptsReplacementOid<BufferFormatter, Buffer>;
101 auto len_start = buffer.size();
102 buffer.resize(buffer.size() + size_len);
103 auto size_before = buffer.size();
104 if constexpr (AcceptsReplacementOid{}) {
105 BufferFormatter{value}(types, buffer, replace_oid);
106 } else {
107 io::WriteBuffer(types, buffer, value);
108 }
109 Integer bytes = buffer.size() - size_before;
110 BufferWriter(bytes)(buffer.begin() + len_start);
111 }
112}
113
114} // namespace storages::postgres::io
115
116USERVER_NAMESPACE_END