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 : : buffered_base
38 : {
39 : /** The results of consuming data.
40 : */
41 : struct results
42 : {
43 : /** The error, if any occurred.
44 : */
45 : system::error_code ec;
46 :
47 : /** The number of bytes consumed in the input.
48 : */
49 : std::size_t bytes = 0;
50 :
51 : /** Accumulate results.
52 : */
53 : results&
54 : operator+=(
55 : results const& rv) noexcept;
56 : };
57 :
58 : /** Consume data.
59 :
60 : This function attempts to write to the
61 : sink, by transferring data from the given
62 : constant buffer sequence.
63 : The return value indicates the number of
64 : bytes consumed from the buffers and the
65 : error if any occurred.
66 :
67 : @par Preconditions
68 : @li @ref init was called, and
69 : @li This is the first call to @ref write,
70 : or the last value of `more` was `true`.
71 :
72 : @par Postconditions
73 : @code
74 : rv.ec.failed() == true || rv.bytes == buffer_size(bs)
75 : @endcode
76 :
77 : @return The result of the operation.
78 :
79 : @param bs The buffers to use.
80 : Each buffer in the sequence will be
81 : consumed completely before the next
82 : buffer is accessed.
83 :
84 : @param more `true` if there will be one
85 : or more subsequent calls to @ref write.
86 : */
87 : template<class ConstBufferSequence>
88 : results
89 9 : write(
90 : ConstBufferSequence const& bs,
91 : bool more)
92 : {
93 : static_assert(
94 : buffers::is_const_buffer_sequence<
95 : ConstBufferSequence>::value,
96 : "Type requirements not met");
97 :
98 9 : return write_impl(bs, more);
99 : }
100 :
101 : #ifdef BOOST_HTTP_PROTO_DOCS
102 : protected:
103 : #else
104 : private:
105 : #endif
106 : /** Derived class override.
107 :
108 : This pure virtual function is called by
109 : the implementation and must be overriden.
110 : The callee should attempt to consume data
111 : from the given constant buffer.
112 : The return value must be set to indicate
113 : the number of bytes consumed from the
114 : buffers, and the error if any occurred.
115 :
116 : @par Preconditions
117 : @li @ref init was called, and
118 : @li This is the first call to @ref on_write,
119 : or the last value of `more` was `true`.
120 :
121 : @return The result of the operation.
122 :
123 : @param b The buffer to use.
124 : If `more` is true then the results
125 : must indicate that the buffer was
126 : consumed completely, or that an error
127 : occurred.
128 :
129 : @param more `true` if there will be one
130 : or more subsequent calls to @ref write.
131 : */
132 : virtual
133 : results
134 : on_write(
135 : buffers::const_buffer b,
136 : bool more) = 0;
137 :
138 : /** Derived class override.
139 :
140 : This pure virtual function is called by
141 : the implementation and must be overriden.
142 : The callee should attempt to consume data
143 : from the given constant buffer sequence.
144 : The return value must be set to indicate
145 : the number of bytes consumed from the
146 : buffers, and the error if any occurred.
147 :
148 : @par Preconditions
149 : @li @ref init was called, and
150 : @li This is the first call to @ref on_write,
151 : or the last value of `more` was `true`.
152 :
153 : @return The result of the operation.
154 :
155 : @param bs The buffer sequence to use.
156 : Each buffer in the sequence must
157 : be completely consumed before data
158 : is consumed from the next buffer.
159 : If `more` is true then the results
160 : must indicate that the buffer was
161 : consumed completely, or that an error
162 : occurred.
163 :
164 : @param more `true` if there will be one
165 : or more subsequent calls to @ref write.
166 : */
167 : virtual
168 : results
169 : on_write(
170 : buffers::const_buffer_span bs,
171 : bool more);
172 :
173 : private:
174 : results
175 2 : write_impl(
176 : buffers::const_buffer const& b,
177 : bool more)
178 : {
179 2 : return on_write(b, more);
180 : }
181 :
182 : results
183 2 : write_impl(
184 : buffers::mutable_buffer const& b,
185 : bool more)
186 : {
187 2 : return on_write(b, more);
188 : }
189 :
190 : results
191 5 : write_impl(
192 : buffers::const_buffer_span const& bs,
193 : bool more)
194 : {
195 5 : return on_write(bs, more);
196 : }
197 :
198 : template<class T>
199 : results
200 : write_impl(T const&, bool);
201 : };
202 :
203 : //------------------------------------------------
204 :
205 : /** Metafunction which determines if T is a sink
206 :
207 : @see
208 : @ref sink.
209 : */
210 : #ifdef BOOST_HTTP_PROTO_DOCS
211 : template<class T>
212 : using is_sink = __see_below__;
213 : #else
214 : template<class T>
215 : using is_sink =
216 : std::is_convertible<
217 : typename std::decay<T>::type*,
218 : sink*>;
219 : #endif
220 :
221 : } // http_proto
222 : } // boost
223 :
224 : #include <boost/http_proto/impl/sink.hpp>
225 :
226 : #endif
|