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 <memory>
23 : #include <spb/io/io.hpp>
24 : #include <stdexcept>
25 : #include <string_view>
26 : #include <type_traits>
27 :
28 : namespace spb::pb::detail
29 : {
30 :
31 : struct istream_reader
32 : {
33 : size_t bytes_left;
34 : size_t consumed_bytes = 0;
35 : spb::io::reader on_read;
36 :
37 1540 : istream_reader(spb::io::reader reader, size_t size = std::numeric_limits<size_t>::max()) noexcept
38 1540 : : bytes_left(size), on_read(reader)
39 : {
40 1540 : }
41 772 : size_t consumed_size() const noexcept
42 : {
43 772 : return consumed_bytes;
44 : }
45 4352 : size_t size() const noexcept
46 : {
47 4352 : return bytes_left;
48 : }
49 2302 : bool empty() const noexcept
50 : {
51 2302 : return bytes_left == 0;
52 : }
53 :
54 3084 : [[nodiscard]] size_t read(void *data, size_t data_size)
55 : {
56 3084 : data_size = std::min(data_size, size());
57 3084 : if (data_size == 0) [[unlikely]]
58 0 : return 0;
59 :
60 3084 : const auto size = on_read(data, data_size);
61 3084 : bytes_left -= size;
62 3084 : consumed_bytes += size;
63 3084 : return size;
64 : }
65 :
66 1312 : [[nodiscard]] uint8_t read_byte_or_throw()
67 : {
68 : uint8_t result;
69 :
70 1312 : if (read(&result, sizeof(result)) != sizeof(result)) [[unlikely]]
71 0 : throw std::runtime_error("unexpected end of stream");
72 :
73 1312 : return result;
74 : }
75 :
76 1212 : [[nodiscard]] int read_byte_or_eof()
77 : {
78 : uint8_t result;
79 2424 : return read(&result, sizeof(result)) == sizeof(result) ? result : -1;
80 : }
81 :
82 566 : void read_exact_or_throw(void *data, size_t data_size)
83 : {
84 1126 : while (data_size > 0)
85 : {
86 560 : auto chunk_size = read(data, data_size);
87 560 : if (chunk_size == 0) [[unlikely]]
88 0 : throw std::runtime_error("unexpected end of stream");
89 :
90 560 : data_size -= chunk_size;
91 : }
92 566 : }
93 :
94 768 : [[nodiscard]] istream_reader sub_stream(size_t sub_size)
95 : {
96 768 : if (size() < sub_size) [[unlikely]]
97 0 : throw std::runtime_error("unexpected end of stream");
98 :
99 768 : bytes_left -= sub_size;
100 768 : consumed_bytes += sub_size;
101 768 : return istream_reader(on_read, sub_size);
102 : }
103 :
104 0 : void skip_or_throw(size_t size)
105 : {
106 : uint8_t buffer[128];
107 0 : while (size > 0)
108 : {
109 0 : const auto chunk_size = std::min(size, sizeof(buffer));
110 0 : read_exact_or_throw(buffer, chunk_size);
111 0 : size -= chunk_size;
112 : }
113 0 : }
114 : };
115 :
116 : struct istream_buffer
117 : {
118 : const uint8_t *p_start;
119 : const uint8_t *p_end;
120 :
121 : istream_buffer(const uint8_t *start, const uint8_t *end) noexcept : p_start(start), p_end(end)
122 : {
123 : assert(start <= end);
124 : }
125 3751 : istream_buffer(const uint8_t *start, size_t size) noexcept : p_start(start), p_end(start + size)
126 : {
127 3751 : }
128 5885 : size_t size() const noexcept
129 : {
130 5885 : return p_end - p_start;
131 : }
132 5609 : bool empty() const noexcept
133 : {
134 5609 : return p_start >= p_end;
135 : }
136 :
137 1268 : [[nodiscard]] size_t read(void *data, size_t data_size) noexcept
138 : {
139 1268 : data_size = std::min(data_size, size());
140 1268 : memcpy(data, p_start, data_size);
141 1268 : p_start += data_size;
142 1268 : return data_size;
143 : }
144 :
145 3460 : [[nodiscard]] uint8_t read_byte_or_throw()
146 : {
147 3460 : if (p_start >= p_end) [[unlikely]]
148 43 : throw std::runtime_error("unexpected end of stream");
149 :
150 3417 : return *p_start++;
151 : }
152 :
153 2218 : [[nodiscard]] int read_byte_or_eof() noexcept
154 : {
155 2218 : if (p_start < p_end) [[likely]]
156 2218 : return *p_start++;
157 :
158 0 : return -1;
159 : }
160 :
161 1268 : void read_exact_or_throw(void *data, size_t data_size)
162 : {
163 1268 : if (read(data, data_size) != data_size) [[unlikely]]
164 20 : throw std::runtime_error("unexpected end of stream");
165 1248 : }
166 :
167 1809 : [[nodiscard]] istream_buffer sub_stream(size_t sub_size)
168 : {
169 1809 : if (size() < sub_size) [[unlikely]]
170 43 : throw std::runtime_error("unexpected end of stream");
171 :
172 1766 : const auto sub_start = p_start;
173 1766 : p_start += sub_size;
174 1766 : return istream_buffer(sub_start, sub_size);
175 : }
176 :
177 74 : void skip_or_throw(size_t size)
178 : {
179 74 : if (this->size() < size) [[unlikely]]
180 6 : throw std::runtime_error("unexpected end of stream");
181 :
182 68 : p_start += size;
183 68 : }
184 : };
185 :
186 : void skip(auto &stream, wire_type);
187 :
188 : template <typename T> void check_enum_value_or_throw(enum_type);
189 :
190 : template <serialize_mode, size_t ordinal, typename T>
191 : void deserialize_variant(auto &stream, T &variant, wire_type type);
192 :
193 : template <serialize_mode, typename T>
194 : auto deserialize_bitfield(auto &stream, uint32_t bits, wire_type type) -> T;
195 :
196 6174 : [[nodiscard]] inline auto wire_type_from_tag(tag_type tag) -> wire_type
197 : {
198 6174 : return wire_type(uint32_t(tag) & 0x07);
199 : }
200 :
201 6278 : [[nodiscard]] inline auto field_from_tag(tag_type tag) -> uint32_t
202 : {
203 6278 : return uint32_t(tag) >> 3;
204 : }
205 :
206 3175 : inline void check_tag_or_throw(tag_type tag)
207 : {
208 3175 : if (field_from_tag(tag) == 0) [[unlikely]]
209 1 : throw std::runtime_error("invalid field id");
210 3174 : }
211 :
212 6001 : inline void check_wire_type_or_throw(wire_type type1, wire_type type2)
213 : {
214 6001 : if (type1 != type2) [[unlikely]]
215 9 : throw std::runtime_error("invalid wire type");
216 5992 : }
217 :
218 1278 : void check_if_empty_or_throw(auto &stream)
219 : {
220 1278 : if (!stream.empty()) [[unlikely]]
221 4 : throw std::runtime_error("unexpected data in stream");
222 1274 : }
223 :
224 3430 : [[nodiscard]] auto read_tag_or_eof(auto &stream) -> tag_type
225 : {
226 3430 : auto byte_or_eof = stream.read_byte_or_eof();
227 3430 : if (byte_or_eof < 0) [[unlikely]]
228 386 : return tag_type::invalid;
229 :
230 3044 : auto byte = (uint8_t)(byte_or_eof);
231 3044 : auto tag = (uint32_t)(byte & 0x7F);
232 :
233 3079 : for (size_t shift = CHAR_BIT - 1; (byte & 0x80) != 0; shift += CHAR_BIT - 1)
234 : {
235 36 : if (shift >= sizeof(tag) * CHAR_BIT) [[unlikely]]
236 1 : throw std::runtime_error("invalid tag");
237 :
238 35 : byte = stream.read_byte_or_throw();
239 35 : tag |= uint64_t(byte & 0x7F) << shift;
240 : }
241 :
242 3043 : const auto result = tag_type(tag);
243 3043 : check_tag_or_throw(result);
244 3042 : return result;
245 : }
246 :
247 3902 : template <typename T> [[nodiscard]] auto read_varint(auto &stream) -> T
248 : {
249 : if constexpr (std::is_same_v<T, bool>)
250 : {
251 86 : switch (stream.read_byte_or_throw())
252 : {
253 30 : case 0:
254 30 : return false;
255 46 : case 1:
256 46 : return true;
257 6 : default:
258 6 : throw std::runtime_error("invalid varint for bool");
259 : }
260 : }
261 : else
262 : {
263 3816 : auto value = uint64_t(0);
264 :
265 4665 : for (auto shift = 0U; shift < sizeof(value) * CHAR_BIT; shift += CHAR_BIT - 1)
266 : {
267 4651 : uint8_t byte = stream.read_byte_or_throw();
268 4612 : value |= uint64_t(byte & 0x7F) << shift;
269 4612 : if ((byte & 0x80) == 0)
270 : {
271 : if constexpr (std::is_signed_v<T> && sizeof(T) < sizeof(value))
272 : {
273 : //- GPB encodes signed varints always as 64-bits
274 : //- so int32_t(-2) is encoded as "\xfe\xff\xff\xff\xff\xff\xff\xff\xff\x01",
275 : // same as int64_t(-2)
276 : //- but it should be encoded as "\xfe\xff\xff\xff\x0f"
277 627 : value = T(value);
278 : }
279 3763 : auto result = T(value);
280 : if constexpr (std::is_signed_v<T>)
281 : {
282 701 : if (result == std::make_signed_t<T>(value)) [[likely]]
283 701 : return result;
284 : }
285 : else
286 : {
287 3062 : if (result == value) [[likely]]
288 3056 : return result;
289 : }
290 :
291 6 : break;
292 : }
293 : }
294 20 : throw std::runtime_error("invalid varint");
295 : }
296 : }
297 :
298 : template <serialize_mode>
299 : void deserialize(auto &stream, spb::detail::proto_message auto &value, wire_type type);
300 : template <serialize_mode>
301 : void deserialize(auto &stream, spb::detail::proto_field_int_or_float auto &value, wire_type type);
302 : template <serialize_mode>
303 : void deserialize(auto &stream, spb::detail::proto_field_bytes auto &value, wire_type type);
304 : template <serialize_mode>
305 : void deserialize(auto &stream, spb::detail::proto_field_string auto &value, wire_type type);
306 : template <serialize_mode, spb::detail::proto_label_repeated Container>
307 : void deserialize(auto &stream, Container &value, wire_type type);
308 : template <serialize_mode, spb::detail::proto_label_repeated_fixed_size Container>
309 : void deserialize(auto &stream, Container &value, wire_type type);
310 : template <serialize_mode, spb::detail::proto_label_optional Container>
311 : void deserialize(auto &stream, Container &p_value, wire_type type);
312 :
313 : template <serialize_mode> void deserialize(auto &stream, spb::detail::proto_map auto &value, wire_type type);
314 :
315 : template <serialize_mode, typename T>
316 : void deserialize(auto &stream, std::unique_ptr<T> &value, wire_type type);
317 :
318 220 : template <typename T, typename signedT, typename unsignedT> auto create_tmp_var()
319 : {
320 : if constexpr (std::is_signed<T>::value)
321 : {
322 88 : return signedT();
323 : }
324 : else
325 : {
326 132 : return unsignedT();
327 : }
328 : }
329 :
330 : template <serialize_mode mode, typename T>
331 564 : auto deserialize_bitfield(auto &stream, uint32_t bits, wire_type type) -> T
332 : {
333 564 : auto value = T();
334 : if constexpr (scalar_encoder(mode.encoder) == scalar_encoder::svarint)
335 : {
336 52 : check_wire_type_or_throw(type, wire_type::varint);
337 :
338 52 : auto tmp = read_varint<std::make_unsigned_t<T>>(stream);
339 52 : value = T((tmp >> 1) ^ (~(tmp & 1) + 1));
340 : }
341 : else if constexpr (scalar_encoder(mode.encoder) == scalar_encoder::varint)
342 : {
343 116 : check_wire_type_or_throw(type, wire_type::varint);
344 116 : value = read_varint<T>(stream);
345 : }
346 : else if constexpr (scalar_encoder(mode.encoder) == scalar_encoder::i32)
347 : {
348 : static_assert(sizeof(T) <= sizeof(uint32_t));
349 :
350 220 : check_wire_type_or_throw(type, wire_type::fixed32);
351 :
352 : if constexpr (sizeof(value) == sizeof(uint32_t))
353 : {
354 88 : stream.read_exact_or_throw(&value, sizeof(value));
355 : }
356 : else
357 : {
358 132 : auto tmp = create_tmp_var<T, int32_t, uint32_t>();
359 132 : stream.read_exact_or_throw(&tmp, sizeof(tmp));
360 132 : spb::detail::check_if_value_fit_in_bits(tmp, bits);
361 108 : value = T(tmp);
362 : }
363 : }
364 : else if constexpr (scalar_encoder(mode.encoder) == scalar_encoder::i64)
365 : {
366 : static_assert(sizeof(T) <= sizeof(uint64_t));
367 176 : check_wire_type_or_throw(type, wire_type::fixed64);
368 :
369 : if constexpr (sizeof(value) == sizeof(uint64_t))
370 : {
371 88 : stream.read_exact_or_throw(&value, sizeof(value));
372 : }
373 : else
374 : {
375 88 : auto tmp = create_tmp_var<T, int64_t, uint64_t>();
376 88 : stream.read_exact_or_throw(&tmp, sizeof(tmp));
377 88 : spb::detail::check_if_value_fit_in_bits(tmp, bits);
378 72 : value = T(tmp);
379 : }
380 : }
381 520 : spb::detail::check_if_value_fit_in_bits(value, bits);
382 468 : return value;
383 : }
384 :
385 : template <serialize_mode mode>
386 125 : void deserialize(auto &stream, spb::detail::proto_enum auto &value, wire_type type)
387 : {
388 : using T = std::remove_cvref_t<decltype(value)>;
389 :
390 : if constexpr (!is_packed(mode.encoder))
391 : {
392 125 : check_wire_type_or_throw(type, wire_type::varint);
393 : }
394 125 : const auto int_enum = read_varint<enum_type>(stream);
395 125 : check_enum_value_or_throw<T>(int_enum);
396 120 : value = (T)int_enum;
397 120 : }
398 :
399 : template <serialize_mode mode>
400 1544 : void deserialize(auto &stream, spb::detail::proto_field_int_or_float auto &value, wire_type type)
401 : {
402 : using T = std::remove_cvref_t<decltype(value)>;
403 :
404 : if constexpr (scalar_encoder(mode.encoder) == scalar_encoder::svarint)
405 : {
406 : if constexpr (!is_packed(mode.encoder))
407 : {
408 160 : check_wire_type_or_throw(type, wire_type::varint);
409 : }
410 160 : auto tmp = read_varint<std::make_unsigned_t<T>>(stream);
411 146 : value = T((tmp >> 1) ^ (~(tmp & 1) + 1));
412 : }
413 : else if constexpr (scalar_encoder(mode.encoder) == scalar_encoder::varint)
414 : {
415 : if constexpr (!is_packed(mode.encoder))
416 : {
417 654 : check_wire_type_or_throw(type, wire_type::varint);
418 : }
419 652 : value = read_varint<T>(stream);
420 : }
421 : else if constexpr (scalar_encoder(mode.encoder) == scalar_encoder::i32)
422 : {
423 : static_assert(sizeof(T) <= sizeof(uint32_t));
424 :
425 : if constexpr (!is_packed(mode.encoder))
426 : {
427 420 : check_wire_type_or_throw(type, wire_type::fixed32);
428 : }
429 : if constexpr (sizeof(value) == sizeof(uint32_t))
430 : {
431 220 : stream.read_exact_or_throw(&value, sizeof(value));
432 : }
433 : else
434 : {
435 : if constexpr (std::is_signed_v<T>)
436 : {
437 66 : auto tmp = int32_t(0);
438 66 : stream.read_exact_or_throw(&tmp, sizeof(tmp));
439 64 : if (tmp > std::numeric_limits<T>::max() || tmp < std::numeric_limits<T>::min()) [[unlikely]]
440 4 : throw std::runtime_error("int overflow");
441 :
442 60 : value = T(tmp);
443 : }
444 : else
445 : {
446 132 : auto tmp = uint32_t(0);
447 132 : stream.read_exact_or_throw(&tmp, sizeof(tmp));
448 128 : if (tmp > std::numeric_limits<T>::max()) [[unlikely]]
449 8 : throw std::runtime_error("int overflow");
450 :
451 120 : value = T(tmp);
452 : }
453 : }
454 : }
455 : else if constexpr (scalar_encoder(mode.encoder) == scalar_encoder::i64)
456 : {
457 : static_assert(sizeof(T) <= sizeof(uint64_t));
458 : if constexpr (!is_packed(mode.encoder))
459 : {
460 310 : check_wire_type_or_throw(type, wire_type::fixed64);
461 : }
462 : if constexpr (sizeof(value) == sizeof(uint64_t))
463 : {
464 176 : stream.read_exact_or_throw(&value, sizeof(value));
465 : }
466 : else
467 : {
468 : if constexpr (std::is_signed_v<T>)
469 : {
470 66 : auto tmp = int64_t(0);
471 66 : stream.read_exact_or_throw(&tmp, sizeof(tmp));
472 64 : if (tmp > std::numeric_limits<T>::max() || tmp < std::numeric_limits<T>::min()) [[unlikely]]
473 4 : throw std::runtime_error("int overflow");
474 :
475 60 : value = T(tmp);
476 : }
477 : else
478 : {
479 66 : auto tmp = uint64_t(0);
480 66 : stream.read_exact_or_throw(&tmp, sizeof(tmp));
481 64 : if (tmp > std::numeric_limits<T>::max()) [[unlikely]]
482 4 : throw std::runtime_error("int overflow");
483 :
484 60 : value = T(tmp);
485 : }
486 : }
487 : }
488 1452 : }
489 :
490 : template <serialize_mode mode, spb::detail::proto_label_optional Container>
491 543 : void deserialize(auto &stream, Container &p_value, wire_type type)
492 : {
493 593 : auto &value = p_value.emplace(typename Container::value_type());
494 543 : deserialize<mode>(stream, value, type);
495 505 : }
496 :
497 : template <serialize_mode mode>
498 493 : void deserialize(auto &stream, spb::detail::proto_field_string auto &value, wire_type type)
499 : {
500 493 : check_wire_type_or_throw(type, wire_type::length_delimited);
501 : if constexpr (mode.max_size)
502 64 : check_size(stream.size(), mode.max_size);
503 :
504 : if constexpr (spb::detail::proto_field_string_resizable<decltype(value)>)
505 : {
506 416 : value.resize(stream.size());
507 : }
508 : else
509 : {
510 58 : if (value.size() != stream.size()) [[unlikely]]
511 14 : throw std::runtime_error("invalid string size");
512 : }
513 504 : stream.read_exact_or_throw(value.data(), stream.size());
514 504 : spb::detail::utf8::validate(std::string_view(value.data(), value.size()));
515 459 : }
516 :
517 : template <serialize_mode mode, typename T>
518 : void deserialize(auto &stream, std::unique_ptr<T> &value, wire_type type)
519 : {
520 : value = std::make_unique<T>();
521 : deserialize<mode>(stream, *value, type);
522 : }
523 :
524 : template <serialize_mode mode>
525 280 : void deserialize(auto &stream, spb::detail::proto_field_bytes auto &value, wire_type type)
526 : {
527 280 : check_wire_type_or_throw(type, wire_type::length_delimited);
528 :
529 : if constexpr (mode.max_size)
530 64 : check_size(stream.size(), mode.max_size);
531 :
532 : if constexpr (spb::detail::proto_field_bytes_resizable<decltype(value)>)
533 : {
534 216 : value.resize(stream.size());
535 : }
536 : else
537 : {
538 96 : if (stream.size() != value.size()) [[unlikely]]
539 12 : throw std::runtime_error("invalid bytes size");
540 : }
541 288 : stream.read_exact_or_throw(value.data(), stream.size());
542 252 : }
543 :
544 : template <serialize_mode mode, spb::detail::proto_label_repeated Container>
545 330 : void deserialize_packed(auto &stream, Container &value)
546 : {
547 : static_assert(is_packed(mode.encoder));
548 :
549 848 : while (!stream.empty())
550 : {
551 : if constexpr (mode.max_count)
552 222 : check_size(value.size() + 1, mode.max_count);
553 :
554 : if constexpr (std::is_same_v<typename Container::value_type, bool>)
555 : {
556 20 : value.emplace_back(read_varint<bool>(stream));
557 : }
558 : else
559 : {
560 510 : deserialize<reset_packed(mode)>(stream, value.emplace_back(), to_wire_type(mode.encoder));
561 : }
562 : }
563 288 : }
564 :
565 : template <serialize_mode mode, spb::detail::proto_label_repeated_fixed_size Container>
566 20 : void deserialize_packed(auto &stream, Container &value)
567 : {
568 : static_assert(is_packed(mode.encoder));
569 :
570 : using value_type = typename Container::value_type;
571 :
572 116 : for (size_t i = 0; i < value.size(); i++)
573 : {
574 : if constexpr (std::is_same_v<value_type, bool>)
575 : {
576 : value[i] = read_varint<bool>(stream);
577 : }
578 : else
579 : {
580 : value_type tmp;
581 80 : deserialize<reset_packed(mode)>(stream, tmp, to_wire_type(mode.encoder));
582 76 : value[i] = tmp;
583 : }
584 : }
585 16 : check_if_empty_or_throw(stream);
586 12 : }
587 :
588 : template <serialize_mode mode, spb::detail::proto_label_repeated_fixed_size Container>
589 20 : void deserialize(auto &stream, Container &value, wire_type type)
590 : {
591 : static_assert(is_packed(mode.encoder), "repeated field with fixed size has to have attribute 'packed'");
592 :
593 20 : check_wire_type_or_throw(type, wire_type::length_delimited);
594 20 : deserialize_packed<mode>(stream, value);
595 12 : }
596 :
597 : template <serialize_mode mode, spb::detail::proto_label_repeated Container>
598 1154 : void deserialize(auto &stream, Container &value, wire_type type)
599 : {
600 : if constexpr (is_packed(mode.encoder))
601 : {
602 330 : deserialize_packed<mode>(stream, value);
603 : }
604 : else
605 : {
606 : if constexpr (mode.max_count)
607 356 : check_size(value.size() + 1, mode.max_count);
608 :
609 : if constexpr (std::is_same_v<typename Container::value_type, bool>)
610 : {
611 26 : value.emplace_back(read_varint<bool>(stream));
612 : }
613 : else
614 : {
615 794 : deserialize<mode>(stream, value.emplace_back(), type);
616 : }
617 : }
618 1096 : }
619 :
620 : template <serialize_mode mode>
621 66 : void deserialize(auto &stream, spb::detail::proto_map auto &value, wire_type type)
622 : {
623 : using map_type = std::remove_cvref_t<decltype(value)>;
624 : using key_type = typename map_type::key_type;
625 : using mapped_type = typename map_type::mapped_type;
626 :
627 66 : constexpr auto key_encoder = serialize_mode{.encoder = mode.encoder};
628 66 : constexpr auto value_encoder = serialize_mode{.encoder = mode.encoder2};
629 :
630 66 : check_wire_type_or_throw(type, wire_type::length_delimited);
631 :
632 66 : auto pair = std::pair<key_type, mapped_type>();
633 66 : auto key_or_value_defined = false;
634 198 : while (!stream.empty())
635 : {
636 132 : const auto tag = tag_type(read_varint<uint32_t>(stream));
637 132 : const auto field_number = field_from_tag(tag);
638 132 : const auto field_type = wire_type_from_tag(tag);
639 :
640 132 : check_tag_or_throw(tag);
641 :
642 132 : switch (field_number)
643 : {
644 66 : case 1:
645 : if constexpr (std::is_integral_v<key_type>)
646 : {
647 30 : deserialize<key_encoder>(stream, pair.first, field_type);
648 : }
649 : else
650 : {
651 36 : if (field_type == wire_type::length_delimited)
652 : {
653 36 : const auto size = read_varint<uint32_t>(stream);
654 36 : auto substream = stream.sub_stream(size);
655 36 : deserialize<key_encoder>(substream, pair.first, field_type);
656 36 : check_if_empty_or_throw(substream);
657 : }
658 : else
659 : {
660 0 : deserialize<key_encoder>(stream, pair.first, field_type);
661 : }
662 : }
663 66 : key_or_value_defined = true;
664 66 : break;
665 66 : case 2:
666 : if constexpr (spb::detail::proto_field_number<mapped_type>)
667 : {
668 30 : deserialize<value_encoder>(stream, pair.second, field_type);
669 : }
670 : else
671 : {
672 36 : if (field_type == wire_type::length_delimited)
673 : {
674 36 : const auto size = read_varint<uint32_t>(stream);
675 36 : auto substream = stream.sub_stream(size);
676 36 : deserialize<value_encoder>(substream, pair.second, field_type);
677 36 : check_if_empty_or_throw(substream);
678 : }
679 0 : else [[unlikely]]
680 : {
681 0 : throw std::runtime_error("invalid field");
682 : }
683 : }
684 66 : key_or_value_defined = true;
685 66 : break;
686 0 : default:
687 0 : throw std::runtime_error("invalid field");
688 : }
689 : }
690 66 : if (key_or_value_defined) [[likely]]
691 : {
692 66 : value.insert(std::move(pair));
693 : }
694 66 : }
695 :
696 : template <serialize_mode mode, size_t ordinal, typename T>
697 24 : void deserialize_variant(auto &stream, T &variant, wire_type type)
698 : {
699 24 : deserialize<mode>(stream, variant.template emplace<ordinal>(), type);
700 24 : }
701 :
702 : template <serialize_mode>
703 2909 : void deserialize(auto &stream, spb::detail::proto_message auto &value, wire_type type)
704 : {
705 2909 : check_wire_type_or_throw(type, wire_type::length_delimited);
706 :
707 5587 : while (!stream.empty())
708 : {
709 3430 : const auto tag = read_tag_or_eof(stream);
710 3428 : if (tag == tag_type::invalid)
711 386 : return;
712 :
713 3042 : const auto field_type = wire_type_from_tag(tag);
714 3042 : if (field_type == wire_type::length_delimited)
715 : {
716 1345 : const auto size = read_varint<uint32_t>(stream);
717 1345 : auto substream = stream.sub_stream(size);
718 1303 : deserialize_value(substream, value, tag);
719 1190 : check_if_empty_or_throw(substream);
720 : }
721 : else
722 : {
723 1697 : deserialize_value(stream, value, tag);
724 : }
725 : }
726 : }
727 2756 : template <serialize_mode mode> void deserialize(auto &stream, spb::detail::proto_message auto &value)
728 : {
729 2756 : return deserialize<mode>(stream, value, wire_type::length_delimited);
730 : }
731 :
732 117 : void skip(auto &stream, wire_type type)
733 : {
734 117 : switch (type)
735 : {
736 42 : case wire_type::varint:
737 42 : return (void)read_varint<uint64_t>(stream);
738 35 : case wire_type::length_delimited:
739 35 : return stream.skip_or_throw(stream.size());
740 20 : case wire_type::fixed32:
741 20 : return stream.skip_or_throw(sizeof(uint32_t));
742 19 : case wire_type::fixed64:
743 19 : return stream.skip_or_throw(sizeof(uint64_t));
744 1 : default:
745 1 : throw std::runtime_error("invalid wire type");
746 : }
747 : }
748 : } // namespace spb::pb::detail
|