Line data Source code
1 : //
2 : // Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2025 Mohammad Nejati
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 : //
8 : // Official repository: https://github.com/cppalliance/http_proto
9 : //
10 :
11 : #ifndef BOOST_HTTP_PROTO_IMPL_SERIALIZER_HPP
12 : #define BOOST_HTTP_PROTO_IMPL_SERIALIZER_HPP
13 :
14 : #include <boost/http_proto/detail/except.hpp>
15 :
16 : namespace boost {
17 : namespace http_proto {
18 :
19 : class serializer::cbs_gen
20 : {
21 : public:
22 : struct stats_t
23 : {
24 : std::size_t size = 0;
25 : std::size_t count = 0;
26 : };
27 :
28 : // Return the next non-empty buffer or an
29 : // empty buffer if none remain.
30 : virtual
31 : buffers::const_buffer
32 : next() = 0;
33 :
34 : // Return the total size and count of
35 : // remaining non-empty buffers.
36 : virtual
37 : stats_t
38 : stats() const = 0;
39 :
40 : // Return true if there are no remaining
41 : // non-empty buffers.
42 : virtual
43 : bool
44 : is_empty() const = 0;
45 : };
46 :
47 : template<class ConstBufferSequence>
48 : class serializer::cbs_gen_impl
49 : : public cbs_gen
50 : {
51 : using it_t = decltype(buffers::begin(
52 : std::declval<ConstBufferSequence>()));
53 :
54 : ConstBufferSequence cbs_;
55 : it_t curr_;
56 :
57 : public:
58 : using const_buffer =
59 : buffers::const_buffer;
60 :
61 : explicit
62 24 : cbs_gen_impl(ConstBufferSequence cbs)
63 32 : : cbs_(std::move(cbs))
64 40 : , curr_(buffers::begin(cbs_))
65 : {
66 24 : }
67 :
68 : const_buffer
69 2056 : next() override
70 : {
71 2060 : while(curr_ != buffers::end(cbs_))
72 : {
73 : // triggers conversion operator
74 2042 : const_buffer buf = *curr_++;
75 2042 : if(buf.size() != 0)
76 2038 : return buf;
77 : }
78 18 : return {};
79 : }
80 :
81 : stats_t
82 8 : stats() const override
83 : {
84 8 : stats_t r;
85 104 : for(auto it = curr_; it != buffers::end(cbs_); ++it)
86 : {
87 : // triggers conversion operator
88 96 : const_buffer buf = *it;
89 96 : if(buf.size() != 0)
90 : {
91 46 : r.size += buf.size();
92 46 : r.count += 1;
93 : }
94 : }
95 8 : return r;
96 : }
97 :
98 : bool
99 4 : is_empty() const override
100 : {
101 4 : for(auto it = curr_; it != buffers::end(cbs_); ++it)
102 : {
103 : // triggers conversion operator
104 2 : const_buffer buf = *it;
105 2 : if(buf.size() != 0)
106 2 : return false;
107 : }
108 2 : return true;
109 : }
110 : };
111 :
112 : //---------------------------------------------------------
113 :
114 : template<
115 : class ConstBufferSequence,
116 : class>
117 : void
118 24 : serializer::
119 : start(
120 : message_base const& m,
121 : ConstBufferSequence&& cbs)
122 : {
123 : static_assert(buffers::is_const_buffer_sequence<
124 : ConstBufferSequence>::value,
125 : "ConstBufferSequence type requirements not met");
126 :
127 24 : set_headers(m);
128 24 : start_buffers_impl(
129 24 : ws().emplace<cbs_gen_impl<typename
130 24 : std::decay<ConstBufferSequence>::type>>(
131 : std::forward<ConstBufferSequence>(cbs)));
132 24 : }
133 :
134 : template<
135 : class ConstBufferSequence,
136 : class>
137 : void
138 : serializer::
139 : start(
140 : ConstBufferSequence&& cbs)
141 : {
142 : static_assert(buffers::is_const_buffer_sequence<
143 : ConstBufferSequence>::value,
144 : "ConstBufferSequence type requirements not met");
145 :
146 : start_buffers_impl(
147 : ws().emplace<cbs_gen_impl<typename
148 : std::decay<ConstBufferSequence>::type>>(
149 : std::forward<ConstBufferSequence>(cbs)));
150 : }
151 :
152 : template<
153 : class Source,
154 : class... Args,
155 : class>
156 : Source&
157 25 : serializer::
158 : start(
159 : message_base const& m,
160 : Args&&... args)
161 : {
162 : static_assert(
163 : !std::is_abstract<Source>::value, "");
164 : static_assert(
165 : std::is_constructible<Source, Args...>::value ||
166 : std::is_constructible<Source, detail::workspace&, Args...>::value,
167 : "The Source cannot be constructed with the given arguments");
168 :
169 25 : set_headers(m);
170 25 : auto& source = ws().emplace<Source>(
171 : std::forward<Args>(args)...);
172 25 : start_source_impl(source);
173 25 : return source;
174 : }
175 :
176 : template<
177 : class Source,
178 : class Arg0,
179 : class... Args,
180 : class>
181 : Source&
182 : serializer::
183 : start(
184 : Arg0&& arg0,
185 : Args&&... args)
186 : {
187 : static_assert(
188 : !std::is_abstract<Source>::value, "");
189 : static_assert(
190 : std::is_constructible<Source, Arg0, Args...>::value ||
191 : std::is_constructible<Source, detail::workspace&, Arg0, Args...>::value,
192 : "The Source cannot be constructed with the given arguments");
193 :
194 : auto& source = ws().emplace<Source>(
195 : std::forward<Arg0>(arg0),
196 : std::forward<Args>(args)...);
197 : start_source_impl(source);
198 : return source;
199 : }
200 :
201 : template<
202 : class Source,
203 : class>
204 : Source&
205 : serializer::
206 : start()
207 : {
208 : static_assert(
209 : !std::is_abstract<Source>::value, "");
210 : static_assert(
211 : std::is_default_constructible<Source>::value ||
212 : std::is_constructible<Source, detail::workspace&>::value,
213 : "The Source cannot be default-constructed");
214 :
215 : auto& source = ws().emplace<Source>();
216 : start_source_impl(source);
217 : return source;
218 : }
219 :
220 : } // http_proto
221 : } // boost
222 :
223 : #endif
|