1# Protocol Buffers - Google's data interchange format 
    2# Copyright 2008 Google Inc.  All rights reserved. 
    3# 
    4# Use of this source code is governed by a BSD-style 
    5# license that can be found in the LICENSE file or at 
    6# https://developers.google.com/open-source/licenses/bsd 
    7 
    8"""Code for encoding protocol message primitives. 
    9 
    10Contains the logic for encoding every logical protocol field type 
    11into one of the 5 physical wire types. 
    12 
    13This code is designed to push the Python interpreter's performance to the 
    14limits. 
    15 
    16The basic idea is that at startup time, for every field (i.e. every 
    17FieldDescriptor) we construct two functions:  a "sizer" and an "encoder".  The 
    18sizer takes a value of this field's type and computes its byte size.  The 
    19encoder takes a writer function and a value.  It encodes the value into byte 
    20strings and invokes the writer function to write those strings.  Typically the 
    21writer function is the write() method of a BytesIO. 
    22 
    23We try to do as much work as possible when constructing the writer and the 
    24sizer rather than when calling them.  In particular: 
    25* We copy any needed global functions to local variables, so that we do not need 
    26  to do costly global table lookups at runtime. 
    27* Similarly, we try to do any attribute lookups at startup time if possible. 
    28* Every field's tag is encoded to bytes at startup, since it can't change at 
    29  runtime. 
    30* Whatever component of the field size we can compute at startup, we do. 
    31* We *avoid* sharing code if doing so would make the code slower and not sharing 
    32  does not burden us too much.  For example, encoders for repeated fields do 
    33  not just call the encoders for singular fields in a loop because this would 
    34  add an extra function call overhead for every loop iteration; instead, we 
    35  manually inline the single-value encoder into the loop. 
    36* If a Python function lacks a return statement, Python actually generates 
    37  instructions to pop the result of the last statement off the stack, push 
    38  None onto the stack, and then return that.  If we really don't care what 
    39  value is returned, then we can save two instructions by returning the 
    40  result of the last statement.  It looks funny but it helps. 
    41* We assume that type and bounds checking has happened at a higher level. 
    42""" 
    43 
    44__author__ = 'kenton@google.com (Kenton Varda)' 
    45 
    46import struct 
    47 
    48from google.protobuf.internal import wire_format 
    49 
    50 
    51# This will overflow and thus become IEEE-754 "infinity".  We would use 
    52# "float('inf')" but it doesn't work on Windows pre-Python-2.6. 
    53_POS_INF = 1e10000 
    54_NEG_INF = -_POS_INF 
    55 
    56 
    57def _VarintSize(value): 
    58  """Compute the size of a varint value.""" 
    59  if value <= 0x7f: return 1 
    60  if value <= 0x3fff: return 2 
    61  if value <= 0x1fffff: return 3 
    62  if value <= 0xfffffff: return 4 
    63  if value <= 0x7ffffffff: return 5 
    64  if value <= 0x3ffffffffff: return 6 
    65  if value <= 0x1ffffffffffff: return 7 
    66  if value <= 0xffffffffffffff: return 8 
    67  if value <= 0x7fffffffffffffff: return 9 
    68  return 10 
    69 
    70 
    71def _SignedVarintSize(value): 
    72  """Compute the size of a signed varint value.""" 
    73  if value < 0: return 10 
    74  if value <= 0x7f: return 1 
    75  if value <= 0x3fff: return 2 
    76  if value <= 0x1fffff: return 3 
    77  if value <= 0xfffffff: return 4 
    78  if value <= 0x7ffffffff: return 5 
    79  if value <= 0x3ffffffffff: return 6 
    80  if value <= 0x1ffffffffffff: return 7 
    81  if value <= 0xffffffffffffff: return 8 
    82  if value <= 0x7fffffffffffffff: return 9 
    83  return 10 
    84 
    85 
    86def _TagSize(field_number): 
    87  """Returns the number of bytes required to serialize a tag with this field 
    88  number.""" 
    89  # Just pass in type 0, since the type won't affect the tag+type size. 
    90  return _VarintSize(wire_format.PackTag(field_number, 0)) 
    91 
    92 
    93# -------------------------------------------------------------------- 
    94# In this section we define some generic sizers.  Each of these functions 
    95# takes parameters specific to a particular field type, e.g. int32 or fixed64. 
    96# It returns another function which in turn takes parameters specific to a 
    97# particular field, e.g. the field number and whether it is repeated or packed. 
    98# Look at the next section to see how these are used. 
    99 
    100 
    101def _SimpleSizer(compute_value_size): 
    102  """A sizer which uses the function compute_value_size to compute the size of 
    103  each value.  Typically compute_value_size is _VarintSize.""" 
    104 
    105  def SpecificSizer(field_number, is_repeated, is_packed): 
    106    tag_size = _TagSize(field_number) 
    107    if is_packed: 
    108      local_VarintSize = _VarintSize 
    109      def PackedFieldSize(value): 
    110        result = 0 
    111        for element in value: 
    112          result += compute_value_size(element) 
    113        return result + local_VarintSize(result) + tag_size 
    114      return PackedFieldSize 
    115    elif is_repeated: 
    116      def RepeatedFieldSize(value): 
    117        result = tag_size * len(value) 
    118        for element in value: 
    119          result += compute_value_size(element) 
    120        return result 
    121      return RepeatedFieldSize 
    122    else: 
    123      def FieldSize(value): 
    124        return tag_size + compute_value_size(value) 
    125      return FieldSize 
    126 
    127  return SpecificSizer 
    128 
    129 
    130def _ModifiedSizer(compute_value_size, modify_value): 
    131  """Like SimpleSizer, but modify_value is invoked on each value before it is 
    132  passed to compute_value_size.  modify_value is typically ZigZagEncode.""" 
    133 
    134  def SpecificSizer(field_number, is_repeated, is_packed): 
    135    tag_size = _TagSize(field_number) 
    136    if is_packed: 
    137      local_VarintSize = _VarintSize 
    138      def PackedFieldSize(value): 
    139        result = 0 
    140        for element in value: 
    141          result += compute_value_size(modify_value(element)) 
    142        return result + local_VarintSize(result) + tag_size 
    143      return PackedFieldSize 
    144    elif is_repeated: 
    145      def RepeatedFieldSize(value): 
    146        result = tag_size * len(value) 
    147        for element in value: 
    148          result += compute_value_size(modify_value(element)) 
    149        return result 
    150      return RepeatedFieldSize 
    151    else: 
    152      def FieldSize(value): 
    153        return tag_size + compute_value_size(modify_value(value)) 
    154      return FieldSize 
    155 
    156  return SpecificSizer 
    157 
    158 
    159def _FixedSizer(value_size): 
    160  """Like _SimpleSizer except for a fixed-size field.  The input is the size 
    161  of one value.""" 
    162 
    163  def SpecificSizer(field_number, is_repeated, is_packed): 
    164    tag_size = _TagSize(field_number) 
    165    if is_packed: 
    166      local_VarintSize = _VarintSize 
    167      def PackedFieldSize(value): 
    168        result = len(value) * value_size 
    169        return result + local_VarintSize(result) + tag_size 
    170      return PackedFieldSize 
    171    elif is_repeated: 
    172      element_size = value_size + tag_size 
    173      def RepeatedFieldSize(value): 
    174        return len(value) * element_size 
    175      return RepeatedFieldSize 
    176    else: 
    177      field_size = value_size + tag_size 
    178      def FieldSize(value): 
    179        return field_size 
    180      return FieldSize 
    181 
    182  return SpecificSizer 
    183 
    184 
    185# ==================================================================== 
    186# Here we declare a sizer constructor for each field type.  Each "sizer 
    187# constructor" is a function that takes (field_number, is_repeated, is_packed) 
    188# as parameters and returns a sizer, which in turn takes a field value as 
    189# a parameter and returns its encoded size. 
    190 
    191 
    192Int32Sizer = Int64Sizer = EnumSizer = _SimpleSizer(_SignedVarintSize) 
    193 
    194UInt32Sizer = UInt64Sizer = _SimpleSizer(_VarintSize) 
    195 
    196SInt32Sizer = SInt64Sizer = _ModifiedSizer( 
    197    _SignedVarintSize, wire_format.ZigZagEncode) 
    198 
    199Fixed32Sizer = SFixed32Sizer = FloatSizer  = _FixedSizer(4) 
    200Fixed64Sizer = SFixed64Sizer = DoubleSizer = _FixedSizer(8) 
    201 
    202BoolSizer = _FixedSizer(1) 
    203 
    204 
    205def StringSizer(field_number, is_repeated, is_packed): 
    206  """Returns a sizer for a string field.""" 
    207 
    208  tag_size = _TagSize(field_number) 
    209  local_VarintSize = _VarintSize 
    210  local_len = len 
    211  assert not is_packed 
    212  if is_repeated: 
    213    def RepeatedFieldSize(value): 
    214      result = tag_size * len(value) 
    215      for element in value: 
    216        l = local_len(element.encode('utf-8')) 
    217        result += local_VarintSize(l) + l 
    218      return result 
    219    return RepeatedFieldSize 
    220  else: 
    221    def FieldSize(value): 
    222      l = local_len(value.encode('utf-8')) 
    223      return tag_size + local_VarintSize(l) + l 
    224    return FieldSize 
    225 
    226 
    227def BytesSizer(field_number, is_repeated, is_packed): 
    228  """Returns a sizer for a bytes field.""" 
    229 
    230  tag_size = _TagSize(field_number) 
    231  local_VarintSize = _VarintSize 
    232  local_len = len 
    233  assert not is_packed 
    234  if is_repeated: 
    235    def RepeatedFieldSize(value): 
    236      result = tag_size * len(value) 
    237      for element in value: 
    238        l = local_len(element) 
    239        result += local_VarintSize(l) + l 
    240      return result 
    241    return RepeatedFieldSize 
    242  else: 
    243    def FieldSize(value): 
    244      l = local_len(value) 
    245      return tag_size + local_VarintSize(l) + l 
    246    return FieldSize 
    247 
    248 
    249def GroupSizer(field_number, is_repeated, is_packed): 
    250  """Returns a sizer for a group field.""" 
    251 
    252  tag_size = _TagSize(field_number) * 2 
    253  assert not is_packed 
    254  if is_repeated: 
    255    def RepeatedFieldSize(value): 
    256      result = tag_size * len(value) 
    257      for element in value: 
    258        result += element.ByteSize() 
    259      return result 
    260    return RepeatedFieldSize 
    261  else: 
    262    def FieldSize(value): 
    263      return tag_size + value.ByteSize() 
    264    return FieldSize 
    265 
    266 
    267def MessageSizer(field_number, is_repeated, is_packed): 
    268  """Returns a sizer for a message field.""" 
    269 
    270  tag_size = _TagSize(field_number) 
    271  local_VarintSize = _VarintSize 
    272  assert not is_packed 
    273  if is_repeated: 
    274    def RepeatedFieldSize(value): 
    275      result = tag_size * len(value) 
    276      for element in value: 
    277        l = element.ByteSize() 
    278        result += local_VarintSize(l) + l 
    279      return result 
    280    return RepeatedFieldSize 
    281  else: 
    282    def FieldSize(value): 
    283      l = value.ByteSize() 
    284      return tag_size + local_VarintSize(l) + l 
    285    return FieldSize 
    286 
    287 
    288# -------------------------------------------------------------------- 
    289# MessageSet is special: it needs custom logic to compute its size properly. 
    290 
    291 
    292def MessageSetItemSizer(field_number): 
    293  """Returns a sizer for extensions of MessageSet. 
    294 
    295  The message set message looks like this: 
    296    message MessageSet { 
    297      repeated group Item = 1 { 
    298        required int32 type_id = 2; 
    299        required string message = 3; 
    300      } 
    301    } 
    302  """ 
    303  static_size = (_TagSize(1) * 2 + _TagSize(2) + _VarintSize(field_number) + 
    304                 _TagSize(3)) 
    305  local_VarintSize = _VarintSize 
    306 
    307  def FieldSize(value): 
    308    l = value.ByteSize() 
    309    return static_size + local_VarintSize(l) + l 
    310 
    311  return FieldSize 
    312 
    313 
    314# -------------------------------------------------------------------- 
    315# Map is special: it needs custom logic to compute its size properly. 
    316 
    317 
    318def MapSizer(field_descriptor, is_message_map): 
    319  """Returns a sizer for a map field.""" 
    320 
    321  # Can't look at field_descriptor.message_type._concrete_class because it may 
    322  # not have been initialized yet. 
    323  message_type = field_descriptor.message_type 
    324  message_sizer = MessageSizer(field_descriptor.number, False, False) 
    325 
    326  def FieldSize(map_value): 
    327    total = 0 
    328    for key in map_value: 
    329      value = map_value[key] 
    330      # It's wasteful to create the messages and throw them away one second 
    331      # later since we'll do the same for the actual encode.  But there's not an 
    332      # obvious way to avoid this within the current design without tons of code 
    333      # duplication. For message map, value.ByteSize() should be called to 
    334      # update the status. 
    335      entry_msg = message_type._concrete_class(key=key, value=value) 
    336      total += message_sizer(entry_msg) 
    337      if is_message_map: 
    338        value.ByteSize() 
    339    return total 
    340 
    341  return FieldSize 
    342 
    343# ==================================================================== 
    344# Encoders! 
    345 
    346 
    347def _VarintEncoder(): 
    348  """Return an encoder for a basic varint value (does not include tag).""" 
    349 
    350  local_int2byte = struct.Struct('>B').pack 
    351 
    352  def EncodeVarint(write, value, unused_deterministic=None): 
    353    bits = value & 0x7f 
    354    value >>= 7 
    355    while value: 
    356      write(local_int2byte(0x80|bits)) 
    357      bits = value & 0x7f 
    358      value >>= 7 
    359    return write(local_int2byte(bits)) 
    360 
    361  return EncodeVarint 
    362 
    363 
    364def _SignedVarintEncoder(): 
    365  """Return an encoder for a basic signed varint value (does not include 
    366  tag).""" 
    367 
    368  local_int2byte = struct.Struct('>B').pack 
    369 
    370  def EncodeSignedVarint(write, value, unused_deterministic=None): 
    371    if value < 0: 
    372      value += (1 << 64) 
    373    bits = value & 0x7f 
    374    value >>= 7 
    375    while value: 
    376      write(local_int2byte(0x80|bits)) 
    377      bits = value & 0x7f 
    378      value >>= 7 
    379    return write(local_int2byte(bits)) 
    380 
    381  return EncodeSignedVarint 
    382 
    383 
    384_EncodeVarint = _VarintEncoder() 
    385_EncodeSignedVarint = _SignedVarintEncoder() 
    386 
    387 
    388def _VarintBytes(value): 
    389  """Encode the given integer as a varint and return the bytes.  This is only 
    390  called at startup time so it doesn't need to be fast.""" 
    391 
    392  pieces = [] 
    393  _EncodeVarint(pieces.append, value, True) 
    394  return b"".join(pieces) 
    395 
    396 
    397def TagBytes(field_number, wire_type): 
    398  """Encode the given tag and return the bytes.  Only called at startup.""" 
    399 
    400  return bytes(_VarintBytes(wire_format.PackTag(field_number, wire_type))) 
    401 
    402# -------------------------------------------------------------------- 
    403# As with sizers (see above), we have a number of common encoder 
    404# implementations. 
    405 
    406 
    407def _SimpleEncoder(wire_type, encode_value, compute_value_size): 
    408  """Return a constructor for an encoder for fields of a particular type. 
    409 
    410  Args: 
    411      wire_type:  The field's wire type, for encoding tags. 
    412      encode_value:  A function which encodes an individual value, e.g. 
    413        _EncodeVarint(). 
    414      compute_value_size:  A function which computes the size of an individual 
    415        value, e.g. _VarintSize(). 
    416  """ 
    417 
    418  def SpecificEncoder(field_number, is_repeated, is_packed): 
    419    if is_packed: 
    420      tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 
    421      local_EncodeVarint = _EncodeVarint 
    422      def EncodePackedField(write, value, deterministic): 
    423        write(tag_bytes) 
    424        size = 0 
    425        for element in value: 
    426          size += compute_value_size(element) 
    427        local_EncodeVarint(write, size, deterministic) 
    428        for element in value: 
    429          encode_value(write, element, deterministic) 
    430      return EncodePackedField 
    431    elif is_repeated: 
    432      tag_bytes = TagBytes(field_number, wire_type) 
    433      def EncodeRepeatedField(write, value, deterministic): 
    434        for element in value: 
    435          write(tag_bytes) 
    436          encode_value(write, element, deterministic) 
    437      return EncodeRepeatedField 
    438    else: 
    439      tag_bytes = TagBytes(field_number, wire_type) 
    440      def EncodeField(write, value, deterministic): 
    441        write(tag_bytes) 
    442        return encode_value(write, value, deterministic) 
    443      return EncodeField 
    444 
    445  return SpecificEncoder 
    446 
    447 
    448def _ModifiedEncoder(wire_type, encode_value, compute_value_size, modify_value): 
    449  """Like SimpleEncoder but additionally invokes modify_value on every value 
    450  before passing it to encode_value.  Usually modify_value is ZigZagEncode.""" 
    451 
    452  def SpecificEncoder(field_number, is_repeated, is_packed): 
    453    if is_packed: 
    454      tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 
    455      local_EncodeVarint = _EncodeVarint 
    456      def EncodePackedField(write, value, deterministic): 
    457        write(tag_bytes) 
    458        size = 0 
    459        for element in value: 
    460          size += compute_value_size(modify_value(element)) 
    461        local_EncodeVarint(write, size, deterministic) 
    462        for element in value: 
    463          encode_value(write, modify_value(element), deterministic) 
    464      return EncodePackedField 
    465    elif is_repeated: 
    466      tag_bytes = TagBytes(field_number, wire_type) 
    467      def EncodeRepeatedField(write, value, deterministic): 
    468        for element in value: 
    469          write(tag_bytes) 
    470          encode_value(write, modify_value(element), deterministic) 
    471      return EncodeRepeatedField 
    472    else: 
    473      tag_bytes = TagBytes(field_number, wire_type) 
    474      def EncodeField(write, value, deterministic): 
    475        write(tag_bytes) 
    476        return encode_value(write, modify_value(value), deterministic) 
    477      return EncodeField 
    478 
    479  return SpecificEncoder 
    480 
    481 
    482def _StructPackEncoder(wire_type, format): 
    483  """Return a constructor for an encoder for a fixed-width field. 
    484 
    485  Args: 
    486      wire_type:  The field's wire type, for encoding tags. 
    487      format:  The format string to pass to struct.pack(). 
    488  """ 
    489 
    490  value_size = struct.calcsize(format) 
    491 
    492  def SpecificEncoder(field_number, is_repeated, is_packed): 
    493    local_struct_pack = struct.pack 
    494    if is_packed: 
    495      tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 
    496      local_EncodeVarint = _EncodeVarint 
    497      def EncodePackedField(write, value, deterministic): 
    498        write(tag_bytes) 
    499        local_EncodeVarint(write, len(value) * value_size, deterministic) 
    500        for element in value: 
    501          write(local_struct_pack(format, element)) 
    502      return EncodePackedField 
    503    elif is_repeated: 
    504      tag_bytes = TagBytes(field_number, wire_type) 
    505      def EncodeRepeatedField(write, value, unused_deterministic=None): 
    506        for element in value: 
    507          write(tag_bytes) 
    508          write(local_struct_pack(format, element)) 
    509      return EncodeRepeatedField 
    510    else: 
    511      tag_bytes = TagBytes(field_number, wire_type) 
    512      def EncodeField(write, value, unused_deterministic=None): 
    513        write(tag_bytes) 
    514        return write(local_struct_pack(format, value)) 
    515      return EncodeField 
    516 
    517  return SpecificEncoder 
    518 
    519 
    520def _FloatingPointEncoder(wire_type, format): 
    521  """Return a constructor for an encoder for float fields. 
    522 
    523  This is like StructPackEncoder, but catches errors that may be due to 
    524  passing non-finite floating-point values to struct.pack, and makes a 
    525  second attempt to encode those values. 
    526 
    527  Args: 
    528      wire_type:  The field's wire type, for encoding tags. 
    529      format:  The format string to pass to struct.pack(). 
    530  """ 
    531 
    532  value_size = struct.calcsize(format) 
    533  if value_size == 4: 
    534    def EncodeNonFiniteOrRaise(write, value): 
    535      # Remember that the serialized form uses little-endian byte order. 
    536      if value == _POS_INF: 
    537        write(b'\x00\x00\x80\x7F') 
    538      elif value == _NEG_INF: 
    539        write(b'\x00\x00\x80\xFF') 
    540      elif value != value:           # NaN 
    541        write(b'\x00\x00\xC0\x7F') 
    542      else: 
    543        raise 
    544  elif value_size == 8: 
    545    def EncodeNonFiniteOrRaise(write, value): 
    546      if value == _POS_INF: 
    547        write(b'\x00\x00\x00\x00\x00\x00\xF0\x7F') 
    548      elif value == _NEG_INF: 
    549        write(b'\x00\x00\x00\x00\x00\x00\xF0\xFF') 
    550      elif value != value:                         # NaN 
    551        write(b'\x00\x00\x00\x00\x00\x00\xF8\x7F') 
    552      else: 
    553        raise 
    554  else: 
    555    raise ValueError('Can\'t encode floating-point values that are ' 
    556                     '%d bytes long (only 4 or 8)' % value_size) 
    557 
    558  def SpecificEncoder(field_number, is_repeated, is_packed): 
    559    local_struct_pack = struct.pack 
    560    if is_packed: 
    561      tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 
    562      local_EncodeVarint = _EncodeVarint 
    563      def EncodePackedField(write, value, deterministic): 
    564        write(tag_bytes) 
    565        local_EncodeVarint(write, len(value) * value_size, deterministic) 
    566        for element in value: 
    567          # This try/except block is going to be faster than any code that 
    568          # we could write to check whether element is finite. 
    569          try: 
    570            write(local_struct_pack(format, element)) 
    571          except SystemError: 
    572            EncodeNonFiniteOrRaise(write, element) 
    573      return EncodePackedField 
    574    elif is_repeated: 
    575      tag_bytes = TagBytes(field_number, wire_type) 
    576      def EncodeRepeatedField(write, value, unused_deterministic=None): 
    577        for element in value: 
    578          write(tag_bytes) 
    579          try: 
    580            write(local_struct_pack(format, element)) 
    581          except SystemError: 
    582            EncodeNonFiniteOrRaise(write, element) 
    583      return EncodeRepeatedField 
    584    else: 
    585      tag_bytes = TagBytes(field_number, wire_type) 
    586      def EncodeField(write, value, unused_deterministic=None): 
    587        write(tag_bytes) 
    588        try: 
    589          write(local_struct_pack(format, value)) 
    590        except SystemError: 
    591          EncodeNonFiniteOrRaise(write, value) 
    592      return EncodeField 
    593 
    594  return SpecificEncoder 
    595 
    596 
    597# ==================================================================== 
    598# Here we declare an encoder constructor for each field type.  These work 
    599# very similarly to sizer constructors, described earlier. 
    600 
    601 
    602Int32Encoder = Int64Encoder = EnumEncoder = _SimpleEncoder( 
    603    wire_format.WIRETYPE_VARINT, _EncodeSignedVarint, _SignedVarintSize) 
    604 
    605UInt32Encoder = UInt64Encoder = _SimpleEncoder( 
    606    wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize) 
    607 
    608SInt32Encoder = SInt64Encoder = _ModifiedEncoder( 
    609    wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize, 
    610    wire_format.ZigZagEncode) 
    611 
    612# Note that Python conveniently guarantees that when using the '<' prefix on 
    613# formats, they will also have the same size across all platforms (as opposed 
    614# to without the prefix, where their sizes depend on the C compiler's basic 
    615# type sizes). 
    616Fixed32Encoder  = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<I') 
    617Fixed64Encoder  = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<Q') 
    618SFixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<i') 
    619SFixed64Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<q') 
    620FloatEncoder    = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED32, '<f') 
    621DoubleEncoder   = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED64, '<d') 
    622 
    623 
    624def BoolEncoder(field_number, is_repeated, is_packed): 
    625  """Returns an encoder for a boolean field.""" 
    626 
    627  false_byte = b'\x00' 
    628  true_byte = b'\x01' 
    629  if is_packed: 
    630    tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 
    631    local_EncodeVarint = _EncodeVarint 
    632    def EncodePackedField(write, value, deterministic): 
    633      write(tag_bytes) 
    634      local_EncodeVarint(write, len(value), deterministic) 
    635      for element in value: 
    636        if element: 
    637          write(true_byte) 
    638        else: 
    639          write(false_byte) 
    640    return EncodePackedField 
    641  elif is_repeated: 
    642    tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT) 
    643    def EncodeRepeatedField(write, value, unused_deterministic=None): 
    644      for element in value: 
    645        write(tag_bytes) 
    646        if element: 
    647          write(true_byte) 
    648        else: 
    649          write(false_byte) 
    650    return EncodeRepeatedField 
    651  else: 
    652    tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT) 
    653    def EncodeField(write, value, unused_deterministic=None): 
    654      write(tag_bytes) 
    655      if value: 
    656        return write(true_byte) 
    657      return write(false_byte) 
    658    return EncodeField 
    659 
    660 
    661def StringEncoder(field_number, is_repeated, is_packed): 
    662  """Returns an encoder for a string field.""" 
    663 
    664  tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 
    665  local_EncodeVarint = _EncodeVarint 
    666  local_len = len 
    667  assert not is_packed 
    668  if is_repeated: 
    669    def EncodeRepeatedField(write, value, deterministic): 
    670      for element in value: 
    671        encoded = element.encode('utf-8') 
    672        write(tag) 
    673        local_EncodeVarint(write, local_len(encoded), deterministic) 
    674        write(encoded) 
    675    return EncodeRepeatedField 
    676  else: 
    677    def EncodeField(write, value, deterministic): 
    678      encoded = value.encode('utf-8') 
    679      write(tag) 
    680      local_EncodeVarint(write, local_len(encoded), deterministic) 
    681      return write(encoded) 
    682    return EncodeField 
    683 
    684 
    685def BytesEncoder(field_number, is_repeated, is_packed): 
    686  """Returns an encoder for a bytes field.""" 
    687 
    688  tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 
    689  local_EncodeVarint = _EncodeVarint 
    690  local_len = len 
    691  assert not is_packed 
    692  if is_repeated: 
    693    def EncodeRepeatedField(write, value, deterministic): 
    694      for element in value: 
    695        write(tag) 
    696        local_EncodeVarint(write, local_len(element), deterministic) 
    697        write(element) 
    698    return EncodeRepeatedField 
    699  else: 
    700    def EncodeField(write, value, deterministic): 
    701      write(tag) 
    702      local_EncodeVarint(write, local_len(value), deterministic) 
    703      return write(value) 
    704    return EncodeField 
    705 
    706 
    707def GroupEncoder(field_number, is_repeated, is_packed): 
    708  """Returns an encoder for a group field.""" 
    709 
    710  start_tag = TagBytes(field_number, wire_format.WIRETYPE_START_GROUP) 
    711  end_tag = TagBytes(field_number, wire_format.WIRETYPE_END_GROUP) 
    712  assert not is_packed 
    713  if is_repeated: 
    714    def EncodeRepeatedField(write, value, deterministic): 
    715      for element in value: 
    716        write(start_tag) 
    717        element._InternalSerialize(write, deterministic) 
    718        write(end_tag) 
    719    return EncodeRepeatedField 
    720  else: 
    721    def EncodeField(write, value, deterministic): 
    722      write(start_tag) 
    723      value._InternalSerialize(write, deterministic) 
    724      return write(end_tag) 
    725    return EncodeField 
    726 
    727 
    728def MessageEncoder(field_number, is_repeated, is_packed): 
    729  """Returns an encoder for a message field.""" 
    730 
    731  tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 
    732  local_EncodeVarint = _EncodeVarint 
    733  assert not is_packed 
    734  if is_repeated: 
    735    def EncodeRepeatedField(write, value, deterministic): 
    736      for element in value: 
    737        write(tag) 
    738        local_EncodeVarint(write, element.ByteSize(), deterministic) 
    739        element._InternalSerialize(write, deterministic) 
    740    return EncodeRepeatedField 
    741  else: 
    742    def EncodeField(write, value, deterministic): 
    743      write(tag) 
    744      local_EncodeVarint(write, value.ByteSize(), deterministic) 
    745      return value._InternalSerialize(write, deterministic) 
    746    return EncodeField 
    747 
    748 
    749# -------------------------------------------------------------------- 
    750# As before, MessageSet is special. 
    751 
    752 
    753def MessageSetItemEncoder(field_number): 
    754  """Encoder for extensions of MessageSet. 
    755 
    756  The message set message looks like this: 
    757    message MessageSet { 
    758      repeated group Item = 1 { 
    759        required int32 type_id = 2; 
    760        required string message = 3; 
    761      } 
    762    } 
    763  """ 
    764  start_bytes = b"".join([ 
    765      TagBytes(1, wire_format.WIRETYPE_START_GROUP), 
    766      TagBytes(2, wire_format.WIRETYPE_VARINT), 
    767      _VarintBytes(field_number), 
    768      TagBytes(3, wire_format.WIRETYPE_LENGTH_DELIMITED)]) 
    769  end_bytes = TagBytes(1, wire_format.WIRETYPE_END_GROUP) 
    770  local_EncodeVarint = _EncodeVarint 
    771 
    772  def EncodeField(write, value, deterministic): 
    773    write(start_bytes) 
    774    local_EncodeVarint(write, value.ByteSize(), deterministic) 
    775    value._InternalSerialize(write, deterministic) 
    776    return write(end_bytes) 
    777 
    778  return EncodeField 
    779 
    780 
    781# -------------------------------------------------------------------- 
    782# As before, Map is special. 
    783 
    784 
    785def MapEncoder(field_descriptor): 
    786  """Encoder for extensions of MessageSet. 
    787 
    788  Maps always have a wire format like this: 
    789    message MapEntry { 
    790      key_type key = 1; 
    791      value_type value = 2; 
    792    } 
    793    repeated MapEntry map = N; 
    794  """ 
    795  # Can't look at field_descriptor.message_type._concrete_class because it may 
    796  # not have been initialized yet. 
    797  message_type = field_descriptor.message_type 
    798  encode_message = MessageEncoder(field_descriptor.number, False, False) 
    799 
    800  def EncodeField(write, value, deterministic): 
    801    value_keys = sorted(value.keys()) if deterministic else value 
    802    for key in value_keys: 
    803      entry_msg = message_type._concrete_class(key=key, value=value[key]) 
    804      encode_message(write, entry_msg, deterministic) 
    805 
    806  return EncodeField