Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
encoder.py807 linesDownload Raw Back to internal
1# Protocol Buffers - Google's data interchange format2# Copyright 2008 Google Inc.  All rights reserved.3#4# Use of this source code is governed by a BSD-style5# license that can be found in the LICENSE file or at6# https://developers.google.com/open-source/licenses/bsd7 8"""Code for encoding protocol message primitives.9 10Contains the logic for encoding every logical protocol field type11into one of the 5 physical wire types.12 13This code is designed to push the Python interpreter's performance to the14limits.15 16The basic idea is that at startup time, for every field (i.e. every17FieldDescriptor) we construct two functions:  a "sizer" and an "encoder".  The18sizer takes a value of this field's type and computes its byte size.  The19encoder takes a writer function and a value.  It encodes the value into byte20strings and invokes the writer function to write those strings.  Typically the21writer function is the write() method of a BytesIO.22 23We try to do as much work as possible when constructing the writer and the24sizer rather than when calling them.  In particular:25* We copy any needed global functions to local variables, so that we do not need26  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 at29  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 sharing32  does not burden us too much.  For example, encoders for repeated fields do33  not just call the encoders for singular fields in a loop because this would34  add an extra function call overhead for every loop iteration; instead, we35  manually inline the single-value encoder into the loop.36* If a Python function lacks a return statement, Python actually generates37  instructions to pop the result of the last statement off the stack, push38  None onto the stack, and then return that.  If we really don't care what39  value is returned, then we can save two instructions by returning the40  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 struct47 48from google.protobuf.internal import wire_format49 50 51# This will overflow and thus become IEEE-754 "infinity".  We would use52# "float('inf')" but it doesn't work on Windows pre-Python-2.6.53_POS_INF = 1e1000054_NEG_INF = -_POS_INF55 56 57def _VarintSize(value):58  """Compute the size of a varint value."""59  if value <= 0x7f: return 160  if value <= 0x3fff: return 261  if value <= 0x1fffff: return 362  if value <= 0xfffffff: return 463  if value <= 0x7ffffffff: return 564  if value <= 0x3ffffffffff: return 665  if value <= 0x1ffffffffffff: return 766  if value <= 0xffffffffffffff: return 867  if value <= 0x7fffffffffffffff: return 968  return 1069 70 71def _SignedVarintSize(value):72  """Compute the size of a signed varint value."""73  if value < 0: return 1074  if value <= 0x7f: return 175  if value <= 0x3fff: return 276  if value <= 0x1fffff: return 377  if value <= 0xfffffff: return 478  if value <= 0x7ffffffff: return 579  if value <= 0x3ffffffffff: return 680  if value <= 0x1ffffffffffff: return 781  if value <= 0xffffffffffffff: return 882  if value <= 0x7fffffffffffffff: return 983  return 1084 85 86def _TagSize(field_number):87  """Returns the number of bytes required to serialize a tag with this field88  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 functions95# 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 a97# 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 of103  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 = _VarintSize109      def PackedFieldSize(value):110        result = 0111        for element in value:112          result += compute_value_size(element)113        return result + local_VarintSize(result) + tag_size114      return PackedFieldSize115    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 result121      return RepeatedFieldSize122    else:123      def FieldSize(value):124        return tag_size + compute_value_size(value)125      return FieldSize126 127  return SpecificSizer128 129 130def _ModifiedSizer(compute_value_size, modify_value):131  """Like SimpleSizer, but modify_value is invoked on each value before it is132  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 = _VarintSize138      def PackedFieldSize(value):139        result = 0140        for element in value:141          result += compute_value_size(modify_value(element))142        return result + local_VarintSize(result) + tag_size143      return PackedFieldSize144    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 result150      return RepeatedFieldSize151    else:152      def FieldSize(value):153        return tag_size + compute_value_size(modify_value(value))154      return FieldSize155 156  return SpecificSizer157 158 159def _FixedSizer(value_size):160  """Like _SimpleSizer except for a fixed-size field.  The input is the size161  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 = _VarintSize167      def PackedFieldSize(value):168        result = len(value) * value_size169        return result + local_VarintSize(result) + tag_size170      return PackedFieldSize171    elif is_repeated:172      element_size = value_size + tag_size173      def RepeatedFieldSize(value):174        return len(value) * element_size175      return RepeatedFieldSize176    else:177      field_size = value_size + tag_size178      def FieldSize(value):179        return field_size180      return FieldSize181 182  return SpecificSizer183 184 185# ====================================================================186# Here we declare a sizer constructor for each field type.  Each "sizer187# 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 as189# 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 = _VarintSize210  local_len = len211  assert not is_packed212  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) + l218      return result219    return RepeatedFieldSize220  else:221    def FieldSize(value):222      l = local_len(value.encode('utf-8'))223      return tag_size + local_VarintSize(l) + l224    return FieldSize225 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 = _VarintSize232  local_len = len233  assert not is_packed234  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) + l240      return result241    return RepeatedFieldSize242  else:243    def FieldSize(value):244      l = local_len(value)245      return tag_size + local_VarintSize(l) + l246    return FieldSize247 248 249def GroupSizer(field_number, is_repeated, is_packed):250  """Returns a sizer for a group field."""251 252  tag_size = _TagSize(field_number) * 2253  assert not is_packed254  if is_repeated:255    def RepeatedFieldSize(value):256      result = tag_size * len(value)257      for element in value:258        result += element.ByteSize()259      return result260    return RepeatedFieldSize261  else:262    def FieldSize(value):263      return tag_size + value.ByteSize()264    return FieldSize265 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 = _VarintSize272  assert not is_packed273  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) + l279      return result280    return RepeatedFieldSize281  else:282    def FieldSize(value):283      l = value.ByteSize()284      return tag_size + local_VarintSize(l) + l285    return FieldSize286 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 = _VarintSize306 307  def FieldSize(value):308    l = value.ByteSize()309    return static_size + local_VarintSize(l) + l310 311  return FieldSize312 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 may322  # not have been initialized yet.323  message_type = field_descriptor.message_type324  message_sizer = MessageSizer(field_descriptor.number, False, False)325 326  def FieldSize(map_value):327    total = 0328    for key in map_value:329      value = map_value[key]330      # It's wasteful to create the messages and throw them away one second331      # later since we'll do the same for the actual encode.  But there's not an332      # obvious way to avoid this within the current design without tons of code333      # duplication. For message map, value.ByteSize() should be called to334      # 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 total340 341  return FieldSize342 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').pack351 352  def EncodeVarint(write, value, unused_deterministic=None):353    bits = value & 0x7f354    value >>= 7355    while value:356      write(local_int2byte(0x80|bits))357      bits = value & 0x7f358      value >>= 7359    return write(local_int2byte(bits))360 361  return EncodeVarint362 363 364def _SignedVarintEncoder():365  """Return an encoder for a basic signed varint value (does not include366  tag)."""367 368  local_int2byte = struct.Struct('>B').pack369 370  def EncodeSignedVarint(write, value, unused_deterministic=None):371    if value < 0:372      value += (1 << 64)373    bits = value & 0x7f374    value >>= 7375    while value:376      write(local_int2byte(0x80|bits))377      bits = value & 0x7f378      value >>= 7379    return write(local_int2byte(bits))380 381  return EncodeSignedVarint382 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 only390  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 encoder404# 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 individual415        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 = _EncodeVarint422      def EncodePackedField(write, value, deterministic):423        write(tag_bytes)424        size = 0425        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 EncodePackedField431    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 EncodeRepeatedField438    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 EncodeField444 445  return SpecificEncoder446 447 448def _ModifiedEncoder(wire_type, encode_value, compute_value_size, modify_value):449  """Like SimpleEncoder but additionally invokes modify_value on every value450  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 = _EncodeVarint456      def EncodePackedField(write, value, deterministic):457        write(tag_bytes)458        size = 0459        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 EncodePackedField465    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 EncodeRepeatedField472    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 EncodeField478 479  return SpecificEncoder480 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.pack494    if is_packed:495      tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)496      local_EncodeVarint = _EncodeVarint497      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 EncodePackedField503    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 EncodeRepeatedField510    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 EncodeField516 517  return SpecificEncoder518 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 to524  passing non-finite floating-point values to struct.pack, and makes a525  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:           # NaN541        write(b'\x00\x00\xC0\x7F')542      else:543        raise544  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:                         # NaN551        write(b'\x00\x00\x00\x00\x00\x00\xF8\x7F')552      else:553        raise554  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.pack560    if is_packed:561      tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)562      local_EncodeVarint = _EncodeVarint563      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 that568          # 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 EncodePackedField574    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 EncodeRepeatedField584    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 EncodeField593 594  return SpecificEncoder595 596 597# ====================================================================598# Here we declare an encoder constructor for each field type.  These work599# 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 on613# formats, they will also have the same size across all platforms (as opposed614# to without the prefix, where their sizes depend on the C compiler's basic615# 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 = _EncodeVarint632    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 EncodePackedField641  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 EncodeRepeatedField651  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 EncodeField659 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 = _EncodeVarint666  local_len = len667  assert not is_packed668  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 EncodeRepeatedField676  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 EncodeField683 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 = _EncodeVarint690  local_len = len691  assert not is_packed692  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 EncodeRepeatedField699  else:700    def EncodeField(write, value, deterministic):701      write(tag)702      local_EncodeVarint(write, local_len(value), deterministic)703      return write(value)704    return EncodeField705 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_packed713  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 EncodeRepeatedField720  else:721    def EncodeField(write, value, deterministic):722      write(start_tag)723      value._InternalSerialize(write, deterministic)724      return write(end_tag)725    return EncodeField726 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 = _EncodeVarint733  assert not is_packed734  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 EncodeRepeatedField741  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 EncodeField747 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 = _EncodeVarint771 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 EncodeField779 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 may796  # not have been initialized yet.797  message_type = field_descriptor.message_type798  encode_message = MessageEncoder(field_descriptor.number, False, False)799 800  def EncodeField(write, value, deterministic):801    value_keys = sorted(value.keys()) if deterministic else value802    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 EncodeField807 
codekingpro/portable-devtools · Team Ai