502
508
return SpecificEncoder
511
def _FloatingPointEncoder(wire_type, format):
512
"""Return a constructor for an encoder for float fields.
514
This is like StructPackEncoder, but catches errors that may be due to
515
passing non-finite floating-point values to struct.pack, and makes a
516
second attempt to encode those values.
519
wire_type: The field's wire type, for encoding tags.
520
format: The format string to pass to struct.pack().
523
value_size = struct.calcsize(format)
525
def EncodeNonFiniteOrRaise(write, value):
526
# Remember that the serialized form uses little-endian byte order.
527
if value == _POS_INF:
528
write('\x00\x00\x80\x7F')
529
elif value == _NEG_INF:
530
write('\x00\x00\x80\xFF')
531
elif value != value: # NaN
532
write('\x00\x00\xC0\x7F')
535
elif value_size == 8:
536
def EncodeNonFiniteOrRaise(write, value):
537
if value == _POS_INF:
538
write('\x00\x00\x00\x00\x00\x00\xF0\x7F')
539
elif value == _NEG_INF:
540
write('\x00\x00\x00\x00\x00\x00\xF0\xFF')
541
elif value != value: # NaN
542
write('\x00\x00\x00\x00\x00\x00\xF8\x7F')
546
raise ValueError('Can\'t encode floating-point values that are '
547
'%d bytes long (only 4 or 8)' % value_size)
549
def SpecificEncoder(field_number, is_repeated, is_packed):
550
local_struct_pack = struct.pack
552
tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
553
local_EncodeVarint = _EncodeVarint
554
def EncodePackedField(write, value):
556
local_EncodeVarint(write, len(value) * value_size)
557
for element in value:
558
# This try/except block is going to be faster than any code that
559
# we could write to check whether element is finite.
561
write(local_struct_pack(format, element))
563
EncodeNonFiniteOrRaise(write, element)
564
return EncodePackedField
566
tag_bytes = TagBytes(field_number, wire_type)
567
def EncodeRepeatedField(write, value):
568
for element in value:
571
write(local_struct_pack(format, element))
573
EncodeNonFiniteOrRaise(write, element)
574
return EncodeRepeatedField
576
tag_bytes = TagBytes(field_number, wire_type)
577
def EncodeField(write, value):
580
write(local_struct_pack(format, value))
582
EncodeNonFiniteOrRaise(write, value)
585
return SpecificEncoder
505
588
# ====================================================================
506
589
# Here we declare an encoder constructor for each field type. These work
507
590
# very similarly to sizer constructors, described earlier.
525
608
Fixed64Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<Q')
526
609
SFixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<i')
527
610
SFixed64Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<q')
528
FloatEncoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<f')
529
DoubleEncoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<d')
611
FloatEncoder = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED32, '<f')
612
DoubleEncoder = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED64, '<d')
532
615
def BoolEncoder(field_number, is_repeated, is_packed):