userver: userver/dump/operations.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
operations.hpp
1#pragma once
2
3#include <stdexcept>
4#include <string>
5#include <string_view>
6#include <type_traits>
7
8#include <userver/dump/fwd.hpp>
9#include <userver/dump/meta.hpp>
10
11USERVER_NAMESPACE_BEGIN
12
13namespace dump {
14
15/// Indicates a failure reading or writing a dump. No further operations
16/// should be performed with a failed dump.
17class Error final : public std::runtime_error {
18 public:
19 explicit Error(std::string message) : std::runtime_error(message) {}
20};
21
22/// A general interface for binary data output
23class Writer {
24 public:
25 virtual ~Writer() = default;
26
27 /// @brief Writes binary data
28 /// @details Calls ADL-found `Write(writer, data)`
29 /// @throws `Error` and any user-thrown `std::exception`
30 template <typename T>
31 void Write(const T& data);
32
33 /// @brief Must be called once all data has been written
34 /// @warning This method must not be called from within `Write`/`Read`
35 /// @throws `Error` on write operation failure
36 virtual void Finish() = 0;
37
38 protected:
39 /// @brief Writes binary data
40 /// @details Unlike `Write`, doesn't write the size of `data`
41 /// @throws `Error` on write operation failure
42 virtual void WriteRaw(std::string_view data) = 0;
43
44 friend void WriteStringViewUnsafe(Writer& writer, std::string_view value);
45};
46
47/// A general interface for binary data input
48class Reader {
49 public:
50 virtual ~Reader() = default;
51
52 /// @brief Reads binary data
53 /// @details Calls ADL-found `Read(reader, To<T>)`
54 /// @throws `Error` and any user-thrown `std::exception`
55 template <typename T>
56 T Read();
57
58 /// @brief Must be called once all data has been read
59 /// @warning This method must not be called from within `Write`/`Read`
60 /// @throws `Error` on read operation failure or if there is leftover data
61 virtual void Finish() = 0;
62
63 protected:
64 /// @brief Reads binary data
65 /// @note Invalidates the memory returned by the previous call of `ReadRaw`
66 /// @note Normally, exactly `max_size` bytes is returned. On end-of-file,
67 /// the amount of bytes returned can be less than `max_size`.
68 /// @throws `Error` on read operation failure
70
72};
73
74namespace impl {
75
76template <typename T>
77void CallWrite(Writer& writer, const T& data) {
78 Write(writer, data);
79}
80
81template <typename T>
82// NOLINTNEXTLINE(readability-const-return-type)
83T CallRead(Reader& reader, To<T> to) {
84 return Read(reader, to);
85}
86
87} // namespace impl
88
89template <typename T>
90void Writer::Write(const T& data) {
91 if constexpr (kIsWritable<T>) {
92 impl::CallWrite(*this, data);
93 } else if constexpr (std::is_aggregate_v<T>) {
94 static_assert(
95 !sizeof(T),
96 "Serialization is not implemented for this type. You "
97 "either forgot to specialize IsDumpedAggregate for your type "
98 "(see <userver/dump/aggregates.hpp>)"
99 "or you've got a non-standard data type and need to implement "
100 "`void Write(dump::Writer& writer, const T& data);` and put it "
101 "in the namespace of `T` or in `dump`.");
102 } else {
103 static_assert(
104 !sizeof(T),
105 "You either forgot to `#include <userver/dump/common_containers.hpp>`, "
106 "or you've got a non-standard data type and need to implement "
107 "`void Write(dump::Writer& writer, const T& data);` and put it "
108 "in the namespace of `T` or in `dump`.");
109 }
110}
111
112template <typename T>
113// NOLINTNEXTLINE(readability-const-return-type)
114T Reader::Read() {
115 if constexpr (kIsReadable<T>) {
116 return impl::CallRead(*this, To<T>{});
117 } else if constexpr (std::is_aggregate_v<T>) {
118 static_assert(
119 !sizeof(T),
120 "Serialization is not implemented for this type. You "
121 "either forgot to specialize IsDumpedAggregate for your type"
122 "(see <userver/dump/aggregates.hpp>) "
123 "or you've got a non-standard data type and need to implement "
124 "`T Read(dump::Reader& reader, dump::To<T>);` and put it "
125 "in the namespace of `T` or in `dump`.");
126 } else {
127 static_assert(
128 !sizeof(T),
129 "You either forgot to `#include <userver/dump/common_containers.hpp>`, "
130 "or you've got a non-standard data type and need to implement"
131 "`T Read(dump::Reader& reader, dump::To<T>);` and put it "
132 "in the namespace of `T` or in `dump`.");
133 return T{};
134 }
135}
136
137} // namespace dump
138
139USERVER_NAMESPACE_END