| Index: third_party/protobuf/python/google/protobuf/internal/encoder.py
|
| diff --git a/third_party/protobuf/python/google/protobuf/internal/encoder.py b/third_party/protobuf/python/google/protobuf/internal/encoder.py
|
| index aa05d5b3301308e419a9b48cc31442ac3f7f7540..777975e82e042b277be6ff6b1dae3b4f5cf6fa57 100755
|
| --- a/third_party/protobuf/python/google/protobuf/internal/encoder.py
|
| +++ b/third_party/protobuf/python/google/protobuf/internal/encoder.py
|
| @@ -70,6 +70,12 @@ import struct
|
| from google.protobuf.internal import wire_format
|
|
|
|
|
| +# This will overflow and thus become IEEE-754 "infinity". We would use
|
| +# "float('inf')" but it doesn't work on Windows pre-Python-2.6.
|
| +_POS_INF = 1e10000
|
| +_NEG_INF = -_POS_INF
|
| +
|
| +
|
| def _VarintSize(value):
|
| """Compute the size of a varint value."""
|
| if value <= 0x7f: return 1
|
| @@ -502,6 +508,83 @@ def _StructPackEncoder(wire_type, format):
|
| return SpecificEncoder
|
|
|
|
|
| +def _FloatingPointEncoder(wire_type, format):
|
| + """Return a constructor for an encoder for float fields.
|
| +
|
| + This is like StructPackEncoder, but catches errors that may be due to
|
| + passing non-finite floating-point values to struct.pack, and makes a
|
| + second attempt to encode those values.
|
| +
|
| + Args:
|
| + wire_type: The field's wire type, for encoding tags.
|
| + format: The format string to pass to struct.pack().
|
| + """
|
| +
|
| + value_size = struct.calcsize(format)
|
| + if value_size == 4:
|
| + def EncodeNonFiniteOrRaise(write, value):
|
| + # Remember that the serialized form uses little-endian byte order.
|
| + if value == _POS_INF:
|
| + write('\x00\x00\x80\x7F')
|
| + elif value == _NEG_INF:
|
| + write('\x00\x00\x80\xFF')
|
| + elif value != value: # NaN
|
| + write('\x00\x00\xC0\x7F')
|
| + else:
|
| + raise
|
| + elif value_size == 8:
|
| + def EncodeNonFiniteOrRaise(write, value):
|
| + if value == _POS_INF:
|
| + write('\x00\x00\x00\x00\x00\x00\xF0\x7F')
|
| + elif value == _NEG_INF:
|
| + write('\x00\x00\x00\x00\x00\x00\xF0\xFF')
|
| + elif value != value: # NaN
|
| + write('\x00\x00\x00\x00\x00\x00\xF8\x7F')
|
| + else:
|
| + raise
|
| + else:
|
| + raise ValueError('Can\'t encode floating-point values that are '
|
| + '%d bytes long (only 4 or 8)' % value_size)
|
| +
|
| + def SpecificEncoder(field_number, is_repeated, is_packed):
|
| + local_struct_pack = struct.pack
|
| + if is_packed:
|
| + tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
|
| + local_EncodeVarint = _EncodeVarint
|
| + def EncodePackedField(write, value):
|
| + write(tag_bytes)
|
| + local_EncodeVarint(write, len(value) * value_size)
|
| + for element in value:
|
| + # This try/except block is going to be faster than any code that
|
| + # we could write to check whether element is finite.
|
| + try:
|
| + write(local_struct_pack(format, element))
|
| + except SystemError:
|
| + EncodeNonFiniteOrRaise(write, element)
|
| + return EncodePackedField
|
| + elif is_repeated:
|
| + tag_bytes = TagBytes(field_number, wire_type)
|
| + def EncodeRepeatedField(write, value):
|
| + for element in value:
|
| + write(tag_bytes)
|
| + try:
|
| + write(local_struct_pack(format, element))
|
| + except SystemError:
|
| + EncodeNonFiniteOrRaise(write, element)
|
| + return EncodeRepeatedField
|
| + else:
|
| + tag_bytes = TagBytes(field_number, wire_type)
|
| + def EncodeField(write, value):
|
| + write(tag_bytes)
|
| + try:
|
| + write(local_struct_pack(format, value))
|
| + except SystemError:
|
| + EncodeNonFiniteOrRaise(write, value)
|
| + return EncodeField
|
| +
|
| + return SpecificEncoder
|
| +
|
| +
|
| # ====================================================================
|
| # Here we declare an encoder constructor for each field type. These work
|
| # very similarly to sizer constructors, described earlier.
|
| @@ -525,8 +608,8 @@ Fixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<I')
|
| Fixed64Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<Q')
|
| SFixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<i')
|
| SFixed64Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<q')
|
| -FloatEncoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<f')
|
| -DoubleEncoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<d')
|
| +FloatEncoder = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED32, '<f')
|
| +DoubleEncoder = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED64, '<d')
|
|
|
|
|
| def BoolEncoder(field_number, is_repeated, is_packed):
|
|
|