@ -183,11 +183,14 @@ class GeneratedProtocolMessageType(type):
% ( descriptor . full_name ) )
return
cls . _decoders_by_tag = { }
cls . _message_set_decoders_by_tag = { }
cls . _fields_by_tag = { }
if ( descriptor . has_options and
descriptor . GetOptions ( ) . message_set_wire_format ) :
cls . _decoders_by_tag [ decoder . MESSAGE_SET_ITEM_TAG ] = (
decoder . MessageSetItemDecoder ( descriptor ) , None )
cls . _message_set_decoders_by_tag [ decoder . MESSAGE_SET_ITEM_TAG ] = (
decoder . MessageSetItemDecoder ( descriptor ) ,
None ,
)
# Attach stuff to each FieldDescriptor for quick lookup later on.
for field in descriptor . fields :
@ -278,16 +281,36 @@ def _IsMessageSetExtension(field):
def _IsMapField ( field ) :
return ( field . type == _FieldDescriptor . TYPE_MESSAGE and
field . message_type . has_options and
field . message_type . GetOptions ( ) . map_entry )
field . message_type . _is_map_entry )
def _IsMessageMapField ( field ) :
value_type = field . message_type . fields_by_name [ ' value ' ]
return value_type . cpp_type == _FieldDescriptor . CPPTYPE_MESSAGE
def _AttachFieldHelpers ( cls , field_descriptor ) :
is_repeated = field_descriptor . label == _FieldDescriptor . LABEL_REPEATED
field_descriptor . _default_constructor = _DefaultValueConstructorForField (
field_descriptor
)
def AddFieldByTag ( wiretype , is_packed ) :
tag_bytes = encoder . TagBytes ( field_descriptor . number , wiretype )
cls . _fields_by_tag [ tag_bytes ] = ( field_descriptor , is_packed )
AddFieldByTag (
type_checkers . FIELD_TYPE_TO_WIRE_TYPE [ field_descriptor . type ] , False
)
if is_repeated and wire_format . IsTypePackable ( field_descriptor . type ) :
# To support wire compatibility of adding packed = true, add a decoder for
# packed values regardless of the field's options.
AddFieldByTag ( wire_format . WIRETYPE_LENGTH_DELIMITED , True )
def _MaybeAddEncoder ( cls , field_descriptor ) :
if hasattr ( field_descriptor , ' _encoder ' ) :
return
is_repeated = ( field_descriptor . label == _FieldDescriptor . LABEL_REPEATED )
is_map_entry = _IsMapField ( field_descriptor )
is_packed = field_descriptor . is_packed
@ -307,11 +330,17 @@ def _AttachFieldHelpers(cls, field_descriptor):
field_descriptor . _encoder = field_encoder
field_descriptor . _sizer = sizer
field_descriptor . _default_constructor = _DefaultValueConstructorForField (
field_descriptor )
def AddDecoder ( wiretype , is_packed ) :
tag_bytes = encoder . TagBytes ( field_descriptor . number , wiretype )
def _MaybeAddDecoder ( cls , field_descriptor ) :
if hasattr ( field_descriptor , ' _decoders ' ) :
return
is_repeated = field_descriptor . label == _FieldDescriptor . LABEL_REPEATED
is_map_entry = _IsMapField ( field_descriptor )
field_descriptor . _decoders = { }
def AddDecoder ( is_packed ) :
decode_type = field_descriptor . type
if ( decode_type == _FieldDescriptor . TYPE_ENUM and
not field_descriptor . enum_type . is_closed ) :
@ -343,15 +372,14 @@ def _AttachFieldHelpers(cls, field_descriptor):
field_descriptor , field_descriptor . _default_constructor ,
not field_descriptor . has_presence )
cls . _decoders_by_tag [ tag_bytes ] = ( field_decoder , oneof_descriptor )
field_descriptor . _decoders [ is_packed ] = field_decoder
AddDecoder ( type_checkers . FIELD_TYPE_TO_WIRE_TYPE [ field_descriptor . type ] ,
False )
AddDecoder ( False )
if is_repeated and wire_format . IsTypePackable ( field_descriptor . type ) :
# To support wire compatibility of adding packed = true, add a decoder for
# packed values regardless of the field's options.
AddDecoder ( wire_format . WIRETYPE_LENGTH_DELIMITED , True )
AddDecoder ( True )
def _AddClassAttributesForNestedExtensions ( descriptor , dictionary ) :
@ -1035,12 +1063,17 @@ def _AddByteSizeMethod(message_descriptor, cls):
size = 0
descriptor = self . DESCRIPTOR
if descriptor . GetOptions ( ) . map_entry :
if descriptor . _is_ map_entry:
# Fields of map entry should always be serialized.
size = descriptor . fields_by_name [ ' key ' ] . _sizer ( self . key )
size + = descriptor . fields_by_name [ ' value ' ] . _sizer ( self . value )
key_field = descriptor . fields_by_name [ ' key ' ]
_MaybeAddEncoder ( cls , key_field )
size = key_field . _sizer ( self . key )
value_field = descriptor . fields_by_name [ ' value ' ]
_MaybeAddEncoder ( cls , value_field )
size + = value_field . _sizer ( self . value )
else :
for field_descriptor , field_value in self . ListFields ( ) :
_MaybeAddEncoder ( cls , field_descriptor )
size + = field_descriptor . _sizer ( field_value )
for tag_bytes , value_bytes in self . _unknown_fields :
size + = len ( tag_bytes ) + len ( value_bytes )
@ -1083,14 +1116,17 @@ def _AddSerializePartialToStringMethod(message_descriptor, cls):
deterministic = bool ( deterministic )
descriptor = self . DESCRIPTOR
if descriptor . GetOptions ( ) . map_entry :
if descriptor . _is_ map_entry:
# Fields of map entry should always be serialized.
descriptor . fields_by_name [ ' key ' ] . _encoder (
write_bytes , self . key , deterministic )
descriptor . fields_by_name [ ' value ' ] . _encoder (
write_bytes , self . value , deterministic )
key_field = descriptor . fields_by_name [ ' key ' ]
_MaybeAddEncoder ( cls , key_field )
key_field . _encoder ( write_bytes , self . key , deterministic )
value_field = descriptor . fields_by_name [ ' value ' ]
_MaybeAddEncoder ( cls , value_field )
value_field . _encoder ( write_bytes , self . value , deterministic )
else :
for field_descriptor , field_value in self . ListFields ( ) :
_MaybeAddEncoder ( cls , field_descriptor )
field_descriptor . _encoder ( write_bytes , field_value , deterministic )
for tag_bytes , value_bytes in self . _unknown_fields :
write_bytes ( tag_bytes )
@ -1118,7 +1154,8 @@ def _AddMergeFromStringMethod(message_descriptor, cls):
local_ReadTag = decoder . ReadTag
local_SkipField = decoder . SkipField
decoders_by_tag = cls . _decoders_by_tag
fields_by_tag = cls . _fields_by_tag
message_set_decoders_by_tag = cls . _message_set_decoders_by_tag
def InternalParse ( self , buffer , pos , end ) :
""" Create a message from serialized bytes.
@ -1141,8 +1178,14 @@ def _AddMergeFromStringMethod(message_descriptor, cls):
unknown_field_set = self . _unknown_field_set
while pos != end :
( tag_bytes , new_pos ) = local_ReadTag ( buffer , pos )
field_decoder , field_desc = decoders_by_tag . get ( tag_bytes , ( None , None ) )
if field_decoder is None :
field_decoder , field_des = message_set_decoders_by_tag . get (
tag_bytes , ( None , None )
)
if field_decoder :
pos = field_decoder ( buffer , new_pos , end , self , field_dict )
continue
field_des , is_packed = fields_by_tag . get ( tag_bytes , ( None , None ) )
if field_des is None :
if not self . _unknown_fields : # pylint: disable=protected-access
self . _unknown_fields = [ ] # pylint: disable=protected-access
if unknown_field_set is None :
@ -1171,9 +1214,11 @@ def _AddMergeFromStringMethod(message_descriptor, cls):
( tag_bytes , buffer [ old_pos : new_pos ] . tobytes ( ) ) )
pos = new_pos
else :
_MaybeAddDecoder ( cls , field_des )
field_decoder = field_des . _decoders [ is_packed ]
pos = field_decoder ( buffer , new_pos , end , self , field_dict )
if field_desc :
self . _UpdateOneofState ( field_desc )
if field_des . containing_oneof :
self . _UpdateOneofState ( field_des )
return pos
cls . _InternalParse = InternalParse
@ -1209,8 +1254,7 @@ def _AddIsInitializedMethod(message_descriptor, cls):
for field , value in list ( self . _fields . items ( ) ) : # dict can change size!
if field . cpp_type == _FieldDescriptor . CPPTYPE_MESSAGE :
if field . label == _FieldDescriptor . LABEL_REPEATED :
if ( field . message_type . has_options and
field . message_type . GetOptions ( ) . map_entry ) :
if ( field . message_type . _is_map_entry ) :
continue
for element in value :
if not element . IsInitialized ( ) :