2019-06-20 09:12:49 +00:00
# include "config_formats.h"
2019-02-20 04:28:02 +00:00
# if USE_PROTOBUF
2019-06-20 09:12:49 +00:00
# include "ProtobufReader.h"
2019-02-20 04:28:02 +00:00
# include <AggregateFunctions/IAggregateFunction.h>
# include <boost/numeric/conversion/cast.hpp>
# include <DataTypes/DataTypesDecimal.h>
# include <IO/ReadBufferFromString.h>
# include <IO/ReadHelpers.h>
# include <IO/WriteBufferFromVector.h>
# include <IO/WriteHelpers.h>
# include <optional>
namespace DB
{
namespace ErrorCodes
{
extern const int UNKNOWN_PROTOBUF_FORMAT ;
extern const int PROTOBUF_BAD_CAST ;
}
namespace
{
enum WireType
{
VARINT = 0 ,
BITS64 = 1 ,
LENGTH_DELIMITED = 2 ,
GROUP_START = 3 ,
GROUP_END = 4 ,
BITS32 = 5 ,
} ;
2019-07-24 11:41:49 +00:00
// The following condition must always be true:
// any_cursor_position < min(END_OF_VARINT, END_OF_GROUP)
2019-02-21 15:49:42 +00:00
// This inequation helps to check conditions in SimpleReader.
2019-02-20 04:28:02 +00:00
constexpr UInt64 END_OF_VARINT = static_cast < UInt64 > ( - 1 ) ;
constexpr UInt64 END_OF_GROUP = static_cast < UInt64 > ( - 2 ) ;
Int64 decodeZigZag ( UInt64 n ) { return static_cast < Int64 > ( ( n > > 1 ) ^ ( ~ ( n & 1 ) + 1 ) ) ; }
2019-07-19 21:30:22 +00:00
2019-07-24 11:41:49 +00:00
[[noreturn]] void throwUnknownFormat ( )
{
throw Exception ( " Protobuf messages are corrupted or don't match the provided schema. Please note that Protobuf stream is length-delimited: every message is prefixed by its length in varint. " , ErrorCodes : : UNKNOWN_PROTOBUF_FORMAT ) ;
}
2019-02-20 04:28:02 +00:00
}
2019-02-26 16:02:29 +00:00
// SimpleReader is an utility class to deserialize protobufs.
// Knows nothing about protobuf schemas, just provides useful functions to deserialize data.
2019-02-20 04:28:02 +00:00
ProtobufReader : : SimpleReader : : SimpleReader ( ReadBuffer & in_ )
: in ( in_ )
2019-07-24 11:41:49 +00:00
, cursor ( 0 )
, current_message_level ( 0 )
, current_message_end ( 0 )
, field_end ( 0 )
, last_string_pos ( - 1 )
2019-02-20 04:28:02 +00:00
{
}
bool ProtobufReader : : SimpleReader : : startMessage ( )
{
2019-07-24 11:41:49 +00:00
// Start reading a root message.
assert ( ! current_message_level ) ;
if ( unlikely ( in . eof ( ) ) )
return false ;
size_t size_of_message = readVarint ( ) ;
current_message_end = cursor + size_of_message ;
+ + current_message_level ;
field_end = cursor ;
2019-02-20 04:28:02 +00:00
return true ;
}
2019-07-24 11:41:49 +00:00
void ProtobufReader : : SimpleReader : : endMessage ( bool ignore_errors )
2019-02-20 04:28:02 +00:00
{
2019-07-24 11:41:49 +00:00
if ( ! current_message_level )
return ;
2019-02-20 04:28:02 +00:00
2019-07-24 11:41:49 +00:00
UInt64 root_message_end = ( current_message_level = = 1 ) ? current_message_end : parent_message_ends . front ( ) ;
if ( cursor ! = root_message_end )
2019-02-20 04:28:02 +00:00
{
2019-07-24 11:41:49 +00:00
if ( cursor < root_message_end )
ignore ( root_message_end - cursor ) ;
else if ( ignore_errors )
moveCursorBackward ( cursor - root_message_end ) ;
else
throwUnknownFormat ( ) ;
2019-02-20 04:28:02 +00:00
}
2019-07-24 11:41:49 +00:00
current_message_level = 0 ;
parent_message_ends . clear ( ) ;
}
void ProtobufReader : : SimpleReader : : startNestedMessage ( )
{
assert ( current_message_level > = 1 ) ;
// Start reading a nested message which is located inside a length-delimited field
// of another message.
parent_message_ends . emplace_back ( current_message_end ) ;
current_message_end = field_end ;
+ + current_message_level ;
field_end = cursor ;
2019-02-20 04:28:02 +00:00
}
2019-07-24 11:41:49 +00:00
void ProtobufReader : : SimpleReader : : endNestedMessage ( )
2019-02-20 04:28:02 +00:00
{
2019-07-24 11:41:49 +00:00
assert ( current_message_level > = 2 ) ;
if ( cursor ! = current_message_end )
2019-02-20 04:28:02 +00:00
{
2019-07-24 11:41:49 +00:00
if ( current_message_end = = END_OF_GROUP )
{
ignoreGroup ( ) ;
current_message_end = cursor ;
}
else if ( cursor < current_message_end )
ignore ( current_message_end - cursor ) ;
else
throwUnknownFormat ( ) ;
2019-02-20 04:28:02 +00:00
}
2019-07-24 11:41:49 +00:00
- - current_message_level ;
current_message_end = parent_message_ends . back ( ) ;
parent_message_ends . pop_back ( ) ;
field_end = cursor ;
2019-02-20 04:28:02 +00:00
}
bool ProtobufReader : : SimpleReader : : readFieldNumber ( UInt32 & field_number )
{
2019-07-24 11:41:49 +00:00
assert ( current_message_level ) ;
if ( field_end ! = cursor )
2019-02-20 04:28:02 +00:00
{
if ( field_end = = END_OF_VARINT )
2019-07-24 11:41:49 +00:00
{
2019-02-20 04:28:02 +00:00
ignoreVarint ( ) ;
2019-07-24 11:41:49 +00:00
field_end = cursor ;
}
2019-02-20 04:28:02 +00:00
else if ( field_end = = END_OF_GROUP )
2019-07-24 11:41:49 +00:00
{
2019-02-20 04:28:02 +00:00
ignoreGroup ( ) ;
2019-07-24 11:41:49 +00:00
field_end = cursor ;
}
2019-02-20 04:28:02 +00:00
else if ( cursor < field_end )
ignore ( field_end - cursor ) ;
2019-07-24 11:41:49 +00:00
else
throwUnknownFormat ( ) ;
2019-02-20 04:28:02 +00:00
}
if ( cursor > = current_message_end )
return false ;
UInt64 varint = readVarint ( ) ;
2019-02-21 15:49:42 +00:00
if ( unlikely ( varint & ( static_cast < UInt64 > ( 0xFFFFFFFF ) < < 32 ) ) )
2019-07-19 21:30:22 +00:00
throwUnknownFormat ( ) ;
2019-02-20 04:28:02 +00:00
UInt32 key = static_cast < UInt32 > ( varint ) ;
field_number = ( key > > 3 ) ;
WireType wire_type = static_cast < WireType > ( key & 0x07 ) ;
switch ( wire_type )
{
2019-07-24 11:41:49 +00:00
case BITS32 :
{
field_end = cursor + 4 ;
return true ;
}
2019-02-20 04:28:02 +00:00
case BITS64 :
{
field_end = cursor + 8 ;
return true ;
}
case LENGTH_DELIMITED :
{
size_t length = readVarint ( ) ;
field_end = cursor + length ;
return true ;
}
case VARINT :
{
field_end = END_OF_VARINT ;
return true ;
}
case GROUP_START :
{
field_end = END_OF_GROUP ;
return true ;
}
case GROUP_END :
{
if ( current_message_end ! = END_OF_GROUP )
2019-07-19 21:30:22 +00:00
throwUnknownFormat ( ) ;
2019-07-24 11:41:49 +00:00
current_message_end = cursor ;
2019-02-20 04:28:02 +00:00
return false ;
}
}
2019-07-19 21:30:22 +00:00
throwUnknownFormat ( ) ;
2019-02-20 04:28:02 +00:00
}
bool ProtobufReader : : SimpleReader : : readUInt ( UInt64 & value )
{
2019-02-21 15:49:42 +00:00
if ( unlikely ( cursor > = field_end ) )
2019-02-20 04:28:02 +00:00
return false ;
value = readVarint ( ) ;
2019-07-24 11:41:49 +00:00
if ( field_end = = END_OF_VARINT )
field_end = cursor ;
2019-02-20 04:28:02 +00:00
return true ;
}
bool ProtobufReader : : SimpleReader : : readInt ( Int64 & value )
{
UInt64 varint ;
if ( ! readUInt ( varint ) )
return false ;
value = static_cast < Int64 > ( varint ) ;
return true ;
}
bool ProtobufReader : : SimpleReader : : readSInt ( Int64 & value )
{
UInt64 varint ;
if ( ! readUInt ( varint ) )
return false ;
value = decodeZigZag ( varint ) ;
return true ;
}
template < typename T >
bool ProtobufReader : : SimpleReader : : readFixed ( T & value )
{
2019-02-21 15:49:42 +00:00
if ( unlikely ( cursor > = field_end ) )
2019-02-20 04:28:02 +00:00
return false ;
readBinary ( & value , sizeof ( T ) ) ;
return true ;
}
bool ProtobufReader : : SimpleReader : : readStringInto ( PaddedPODArray < UInt8 > & str )
{
2019-07-24 11:41:49 +00:00
if ( unlikely ( cursor = = last_string_pos ) )
return false ; /// We don't want to read the same empty string again.
last_string_pos = cursor ;
2019-02-21 15:49:42 +00:00
if ( unlikely ( cursor > field_end ) )
2019-07-24 11:41:49 +00:00
throwUnknownFormat ( ) ;
2019-02-20 04:28:02 +00:00
size_t length = field_end - cursor ;
size_t old_size = str . size ( ) ;
str . resize ( old_size + length ) ;
readBinary ( reinterpret_cast < char * > ( str . data ( ) + old_size ) , length ) ;
return true ;
}
void ProtobufReader : : SimpleReader : : readBinary ( void * data , size_t size )
{
in . readStrict ( reinterpret_cast < char * > ( data ) , size ) ;
cursor + = size ;
}
void ProtobufReader : : SimpleReader : : ignore ( UInt64 num_bytes )
{
in . ignore ( num_bytes ) ;
cursor + = num_bytes ;
}
void ProtobufReader : : SimpleReader : : moveCursorBackward ( UInt64 num_bytes )
{
if ( in . offset ( ) < num_bytes )
2019-07-19 21:30:22 +00:00
throwUnknownFormat ( ) ;
2019-02-20 04:28:02 +00:00
in . position ( ) - = num_bytes ;
cursor - = num_bytes ;
}
2019-02-21 15:49:42 +00:00
UInt64 ProtobufReader : : SimpleReader : : continueReadingVarint ( UInt64 first_byte )
2019-02-20 04:28:02 +00:00
{
2019-02-21 15:49:42 +00:00
UInt64 result = ( first_byte & ~ static_cast < UInt64 > ( 0x80 ) ) ;
2019-02-20 04:28:02 +00:00
char c ;
2019-02-21 15:49:42 +00:00
# define PROTOBUF_READER_READ_VARINT_BYTE(byteNo) \
2020-03-18 02:02:24 +00:00
do \
2019-02-20 04:28:02 +00:00
{ \
2020-03-18 02:02:24 +00:00
in . readStrict ( c ) ; \
+ + cursor ; \
if constexpr ( ( byteNo ) < 10 ) \
{ \
result | = static_cast < UInt64 > ( static_cast < UInt8 > ( c ) ) < < ( 7 * ( ( byteNo ) - 1 ) ) ; \
if ( likely ( ! ( c & 0x80 ) ) ) \
return result ; \
} \
else \
{ \
if ( likely ( c = = 1 ) ) \
return result ; \
} \
if constexpr ( ( byteNo ) < 9 ) \
result & = ~ ( static_cast < UInt64 > ( 0x80 ) < < ( 7 * ( ( byteNo ) - 1 ) ) ) ; \
} while ( false )
PROTOBUF_READER_READ_VARINT_BYTE ( 2 ) ;
PROTOBUF_READER_READ_VARINT_BYTE ( 3 ) ;
PROTOBUF_READER_READ_VARINT_BYTE ( 4 ) ;
PROTOBUF_READER_READ_VARINT_BYTE ( 5 ) ;
PROTOBUF_READER_READ_VARINT_BYTE ( 6 ) ;
PROTOBUF_READER_READ_VARINT_BYTE ( 7 ) ;
PROTOBUF_READER_READ_VARINT_BYTE ( 8 ) ;
PROTOBUF_READER_READ_VARINT_BYTE ( 9 ) ;
PROTOBUF_READER_READ_VARINT_BYTE ( 10 ) ;
2019-02-21 15:49:42 +00:00
# undef PROTOBUF_READER_READ_VARINT_BYTE
2019-02-20 04:28:02 +00:00
2019-07-19 21:30:22 +00:00
throwUnknownFormat ( ) ;
2019-02-20 04:28:02 +00:00
}
void ProtobufReader : : SimpleReader : : ignoreVarint ( )
{
char c ;
2019-02-21 15:49:42 +00:00
# define PROTOBUF_READER_IGNORE_VARINT_BYTE(byteNo) \
2020-03-18 02:02:24 +00:00
do \
2019-02-20 04:28:02 +00:00
{ \
2020-03-18 02:02:24 +00:00
in . readStrict ( c ) ; \
+ + cursor ; \
if constexpr ( ( byteNo ) < 10 ) \
{ \
if ( likely ( ! ( c & 0x80 ) ) ) \
return ; \
} \
else \
{ \
if ( likely ( c = = 1 ) ) \
return ; \
} \
} while ( false )
PROTOBUF_READER_IGNORE_VARINT_BYTE ( 1 ) ;
PROTOBUF_READER_IGNORE_VARINT_BYTE ( 2 ) ;
PROTOBUF_READER_IGNORE_VARINT_BYTE ( 3 ) ;
PROTOBUF_READER_IGNORE_VARINT_BYTE ( 4 ) ;
PROTOBUF_READER_IGNORE_VARINT_BYTE ( 5 ) ;
PROTOBUF_READER_IGNORE_VARINT_BYTE ( 6 ) ;
PROTOBUF_READER_IGNORE_VARINT_BYTE ( 7 ) ;
PROTOBUF_READER_IGNORE_VARINT_BYTE ( 8 ) ;
PROTOBUF_READER_IGNORE_VARINT_BYTE ( 9 ) ;
PROTOBUF_READER_IGNORE_VARINT_BYTE ( 10 ) ;
2019-02-21 15:49:42 +00:00
# undef PROTOBUF_READER_IGNORE_VARINT_BYTE
2019-02-20 04:28:02 +00:00
2019-07-19 21:30:22 +00:00
throwUnknownFormat ( ) ;
2019-02-20 04:28:02 +00:00
}
void ProtobufReader : : SimpleReader : : ignoreGroup ( )
{
size_t level = 1 ;
while ( true )
{
UInt64 varint = readVarint ( ) ;
WireType wire_type = static_cast < WireType > ( varint & 0x07 ) ;
switch ( wire_type )
{
case VARINT :
{
ignoreVarint ( ) ;
break ;
}
case BITS64 :
{
ignore ( 8 ) ;
break ;
}
case LENGTH_DELIMITED :
{
ignore ( readVarint ( ) ) ;
break ;
}
case GROUP_START :
{
+ + level ;
break ;
}
case GROUP_END :
{
if ( ! - - level )
return ;
break ;
}
case BITS32 :
{
ignore ( 4 ) ;
break ;
}
}
2019-07-19 21:30:22 +00:00
throwUnknownFormat ( ) ;
2019-02-20 04:28:02 +00:00
}
}
2019-02-26 16:02:29 +00:00
// Implementation for a converter from any protobuf field type to any DB data type.
2019-02-20 04:28:02 +00:00
class ProtobufReader : : ConverterBaseImpl : public ProtobufReader : : IConverter
{
public :
ConverterBaseImpl ( SimpleReader & simple_reader_ , const google : : protobuf : : FieldDescriptor * field_ )
: simple_reader ( simple_reader_ ) , field ( field_ ) { }
bool readStringInto ( PaddedPODArray < UInt8 > & ) override
{
cannotConvertType ( " String " ) ;
}
bool readInt8 ( Int8 & ) override
{
cannotConvertType ( " Int8 " ) ;
}
bool readUInt8 ( UInt8 & ) override
{
cannotConvertType ( " UInt8 " ) ;
}
bool readInt16 ( Int16 & ) override
{
cannotConvertType ( " Int16 " ) ;
}
bool readUInt16 ( UInt16 & ) override
{
cannotConvertType ( " UInt16 " ) ;
}
bool readInt32 ( Int32 & ) override
{
cannotConvertType ( " Int32 " ) ;
}
bool readUInt32 ( UInt32 & ) override
{
cannotConvertType ( " UInt32 " ) ;
}
bool readInt64 ( Int64 & ) override
{
cannotConvertType ( " Int64 " ) ;
}
bool readUInt64 ( UInt64 & ) override
{
cannotConvertType ( " UInt64 " ) ;
}
bool readUInt128 ( UInt128 & ) override
{
cannotConvertType ( " UInt128 " ) ;
}
bool readFloat32 ( Float32 & ) override
{
cannotConvertType ( " Float32 " ) ;
}
bool readFloat64 ( Float64 & ) override
{
cannotConvertType ( " Float64 " ) ;
}
void prepareEnumMapping8 ( const std : : vector < std : : pair < std : : string , Int8 > > & ) override { }
void prepareEnumMapping16 ( const std : : vector < std : : pair < std : : string , Int16 > > & ) override { }
bool readEnum8 ( Int8 & ) override
{
cannotConvertType ( " Enum " ) ;
}
bool readEnum16 ( Int16 & ) override
{
cannotConvertType ( " Enum " ) ;
}
bool readUUID ( UUID & ) override
{
cannotConvertType ( " UUID " ) ;
}
bool readDate ( DayNum & ) override
{
cannotConvertType ( " Date " ) ;
}
bool readDateTime ( time_t & ) override
{
cannotConvertType ( " DateTime " ) ;
}
2019-10-02 05:53:38 +00:00
bool readDateTime64 ( DateTime64 & , UInt32 ) override
{
cannotConvertType ( " DateTime64 " ) ;
}
2019-02-20 04:28:02 +00:00
bool readDecimal32 ( Decimal32 & , UInt32 , UInt32 ) override
{
cannotConvertType ( " Decimal32 " ) ;
}
bool readDecimal64 ( Decimal64 & , UInt32 , UInt32 ) override
{
cannotConvertType ( " Decimal64 " ) ;
}
bool readDecimal128 ( Decimal128 & , UInt32 , UInt32 ) override
{
cannotConvertType ( " Decimal128 " ) ;
}
bool readAggregateFunction ( const AggregateFunctionPtr & , AggregateDataPtr , Arena & ) override
{
cannotConvertType ( " AggregateFunction " ) ;
}
protected :
2019-04-10 20:27:14 +00:00
[[noreturn]] void cannotConvertType ( const String & type_name )
2019-02-20 04:28:02 +00:00
{
throw Exception (
String ( " Could not convert type ' " ) + field - > type_name ( ) + " ' from protobuf field ' " + field - > name ( ) + " ' to data type ' "
+ type_name + " ' " ,
ErrorCodes : : PROTOBUF_BAD_CAST ) ;
}
2019-04-10 20:27:14 +00:00
[[noreturn]] void cannotConvertValue ( const String & value , const String & type_name )
2019-02-20 04:28:02 +00:00
{
throw Exception (
" Could not convert value ' " + value + " ' from protobuf field ' " + field - > name ( ) + " ' to data type ' " + type_name + " ' " ,
ErrorCodes : : PROTOBUF_BAD_CAST ) ;
}
template < typename To , typename From >
To numericCast ( From value )
{
if constexpr ( std : : is_same_v < To , From > )
return value ;
To result ;
try
{
result = boost : : numeric_cast < To > ( value ) ;
}
catch ( boost : : numeric : : bad_numeric_cast & )
{
cannotConvertValue ( toString ( value ) , TypeName < To > : : get ( ) ) ;
}
return result ;
}
template < typename To >
To parseFromString ( const PaddedPODArray < UInt8 > & str )
{
try
{
To result ;
ReadBufferFromString buf ( str ) ;
readText ( result , buf ) ;
return result ;
}
catch ( . . . )
{
cannotConvertValue ( StringRef ( str . data ( ) , str . size ( ) ) . toString ( ) , TypeName < To > : : get ( ) ) ;
}
}
SimpleReader & simple_reader ;
const google : : protobuf : : FieldDescriptor * field ;
} ;
class ProtobufReader : : ConverterFromString : public ConverterBaseImpl
{
public :
using ConverterBaseImpl : : ConverterBaseImpl ;
bool readStringInto ( PaddedPODArray < UInt8 > & str ) override { return simple_reader . readStringInto ( str ) ; }
bool readInt8 ( Int8 & value ) override { return readNumeric ( value ) ; }
bool readUInt8 ( UInt8 & value ) override { return readNumeric ( value ) ; }
bool readInt16 ( Int16 & value ) override { return readNumeric ( value ) ; }
bool readUInt16 ( UInt16 & value ) override { return readNumeric ( value ) ; }
bool readInt32 ( Int32 & value ) override { return readNumeric ( value ) ; }
bool readUInt32 ( UInt32 & value ) override { return readNumeric ( value ) ; }
bool readInt64 ( Int64 & value ) override { return readNumeric ( value ) ; }
bool readUInt64 ( UInt64 & value ) override { return readNumeric ( value ) ; }
bool readFloat32 ( Float32 & value ) override { return readNumeric ( value ) ; }
bool readFloat64 ( Float64 & value ) override { return readNumeric ( value ) ; }
void prepareEnumMapping8 ( const std : : vector < std : : pair < String , Int8 > > & name_value_pairs ) override
{
prepareEnumNameToValueMap ( name_value_pairs ) ;
}
void prepareEnumMapping16 ( const std : : vector < std : : pair < String , Int16 > > & name_value_pairs ) override
{
prepareEnumNameToValueMap ( name_value_pairs ) ;
}
bool readEnum8 ( Int8 & value ) override { return readEnum ( value ) ; }
bool readEnum16 ( Int16 & value ) override { return readEnum ( value ) ; }
bool readUUID ( UUID & uuid ) override
{
if ( ! readTempString ( ) )
return false ;
ReadBufferFromString buf ( temp_string ) ;
readUUIDText ( uuid , buf ) ;
return true ;
}
bool readDate ( DayNum & date ) override
{
if ( ! readTempString ( ) )
return false ;
ReadBufferFromString buf ( temp_string ) ;
readDateText ( date , buf ) ;
return true ;
}
bool readDateTime ( time_t & tm ) override
{
if ( ! readTempString ( ) )
return false ;
ReadBufferFromString buf ( temp_string ) ;
readDateTimeText ( tm , buf ) ;
return true ;
}
2019-10-02 05:53:38 +00:00
bool readDateTime64 ( DateTime64 & date_time , UInt32 scale ) override
{
if ( ! readTempString ( ) )
return false ;
ReadBufferFromString buf ( temp_string ) ;
2019-10-12 07:03:38 +00:00
readDateTime64Text ( date_time , scale , buf ) ;
2019-10-02 05:53:38 +00:00
return true ;
}
2019-02-20 04:28:02 +00:00
bool readDecimal32 ( Decimal32 & decimal , UInt32 precision , UInt32 scale ) override { return readDecimal ( decimal , precision , scale ) ; }
bool readDecimal64 ( Decimal64 & decimal , UInt32 precision , UInt32 scale ) override { return readDecimal ( decimal , precision , scale ) ; }
bool readDecimal128 ( Decimal128 & decimal , UInt32 precision , UInt32 scale ) override { return readDecimal ( decimal , precision , scale ) ; }
bool readAggregateFunction ( const AggregateFunctionPtr & function , AggregateDataPtr place , Arena & arena ) override
{
if ( ! readTempString ( ) )
return false ;
ReadBufferFromString buf ( temp_string ) ;
function - > deserialize ( place , buf , & arena ) ;
return true ;
}
private :
bool readTempString ( )
{
temp_string . clear ( ) ;
return simple_reader . readStringInto ( temp_string ) ;
}
template < typename T >
bool readNumeric ( T & value )
{
if ( ! readTempString ( ) )
return false ;
value = parseFromString < T > ( temp_string ) ;
return true ;
}
template < typename T >
bool readEnum ( T & value )
{
if ( ! readTempString ( ) )
return false ;
2019-02-21 15:49:42 +00:00
StringRef ref ( temp_string . data ( ) , temp_string . size ( ) ) ;
auto it = enum_name_to_value_map - > find ( ref ) ;
2019-02-20 04:28:02 +00:00
if ( it = = enum_name_to_value_map - > end ( ) )
2019-02-21 15:49:42 +00:00
cannotConvertValue ( ref . toString ( ) , " Enum " ) ;
2019-02-20 04:28:02 +00:00
value = static_cast < T > ( it - > second ) ;
return true ;
}
template < typename T >
bool readDecimal ( Decimal < T > & decimal , UInt32 precision , UInt32 scale )
{
if ( ! readTempString ( ) )
return false ;
ReadBufferFromString buf ( temp_string ) ;
DataTypeDecimal < Decimal < T > > : : readText ( decimal , buf , precision , scale ) ;
return true ;
}
template < typename T >
void prepareEnumNameToValueMap ( const std : : vector < std : : pair < String , T > > & name_value_pairs )
{
2019-02-21 15:49:42 +00:00
if ( likely ( enum_name_to_value_map . has_value ( ) ) )
2019-02-20 04:28:02 +00:00
return ;
enum_name_to_value_map . emplace ( ) ;
for ( const auto & name_value_pair : name_value_pairs )
enum_name_to_value_map - > emplace ( name_value_pair . first , name_value_pair . second ) ;
}
PaddedPODArray < UInt8 > temp_string ;
std : : optional < std : : unordered_map < StringRef , Int16 > > enum_name_to_value_map ;
} ;
2019-02-26 16:02:29 +00:00
# define PROTOBUF_READER_CREATE_CONVERTER_SPECIALIZATION_FOR_STRINGS(field_type_id) \
template < > \
std : : unique_ptr < ProtobufReader : : IConverter > ProtobufReader : : createConverter < field_type_id > ( \
const google : : protobuf : : FieldDescriptor * field ) \
2019-02-20 04:28:02 +00:00
{ \
2019-02-26 16:02:29 +00:00
return std : : make_unique < ConverterFromString > ( simple_reader , field ) ; \
2019-02-20 04:28:02 +00:00
}
2019-02-26 16:02:29 +00:00
PROTOBUF_READER_CREATE_CONVERTER_SPECIALIZATION_FOR_STRINGS ( google : : protobuf : : FieldDescriptor : : TYPE_STRING )
PROTOBUF_READER_CREATE_CONVERTER_SPECIALIZATION_FOR_STRINGS ( google : : protobuf : : FieldDescriptor : : TYPE_BYTES )
# undef PROTOBUF_READER_CREATE_CONVERTER_SPECIALIZATION_FOR_STRINGS
2019-02-20 04:28:02 +00:00
2019-02-26 16:02:29 +00:00
template < int field_type_id , typename FromType >
2019-02-20 04:28:02 +00:00
class ProtobufReader : : ConverterFromNumber : public ConverterBaseImpl
{
public :
using ConverterBaseImpl : : ConverterBaseImpl ;
bool readStringInto ( PaddedPODArray < UInt8 > & str ) override
{
2019-02-26 16:02:29 +00:00
FromType number ;
2019-02-20 04:28:02 +00:00
if ( ! readField ( number ) )
return false ;
WriteBufferFromVector < PaddedPODArray < UInt8 > > buf ( str ) ;
writeText ( number , buf ) ;
return true ;
}
bool readInt8 ( Int8 & value ) override { return readNumeric ( value ) ; }
bool readUInt8 ( UInt8 & value ) override { return readNumeric ( value ) ; }
bool readInt16 ( Int16 & value ) override { return readNumeric ( value ) ; }
bool readUInt16 ( UInt16 & value ) override { return readNumeric ( value ) ; }
bool readInt32 ( Int32 & value ) override { return readNumeric ( value ) ; }
bool readUInt32 ( UInt32 & value ) override { return readNumeric ( value ) ; }
bool readInt64 ( Int64 & value ) override { return readNumeric ( value ) ; }
bool readUInt64 ( UInt64 & value ) override { return readNumeric ( value ) ; }
bool readFloat32 ( Float32 & value ) override { return readNumeric ( value ) ; }
bool readFloat64 ( Float64 & value ) override { return readNumeric ( value ) ; }
bool readEnum8 ( Int8 & value ) override { return readEnum ( value ) ; }
bool readEnum16 ( Int16 & value ) override { return readEnum ( value ) ; }
void prepareEnumMapping8 ( const std : : vector < std : : pair < String , Int8 > > & name_value_pairs ) override
{
prepareSetOfEnumValues ( name_value_pairs ) ;
}
void prepareEnumMapping16 ( const std : : vector < std : : pair < String , Int16 > > & name_value_pairs ) override
{
prepareSetOfEnumValues ( name_value_pairs ) ;
}
bool readDate ( DayNum & date ) override
{
UInt16 number ;
if ( ! readNumeric ( number ) )
return false ;
date = DayNum ( number ) ;
return true ;
}
bool readDateTime ( time_t & tm ) override
{
UInt32 number ;
if ( ! readNumeric ( number ) )
return false ;
tm = number ;
return true ;
}
2019-10-02 05:53:38 +00:00
bool readDateTime64 ( DateTime64 & date_time , UInt32 scale ) override
{
return readDecimal ( date_time , scale ) ;
}
2019-02-20 04:28:02 +00:00
bool readDecimal32 ( Decimal32 & decimal , UInt32 , UInt32 scale ) override { return readDecimal ( decimal , scale ) ; }
bool readDecimal64 ( Decimal64 & decimal , UInt32 , UInt32 scale ) override { return readDecimal ( decimal , scale ) ; }
bool readDecimal128 ( Decimal128 & decimal , UInt32 , UInt32 scale ) override { return readDecimal ( decimal , scale ) ; }
private :
template < typename To >
bool readNumeric ( To & value )
{
2019-02-26 16:02:29 +00:00
FromType number ;
2019-02-20 04:28:02 +00:00
if ( ! readField ( number ) )
return false ;
value = numericCast < To > ( number ) ;
return true ;
}
template < typename EnumType >
bool readEnum ( EnumType & value )
{
2019-11-02 05:55:06 +00:00
if constexpr ( ! is_integral_v < FromType > )
2019-02-20 04:28:02 +00:00
cannotConvertType ( " Enum " ) ; // It's not correct to convert floating point to enum.
2019-02-26 16:02:29 +00:00
FromType number ;
2019-02-20 04:28:02 +00:00
if ( ! readField ( number ) )
return false ;
value = numericCast < EnumType > ( number ) ;
2019-02-21 15:49:42 +00:00
if ( set_of_enum_values - > find ( value ) = = set_of_enum_values - > end ( ) )
2019-02-20 04:28:02 +00:00
cannotConvertValue ( toString ( value ) , " Enum " ) ;
return true ;
}
template < typename EnumType >
void prepareSetOfEnumValues ( const std : : vector < std : : pair < String , EnumType > > & name_value_pairs )
{
2019-02-21 15:49:42 +00:00
if ( likely ( set_of_enum_values . has_value ( ) ) )
2019-02-20 04:28:02 +00:00
return ;
set_of_enum_values . emplace ( ) ;
for ( const auto & name_value_pair : name_value_pairs )
set_of_enum_values - > emplace ( name_value_pair . second ) ;
}
template < typename S >
bool readDecimal ( Decimal < S > & decimal , UInt32 scale )
{
2019-02-26 16:02:29 +00:00
FromType number ;
2019-02-20 04:28:02 +00:00
if ( ! readField ( number ) )
return false ;
2019-02-26 16:02:29 +00:00
decimal . value = convertToDecimal < DataTypeNumber < FromType > , DataTypeDecimal < Decimal < S > > > ( number , scale ) ;
2019-02-20 04:28:02 +00:00
return true ;
}
2019-02-26 16:02:29 +00:00
bool readField ( FromType & value )
2019-02-20 04:28:02 +00:00
{
2019-02-26 16:02:29 +00:00
if constexpr ( ( ( field_type_id = = google : : protobuf : : FieldDescriptor : : TYPE_INT32 ) & & std : : is_same_v < FromType , Int64 > )
| | ( ( field_type_id = = google : : protobuf : : FieldDescriptor : : TYPE_INT64 ) & & std : : is_same_v < FromType , Int64 > ) )
{
2019-02-20 04:28:02 +00:00
return simple_reader . readInt ( value ) ;
2019-02-26 16:02:29 +00:00
}
else if constexpr ( ( ( field_type_id = = google : : protobuf : : FieldDescriptor : : TYPE_UINT32 ) & & std : : is_same_v < FromType , UInt64 > )
| | ( ( field_type_id = = google : : protobuf : : FieldDescriptor : : TYPE_UINT64 ) & & std : : is_same_v < FromType , UInt64 > ) )
{
2019-02-20 04:28:02 +00:00
return simple_reader . readUInt ( value ) ;
2019-02-26 16:02:29 +00:00
}
else if constexpr ( ( ( field_type_id = = google : : protobuf : : FieldDescriptor : : TYPE_SINT32 ) & & std : : is_same_v < FromType , Int64 > )
| | ( ( field_type_id = = google : : protobuf : : FieldDescriptor : : TYPE_SINT64 ) & & std : : is_same_v < FromType , Int64 > ) )
{
2019-02-20 04:28:02 +00:00
return simple_reader . readSInt ( value ) ;
2019-02-26 16:02:29 +00:00
}
2019-02-20 04:28:02 +00:00
else
{
2019-02-26 16:02:29 +00:00
static_assert ( ( ( field_type_id = = google : : protobuf : : FieldDescriptor : : TYPE_FIXED32 ) & & std : : is_same_v < FromType , UInt32 > )
| | ( ( field_type_id = = google : : protobuf : : FieldDescriptor : : TYPE_SFIXED32 ) & & std : : is_same_v < FromType , Int32 > )
| | ( ( field_type_id = = google : : protobuf : : FieldDescriptor : : TYPE_FIXED64 ) & & std : : is_same_v < FromType , UInt64 > )
| | ( ( field_type_id = = google : : protobuf : : FieldDescriptor : : TYPE_SFIXED64 ) & & std : : is_same_v < FromType , Int64 > )
| | ( ( field_type_id = = google : : protobuf : : FieldDescriptor : : TYPE_FLOAT ) & & std : : is_same_v < FromType , float > )
| | ( ( field_type_id = = google : : protobuf : : FieldDescriptor : : TYPE_DOUBLE ) & & std : : is_same_v < FromType , double > ) ) ;
2019-02-20 04:28:02 +00:00
return simple_reader . readFixed ( value ) ;
}
}
std : : optional < std : : unordered_set < Int16 > > set_of_enum_values ;
} ;
2019-02-26 16:02:29 +00:00
# define PROTOBUF_READER_CREATE_CONVERTER_SPECIALIZATION_FOR_NUMBERS(field_type_id, field_type) \
template < > \
std : : unique_ptr < ProtobufReader : : IConverter > ProtobufReader : : createConverter < field_type_id > ( \
const google : : protobuf : : FieldDescriptor * field ) \
2019-02-20 04:28:02 +00:00
{ \
2020-03-18 02:02:24 +00:00
return std : : make_unique < ConverterFromNumber < field_type_id , field_type > > ( simple_reader , field ) ; /* NOLINT */ \
2019-02-26 16:02:29 +00:00
}
PROTOBUF_READER_CREATE_CONVERTER_SPECIALIZATION_FOR_NUMBERS ( google : : protobuf : : FieldDescriptor : : TYPE_INT32 , Int64 ) ;
PROTOBUF_READER_CREATE_CONVERTER_SPECIALIZATION_FOR_NUMBERS ( google : : protobuf : : FieldDescriptor : : TYPE_SINT32 , Int64 ) ;
PROTOBUF_READER_CREATE_CONVERTER_SPECIALIZATION_FOR_NUMBERS ( google : : protobuf : : FieldDescriptor : : TYPE_UINT32 , UInt64 ) ;
PROTOBUF_READER_CREATE_CONVERTER_SPECIALIZATION_FOR_NUMBERS ( google : : protobuf : : FieldDescriptor : : TYPE_INT64 , Int64 ) ;
PROTOBUF_READER_CREATE_CONVERTER_SPECIALIZATION_FOR_NUMBERS ( google : : protobuf : : FieldDescriptor : : TYPE_SINT64 , Int64 ) ;
PROTOBUF_READER_CREATE_CONVERTER_SPECIALIZATION_FOR_NUMBERS ( google : : protobuf : : FieldDescriptor : : TYPE_UINT64 , UInt64 ) ;
PROTOBUF_READER_CREATE_CONVERTER_SPECIALIZATION_FOR_NUMBERS ( google : : protobuf : : FieldDescriptor : : TYPE_FIXED32 , UInt32 ) ;
PROTOBUF_READER_CREATE_CONVERTER_SPECIALIZATION_FOR_NUMBERS ( google : : protobuf : : FieldDescriptor : : TYPE_SFIXED32 , Int32 ) ;
PROTOBUF_READER_CREATE_CONVERTER_SPECIALIZATION_FOR_NUMBERS ( google : : protobuf : : FieldDescriptor : : TYPE_FIXED64 , UInt64 ) ;
PROTOBUF_READER_CREATE_CONVERTER_SPECIALIZATION_FOR_NUMBERS ( google : : protobuf : : FieldDescriptor : : TYPE_SFIXED64 , Int64 ) ;
PROTOBUF_READER_CREATE_CONVERTER_SPECIALIZATION_FOR_NUMBERS ( google : : protobuf : : FieldDescriptor : : TYPE_FLOAT , float ) ;
PROTOBUF_READER_CREATE_CONVERTER_SPECIALIZATION_FOR_NUMBERS ( google : : protobuf : : FieldDescriptor : : TYPE_DOUBLE , double ) ;
# undef PROTOBUF_READER_CREATE_CONVERTER_SPECIALIZATION_FOR_NUMBERS
class ProtobufReader : : ConverterFromBool : public ConverterBaseImpl
2019-02-20 04:28:02 +00:00
{
public :
using ConverterBaseImpl : : ConverterBaseImpl ;
bool readStringInto ( PaddedPODArray < UInt8 > & str ) override
{
bool b ;
if ( ! readField ( b ) )
return false ;
2019-02-21 15:49:42 +00:00
StringRef ref ( b ? " true " : " false " ) ;
str . insert ( ref . data , ref . data + ref . size ) ;
2019-02-20 04:28:02 +00:00
return true ;
}
bool readInt8 ( Int8 & value ) override { return readNumeric ( value ) ; }
bool readUInt8 ( UInt8 & value ) override { return readNumeric ( value ) ; }
bool readInt16 ( Int16 & value ) override { return readNumeric ( value ) ; }
bool readUInt16 ( UInt16 & value ) override { return readNumeric ( value ) ; }
bool readInt32 ( Int32 & value ) override { return readNumeric ( value ) ; }
bool readUInt32 ( UInt32 & value ) override { return readNumeric ( value ) ; }
bool readInt64 ( Int64 & value ) override { return readNumeric ( value ) ; }
bool readUInt64 ( UInt64 & value ) override { return readNumeric ( value ) ; }
bool readFloat32 ( Float32 & value ) override { return readNumeric ( value ) ; }
bool readFloat64 ( Float64 & value ) override { return readNumeric ( value ) ; }
bool readDecimal32 ( Decimal32 & decimal , UInt32 , UInt32 ) override { return readNumeric ( decimal . value ) ; }
bool readDecimal64 ( Decimal64 & decimal , UInt32 , UInt32 ) override { return readNumeric ( decimal . value ) ; }
bool readDecimal128 ( Decimal128 & decimal , UInt32 , UInt32 ) override { return readNumeric ( decimal . value ) ; }
private :
template < typename T >
bool readNumeric ( T & value )
{
bool b ;
if ( ! readField ( b ) )
return false ;
value = b ? 1 : 0 ;
return true ;
}
bool readField ( bool & b )
{
UInt64 number ;
if ( ! simple_reader . readUInt ( number ) )
return false ;
b = static_cast < bool > ( number ) ;
return true ;
}
} ;
2019-02-26 16:02:29 +00:00
template < >
std : : unique_ptr < ProtobufReader : : IConverter > ProtobufReader : : createConverter < google : : protobuf : : FieldDescriptor : : TYPE_BOOL > (
const google : : protobuf : : FieldDescriptor * field )
{
return std : : make_unique < ConverterFromBool > ( simple_reader , field ) ;
}
2019-02-20 04:28:02 +00:00
2019-02-26 16:02:29 +00:00
class ProtobufReader : : ConverterFromEnum : public ConverterBaseImpl
2019-02-20 04:28:02 +00:00
{
public :
using ConverterBaseImpl : : ConverterBaseImpl ;
bool readStringInto ( PaddedPODArray < UInt8 > & str ) override
{
prepareEnumPbNumberToNameMap ( ) ;
Int64 pbnumber ;
if ( ! readField ( pbnumber ) )
return false ;
auto it = enum_pbnumber_to_name_map - > find ( pbnumber ) ;
if ( it = = enum_pbnumber_to_name_map - > end ( ) )
cannotConvertValue ( toString ( pbnumber ) , " Enum " ) ;
2019-02-21 15:49:42 +00:00
const auto & ref = it - > second ;
str . insert ( ref . data , ref . data + ref . size ) ;
2019-02-20 04:28:02 +00:00
return true ;
}
bool readInt8 ( Int8 & value ) override { return readNumeric ( value ) ; }
bool readUInt8 ( UInt8 & value ) override { return readNumeric ( value ) ; }
bool readInt16 ( Int16 & value ) override { return readNumeric ( value ) ; }
bool readUInt16 ( UInt16 & value ) override { return readNumeric ( value ) ; }
bool readInt32 ( Int32 & value ) override { return readNumeric ( value ) ; }
bool readUInt32 ( UInt32 & value ) override { return readNumeric ( value ) ; }
bool readInt64 ( Int64 & value ) override { return readNumeric ( value ) ; }
bool readUInt64 ( UInt64 & value ) override { return readNumeric ( value ) ; }
void prepareEnumMapping8 ( const std : : vector < std : : pair < String , Int8 > > & name_value_pairs ) override
{
prepareEnumPbNumberToValueMap ( name_value_pairs ) ;
}
void prepareEnumMapping16 ( const std : : vector < std : : pair < String , Int16 > > & name_value_pairs ) override
{
prepareEnumPbNumberToValueMap ( name_value_pairs ) ;
}
bool readEnum8 ( Int8 & value ) override { return readEnum ( value ) ; }
bool readEnum16 ( Int16 & value ) override { return readEnum ( value ) ; }
private :
template < typename T >
bool readNumeric ( T & value )
{
Int64 pbnumber ;
if ( ! readField ( pbnumber ) )
return false ;
value = numericCast < T > ( pbnumber ) ;
return true ;
}
template < typename T >
bool readEnum ( T & value )
{
Int64 pbnumber ;
if ( ! readField ( pbnumber ) )
return false ;
2019-02-26 16:02:29 +00:00
if ( enum_pbnumber_always_equals_value )
value = static_cast < T > ( pbnumber ) ;
else
{
auto it = enum_pbnumber_to_value_map - > find ( pbnumber ) ;
if ( it = = enum_pbnumber_to_value_map - > end ( ) )
cannotConvertValue ( toString ( pbnumber ) , " Enum " ) ;
value = static_cast < T > ( it - > second ) ;
}
2019-02-20 04:28:02 +00:00
return true ;
}
void prepareEnumPbNumberToNameMap ( )
{
2019-02-21 15:49:42 +00:00
if ( likely ( enum_pbnumber_to_name_map . has_value ( ) ) )
2019-02-20 04:28:02 +00:00
return ;
enum_pbnumber_to_name_map . emplace ( ) ;
const auto * enum_type = field - > enum_type ( ) ;
for ( int i = 0 ; i ! = enum_type - > value_count ( ) ; + + i )
{
const auto * enum_value = enum_type - > value ( i ) ;
enum_pbnumber_to_name_map - > emplace ( enum_value - > number ( ) , enum_value - > name ( ) ) ;
}
}
template < typename T >
void prepareEnumPbNumberToValueMap ( const std : : vector < std : : pair < String , T > > & name_value_pairs )
{
2019-02-21 15:49:42 +00:00
if ( likely ( enum_pbnumber_to_value_map . has_value ( ) ) )
2019-02-20 04:28:02 +00:00
return ;
enum_pbnumber_to_value_map . emplace ( ) ;
2019-02-26 16:02:29 +00:00
enum_pbnumber_always_equals_value = true ;
2019-02-20 04:28:02 +00:00
for ( const auto & name_value_pair : name_value_pairs )
{
Int16 value = name_value_pair . second ;
const auto * enum_descriptor = field - > enum_type ( ) - > FindValueByName ( name_value_pair . first ) ;
if ( enum_descriptor )
2019-02-26 16:02:29 +00:00
{
2019-02-20 04:28:02 +00:00
enum_pbnumber_to_value_map - > emplace ( enum_descriptor - > number ( ) , value ) ;
2019-02-26 16:02:29 +00:00
if ( enum_descriptor - > number ( ) ! = value )
enum_pbnumber_always_equals_value = false ;
}
else
enum_pbnumber_always_equals_value = false ;
2019-02-20 04:28:02 +00:00
}
}
bool readField ( Int64 & enum_pbnumber )
{
return simple_reader . readInt ( enum_pbnumber ) ;
}
std : : optional < std : : unordered_map < Int64 , StringRef > > enum_pbnumber_to_name_map ;
std : : optional < std : : unordered_map < Int64 , Int16 > > enum_pbnumber_to_value_map ;
2019-02-26 16:02:29 +00:00
bool enum_pbnumber_always_equals_value ;
2019-02-20 04:28:02 +00:00
} ;
2019-02-26 16:02:29 +00:00
template < >
std : : unique_ptr < ProtobufReader : : IConverter > ProtobufReader : : createConverter < google : : protobuf : : FieldDescriptor : : TYPE_ENUM > (
const google : : protobuf : : FieldDescriptor * field )
{
return std : : make_unique < ConverterFromEnum > ( simple_reader , field ) ;
}
2019-02-20 04:28:02 +00:00
ProtobufReader : : ProtobufReader (
ReadBuffer & in_ , const google : : protobuf : : Descriptor * message_type , const std : : vector < String > & column_names )
: simple_reader ( in_ )
{
root_message = ProtobufColumnMatcher : : matchColumns < ColumnMatcherTraits > ( column_names , message_type ) ;
setTraitsDataAfterMatchingColumns ( root_message . get ( ) ) ;
}
ProtobufReader : : ~ ProtobufReader ( ) = default ;
void ProtobufReader : : setTraitsDataAfterMatchingColumns ( Message * message )
{
for ( Field & field : message - > fields )
{
if ( field . nested_message )
{
setTraitsDataAfterMatchingColumns ( field . nested_message . get ( ) ) ;
continue ;
}
switch ( field . field_descriptor - > type ( ) )
{
# define PROTOBUF_READER_CONVERTER_CREATING_CASE(field_type_id) \
case field_type_id : \
2019-02-26 16:02:29 +00:00
field . data . converter = createConverter < field_type_id > ( field . field_descriptor ) ; \
2019-02-20 04:28:02 +00:00
break
PROTOBUF_READER_CONVERTER_CREATING_CASE ( google : : protobuf : : FieldDescriptor : : TYPE_STRING ) ;
PROTOBUF_READER_CONVERTER_CREATING_CASE ( google : : protobuf : : FieldDescriptor : : TYPE_BYTES ) ;
PROTOBUF_READER_CONVERTER_CREATING_CASE ( google : : protobuf : : FieldDescriptor : : TYPE_INT32 ) ;
PROTOBUF_READER_CONVERTER_CREATING_CASE ( google : : protobuf : : FieldDescriptor : : TYPE_SINT32 ) ;
PROTOBUF_READER_CONVERTER_CREATING_CASE ( google : : protobuf : : FieldDescriptor : : TYPE_UINT32 ) ;
PROTOBUF_READER_CONVERTER_CREATING_CASE ( google : : protobuf : : FieldDescriptor : : TYPE_FIXED32 ) ;
PROTOBUF_READER_CONVERTER_CREATING_CASE ( google : : protobuf : : FieldDescriptor : : TYPE_SFIXED32 ) ;
PROTOBUF_READER_CONVERTER_CREATING_CASE ( google : : protobuf : : FieldDescriptor : : TYPE_INT64 ) ;
PROTOBUF_READER_CONVERTER_CREATING_CASE ( google : : protobuf : : FieldDescriptor : : TYPE_SINT64 ) ;
PROTOBUF_READER_CONVERTER_CREATING_CASE ( google : : protobuf : : FieldDescriptor : : TYPE_UINT64 ) ;
PROTOBUF_READER_CONVERTER_CREATING_CASE ( google : : protobuf : : FieldDescriptor : : TYPE_FIXED64 ) ;
PROTOBUF_READER_CONVERTER_CREATING_CASE ( google : : protobuf : : FieldDescriptor : : TYPE_SFIXED64 ) ;
PROTOBUF_READER_CONVERTER_CREATING_CASE ( google : : protobuf : : FieldDescriptor : : TYPE_FLOAT ) ;
PROTOBUF_READER_CONVERTER_CREATING_CASE ( google : : protobuf : : FieldDescriptor : : TYPE_DOUBLE ) ;
PROTOBUF_READER_CONVERTER_CREATING_CASE ( google : : protobuf : : FieldDescriptor : : TYPE_BOOL ) ;
PROTOBUF_READER_CONVERTER_CREATING_CASE ( google : : protobuf : : FieldDescriptor : : TYPE_ENUM ) ;
# undef PROTOBUF_READER_CONVERTER_CREATING_CASE
default : __builtin_unreachable ( ) ;
}
message - > data . field_number_to_field_map . emplace ( field . field_number , & field ) ;
}
}
bool ProtobufReader : : startMessage ( )
{
if ( ! simple_reader . startMessage ( ) )
return false ;
current_message = root_message . get ( ) ;
current_field_index = 0 ;
return true ;
}
2019-07-24 11:41:49 +00:00
void ProtobufReader : : endMessage ( bool try_ignore_errors )
2019-02-20 04:28:02 +00:00
{
2019-07-24 11:41:49 +00:00
simple_reader . endMessage ( try_ignore_errors ) ;
2019-02-20 04:28:02 +00:00
current_message = nullptr ;
current_converter = nullptr ;
}
bool ProtobufReader : : readColumnIndex ( size_t & column_index )
{
while ( true )
{
UInt32 field_number ;
if ( ! simple_reader . readFieldNumber ( field_number ) )
{
if ( ! current_message - > parent )
{
current_converter = nullptr ;
return false ;
}
2019-07-24 11:41:49 +00:00
simple_reader . endNestedMessage ( ) ;
2019-02-20 04:28:02 +00:00
current_field_index = current_message - > index_in_parent ;
current_message = current_message - > parent ;
continue ;
}
const Field * field = nullptr ;
for ( ; current_field_index < current_message - > fields . size ( ) ; + + current_field_index )
{
const Field & f = current_message - > fields [ current_field_index ] ;
if ( f . field_number = = field_number )
{
field = & f ;
break ;
}
if ( f . field_number > field_number )
break ;
}
if ( ! field )
{
const auto & field_number_to_field_map = current_message - > data . field_number_to_field_map ;
auto it = field_number_to_field_map . find ( field_number ) ;
if ( it = = field_number_to_field_map . end ( ) )
continue ;
field = it - > second ;
}
if ( field - > nested_message )
{
2019-07-24 11:41:49 +00:00
simple_reader . startNestedMessage ( ) ;
2019-02-20 04:28:02 +00:00
current_message = field - > nested_message . get ( ) ;
current_field_index = 0 ;
continue ;
}
column_index = field - > column_index ;
current_converter = field - > data . converter . get ( ) ;
return true ;
}
}
}
# endif