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