Line data Source code
1 : //
2 : // Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
3 : //
4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 : //
7 : // Official repository: https://github.com/cppalliance/http_proto
8 : //
9 :
10 : #ifndef BOOST_HTTP_PROTO_SINK_HPP
11 : #define BOOST_HTTP_PROTO_SINK_HPP
12 :
13 : #include <boost/http_proto/detail/config.hpp>
14 : #include <boost/http_proto/buffered_base.hpp>
15 : #include <boost/buffers/const_buffer_span.hpp>
16 : #include <boost/buffers/type_traits.hpp>
17 : #include <boost/system/error_code.hpp>
18 : #include <cstddef>
19 : #include <type_traits>
20 :
21 : namespace boost {
22 : namespace http_proto {
23 :
24 : /** An algorithm for consuming buffers of data.
25 :
26 : This interface abstracts the consumption of
27 : a finite stream of data, passed by reading
28 : from caller-provided buffers until there
29 : is no more input data.
30 :
31 : @par Thread Safety
32 : Non-const member functions may not be
33 : called concurrently on the same instance.
34 : */
35 : struct BOOST_HTTP_PROTO_DECL
36 : sink
37 : {
38 : /** The results of consuming data.
39 : */
40 : struct results
41 : {
42 : /** The error, if any occurred.
43 : */
44 : system::error_code ec;
45 :
46 : /** The number of bytes consumed in the input.
47 : */
48 : std::size_t bytes = 0;
49 :
50 : /** Accumulate results.
51 : */
52 : results&
53 : operator+=(
54 : results const& rv) noexcept;
55 : };
56 :
57 : /** Consume data.
58 :
59 : This function attempts to write to the
60 : sink, by transferring data from the given
61 : constant buffer sequence.
62 : The return value indicates the number of
63 : bytes consumed from the buffers and the
64 : error if any occurred.
65 :
66 : @par Preconditions
67 : @li @ref init was called, and
68 : @li This is the first call to @ref write,
69 : or the last value of `more` was `true`.
70 :
71 : @par Postconditions
72 : @code
73 : rv.ec.failed() == true || rv.bytes == buffer_size(bs)
74 : @endcode
75 :
76 : @return The result of the operation.
77 :
78 : @param bs The buffers to use.
79 : Each buffer in the sequence will be
80 : consumed completely before the next
81 : buffer is accessed.
82 :
83 : @param more `true` if there will be one
84 : or more subsequent calls to @ref write.
85 : */
86 : template<class ConstBufferSequence>
87 : results
88 20368 : write(
89 : ConstBufferSequence const& bs,
90 : bool more)
91 : {
92 : static_assert(
93 : buffers::is_const_buffer_sequence<
94 : ConstBufferSequence>::value,
95 : "Type requirements not met");
96 :
97 20368 : return write_impl(bs, more);
98 : }
99 :
100 : #ifdef BOOST_HTTP_PROTO_DOCS
101 : protected:
102 : #else
103 : private:
104 : #endif
105 : /** Derived class override.
106 :
107 : This pure virtual function is called by
108 : the implementation and must be overriden.
109 : The callee should attempt to consume data
110 : from the given constant buffer.
111 : The return value must be set to indicate
112 : the number of bytes consumed from the
113 : buffers, and the error if any occurred.
114 :
115 : @par Preconditions
116 : @li @ref init was called, and
117 : @li This is the first call to @ref on_write,
118 : or the last value of `more` was `true`.
119 :
120 : @return The result of the operation.
121 :
122 : @param b The buffer to use.
123 : If `more` is true then the results
124 : must indicate that the buffer was
125 : consumed completely, or that an error
126 : occurred.
127 :
128 : @param more `true` if there will be one
129 : or more subsequent calls to @ref write.
130 : */
131 : virtual
132 : results
133 : on_write(
134 : buffers::const_buffer b,
135 : bool more) = 0;
136 :
137 : /** Derived class override.
138 :
139 : This pure virtual function is called by
140 : the implementation and must be overriden.
141 : The callee should attempt to consume data
142 : from the given constant buffer sequence.
143 : The return value must be set to indicate
144 : the number of bytes consumed from the
145 : buffers, and the error if any occurred.
146 :
147 : @par Preconditions
148 : @li @ref init was called, and
149 : @li This is the first call to @ref on_write,
150 : or the last value of `more` was `true`.
151 :
152 : @return The result of the operation.
153 :
154 : @param bs The buffer sequence to use.
155 : Each buffer in the sequence must
156 : be completely consumed before data
157 : is consumed from the next buffer.
158 : If `more` is true then the results
159 : must indicate that the buffer was
160 : consumed completely, or that an error
161 : occurred.
162 :
163 : @param more `true` if there will be one
164 : or more subsequent calls to @ref write.
165 : */
166 : virtual
167 : results
168 : on_write(
169 : buffers::const_buffer_span bs,
170 : bool more);
171 :
172 : private:
173 : results
174 2 : write_impl(
175 : buffers::const_buffer const& b,
176 : bool more)
177 : {
178 2 : return on_write(b, more);
179 : }
180 :
181 : results
182 2 : write_impl(
183 : buffers::mutable_buffer const& b,
184 : bool more)
185 : {
186 2 : return on_write(b, more);
187 : }
188 :
189 : results
190 5 : write_impl(
191 : buffers::const_buffer_span const& bs,
192 : bool more)
193 : {
194 5 : return on_write(bs, more);
195 : }
196 :
197 : template<class T>
198 : results
199 : write_impl(T const&, bool);
200 : };
201 :
202 : //------------------------------------------------
203 :
204 : /** Metafunction which determines if T is a sink
205 :
206 : @see
207 : @ref sink.
208 : */
209 : #ifdef BOOST_HTTP_PROTO_DOCS
210 : template<class T>
211 : using is_sink = __see_below__;
212 : #else
213 : template<class T>
214 : using is_sink =
215 : std::is_convertible<
216 : typename std::decay<T>::type*,
217 : sink*>;
218 : #endif
219 :
220 : } // http_proto
221 : } // boost
222 :
223 : #include <boost/http_proto/impl/sink.hpp>
224 :
225 : #endif
|