@@ -127,6 +127,38 @@ namespace msgpack23 {
127
127
return to_big_endian (value);
128
128
}
129
129
130
+ template <typename T>
131
+ class counting_inserter final {
132
+ public:
133
+ using difference_type = std::ptrdiff_t ;
134
+
135
+ constexpr explicit counting_inserter (std::size_t &size) : size_(std::addressof(size)) {}
136
+
137
+ constexpr counting_inserter &operator =(const T &value) {
138
+ ++*size_;
139
+ return *this ;
140
+ }
141
+
142
+ constexpr counting_inserter &operator =(T &&value) {
143
+ ++*size_;
144
+ return *this ;
145
+ }
146
+
147
+ [[nodiscard]] constexpr counting_inserter &operator *() {
148
+ return *this ;
149
+ }
150
+
151
+ constexpr counting_inserter &operator ++() {
152
+ return *this ;
153
+ }
154
+
155
+ constexpr counting_inserter operator ++(int ) {
156
+ return *this ;
157
+ }
158
+ private:
159
+ std::size_t *size_{};
160
+ };
161
+
130
162
template <std::output_iterator<std::byte> Iter>
131
163
class Packer final {
132
164
public:
@@ -217,38 +249,42 @@ namespace msgpack23 {
217
249
template <typename T>
218
250
requires VariantLike<T>
219
251
void pack_type (T const &value) {
220
- std::vector<std::byte> data{} ;
221
- std::visit ([this , &data ](auto const &arg) {
222
- auto const inserter = std::back_insert_iterator (data) ;
223
- Packer packer{inserter};
252
+ std::size_t size = 0 ;
253
+ std::visit ([this , &size ](auto const &arg) {
254
+ const auto inserter = counting_inserter< std::byte>{size} ;
255
+ Packer<counting_inserter<std::byte> > packer{inserter};
224
256
packer (arg);
225
257
}, value);
258
+
226
259
auto const index = static_cast <std::int8_t >(value.index ());
227
260
if (index > 127 ) {
228
261
throw std::overflow_error (" Variant index is to large to be serialized." );
229
262
}
230
263
231
- if (data. size () == 1 ) {
264
+ if (size == 1 ) {
232
265
emplace_constant (FormatConstants::fixext1);
233
- } else if (data. size () == 2 ) {
266
+ } else if (size == 2 ) {
234
267
emplace_constant (FormatConstants::fixext2);
235
- } else if (data. size () == 4 ) {
268
+ } else if (size == 4 ) {
236
269
emplace_constant (FormatConstants::fixext4);
237
- } else if (data. size () == 8 ) {
270
+ } else if (size == 8 ) {
238
271
emplace_constant (FormatConstants::fixext8);
239
- } else if (data. size () == 16 ) {
272
+ } else if (size == 16 ) {
240
273
emplace_constant (FormatConstants::fixext16);
241
- } else if (data. size () < std::numeric_limits<std::uint8_t >::max ()) {
242
- emplace_combined (FormatConstants::ext8, static_cast <std::uint8_t >(data. size () ));
243
- } else if (data. size () < std::numeric_limits<std::uint16_t >::max ()) {
244
- emplace_combined (FormatConstants::ext16, static_cast <std::uint16_t >(data. size () ));
245
- } else if (data. size () < std::numeric_limits<std::uint32_t >::max ()) {
246
- emplace_combined (FormatConstants::ext32, static_cast <std::uint32_t >(data. size () ));
274
+ } else if (size < std::numeric_limits<std::uint8_t >::max ()) {
275
+ emplace_combined (FormatConstants::ext8, static_cast <std::uint8_t >(size));
276
+ } else if (size < std::numeric_limits<std::uint16_t >::max ()) {
277
+ emplace_combined (FormatConstants::ext16, static_cast <std::uint16_t >(size));
278
+ } else if (size < std::numeric_limits<std::uint32_t >::max ()) {
279
+ emplace_combined (FormatConstants::ext32, static_cast <std::uint32_t >(size));
247
280
} else {
248
281
throw std::length_error (" Variant is too long to be serialized." );
249
282
}
250
283
emplace_integral (index );
251
- std::copy (data.begin (), data.end (), store_);
284
+ std::visit ([this ](auto const &arg) {
285
+ Packer packer{store_};
286
+ packer (arg);
287
+ }, value);
252
288
}
253
289
254
290
template <typename T>
0 commit comments