src/detail/serializer.hpp

100.0% Lines (15/15) 66.7% List of functions (10/15) 100.0% Branches (3/3)
serializer.hpp
f(x) Functions (15)
Function Calls Lines Branches Blocks
boost::burl::detail::serializer::serializer(boost::capy::any_write_stream&, boost::http::request_base&) :39 3x 100.0% 100.0% boost::burl::detail::serializer::is_done() const :54 20x 100.0% 100.0% boost::capy::task<boost::capy::io_result<unsigned long> > boost::burl::detail::serializer::write_some<boost::capy::const_buffer>(boost::capy::const_buffer) :61 2x 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_impl<boost::capy::const_buffer>::data_view>(boost::capy::detail::slice_impl<boost::capy::const_buffer>::data_view) :61 27x 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_impl<std::array<boost::capy::const_buffer, 2ul> >::data_view>(boost::capy::detail::slice_impl<std::array<boost::capy::const_buffer, 2ul> >::data_view) :61 0 0.0% 0.0% 0.0% boost::capy::task<boost::capy::io_result<unsigned long> > boost::burl::detail::serializer::write_some<boost::capy::detail::slice_impl<std::span<boost::capy::const_buffer const, 18446744073709551615ul> >::data_view>(boost::capy::detail::slice_impl<std::span<boost::capy::const_buffer const, 18446744073709551615ul> >::data_view) :61 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>) :61 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) :81 27x 100.0% 100.0% 44.0% boost::capy::task<boost::capy::io_result<unsigned long> > boost::burl::detail::serializer::write<std::array<boost::capy::const_buffer, 2ul> >(std::array<boost::capy::const_buffer, 2ul>) :81 0 0.0% 0.0% 0.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>) :81 0 0.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) :99 4x 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>) :99 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>) :99 2x 100.0% 100.0% 44.0% boost::burl::detail::serializer::capacity() const :129 101x 100.0% 100.0% boost::burl::detail::serializer::writable() const :135 29x 100.0% 100.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/http/request_base.hpp>
14
15 #include <boost/capy/buffers.hpp>
16 #include <boost/capy/buffers/buffer_copy.hpp>
17 #include <boost/capy/buffers/buffer_param.hpp>
18 #include <boost/capy/buffers/buffer_slice.hpp>
19 #include <boost/capy/io/any_write_stream.hpp>
20 #include <boost/capy/io_task.hpp>
21
22 namespace boost
23 {
24 namespace burl
25 {
26 namespace detail
27 {
28
29 class serializer
30 {
31 public:
32 struct config
33 {
34 std::size_t buffer_size = 64 * 1024;
35 std::size_t min_prepare = 32 * 1024;
36 std::size_t min_direct = 8 * 1024;
37 };
38
39 3x serializer(
40 capy::any_write_stream& stream,
41 http::request_base& req)
42 3x : serializer(stream, req, {})
43 {
44 3x }
45
46 serializer(
47 capy::any_write_stream& stream,
48 http::request_base& req,
49 config cfg);
50
51 ~serializer();
52
53 bool
54 20x is_done() const noexcept
55 {
56 20x return done_;
57 }
58
59 template<capy::ConstBufferSequence Buffers>
60 capy::io_task<std::size_t>
61
1/1
✓ Branch 1 taken 29 times.
29x write_some(Buffers buffers)
62 {
63 auto const avail = capy::buffer_size(buffers);
64
65 if(avail < cfg_.min_direct)
66 {
67 if(avail >= capacity())
68 if(auto [ec, _] = co_await drain({}, false); ec)
69 co_return { ec, 0 };
70 auto n = capy::buffer_copy(writable(), buffers);
71 avail_ += n;
72 co_return { {}, n };
73 }
74
75 capy::const_buffer_param<Buffers> bp(buffers);
76 co_return co_await drain(bp.data(), false);
77 58x }
78
79 template<capy::ConstBufferSequence Buffers>
80 capy::io_task<std::size_t>
81
1/1
✓ Branch 1 taken 27 times.
27x write(Buffers buffers)
82 {
83 auto const avail = capy::buffer_size(buffers);
84 auto slice = capy::buffer_slice(buffers);
85 std::size_t written = 0;
86 while(written < avail)
87 {
88 auto [ec, n] = co_await write_some(slice.data());
89 written += n;
90 if(ec)
91 co_return { ec, written };
92 slice.remove_prefix(n);
93 }
94 co_return { {}, avail };
95 54x }
96
97 template<capy::ConstBufferSequence Buffers>
98 capy::io_task<std::size_t>
99
1/1
✓ Branch 1 taken 7 times.
7x write_eof(Buffers buffers)
100 {
101 decide_framing(capy::buffer_size(buffers));
102
103 capy::const_buffer_param<Buffers> bp(buffers);
104
105 if(!bp.more())
106 co_return co_await drain(bp.data(), true);
107
108 auto [ec1, n] = co_await write(buffers);
109 if(ec1)
110 co_return { ec1, n };
111 auto [ec2, _] = co_await drain({}, true);
112 co_return { ec2, n };
113 14x }
114
115 capy::io_task<>
116 write_eof();
117
118 std::span<capy::mutable_buffer>
119 prepare(std::span<capy::mutable_buffer> dest);
120
121 capy::io_task<>
122 commit(std::size_t n);
123
124 capy::io_task<>
125 commit_eof(std::size_t n);
126
127 private:
128 std::size_t
129 101x capacity() const noexcept
130 {
131 101x return cfg_.buffer_size - avail_;
132 }
133
134 capy::mutable_buffer
135 29x writable() const noexcept
136 {
137 29x return { storage_ + avail_, capacity() };
138 }
139
140 void
141 decide_framing(std::size_t remaining) noexcept;
142
143 capy::io_task<std::size_t>
144 drain(
145 std::span<capy::const_buffer const> tail,
146 bool eof);
147
148 // TODO: replace this with capy's version
149 capy::io_task<std::size_t>
150 write_at_least(
151 std::span<capy::const_buffer> buffers,
152 std::size_t bytes);
153
154 capy::const_buffer
155 chunk_frame(std::size_t tail_size) noexcept;
156
157 static constexpr std::size_t margin = 24;
158
159 capy::any_write_stream& stream_;
160 http::request_base& req_;
161 config cfg_;
162 unsigned char* storage_;
163 std::uint64_t total_body_ = 0;
164 std::size_t avail_ = 0;
165 bool hdr_sent_ = false;
166 bool done_ = false;
167 };
168
169 } // namespace detail
170 } // namespace burl
171 } // namespace boost
172
173 #endif
174