src/detail/serializer.hpp

100.0% Lines (17/17) 81.2% List of functions (13/16) 75.0% Branches (3/4)
serializer.hpp
f(x) Functions (16)
Function Calls Lines Branches Blocks
boost::burl::detail::serializer::encoder::~encoder() :41 35x 100.0% 100.0% boost::burl::detail::serializer::is_done() const :76 94x 100.0% 100.0% boost::burl::detail::serializer::stream() const :82 2x 100.0% 100.0% boost::burl::detail::serializer::message() const :88 2x 100.0% 100.0% boost::burl::detail::serializer::reset(boost::http::message_base*, boost::burl::detail::serializer::encoder*, bool) :101 72x 100.0% 50.0% 75.0% boost::capy::task<boost::capy::io_result<unsigned long> > boost::burl::detail::serializer::write_some<boost::capy::const_buffer>(boost::capy::const_buffer) :191 4x 100.0% 100.0% 44.0% boost::capy::task<boost::capy::io_result<unsigned long> > boost::burl::detail::serializer::write_some<boost::capy::detail::slice_of<boost::capy::const_buffer> >(boost::capy::detail::slice_of<boost::capy::const_buffer>) :191 67x 100.0% 100.0% 44.0% boost::capy::task<boost::capy::io_result<unsigned long> > boost::burl::detail::serializer::write_some<boost::capy::detail::slice_of<std::span<boost::capy::const_buffer const, 18446744073709551615ul> > >(boost::capy::detail::slice_of<std::span<boost::capy::const_buffer const, 18446744073709551615ul> >) :191 0 0.0% 0.0% 0.0% boost::capy::task<boost::capy::io_result<unsigned long> > boost::burl::detail::serializer::write_some<std::span<boost::capy::const_buffer const, 18446744073709551615ul> >(std::span<boost::capy::const_buffer const, 18446744073709551615ul>) :191 0 0.0% 0.0% 0.0% boost::capy::task<boost::capy::io_result<unsigned long> > boost::burl::detail::serializer::write<boost::capy::const_buffer>(boost::capy::const_buffer) :206 50x 100.0% 100.0% boost::capy::task<boost::capy::io_result<unsigned long> > boost::burl::detail::serializer::write<std::span<boost::capy::const_buffer const, 18446744073709551615ul> >(std::span<boost::capy::const_buffer const, 18446744073709551615ul>) :206 0 0.0% 0.0% boost::capy::task<boost::capy::io_result<unsigned long> > boost::burl::detail::serializer::write_eof<boost::capy::const_buffer>(boost::capy::const_buffer) :214 16x 100.0% 100.0% 44.0% boost::capy::task<boost::capy::io_result<unsigned long> > boost::burl::detail::serializer::write_eof<std::array<boost::capy::const_buffer, 24ul> >(std::array<boost::capy::const_buffer, 24ul>) :214 1x 100.0% 100.0% 44.0% boost::capy::task<boost::capy::io_result<unsigned long> > boost::burl::detail::serializer::write_eof<std::array<boost::capy::const_buffer, 2ul> >(std::array<boost::capy::const_buffer, 2ul>) :214 1x 100.0% 100.0% 44.0% boost::capy::task<boost::capy::io_result<unsigned long> > boost::burl::detail::serializer::write_eof<std::array<boost::capy::const_buffer, 3ul> >(std::array<boost::capy::const_buffer, 3ul>) :214 1x 100.0% 100.0% 44.0% boost::capy::task<boost::capy::io_result<unsigned long> > boost::burl::detail::serializer::write_eof<std::span<boost::capy::const_buffer const, 18446744073709551615ul> >(std::span<boost::capy::const_buffer const, 18446744073709551615ul>) :214 2x 100.0% 100.0% 44.0%
Line Branch TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Mohammad Nejati
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/burl
8 //
9
10 #ifndef BOOST_BURL_SRC_DETAIL_SERIALIZER_HPP
11 #define BOOST_BURL_SRC_DETAIL_SERIALIZER_HPP
12
13 #include <boost/burl/error.hpp>
14
15 #include <boost/capy/buffers/buffer_copy.hpp>
16 #include <boost/capy/buffers/buffer_param.hpp>
17 #include <boost/capy/io/any_write_stream.hpp>
18 #include <boost/capy/io_task.hpp>
19 #include <boost/capy/write.hpp>
20 #include <boost/http/message_base.hpp>
21
22 namespace boost
23 {
24 namespace burl
25 {
26 namespace detail
27 {
28
29 class serializer
30 {
31 public:
32 struct encoder
33 {
34 struct result
35 {
36 std::size_t consumed;
37 std::size_t produced;
38 std::error_code ec;
39 };
40
41 35x virtual ~encoder() = default;
42
43 virtual result
44 process(
45 capy::mutable_buffer out,
46 capy::const_buffer in,
47 bool eof) = 0;
48 };
49
50 struct config
51 {
52 std::size_t out_buffer = 64 * 1024;
53 std::size_t min_prepare = 4 * 1024;
54 std::size_t direct_thr = 2 * 1024;
55 std::size_t enc_buffer = 8 * 1024;
56 std::size_t enc_thr = 4 * 1024;
57 };
58
59 serializer(
60 config const& cfg,
61 capy::any_write_stream* stream = nullptr);
62
63 serializer(serializer&& other) noexcept;
64
65 serializer&
66 operator=(serializer&& other) noexcept;
67
68 serializer(const serializer&) = delete;
69
70 serializer&
71 operator=(const serializer&) = delete;
72
73 ~serializer();
74
75 bool
76 94x is_done() const noexcept
77 {
78 94x return done_;
79 }
80
81 capy::any_write_stream*
82 2x stream() const noexcept
83 {
84 2x return stream_;
85 }
86
87 http::message_base*
88 2x message() const noexcept
89 {
90 2x return msg_;
91 }
92
93 void
94 reset(
95 capy::any_write_stream* stream,
96 http::message_base* msg,
97 encoder* enc = nullptr,
98 bool head = false) noexcept;
99
100 void
101 72x reset(
102 http::message_base* msg,
103 encoder* enc = nullptr,
104 bool head = false) noexcept
105 {
106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72x BOOST_ASSERT(stream_);
107 72x reset(stream_, msg, enc, head);
108 72x }
109
110 template<capy::ConstBufferSequence Buffers>
111 capy::io_task<std::size_t>
112 write_some(Buffers buffers);
113
114 template<capy::ConstBufferSequence Buffers>
115 capy::io_task<std::size_t>
116 write(Buffers buffers);
117
118 template<capy::ConstBufferSequence Buffers>
119 capy::io_task<std::size_t>
120 write_eof(Buffers buffers);
121
122 capy::io_task<>
123 write_eof();
124
125 std::span<capy::mutable_buffer>
126 prepare(std::span<capy::mutable_buffer> dest);
127
128 capy::io_task<>
129 commit(std::size_t n);
130
131 capy::io_task<>
132 commit_eof(std::size_t n);
133
134 private:
135 std::size_t
136 capacity() const noexcept;
137
138 capy::mutable_buffer
139 do_prepare() noexcept;
140
141 void
142 do_commit(std::size_t n) noexcept;
143
144 bool
145 should_coalesce(std::size_t avail) const noexcept;
146
147 void
148 finalize(std::size_t remaining) noexcept;
149
150 void
151 decide_framing(std::size_t remaining) noexcept;
152
153 capy::io_task<std::size_t>
154 process(
155 std::span<capy::const_buffer const> tail,
156 bool eof);
157
158 capy::io_task<std::size_t>
159 encode(
160 std::span<capy::const_buffer const> tail,
161 bool eof);
162
163 capy::io_task<std::size_t>
164 flush(
165 std::span<capy::const_buffer const> tail,
166 bool eof);
167
168 static constexpr std::size_t margin = 24;
169
170 capy::any_write_stream* stream_;
171 http::message_base* msg_ = nullptr;
172 encoder* enc_ = nullptr;
173 std::size_t min_prepare_;
174 std::size_t direct_thr_;
175 std::size_t enc_thr_;
176 unsigned char* out_;
177 std::size_t out_cap_;
178 std::size_t out_len_ = 0;
179 unsigned char* in_;
180 std::size_t in_cap_;
181 std::size_t in_len_ = 0;
182 std::uint64_t total_body_ = 0;
183 bool head_ = false;
184 bool enc_started_ = false;
185 bool hdr_sent_ = false;
186 bool done_ = false;
187 };
188
189 template<capy::ConstBufferSequence Buffers>
190 capy::io_task<std::size_t>
191
1/1
✓ Branch 1 taken 71 times.
71x serializer::
192 write_some(Buffers buffers)
193 {
194 auto const avail = capy::buffer_size(buffers);
195 if(should_coalesce(avail))
196 {
197 do_commit(capy::buffer_copy(do_prepare(), buffers));
198 co_return { {}, avail };
199 }
200 co_return co_await process(
201 capy::buffer_param(buffers).data(), false);
202 142x }
203
204 template<capy::ConstBufferSequence Buffers>
205 capy::io_task<std::size_t>
206 50x serializer::
207 write(Buffers buffers)
208 {
209 50x return capy::write(*this, std::move(buffers));
210 }
211
212 template<capy::ConstBufferSequence Buffers>
213 capy::io_task<std::size_t>
214
1/1
✓ Branch 1 taken 21 times.
21x serializer::
215 write_eof(Buffers buffers)
216 {
217 finalize(capy::buffer_size(buffers));
218 capy::buffer_param bp(buffers);
219 std::size_t sum = 0;
220 for(;;)
221 {
222 bool eof = !bp.more();
223 auto [ec, n] = co_await process(bp.data(), eof);
224 sum += n;
225 bp.consume(n);
226 if(ec || eof)
227 co_return { ec, sum };
228 }
229 42x }
230
231 } // namespace detail
232 } // namespace burl
233 } // namespace boost
234
235 #endif
236