Line data Source code
1 : /***************************************************************************\
2 : * Name : deserialize library for protobuf *
3 : * Description : all protobuf deserialization functions *
4 : * Author : antonin.kriz@gmail.com *
5 : * ------------------------------------------------------------------------- *
6 : * This is free software; you can redistribute it and/or modify it under the *
7 : * terms of the MIT license. A copy of the license can be found in the file *
8 : * "LICENSE" at the root of this distribution. *
9 : \***************************************************************************/
10 :
11 : #pragma once
12 :
13 : #include "../bits.h"
14 : #include "../concepts.h"
15 : #include "../utf8.h"
16 : #include "wire-types.h"
17 : #include <climits>
18 : #include <cstddef>
19 : #include <cstdint>
20 : #include <cstring>
21 : #include <limits>
22 : #include <map>
23 : #include <memory>
24 : #include <spb/io/io.hpp>
25 : #include <stdexcept>
26 : #include <string_view>
27 : #include <type_traits>
28 :
29 : namespace spb::pb::detail
30 : {
31 :
32 : struct istream
33 : {
34 : private:
35 : spb::io::reader on_read;
36 : size_t m_size;
37 :
38 : public:
39 1773 : istream(spb::io::reader reader, size_t size = std::numeric_limits<size_t>::max()) noexcept
40 1773 : : on_read(reader), m_size(size)
41 : {
42 1773 : }
43 :
44 : void skip(wire_type);
45 : void read_skip(size_t size);
46 :
47 : void deserialize(auto &value, const field_attributes &field);
48 :
49 : template <scalar_encoder encoder> void deserialize_as(auto &value, const field_attributes &field);
50 :
51 : template <size_t ordinal, typename T> void deserialize_variant(T &variant, const field_attributes &field);
52 :
53 : template <size_t ordinal, scalar_encoder encoder, typename T>
54 : void deserialize_variant_as(T &variant, const field_attributes &field);
55 :
56 : template <scalar_encoder encoder, typename T>
57 : auto deserialize_bitfield_as(uint32_t bits, const field_attributes &field) -> T;
58 :
59 1723 : [[nodiscard]] auto read_byte() -> uint8_t
60 : {
61 1723 : uint8_t result = {};
62 1723 : read_exact(&result, sizeof(result));
63 1663 : return result;
64 : }
65 :
66 2124 : [[nodiscard]] auto read_byte_or_eof() -> int
67 : {
68 2124 : uint8_t result = {};
69 2124 : if (on_read(&result, sizeof(result)) == 0)
70 817 : return -1;
71 :
72 1307 : return result;
73 : }
74 :
75 4702 : [[nodiscard]] auto size() const -> size_t
76 : {
77 4702 : return m_size;
78 : }
79 :
80 2502 : void read_exact(void *data, size_t size)
81 : {
82 2502 : if (this->size() < size) [[unlikely]]
83 14 : throw std::runtime_error("unexpected end of stream");
84 :
85 4928 : while (size > 0)
86 : {
87 2536 : auto chunk_size = on_read(data, size);
88 2536 : if (chunk_size == 0) [[unlikely]]
89 96 : throw std::runtime_error("unexpected end of stream");
90 :
91 2440 : size -= chunk_size;
92 2440 : m_size -= chunk_size;
93 : }
94 2392 : }
95 :
96 1020 : [[nodiscard]] auto empty() const -> bool
97 : {
98 1020 : return size() == 0;
99 : }
100 :
101 594 : [[nodiscard]] auto sub_stream(size_t sub_size) -> istream
102 : {
103 594 : if (size() < sub_size) [[unlikely]]
104 1 : throw std::runtime_error("unexpected end of stream");
105 :
106 593 : m_size -= sub_size;
107 593 : return istream(on_read, sub_size);
108 : }
109 : };
110 :
111 2705 : [[nodiscard]] static inline auto wire_type_from_tag(tag_type tag) -> wire_type
112 : {
113 2705 : return wire_type(uint32_t(tag) & 0x07);
114 : }
115 :
116 2669 : [[nodiscard]] static inline auto field_from_tag(tag_type tag) -> uint32_t
117 : {
118 2669 : return uint32_t(tag) >> 3;
119 : }
120 :
121 1356 : static inline void check_tag(tag_type tag)
122 : {
123 1356 : if (field_from_tag(tag) == 0) [[unlikely]]
124 4 : throw std::runtime_error("invalid field id");
125 1352 : }
126 :
127 999 : static inline void check_wire_type(wire_type type1, wire_type type2)
128 : {
129 999 : if (type1 != type2) [[unlikely]]
130 9 : throw std::runtime_error("invalid wire type");
131 990 : }
132 :
133 445 : static inline void check_if_empty(istream &stream)
134 : {
135 445 : if (!stream.empty()) [[unlikely]]
136 4 : throw std::runtime_error("unexpected data in stream");
137 441 : }
138 :
139 2124 : [[nodiscard]] static inline auto read_tag_or_eof(istream &stream) -> tag_type
140 : {
141 2124 : auto byte_or_eof = stream.read_byte_or_eof();
142 2124 : if (byte_or_eof < 0)
143 817 : return tag_type::invalid;
144 :
145 1307 : auto byte = uint8_t(byte_or_eof);
146 1307 : auto tag = uint32_t(byte & 0x7F);
147 :
148 1322 : for (size_t shift = CHAR_BIT - 1; (byte & 0x80) != 0; shift += CHAR_BIT - 1)
149 : {
150 16 : if (shift >= sizeof(tag) * CHAR_BIT) [[unlikely]]
151 1 : throw std::runtime_error("invalid tag");
152 :
153 15 : byte = stream.read_byte();
154 15 : tag |= uint64_t(byte & 0x7F) << shift;
155 : }
156 :
157 1306 : const auto result = tag_type(tag);
158 1306 : check_tag(result);
159 :
160 1304 : return result;
161 : }
162 :
163 1243 : template <typename T> [[nodiscard]] static inline auto read_varint(istream &stream) -> T
164 : {
165 : if constexpr (std::is_same_v<T, bool>)
166 : {
167 40 : switch (stream.read_byte())
168 : {
169 10 : case 0:
170 10 : return false;
171 18 : case 1:
172 18 : return true;
173 8 : default:
174 8 : throw std::runtime_error("invalid varint for bool");
175 : }
176 : }
177 : else
178 : {
179 1203 : auto value = uint64_t(0);
180 :
181 1682 : for (auto shift = 0U; shift < sizeof(value) * CHAR_BIT; shift += CHAR_BIT - 1)
182 : {
183 1668 : uint8_t byte = stream.read_byte();
184 1612 : value |= uint64_t(byte & 0x7F) << shift;
185 1612 : if ((byte & 0x80) == 0)
186 : {
187 : if constexpr (std::is_signed_v<T> && sizeof(T) < sizeof(value))
188 : {
189 : //- GPB encodes signed varints always as 64-bits
190 : //- so int32_t(-2) is encoded as "\xfe\xff\xff\xff\xff\xff\xff\xff\xff\x01",
191 : // same as int64_t(-2)
192 : //- but it should be encoded as "\xfe\xff\xff\xff\x0f"
193 306 : value = T(value);
194 : }
195 1133 : auto result = T(value);
196 : if constexpr (std::is_signed_v<T>)
197 : {
198 334 : if (result == std::make_signed_t<T>(value))
199 334 : return result;
200 : }
201 : else
202 : {
203 799 : if (result == value)
204 793 : return result;
205 : }
206 :
207 6 : break;
208 : }
209 : }
210 20 : throw std::runtime_error("invalid varint");
211 : }
212 : }
213 :
214 : static inline void deserialize(istream &stream, spb::detail::proto_message auto &value,
215 : const field_attributes &field);
216 :
217 : template <scalar_encoder encoder>
218 : static inline void deserialize_as(istream &stream, spb::detail::proto_field_int_or_float auto &value,
219 : const field_attributes &field);
220 : static inline void deserialize(istream &stream, spb::detail::proto_field_bytes auto &value,
221 : const field_attributes &field);
222 : static inline void deserialize(istream &stream, spb::detail::proto_label_repeated auto &value,
223 : const field_attributes &field);
224 : static inline void deserialize(istream &stream, spb::detail::proto_field_string auto &value,
225 : const field_attributes &field);
226 :
227 : template <scalar_encoder encoder, spb::detail::proto_label_repeated C>
228 : static inline void deserialize_as(istream &stream, C &value, const field_attributes &field);
229 :
230 : template <scalar_encoder encoder, spb::detail::proto_label_repeated_fixed_size C>
231 : static inline void deserialize_as(istream &stream, C &value, const field_attributes &field);
232 :
233 : template <scalar_encoder encoder, typename keyT, typename valueT>
234 : static inline void deserialize_as(istream &stream, std::map<keyT, valueT> &value,
235 : const field_attributes &field);
236 :
237 : static inline void deserialize(istream &stream, spb::detail::proto_label_optional auto &p_value,
238 : const field_attributes &field);
239 :
240 : template <scalar_encoder encoder, spb::detail::proto_label_optional C>
241 : static inline void deserialize_as(istream &stream, C &p_value, const field_attributes &field);
242 :
243 : template <typename T>
244 : static inline void deserialize(istream &stream, std::unique_ptr<T> &value, const field_attributes &field);
245 :
246 100 : template <typename T, typename signedT, typename unsignedT> static auto create_tmp_var()
247 : {
248 : if constexpr (std::is_signed<T>::value)
249 : {
250 40 : return signedT();
251 : }
252 : else
253 : {
254 60 : return unsignedT();
255 : }
256 : }
257 :
258 : template <scalar_encoder encoder, typename T>
259 252 : static inline auto deserialize_bitfield_as(istream &stream, uint32_t bits, const field_attributes &field) -> T
260 : {
261 252 : auto value = T();
262 : if constexpr (scalar_encoder_type1(encoder) == scalar_encoder::svarint)
263 : {
264 20 : check_wire_type(field.type, wire_type::varint);
265 :
266 20 : auto tmp = read_varint<std::make_unsigned_t<T>>(stream);
267 20 : value = T((tmp >> 1) ^ (~(tmp & 1) + 1));
268 : }
269 : else if constexpr (scalar_encoder_type1(encoder) == scalar_encoder::varint)
270 : {
271 52 : check_wire_type(field.type, wire_type::varint);
272 52 : value = read_varint<T>(stream);
273 : }
274 : else if constexpr (scalar_encoder_type1(encoder) == scalar_encoder::i32)
275 : {
276 : static_assert(sizeof(T) <= sizeof(uint32_t));
277 :
278 100 : check_wire_type(field.type, wire_type::fixed32);
279 :
280 : if constexpr (sizeof(value) == sizeof(uint32_t))
281 : {
282 40 : stream.read_exact(&value, sizeof(value));
283 : }
284 : else
285 : {
286 60 : auto tmp = create_tmp_var<T, int32_t, uint32_t>();
287 60 : stream.read_exact(&tmp, sizeof(tmp));
288 60 : spb::detail::check_if_value_fit_in_bits(tmp, bits);
289 36 : value = T(tmp);
290 : }
291 : }
292 : else if constexpr (scalar_encoder_type1(encoder) == scalar_encoder::i64)
293 : {
294 : static_assert(sizeof(T) <= sizeof(uint64_t));
295 80 : check_wire_type(field.type, wire_type::fixed64);
296 :
297 : if constexpr (sizeof(value) == sizeof(uint64_t))
298 : {
299 40 : stream.read_exact(&value, sizeof(value));
300 : }
301 : else
302 : {
303 40 : auto tmp = create_tmp_var<T, int64_t, uint64_t>();
304 40 : stream.read_exact(&tmp, sizeof(tmp));
305 40 : spb::detail::check_if_value_fit_in_bits(tmp, bits);
306 24 : value = T(tmp);
307 : }
308 : }
309 208 : spb::detail::check_if_value_fit_in_bits(value, bits);
310 156 : return value;
311 : }
312 :
313 : template <scalar_encoder encoder>
314 50 : static inline void deserialize_as(istream &stream, spb::detail::proto_enum auto &value,
315 : const field_attributes &field)
316 : {
317 : using T = std::remove_cvref_t<decltype(value)>;
318 : using int_type = std::underlying_type_t<T>;
319 :
320 : if constexpr (!scalar_encoder_is_packed(encoder))
321 : {
322 26 : check_wire_type(field.type, wire_type::varint);
323 : }
324 :
325 50 : value = T(read_varint<int_type>(stream));
326 46 : }
327 :
328 : template <scalar_encoder encoder>
329 706 : static inline void deserialize_as(istream &stream, spb::detail::proto_field_int_or_float auto &value,
330 : const field_attributes &field)
331 : {
332 : using T = std::remove_cvref_t<decltype(value)>;
333 :
334 : if constexpr (scalar_encoder_type1(encoder) == scalar_encoder::svarint)
335 : {
336 : if constexpr (!scalar_encoder_is_packed(encoder))
337 : {
338 48 : check_wire_type(field.type, wire_type::varint);
339 : }
340 74 : auto tmp = read_varint<std::make_unsigned_t<T>>(stream);
341 54 : value = T((tmp >> 1) ^ (~(tmp & 1) + 1));
342 : }
343 : else if constexpr (scalar_encoder_type1(encoder) == scalar_encoder::varint)
344 : {
345 : if constexpr (!scalar_encoder_is_packed(encoder))
346 : {
347 128 : check_wire_type(field.type, wire_type::varint);
348 : }
349 336 : value = read_varint<T>(stream);
350 : }
351 : else if constexpr (scalar_encoder_type1(encoder) == scalar_encoder::i32)
352 : {
353 : static_assert(sizeof(T) <= sizeof(uint32_t));
354 :
355 : if constexpr (!scalar_encoder_is_packed(encoder))
356 : {
357 114 : check_wire_type(field.type, wire_type::fixed32);
358 : }
359 : if constexpr (sizeof(value) == sizeof(uint32_t))
360 : {
361 92 : stream.read_exact(&value, sizeof(value));
362 : }
363 : else
364 : {
365 : if constexpr (std::is_signed_v<T>)
366 : {
367 26 : auto tmp = int32_t(0);
368 26 : stream.read_exact(&tmp, sizeof(tmp));
369 24 : if (tmp > std::numeric_limits<T>::max() || tmp < std::numeric_limits<T>::min())
370 4 : throw std::runtime_error("int overflow");
371 :
372 20 : value = T(tmp);
373 : }
374 : else
375 : {
376 60 : auto tmp = uint32_t(0);
377 60 : stream.read_exact(&tmp, sizeof(tmp));
378 52 : if (tmp > std::numeric_limits<T>::max())
379 8 : throw std::runtime_error("int overflow");
380 :
381 44 : value = T(tmp);
382 : }
383 : }
384 : }
385 : else if constexpr (scalar_encoder_type1(encoder) == scalar_encoder::i64)
386 : {
387 : static_assert(sizeof(T) <= sizeof(uint64_t));
388 : if constexpr (!scalar_encoder_is_packed(encoder))
389 : {
390 90 : check_wire_type(field.type, wire_type::fixed64);
391 : }
392 : if constexpr (sizeof(value) == sizeof(uint64_t))
393 : {
394 60 : stream.read_exact(&value, sizeof(value));
395 : }
396 : else
397 : {
398 : if constexpr (std::is_signed_v<T>)
399 : {
400 26 : auto tmp = int64_t(0);
401 26 : stream.read_exact(&tmp, sizeof(tmp));
402 24 : if (tmp > std::numeric_limits<T>::max() || tmp < std::numeric_limits<T>::min())
403 4 : throw std::runtime_error("int overflow");
404 :
405 20 : value = T(tmp);
406 : }
407 : else
408 : {
409 26 : auto tmp = uint64_t(0);
410 26 : stream.read_exact(&tmp, sizeof(tmp));
411 24 : if (tmp > std::numeric_limits<T>::max())
412 4 : throw std::runtime_error("int overflow");
413 :
414 20 : value = T(tmp);
415 : }
416 : }
417 : }
418 596 : }
419 :
420 107 : static inline void deserialize(istream &stream, spb::detail::proto_label_optional auto &p_value,
421 : const field_attributes &field)
422 : {
423 137 : auto &value = p_value.emplace(typename std::decay_t<decltype(p_value)>::value_type());
424 107 : deserialize(stream, value, field);
425 78 : }
426 :
427 : template <scalar_encoder encoder, spb::detail::proto_label_optional C>
428 102 : static inline void deserialize_as(istream &stream, C &p_value, const field_attributes &field)
429 : {
430 102 : auto &value = p_value.emplace(typename C::value_type());
431 102 : deserialize_as<encoder>(stream, value, field);
432 94 : }
433 :
434 175 : static inline void deserialize(istream &stream, spb::detail::proto_field_string auto &value,
435 : const field_attributes &field)
436 : {
437 175 : check_wire_type(field.type, wire_type::length_delimited);
438 172 : if (field.max_size && stream.size() > field.max_size)
439 16 : throw std::length_error("string is too large");
440 :
441 : if constexpr (spb::detail::proto_field_string_resizable<decltype(value)>)
442 : {
443 126 : value.resize(stream.size());
444 : }
445 : else
446 : {
447 30 : if (value.size() != stream.size()) [[unlikely]]
448 14 : throw std::runtime_error("invalid string size");
449 : }
450 158 : stream.read_exact(value.data(), stream.size());
451 151 : spb::detail::utf8::validate(std::string_view(value.data(), value.size()));
452 134 : }
453 :
454 : template <typename T>
455 : static inline void deserialize(istream &stream, std::unique_ptr<T> &value, const field_attributes &field)
456 : {
457 : value = std::make_unique<T>();
458 : deserialize(stream, *value, field);
459 : }
460 :
461 112 : static inline void deserialize(istream &stream, spb::detail::proto_field_bytes auto &value,
462 : const field_attributes &field)
463 : {
464 112 : check_wire_type(field.type, wire_type::length_delimited);
465 112 : if (field.max_size && stream.size() > field.max_size)
466 16 : throw std::length_error("bytes is too large");
467 :
468 : if constexpr (spb::detail::proto_field_bytes_resizable<decltype(value)>)
469 : {
470 72 : value.resize(stream.size());
471 : }
472 : else
473 : {
474 48 : if (stream.size() != value.size()) [[unlikely]]
475 12 : throw std::runtime_error("invalid bytes size");
476 : }
477 96 : stream.read_exact(value.data(), stream.size());
478 82 : }
479 :
480 134 : static inline void deserialize(istream &stream, spb::detail::proto_label_repeated auto &value,
481 : const field_attributes &field)
482 : {
483 134 : if (field.max_count && value.size() >= field.max_count) [[unlikely]]
484 0 : throw std::length_error("repeated is too large");
485 :
486 134 : deserialize(stream, value.emplace_back(), field);
487 126 : }
488 :
489 : template <scalar_encoder encoder, spb::detail::proto_label_repeated C>
490 208 : static inline void deserialize_packed_as(istream &stream, C &value, const field_attributes &field)
491 : {
492 486 : while (!stream.empty())
493 : {
494 342 : if (field.max_count && value.size() >= field.max_count) [[unlikely]]
495 30 : throw std::length_error("repeated is too large");
496 :
497 : if constexpr (std::is_same_v<typename C::value_type, bool>)
498 : {
499 10 : value.emplace_back(read_varint<bool>(stream));
500 : }
501 : else
502 : {
503 302 : deserialize_as<encoder>(stream, value.emplace_back(), field);
504 : }
505 : }
506 144 : }
507 :
508 : template <scalar_encoder encoder, spb::detail::proto_label_repeated_fixed_size C>
509 12 : static inline void deserialize_packed_as(istream &stream, C &value, const field_attributes &field)
510 : {
511 68 : for (size_t i = 0; i < value.size(); i++)
512 : {
513 : if constexpr (std::is_same_v<typename C::value_type, bool>)
514 : {
515 : value[i] = read_varint<bool>(stream);
516 : }
517 : else
518 : {
519 : typename C::value_type tmp;
520 48 : deserialize_as<encoder>(stream, tmp, field);
521 44 : value[i] = tmp;
522 : }
523 : }
524 8 : check_if_empty(stream);
525 4 : }
526 :
527 : template <scalar_encoder encoder, spb::detail::proto_label_repeated_fixed_size C>
528 12 : static inline void deserialize_as(istream &stream, C &value, const field_attributes &field)
529 : {
530 : static_assert(scalar_encoder_is_packed(encoder),
531 : "repeated field with fixed size has to have attribute 'packed'");
532 :
533 12 : check_wire_type(field.type, wire_type::length_delimited);
534 12 : deserialize_packed_as<encoder>(stream, value, field);
535 4 : }
536 :
537 : template <scalar_encoder encoder, spb::detail::proto_label_repeated C>
538 368 : static inline void deserialize_as(istream &stream, C &value, const field_attributes &field)
539 : {
540 : if constexpr (scalar_encoder_is_packed(encoder))
541 : {
542 208 : deserialize_packed_as<encoder>(stream, value, field);
543 : }
544 : else
545 : {
546 160 : if (field.max_count && value.size() >= field.max_count) [[unlikely]]
547 4 : throw std::length_error("repeated is too large");
548 :
549 : if constexpr (std::is_same_v<typename C::value_type, bool>)
550 : {
551 14 : value.emplace_back(read_varint<bool>(stream));
552 : }
553 : else
554 : {
555 142 : deserialize_as<encoder>(stream, value.emplace_back(), field);
556 : }
557 : }
558 296 : }
559 :
560 : template <scalar_encoder encoder, typename keyT, typename valueT>
561 : static inline void deserialize_as(istream &stream, std::map<keyT, valueT> &value,
562 : const field_attributes &field)
563 : {
564 : const auto key_encoder = scalar_encoder_type1(encoder);
565 : const auto value_encoder = scalar_encoder_type2(encoder);
566 :
567 : check_wire_type(field.type, wire_type::length_delimited);
568 :
569 : auto pair = std::pair<keyT, valueT>();
570 : auto key_defined = false;
571 : auto value_defined = false;
572 : while (!stream.empty())
573 : {
574 : const auto tag = tag_type(read_varint<uint32_t>(stream));
575 : const auto field_number = field_from_tag(tag);
576 : const auto field_type = wire_type_from_tag(tag);
577 :
578 : check_tag(tag);
579 :
580 : switch (field_number)
581 : {
582 : case 1:
583 : check_wire_type(field_type, field.type);
584 : if constexpr (std::is_integral_v<keyT>)
585 : {
586 : deserialize_as<key_encoder>(stream, pair.first, field);
587 : }
588 : else
589 : {
590 : if (field_type == wire_type::length_delimited)
591 : {
592 : const auto size = read_varint<uint32_t>(stream);
593 : auto substream = stream.sub_stream(size);
594 : deserialize(substream, pair.first, field);
595 : check_if_empty(substream);
596 : }
597 : else
598 : {
599 : deserialize(stream, pair.first, field);
600 : }
601 : }
602 : key_defined = true;
603 : break;
604 : case 2:
605 : check_wire_type(field_type, field.type);
606 : if constexpr (spb::detail::proto_field_number<valueT>)
607 : {
608 : deserialize_as<value_encoder>(stream, pair.second, field);
609 : }
610 : else
611 : {
612 : if (field_type == wire_type::length_delimited)
613 : {
614 : const auto size = read_varint<uint32_t>(stream);
615 : auto substream = stream.sub_stream(size);
616 : deserialize(substream, pair.second, field);
617 : check_if_empty(substream);
618 : }
619 : else [[unlikely]]
620 : {
621 : throw std::runtime_error("invalid field");
622 : }
623 : }
624 : value_defined = true;
625 : break;
626 : default:
627 : throw std::runtime_error("invalid field");
628 : }
629 : }
630 : if (key_defined && value_defined)
631 : {
632 : value.insert(std::move(pair));
633 : }
634 : else [[unlikely]]
635 : {
636 : throw std::runtime_error("invalid map item");
637 : }
638 : }
639 :
640 : template <size_t ordinal, typename T>
641 6 : static inline void deserialize_variant(istream &stream, T &variant, const field_attributes &field)
642 : {
643 6 : deserialize(stream, variant.template emplace<ordinal>(), field);
644 6 : }
645 :
646 : template <size_t ordinal, scalar_encoder encoder, typename T>
647 2 : static inline void deserialize_variant_as(istream &stream, T &variant, const field_attributes &field)
648 : {
649 2 : deserialize_as<encoder>(stream, variant.template emplace<ordinal>(), field);
650 2 : }
651 :
652 1180 : static inline void deserialize_main(istream &stream, spb::detail::proto_message auto &value)
653 : {
654 944 : for (;;)
655 : {
656 2124 : const auto tag = read_tag_or_eof(stream);
657 2121 : if (tag == tag_type::invalid)
658 817 : break;
659 :
660 1304 : const auto field_type = wire_type_from_tag(tag);
661 :
662 1304 : if (field_type == wire_type::length_delimited)
663 : {
664 552 : const auto size = read_varint<uint32_t>(stream);
665 552 : auto substream = stream.sub_stream(size);
666 552 : deserialize_value(substream, value, tag);
667 398 : check_if_empty(substream);
668 : }
669 : else
670 : {
671 752 : deserialize_value(stream, value, tag);
672 : }
673 : }
674 817 : }
675 :
676 42 : static inline void deserialize(istream &stream, spb::detail::proto_message auto &value,
677 : const field_attributes &field)
678 : {
679 42 : check_wire_type(field.type, wire_type::length_delimited);
680 :
681 89 : while (!stream.empty())
682 : {
683 51 : const auto tag = tag_type(read_varint<uint32_t>(stream));
684 50 : const auto field_type = wire_type_from_tag(tag);
685 50 : check_tag(tag);
686 :
687 48 : if (field_type == wire_type::length_delimited)
688 : {
689 40 : const auto size = read_varint<uint32_t>(stream);
690 40 : auto substream = stream.sub_stream(size);
691 39 : deserialize_value(substream, value, tag);
692 39 : check_if_empty(substream);
693 : }
694 : else
695 : {
696 8 : deserialize_value(stream, value, tag);
697 : }
698 : }
699 38 : }
700 :
701 323 : inline void istream::deserialize(auto &value, const field_attributes &field)
702 : {
703 323 : detail::deserialize(*this, value, field);
704 248 : }
705 :
706 83 : inline void istream::read_skip(size_t size)
707 : {
708 : uint8_t buffer[64];
709 151 : while (size > 0)
710 : {
711 83 : auto chunk_size = std::min(size, sizeof(buffer));
712 83 : read_exact(buffer, chunk_size);
713 68 : size -= chunk_size;
714 : }
715 68 : }
716 :
717 126 : inline void istream::skip(wire_type type)
718 : {
719 126 : switch (type)
720 : {
721 42 : case wire_type::varint:
722 42 : return (void)read_varint<uint64_t>(*this);
723 44 : case wire_type::length_delimited:
724 44 : return read_skip(size());
725 20 : case wire_type::fixed32:
726 20 : return read_skip(sizeof(uint32_t));
727 19 : case wire_type::fixed64:
728 19 : return read_skip(sizeof(uint64_t));
729 1 : default:
730 1 : throw std::runtime_error("invalid wire type");
731 : }
732 : }
733 :
734 : template <scalar_encoder encoder>
735 642 : inline void istream::deserialize_as(auto &value, const field_attributes &field)
736 : {
737 642 : detail::deserialize_as<encoder>(*this, value, field);
738 482 : }
739 :
740 : template <size_t ordinal, typename T>
741 6 : inline void istream::deserialize_variant(T &variant, const field_attributes &field)
742 : {
743 6 : detail::deserialize_variant<ordinal>(*this, variant, field);
744 6 : }
745 :
746 : template <size_t ordinal, scalar_encoder encoder, typename T>
747 2 : inline void istream::deserialize_variant_as(T &variant, const field_attributes &field)
748 : {
749 2 : detail::deserialize_variant_as<ordinal, encoder>(*this, variant, field);
750 2 : }
751 :
752 : template <scalar_encoder encoder, typename T>
753 252 : inline auto istream::deserialize_bitfield_as(uint32_t bits, const field_attributes &field) -> T
754 : {
755 252 : return detail::deserialize_bitfield_as<encoder, T>(*this, bits, field);
756 : }
757 :
758 : static inline void deserialize(auto &value, spb::io::reader on_read)
759 : {
760 : using T = std::remove_cvref_t<decltype(value)>;
761 : static_assert(spb::detail::proto_message<T>);
762 :
763 : auto stream = istream(on_read);
764 : deserialize_main(stream, value);
765 : }
766 :
767 : } // namespace spb::pb::detail
|