GCC Code Coverage Report


Directory: libs/http_proto/
File: boost/http_proto/serializer.hpp
Date: 2024-03-19 15:22:01
Exec Total Coverage
Lines: 11 15 73.3%
Functions: 7 9 77.8%
Branches: 0 0 -%

Line Branch Exec Source
1 //
2 // Copyright (c) 2019 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_SERIALIZER_HPP
11 #define BOOST_HTTP_PROTO_SERIALIZER_HPP
12
13 #include <boost/http_proto/buffered_base.hpp>
14 #include <boost/http_proto/detail/config.hpp>
15 #include <boost/http_proto/detail/array_of_buffers.hpp>
16 #include <boost/http_proto/detail/header.hpp>
17 #include <boost/http_proto/detail/workspace.hpp>
18 #include <boost/buffers/circular_buffer.hpp>
19 #include <boost/buffers/mutable_buffer_span.hpp>
20 #include <boost/buffers/range.hpp>
21 #include <boost/buffers/type_traits.hpp>
22 #include <boost/buffers/type_traits.hpp>
23 #include <boost/system/result.hpp>
24 #include <type_traits>
25
26 namespace boost {
27 namespace http_proto {
28
29 #ifndef BOOST_HTTP_PROTO_DOCS
30 class request;
31 class response;
32 class request_view;
33 class response_view;
34 class message_view_base;
35 #endif
36
37 /** A serializer for HTTP/1 messages
38
39 This is used to serialize one or more complete
40 HTTP/1 messages. Each message consists of a
41 required header followed by an optional body.
42 */
43 class BOOST_SYMBOL_VISIBLE
44 serializer
45 {
46 public:
47 /** A ConstBuffers representing the output
48 */
49 class const_buffers_type;
50
51 struct source;
52 struct stream;
53
54 /** Destructor
55 */
56 BOOST_HTTP_PROTO_DECL
57 ~serializer();
58
59 /** Constructor
60 */
61 BOOST_HTTP_PROTO_DECL
62 serializer();
63
64 /** Constructor
65 */
66 BOOST_HTTP_PROTO_DECL
67 serializer(
68 serializer&&) noexcept;
69
70 /** Constructor
71 */
72 BOOST_HTTP_PROTO_DECL
73 explicit
74 serializer(
75 std::size_t buffer_size);
76
77 //--------------------------------------------
78
79 /** Prepare the serializer for a new stream
80 */
81 BOOST_HTTP_PROTO_DECL
82 void
83 reset() noexcept;
84
85 /** Prepare the serializer for a new message
86
87 The message will not contain a body.
88 Changing the contents of the message
89 after calling this function and before
90 @ref is_done returns `true` results in
91 undefined behavior.
92 */
93 void
94 4 start(
95 message_view_base const& m)
96 {
97 4 start_empty(m);
98 4 }
99
100 /** Prepare the serializer for a new message
101
102 Changing the contents of the message
103 after calling this function and before
104 @ref is_done returns `true` results in
105 undefined behavior.
106
107 @par Constraints
108 @code
109 is_const_buffers< ConstBuffers >::value == true
110 @endcode
111 */
112 template<
113 class ConstBufferSequence
114 #ifndef BOOST_HTTP_PROTO_DOCS
115 ,class = typename
116 std::enable_if<
117 buffers::is_const_buffer_sequence<
118 ConstBufferSequence>::value
119 >::type
120 #endif
121 >
122 void
123 start(
124 message_view_base const& m,
125 ConstBufferSequence&& body);
126
127 /** Prepare the serializer for a new message
128
129 Changing the contents of the message
130 after calling this function and before
131 @ref is_done returns `true` results in
132 undefined behavior.
133 */
134 template<
135 class Source
136 #ifndef BOOST_HTTP_PROTO_DOCS
137 ,class = typename std::enable_if<
138 std::is_convertible<
139 typename std::decay<Source>::type*,
140 source*>::value>::type
141 #endif
142 >
143 auto
144 start(
145 message_view_base const& m,
146 Source&& body) ->
147 typename std::decay<
148 Source>::type&;
149
150 //--------------------------------------------
151
152 BOOST_HTTP_PROTO_DECL
153 stream
154 start_stream(
155 message_view_base const& m);
156
157 //--------------------------------------------
158
159 /** Return true if serialization is complete.
160 */
161 bool
162 41 is_done() const noexcept
163 {
164 41 return is_done_;
165 }
166
167 /** Return the output area.
168
169 This function will serialize some or
170 all of the content and return the
171 corresponding output buffers.
172
173 @par Preconditions
174 @code
175 this->is_done() == false
176 @endcode
177 */
178 BOOST_HTTP_PROTO_DECL
179 auto
180 prepare() ->
181 system::result<
182 const_buffers_type>;
183
184 /** Consume bytes from the output area.
185 */
186 BOOST_HTTP_PROTO_DECL
187 void
188 consume(std::size_t n);
189
190 private:
191 static void copy(
192 buffers::const_buffer*,
193 buffers::const_buffer const*,
194 std::size_t n) noexcept;
195 auto
196 make_array(std::size_t n) ->
197 detail::array_of_const_buffers;
198
199 BOOST_HTTP_PROTO_DECL void start_init(message_view_base const&);
200 BOOST_HTTP_PROTO_DECL void start_empty(message_view_base const&);
201 BOOST_HTTP_PROTO_DECL void start_buffers(message_view_base const&);
202 BOOST_HTTP_PROTO_DECL void start_source(message_view_base const&, source*);
203
204 enum class style
205 {
206 empty,
207 buffers,
208 source,
209 stream
210 };
211
212 static
213 constexpr
214 std::size_t
215 chunked_overhead_ =
216 16 + // size
217 2 + // CRLF
218 2 + // CRLF
219 1 + // "0"
220 2 + // CRLF
221 2; // CRLF
222
223 detail::workspace ws_;
224 detail::array_of_const_buffers buf_;
225 source* src_;
226
227 buffers::circular_buffer tmp0_;
228 buffers::circular_buffer tmp1_;
229 detail::array_of_const_buffers out_;
230
231 buffers::const_buffer* hp_; // header
232
233 style st_;
234 bool more_;
235 bool is_done_;
236 bool is_chunked_;
237 bool is_expect_continue_;
238 };
239
240 //------------------------------------------------
241
242 /** An algorithm for producing buffers of data.
243
244 This interface abstracts the production of
245 a finite stream of data, returned by writing
246 into caller-provided buffers until there
247 is no more output data.
248
249 @par Thread Safety
250 Non-const member functions may not be
251 called concurrently on the same instance.
252 */
253 struct BOOST_HTTP_PROTO_DECL
254 serializer::source
255 : buffered_base
256 {
257 /** The results of producing data.
258 */
259 struct results
260 {
261 /** The error, if any occurred.
262 */
263 system::error_code ec;
264
265 /** The number of bytes produced in the output.
266 */
267 std::size_t bytes = 0;
268
269 /** True if there will be no more output.
270 */
271 bool finished = false;
272
273 /** Accumulate results.
274 */
275 results&
276 operator+=(
277 results const& rv) noexcept;
278 };
279
280 /** Produce data.
281
282 This function attempts to read from the
283 source, placing the data into the given
284 mutable buffer sequence.
285 The return value indicates the number of
286 bytes placed into the buffers, the error
287 if any occurred, and a `bool` indicating
288 whether or not there is more data
289 remaining in the source.
290
291 @par Preconditions
292 @li @ref init was called, and
293 @li There is more data remaining.
294
295 @return The result of the operation.
296
297 @param bs The buffers to use.
298 Each buffer in the sequence will
299 be filled completely before data
300 is placed in the next buffer.
301 */
302 template<class MutableBufferSequence>
303 results
304 31 read(MutableBufferSequence const& bs)
305 {
306 static_assert(
307 buffers::is_mutable_buffer_sequence<
308 MutableBufferSequence>::value,
309 "Type requirements not met");
310
311 31 return read_impl(bs);
312 }
313
314 #ifdef BOOST_HTTP_PROTO_DOCS
315 protected:
316 #else
317 private:
318 #endif
319 /** Derived class override.
320
321 This pure virtual function is called by
322 the implementation and must be overriden.
323 The callee should attempt to place data
324 into the given mutable buffer.
325 The return value must be set to indicate
326 the number of bytes placed into the
327 buffers, the error if any occurred,
328 and a `bool` indicating whether or
329 not there is more data remaining
330 in the source.
331
332 @par Preconditions
333 @li @ref init was called, and
334 @li There is more data remaining.
335
336 @return The result of the operation.
337
338 @param b The buffer to use.
339 If this is not filled completely,
340 then the result must indicate failure
341 or that no more data remains (or both).
342 */
343 virtual
344 results
345 on_read(
346 buffers::mutable_buffer b) = 0;
347
348 /** Derived class override.
349
350 This pure virtual function is called by
351 the implementation and must be overriden.
352 The callee should attempt to place data
353 into the given mutable buffer sequence.
354 The return value must be set to indicate
355 the number of bytes placed into the
356 buffers, the error if any occurred,
357 and a `bool` indicating whether or
358 not there is more data remaining
359 in the source.
360
361 @par Preconditions
362 @li @ref init was called, and
363 @li There is more data remaining.
364
365 @return The result of the operation.
366
367 @param bs The buffer sequence to use.
368 Each buffer in the sequence must
369 be filled completely before data
370 is placed in the next buffer.
371 If the buffers are not filled
372 completely, then the result must
373 indicate failure or that no more
374 data remains (or both).
375 */
376 virtual
377 results
378 on_read(
379 buffers::mutable_buffer_span bs);
380
381 private:
382 results
383 2 read_impl(
384 buffers::mutable_buffer const& b)
385 {
386 2 return on_read(b);
387 }
388
389 results
390 5 read_impl(
391 buffers::mutable_buffer_span const& bs)
392 {
393 5 return on_read(bs);
394 }
395
396 template<class T>
397 results
398 read_impl(T const&);
399 };
400
401 //------------------------------------------------
402
403 struct serializer::stream
404 {
405 /** Constructor.
406 */
407 stream() = default;
408
409 /** Constructor.
410 */
411 stream(stream const&) = default;
412
413 /** Constructor.
414 */
415 stream& operator=
416 (stream const&) = default;
417
418 using buffers_type =
419 buffers::mutable_buffer_pair;
420
421 BOOST_HTTP_PROTO_DECL
422 std::size_t
423 capacity() const;
424
425 BOOST_HTTP_PROTO_DECL
426 std::size_t
427 size() const;
428
429 BOOST_HTTP_PROTO_DECL
430 buffers_type
431 prepare(std::size_t n) const;
432
433 BOOST_HTTP_PROTO_DECL
434 void
435 commit(std::size_t n) const;
436
437 BOOST_HTTP_PROTO_DECL
438 void
439 close() const;
440
441 private:
442 friend class serializer;
443
444 explicit
445 stream(
446 serializer& sr) noexcept
447 : sr_(&sr)
448 {
449 }
450
451 serializer* sr_ = nullptr;
452 };
453
454 } // http_proto
455 } // boost
456
457 #include <boost/http_proto/impl/serializer.hpp>
458
459 #endif
460