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 1496 : istream_reader(spb::io::reader reader, size_t size = std::numeric_limits<size_t>::max()) noexcept
38 1496 : : bytes_left(size), on_read(reader)
39 : {
40 1496 : }
41 756 : size_t consumed_size() const noexcept
42 : {
43 756 : return consumed_bytes;
44 : }
45 4250 : size_t size() const noexcept
46 : {
47 4250 : return bytes_left;
48 : }
49 2234 : bool empty() const noexcept
50 : {
51 2234 : return bytes_left == 0;
52 : }
53 :
54 3026 : [[nodiscard]] size_t read(void *data, size_t data_size)
55 : {
56 3026 : data_size = std::min(data_size, size());
57 3026 : if (data_size == 0) [[unlikely]]
58 0 : return 0;
59 :
60 3026 : const auto size = on_read(data, data_size);
61 3026 : bytes_left -= size;
62 3026 : consumed_bytes += size;
63 3026 : return size;
64 : }
65 :
66 1280 : [[nodiscard]] uint8_t read_byte_or_throw()
67 : {
68 : uint8_t result;
69 :
70 1280 : if (read(&result, sizeof(result)) != sizeof(result)) [[unlikely]]
71 0 : throw std::runtime_error("unexpected end of stream");
72 :
73 1280 : return result;
74 : }
75 :
76 1188 : [[nodiscard]] int read_byte_or_eof()
77 : {
78 : uint8_t result;
79 2376 : return read(&result, sizeof(result)) == sizeof(result) ? result : -1;
80 : }
81 :
82 558 : void read_exact_or_throw(void *data, size_t data_size)
83 : {
84 1116 : while (data_size > 0)
85 : {
86 558 : auto chunk_size = read(data, data_size);
87 558 : if (chunk_size == 0) [[unlikely]]
88 0 : throw std::runtime_error("unexpected end of stream");
89 :
90 558 : data_size -= chunk_size;
91 : }
92 558 : }
93 :
94 740 : [[nodiscard]] istream_reader sub_stream(size_t sub_size)
95 : {
96 740 : if (size() < sub_size) [[unlikely]]
97 0 : throw std::runtime_error("unexpected end of stream");
98 :
99 740 : bytes_left -= sub_size;
100 740 : consumed_bytes += sub_size;
101 740 : 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 3662 : istream_buffer(const uint8_t *start, size_t size) noexcept : p_start(start), p_end(start + size)
126 : {
127 3662 : }
128 5749 : size_t size() const noexcept
129 : {
130 5749 : return p_end - p_start;
131 : }
132 5476 : bool empty() const noexcept
133 : {
134 5476 : return p_start >= p_end;
135 : }
136 :
137 1252 : [[nodiscard]] size_t read(void *data, size_t data_size) noexcept
138 : {
139 1252 : data_size = std::min(data_size, size());
140 1252 : memcpy(data, p_start, data_size);
141 1252 : p_start += data_size;
142 1252 : return data_size;
143 : }
144 :
145 3399 : [[nodiscard]] uint8_t read_byte_or_throw()
146 : {
147 3399 : if (p_start >= p_end) [[unlikely]]
148 45 : throw std::runtime_error("unexpected end of stream");
149 :
150 3354 : return *p_start++;
151 : }
152 :
153 2187 : [[nodiscard]] int read_byte_or_eof() noexcept
154 : {
155 2187 : if (p_start < p_end) [[likely]]
156 2187 : return *p_start++;
157 :
158 0 : return -1;
159 : }
160 :
161 1252 : void read_exact_or_throw(void *data, size_t data_size)
162 : {
163 1252 : if (read(data, data_size) != data_size) [[unlikely]]
164 20 : throw std::runtime_error("unexpected end of stream");
165 1232 : }
166 :
167 1753 : [[nodiscard]] istream_buffer sub_stream(size_t sub_size)
168 : {
169 1753 : if (size() < sub_size) [[unlikely]]
170 43 : throw std::runtime_error("unexpected end of stream");
171 :
172 1710 : const auto sub_start = p_start;
173 1710 : p_start += sub_size;
174 1710 : 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 <serialize_mode> void deserialize(auto &stream, auto &value, wire_type 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 6064 : [[nodiscard]] inline auto wire_type_from_tag(tag_type tag) -> wire_type
197 : {
198 6064 : return wire_type(uint32_t(tag) & 0x07);
199 : }
200 :
201 6158 : [[nodiscard]] inline auto field_from_tag(tag_type tag) -> uint32_t
202 : {
203 6158 : return uint32_t(tag) >> 3;
204 : }
205 :
206 3116 : inline void check_tag_or_throw(tag_type tag)
207 : {
208 3116 : if (field_from_tag(tag) == 0) [[unlikely]]
209 3 : throw std::runtime_error("invalid field id");
210 3113 : }
211 :
212 5893 : inline void check_wire_type_or_throw(wire_type type1, wire_type type2)
213 : {
214 5893 : if (type1 != type2) [[unlikely]]
215 9 : throw std::runtime_error("invalid wire type");
216 5884 : }
217 :
218 1218 : void check_if_empty_or_throw(auto &stream)
219 : {
220 1218 : if (!stream.empty()) [[unlikely]]
221 4 : throw std::runtime_error("unexpected data in stream");
222 1214 : }
223 :
224 3375 : [[nodiscard]] auto read_tag_or_eof(auto &stream) -> tag_type
225 : {
226 3375 : auto byte_or_eof = stream.read_byte_or_eof();
227 3375 : if (byte_or_eof < 0) [[unlikely]]
228 378 : return tag_type::invalid;
229 :
230 2997 : auto byte = (uint8_t)(byte_or_eof);
231 2997 : auto tag = (uint32_t)(byte & 0x7F);
232 :
233 3032 : 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 2996 : const auto result = tag_type(tag);
243 2996 : check_tag_or_throw(result);
244 2993 : return result;
245 : }
246 :
247 3807 : 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 3721 : auto value = uint64_t(0);
264 :
265 4572 : for (auto shift = 0U; shift < sizeof(value) * CHAR_BIT; shift += CHAR_BIT - 1)
266 : {
267 4558 : uint8_t byte = stream.read_byte_or_throw();
268 4517 : value |= uint64_t(byte & 0x7F) << shift;
269 4517 : 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 626 : value = T(value);
278 : }
279 3666 : auto result = T(value);
280 : if constexpr (std::is_signed_v<T>)
281 : {
282 700 : if (result == std::make_signed_t<T>(value)) [[likely]]
283 700 : return result;
284 : }
285 : else
286 : {
287 2966 : if (result == value) [[likely]]
288 2960 : 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 126 : void deserialize(auto &stream, spb::detail::proto_enum auto &value, wire_type type)
387 : {
388 : using T = std::remove_cvref_t<decltype(value)>;
389 : using int_type = std::underlying_type_t<T>;
390 :
391 : if constexpr (!is_packed(mode.encoder))
392 : {
393 126 : check_wire_type_or_throw(type, wire_type::varint);
394 : }
395 :
396 126 : value = T(read_varint<int_type>(stream));
397 124 : }
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 537 : void deserialize(auto &stream, Container &p_value, wire_type type)
492 : {
493 587 : auto &value = p_value.emplace(typename Container::value_type());
494 537 : deserialize<mode>(stream, value, type);
495 501 : }
496 :
497 : template <serialize_mode mode>
498 475 : void deserialize(auto &stream, spb::detail::proto_field_string auto &value, wire_type type)
499 : {
500 475 : 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 398 : 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 486 : stream.read_exact_or_throw(value.data(), stream.size());
514 486 : spb::detail::utf8::validate(std::string_view(value.data(), value.size()));
515 441 : }
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 274 : void deserialize(auto &stream, spb::detail::proto_field_bytes auto &value, wire_type type)
526 : {
527 274 : 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 210 : 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 282 : stream.read_exact_or_throw(value.data(), stream.size());
542 246 : }
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 850 : 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 512 : 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 1136 : 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 776 : deserialize<mode>(stream, value.emplace_back(), type);
616 : }
617 : }
618 1078 : }
619 :
620 : template <serialize_mode mode>
621 60 : 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 60 : constexpr auto key_encoder = serialize_mode{.encoder = mode.encoder};
628 60 : constexpr auto value_encoder = serialize_mode{.encoder = mode.encoder2};
629 :
630 60 : check_wire_type_or_throw(type, wire_type::length_delimited);
631 :
632 60 : auto pair = std::pair<key_type, mapped_type>();
633 60 : auto key_defined = false;
634 60 : auto value_defined = false;
635 180 : while (!stream.empty())
636 : {
637 120 : const auto tag = tag_type(read_varint<uint32_t>(stream));
638 120 : const auto field_number = field_from_tag(tag);
639 120 : const auto field_type = wire_type_from_tag(tag);
640 :
641 120 : check_tag_or_throw(tag);
642 :
643 120 : switch (field_number)
644 : {
645 60 : case 1:
646 : if constexpr (std::is_integral_v<key_type>)
647 : {
648 30 : deserialize<key_encoder>(stream, pair.first, field_type);
649 : }
650 : else
651 : {
652 30 : if (field_type == wire_type::length_delimited)
653 : {
654 30 : const auto size = read_varint<uint32_t>(stream);
655 30 : auto substream = stream.sub_stream(size);
656 30 : deserialize<key_encoder>(substream, pair.first, field_type);
657 30 : check_if_empty_or_throw(substream);
658 : }
659 : else
660 : {
661 0 : deserialize<key_encoder>(stream, pair.first, field_type);
662 : }
663 : }
664 60 : key_defined = true;
665 60 : break;
666 60 : case 2:
667 : if constexpr (spb::detail::proto_field_number<mapped_type>)
668 : {
669 30 : deserialize<value_encoder>(stream, pair.second, field_type);
670 : }
671 : else
672 : {
673 30 : if (field_type == wire_type::length_delimited)
674 : {
675 30 : const auto size = read_varint<uint32_t>(stream);
676 30 : auto substream = stream.sub_stream(size);
677 30 : deserialize<value_encoder>(substream, pair.second, field_type);
678 30 : check_if_empty_or_throw(substream);
679 : }
680 0 : else [[unlikely]]
681 : {
682 0 : throw std::runtime_error("invalid field");
683 : }
684 : }
685 60 : value_defined = true;
686 60 : break;
687 0 : default:
688 0 : throw std::runtime_error("invalid field");
689 : }
690 : }
691 60 : if (key_defined && value_defined) [[likely]]
692 : {
693 60 : value.insert(std::move(pair));
694 : }
695 0 : else [[unlikely]]
696 : {
697 0 : throw std::runtime_error("invalid map item");
698 : }
699 60 : }
700 :
701 : template <serialize_mode mode, size_t ordinal, typename T>
702 24 : void deserialize_variant(auto &stream, T &variant, wire_type type)
703 : {
704 24 : deserialize<mode>(stream, variant.template emplace<ordinal>(), type);
705 24 : }
706 :
707 : template <serialize_mode>
708 2830 : void deserialize(auto &stream, spb::detail::proto_message auto &value, wire_type type)
709 : {
710 2830 : check_wire_type_or_throw(type, wire_type::length_delimited);
711 :
712 5462 : while (!stream.empty())
713 : {
714 3375 : const auto tag = read_tag_or_eof(stream);
715 3371 : if (tag == tag_type::invalid)
716 378 : return;
717 :
718 2993 : const auto field_type = wire_type_from_tag(tag);
719 2993 : if (field_type == wire_type::length_delimited)
720 : {
721 1297 : const auto size = read_varint<uint32_t>(stream);
722 1297 : auto substream = stream.sub_stream(size);
723 1255 : deserialize_value(substream, value, tag);
724 1142 : check_if_empty_or_throw(substream);
725 : }
726 : else
727 : {
728 1696 : deserialize_value(stream, value, tag);
729 : }
730 : }
731 : }
732 2707 : template <serialize_mode mode> void deserialize(auto &stream, spb::detail::proto_message auto &value)
733 : {
734 2707 : return deserialize<mode>(stream, value, wire_type::length_delimited);
735 : }
736 :
737 117 : void skip(auto &stream, wire_type type)
738 : {
739 117 : switch (type)
740 : {
741 42 : case wire_type::varint:
742 42 : return (void)read_varint<uint64_t>(stream);
743 35 : case wire_type::length_delimited:
744 35 : return stream.skip_or_throw(stream.size());
745 20 : case wire_type::fixed32:
746 20 : return stream.skip_or_throw(sizeof(uint32_t));
747 19 : case wire_type::fixed64:
748 19 : return stream.skip_or_throw(sizeof(uint64_t));
749 1 : default:
750 1 : throw std::runtime_error("invalid wire type");
751 : }
752 : }
753 : } // namespace spb::pb::detail
|