1# Protocol Buffers - Google's data interchange format
2# Copyright 2008 Google Inc.  All rights reserved.
3# https://developers.google.com/protocol-buffers/
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met:
8#
9#     * Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11#     * Redistributions in binary form must reproduce the above
12# copyright notice, this list of conditions and the following disclaimer
13# in the documentation and/or other materials provided with the
14# distribution.
15#     * Neither the name of Google Inc. nor the names of its
16# contributors may be used to endorse or promote products derived from
17# this software without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31#PY25 compatible for GAE.
32#
33# Copyright 2009 Google Inc. All Rights Reserved.
34
35"""Code for encoding protocol message primitives.
36
37Contains the logic for encoding every logical protocol field type
38into one of the 5 physical wire types.
39
40This code is designed to push the Python interpreter's performance to the
41limits.
42
43The basic idea is that at startup time, for every field (i.e. every
44FieldDescriptor) we construct two functions:  a "sizer" and an "encoder".  The
45sizer takes a value of this field's type and computes its byte size.  The
46encoder takes a writer function and a value.  It encodes the value into byte
47strings and invokes the writer function to write those strings.  Typically the
48writer function is the write() method of a cStringIO.
49
50We try to do as much work as possible when constructing the writer and the
51sizer rather than when calling them.  In particular:
52* We copy any needed global functions to local variables, so that we do not need
53  to do costly global table lookups at runtime.
54* Similarly, we try to do any attribute lookups at startup time if possible.
55* Every field's tag is encoded to bytes at startup, since it can't change at
56  runtime.
57* Whatever component of the field size we can compute at startup, we do.
58* We *avoid* sharing code if doing so would make the code slower and not sharing
59  does not burden us too much.  For example, encoders for repeated fields do
60  not just call the encoders for singular fields in a loop because this would
61  add an extra function call overhead for every loop iteration; instead, we
62  manually inline the single-value encoder into the loop.
63* If a Python function lacks a return statement, Python actually generates
64  instructions to pop the result of the last statement off the stack, push
65  None onto the stack, and then return that.  If we really don't care what
66  value is returned, then we can save two instructions by returning the
67  result of the last statement.  It looks funny but it helps.
68* We assume that type and bounds checking has happened at a higher level.
69"""
70
71__author__ = 'kenton@google.com (Kenton Varda)'
72
73import struct
74import sys  ##PY25
75_PY2 = sys.version_info[0] < 3  ##PY25
76from google.protobuf.internal import wire_format
77
78
79# This will overflow and thus become IEEE-754 "infinity".  We would use
80# "float('inf')" but it doesn't work on Windows pre-Python-2.6.
81_POS_INF = 1e10000
82_NEG_INF = -_POS_INF
83
84
85def _VarintSize(value):
86  """Compute the size of a varint value."""
87  if value <= 0x7f: return 1
88  if value <= 0x3fff: return 2
89  if value <= 0x1fffff: return 3
90  if value <= 0xfffffff: return 4
91  if value <= 0x7ffffffff: return 5
92  if value <= 0x3ffffffffff: return 6
93  if value <= 0x1ffffffffffff: return 7
94  if value <= 0xffffffffffffff: return 8
95  if value <= 0x7fffffffffffffff: return 9
96  return 10
97
98
99def _SignedVarintSize(value):
100  """Compute the size of a signed varint value."""
101  if value < 0: return 10
102  if value <= 0x7f: return 1
103  if value <= 0x3fff: return 2
104  if value <= 0x1fffff: return 3
105  if value <= 0xfffffff: return 4
106  if value <= 0x7ffffffff: return 5
107  if value <= 0x3ffffffffff: return 6
108  if value <= 0x1ffffffffffff: return 7
109  if value <= 0xffffffffffffff: return 8
110  if value <= 0x7fffffffffffffff: return 9
111  return 10
112
113
114def _TagSize(field_number):
115  """Returns the number of bytes required to serialize a tag with this field
116  number."""
117  # Just pass in type 0, since the type won't affect the tag+type size.
118  return _VarintSize(wire_format.PackTag(field_number, 0))
119
120
121# --------------------------------------------------------------------
122# In this section we define some generic sizers.  Each of these functions
123# takes parameters specific to a particular field type, e.g. int32 or fixed64.
124# It returns another function which in turn takes parameters specific to a
125# particular field, e.g. the field number and whether it is repeated or packed.
126# Look at the next section to see how these are used.
127
128
129def _SimpleSizer(compute_value_size):
130  """A sizer which uses the function compute_value_size to compute the size of
131  each value.  Typically compute_value_size is _VarintSize."""
132
133  def SpecificSizer(field_number, is_repeated, is_packed):
134    tag_size = _TagSize(field_number)
135    if is_packed:
136      local_VarintSize = _VarintSize
137      def PackedFieldSize(value):
138        result = 0
139        for element in value:
140          result += compute_value_size(element)
141        return result + local_VarintSize(result) + tag_size
142      return PackedFieldSize
143    elif is_repeated:
144      def RepeatedFieldSize(value):
145        result = tag_size * len(value)
146        for element in value:
147          result += compute_value_size(element)
148        return result
149      return RepeatedFieldSize
150    else:
151      def FieldSize(value):
152        return tag_size + compute_value_size(value)
153      return FieldSize
154
155  return SpecificSizer
156
157
158def _ModifiedSizer(compute_value_size, modify_value):
159  """Like SimpleSizer, but modify_value is invoked on each value before it is
160  passed to compute_value_size.  modify_value is typically ZigZagEncode."""
161
162  def SpecificSizer(field_number, is_repeated, is_packed):
163    tag_size = _TagSize(field_number)
164    if is_packed:
165      local_VarintSize = _VarintSize
166      def PackedFieldSize(value):
167        result = 0
168        for element in value:
169          result += compute_value_size(modify_value(element))
170        return result + local_VarintSize(result) + tag_size
171      return PackedFieldSize
172    elif is_repeated:
173      def RepeatedFieldSize(value):
174        result = tag_size * len(value)
175        for element in value:
176          result += compute_value_size(modify_value(element))
177        return result
178      return RepeatedFieldSize
179    else:
180      def FieldSize(value):
181        return tag_size + compute_value_size(modify_value(value))
182      return FieldSize
183
184  return SpecificSizer
185
186
187def _FixedSizer(value_size):
188  """Like _SimpleSizer except for a fixed-size field.  The input is the size
189  of one value."""
190
191  def SpecificSizer(field_number, is_repeated, is_packed):
192    tag_size = _TagSize(field_number)
193    if is_packed:
194      local_VarintSize = _VarintSize
195      def PackedFieldSize(value):
196        result = len(value) * value_size
197        return result + local_VarintSize(result) + tag_size
198      return PackedFieldSize
199    elif is_repeated:
200      element_size = value_size + tag_size
201      def RepeatedFieldSize(value):
202        return len(value) * element_size
203      return RepeatedFieldSize
204    else:
205      field_size = value_size + tag_size
206      def FieldSize(value):
207        return field_size
208      return FieldSize
209
210  return SpecificSizer
211
212
213# ====================================================================
214# Here we declare a sizer constructor for each field type.  Each "sizer
215# constructor" is a function that takes (field_number, is_repeated, is_packed)
216# as parameters and returns a sizer, which in turn takes a field value as
217# a parameter and returns its encoded size.
218
219
220Int32Sizer = Int64Sizer = EnumSizer = _SimpleSizer(_SignedVarintSize)
221
222UInt32Sizer = UInt64Sizer = _SimpleSizer(_VarintSize)
223
224SInt32Sizer = SInt64Sizer = _ModifiedSizer(
225    _SignedVarintSize, wire_format.ZigZagEncode)
226
227Fixed32Sizer = SFixed32Sizer = FloatSizer  = _FixedSizer(4)
228Fixed64Sizer = SFixed64Sizer = DoubleSizer = _FixedSizer(8)
229
230BoolSizer = _FixedSizer(1)
231
232
233def StringSizer(field_number, is_repeated, is_packed):
234  """Returns a sizer for a string field."""
235
236  tag_size = _TagSize(field_number)
237  local_VarintSize = _VarintSize
238  local_len = len
239  assert not is_packed
240  if is_repeated:
241    def RepeatedFieldSize(value):
242      result = tag_size * len(value)
243      for element in value:
244        l = local_len(element.encode('utf-8'))
245        result += local_VarintSize(l) + l
246      return result
247    return RepeatedFieldSize
248  else:
249    def FieldSize(value):
250      l = local_len(value.encode('utf-8'))
251      return tag_size + local_VarintSize(l) + l
252    return FieldSize
253
254
255def BytesSizer(field_number, is_repeated, is_packed):
256  """Returns a sizer for a bytes field."""
257
258  tag_size = _TagSize(field_number)
259  local_VarintSize = _VarintSize
260  local_len = len
261  assert not is_packed
262  if is_repeated:
263    def RepeatedFieldSize(value):
264      result = tag_size * len(value)
265      for element in value:
266        l = local_len(element)
267        result += local_VarintSize(l) + l
268      return result
269    return RepeatedFieldSize
270  else:
271    def FieldSize(value):
272      l = local_len(value)
273      return tag_size + local_VarintSize(l) + l
274    return FieldSize
275
276
277def GroupSizer(field_number, is_repeated, is_packed):
278  """Returns a sizer for a group field."""
279
280  tag_size = _TagSize(field_number) * 2
281  assert not is_packed
282  if is_repeated:
283    def RepeatedFieldSize(value):
284      result = tag_size * len(value)
285      for element in value:
286        result += element.ByteSize()
287      return result
288    return RepeatedFieldSize
289  else:
290    def FieldSize(value):
291      return tag_size + value.ByteSize()
292    return FieldSize
293
294
295def MessageSizer(field_number, is_repeated, is_packed):
296  """Returns a sizer for a message field."""
297
298  tag_size = _TagSize(field_number)
299  local_VarintSize = _VarintSize
300  assert not is_packed
301  if is_repeated:
302    def RepeatedFieldSize(value):
303      result = tag_size * len(value)
304      for element in value:
305        l = element.ByteSize()
306        result += local_VarintSize(l) + l
307      return result
308    return RepeatedFieldSize
309  else:
310    def FieldSize(value):
311      l = value.ByteSize()
312      return tag_size + local_VarintSize(l) + l
313    return FieldSize
314
315
316# --------------------------------------------------------------------
317# MessageSet is special.
318
319
320def MessageSetItemSizer(field_number):
321  """Returns a sizer for extensions of MessageSet.
322
323  The message set message looks like this:
324    message MessageSet {
325      repeated group Item = 1 {
326        required int32 type_id = 2;
327        required string message = 3;
328      }
329    }
330  """
331  static_size = (_TagSize(1) * 2 + _TagSize(2) + _VarintSize(field_number) +
332                 _TagSize(3))
333  local_VarintSize = _VarintSize
334
335  def FieldSize(value):
336    l = value.ByteSize()
337    return static_size + local_VarintSize(l) + l
338
339  return FieldSize
340
341
342# ====================================================================
343# Encoders!
344
345
346def _VarintEncoder():
347  """Return an encoder for a basic varint value (does not include tag)."""
348
349  local_chr = _PY2 and chr or (lambda x: bytes((x,)))  ##PY25
350##!PY25  local_chr = chr if bytes is str else lambda x: bytes((x,))
351  def EncodeVarint(write, value):
352    bits = value & 0x7f
353    value >>= 7
354    while value:
355      write(local_chr(0x80|bits))
356      bits = value & 0x7f
357      value >>= 7
358    return write(local_chr(bits))
359
360  return EncodeVarint
361
362
363def _SignedVarintEncoder():
364  """Return an encoder for a basic signed varint value (does not include
365  tag)."""
366
367  local_chr = _PY2 and chr or (lambda x: bytes((x,)))  ##PY25
368##!PY25  local_chr = chr if bytes is str else lambda x: bytes((x,))
369  def EncodeSignedVarint(write, value):
370    if value < 0:
371      value += (1 << 64)
372    bits = value & 0x7f
373    value >>= 7
374    while value:
375      write(local_chr(0x80|bits))
376      bits = value & 0x7f
377      value >>= 7
378    return write(local_chr(bits))
379
380  return EncodeSignedVarint
381
382
383_EncodeVarint = _VarintEncoder()
384_EncodeSignedVarint = _SignedVarintEncoder()
385
386
387def _VarintBytes(value):
388  """Encode the given integer as a varint and return the bytes.  This is only
389  called at startup time so it doesn't need to be fast."""
390
391  pieces = []
392  _EncodeVarint(pieces.append, value)
393  return "".encode("latin1").join(pieces)  ##PY25
394##!PY25  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 _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):
423        write(tag_bytes)
424        size = 0
425        for element in value:
426          size += compute_value_size(element)
427        local_EncodeVarint(write, size)
428        for element in value:
429          encode_value(write, element)
430      return EncodePackedField
431    elif is_repeated:
432      tag_bytes = TagBytes(field_number, wire_type)
433      def EncodeRepeatedField(write, value):
434        for element in value:
435          write(tag_bytes)
436          encode_value(write, element)
437      return EncodeRepeatedField
438    else:
439      tag_bytes = TagBytes(field_number, wire_type)
440      def EncodeField(write, value):
441        write(tag_bytes)
442        return encode_value(write, value)
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):
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)
462        for element in value:
463          encode_value(write, modify_value(element))
464      return EncodePackedField
465    elif is_repeated:
466      tag_bytes = TagBytes(field_number, wire_type)
467      def EncodeRepeatedField(write, value):
468        for element in value:
469          write(tag_bytes)
470          encode_value(write, modify_value(element))
471      return EncodeRepeatedField
472    else:
473      tag_bytes = TagBytes(field_number, wire_type)
474      def EncodeField(write, value):
475        write(tag_bytes)
476        return encode_value(write, modify_value(value))
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):
498        write(tag_bytes)
499        local_EncodeVarint(write, len(value) * value_size)
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):
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):
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  b = _PY2 and (lambda x:x) or (lambda x:x.encode('latin1'))  ##PY25
533  value_size = struct.calcsize(format)
534  if value_size == 4:
535    def EncodeNonFiniteOrRaise(write, value):
536      # Remember that the serialized form uses little-endian byte order.
537      if value == _POS_INF:
538        write(b('\x00\x00\x80\x7F'))  ##PY25
539##!PY25        write(b'\x00\x00\x80\x7F')
540      elif value == _NEG_INF:
541        write(b('\x00\x00\x80\xFF'))  ##PY25
542##!PY25        write(b'\x00\x00\x80\xFF')
543      elif value != value:           # NaN
544        write(b('\x00\x00\xC0\x7F'))  ##PY25
545##!PY25        write(b'\x00\x00\xC0\x7F')
546      else:
547        raise
548  elif value_size == 8:
549    def EncodeNonFiniteOrRaise(write, value):
550      if value == _POS_INF:
551        write(b('\x00\x00\x00\x00\x00\x00\xF0\x7F'))  ##PY25
552##!PY25        write(b'\x00\x00\x00\x00\x00\x00\xF0\x7F')
553      elif value == _NEG_INF:
554        write(b('\x00\x00\x00\x00\x00\x00\xF0\xFF'))  ##PY25
555##!PY25        write(b'\x00\x00\x00\x00\x00\x00\xF0\xFF')
556      elif value != value:                         # NaN
557        write(b('\x00\x00\x00\x00\x00\x00\xF8\x7F'))  ##PY25
558##!PY25        write(b'\x00\x00\x00\x00\x00\x00\xF8\x7F')
559      else:
560        raise
561  else:
562    raise ValueError('Can\'t encode floating-point values that are '
563                     '%d bytes long (only 4 or 8)' % value_size)
564
565  def SpecificEncoder(field_number, is_repeated, is_packed):
566    local_struct_pack = struct.pack
567    if is_packed:
568      tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
569      local_EncodeVarint = _EncodeVarint
570      def EncodePackedField(write, value):
571        write(tag_bytes)
572        local_EncodeVarint(write, len(value) * value_size)
573        for element in value:
574          # This try/except block is going to be faster than any code that
575          # we could write to check whether element is finite.
576          try:
577            write(local_struct_pack(format, element))
578          except SystemError:
579            EncodeNonFiniteOrRaise(write, element)
580      return EncodePackedField
581    elif is_repeated:
582      tag_bytes = TagBytes(field_number, wire_type)
583      def EncodeRepeatedField(write, value):
584        for element in value:
585          write(tag_bytes)
586          try:
587            write(local_struct_pack(format, element))
588          except SystemError:
589            EncodeNonFiniteOrRaise(write, element)
590      return EncodeRepeatedField
591    else:
592      tag_bytes = TagBytes(field_number, wire_type)
593      def EncodeField(write, value):
594        write(tag_bytes)
595        try:
596          write(local_struct_pack(format, value))
597        except SystemError:
598          EncodeNonFiniteOrRaise(write, value)
599      return EncodeField
600
601  return SpecificEncoder
602
603
604# ====================================================================
605# Here we declare an encoder constructor for each field type.  These work
606# very similarly to sizer constructors, described earlier.
607
608
609Int32Encoder = Int64Encoder = EnumEncoder = _SimpleEncoder(
610    wire_format.WIRETYPE_VARINT, _EncodeSignedVarint, _SignedVarintSize)
611
612UInt32Encoder = UInt64Encoder = _SimpleEncoder(
613    wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize)
614
615SInt32Encoder = SInt64Encoder = _ModifiedEncoder(
616    wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize,
617    wire_format.ZigZagEncode)
618
619# Note that Python conveniently guarantees that when using the '<' prefix on
620# formats, they will also have the same size across all platforms (as opposed
621# to without the prefix, where their sizes depend on the C compiler's basic
622# type sizes).
623Fixed32Encoder  = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<I')
624Fixed64Encoder  = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<Q')
625SFixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<i')
626SFixed64Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<q')
627FloatEncoder    = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED32, '<f')
628DoubleEncoder   = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED64, '<d')
629
630
631def BoolEncoder(field_number, is_repeated, is_packed):
632  """Returns an encoder for a boolean field."""
633
634##!PY25  false_byte = b'\x00'
635##!PY25  true_byte = b'\x01'
636  false_byte = '\x00'.encode('latin1')  ##PY25
637  true_byte = '\x01'.encode('latin1')  ##PY25
638  if is_packed:
639    tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
640    local_EncodeVarint = _EncodeVarint
641    def EncodePackedField(write, value):
642      write(tag_bytes)
643      local_EncodeVarint(write, len(value))
644      for element in value:
645        if element:
646          write(true_byte)
647        else:
648          write(false_byte)
649    return EncodePackedField
650  elif is_repeated:
651    tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT)
652    def EncodeRepeatedField(write, value):
653      for element in value:
654        write(tag_bytes)
655        if element:
656          write(true_byte)
657        else:
658          write(false_byte)
659    return EncodeRepeatedField
660  else:
661    tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT)
662    def EncodeField(write, value):
663      write(tag_bytes)
664      if value:
665        return write(true_byte)
666      return write(false_byte)
667    return EncodeField
668
669
670def StringEncoder(field_number, is_repeated, is_packed):
671  """Returns an encoder for a string field."""
672
673  tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
674  local_EncodeVarint = _EncodeVarint
675  local_len = len
676  assert not is_packed
677  if is_repeated:
678    def EncodeRepeatedField(write, value):
679      for element in value:
680        encoded = element.encode('utf-8')
681        write(tag)
682        local_EncodeVarint(write, local_len(encoded))
683        write(encoded)
684    return EncodeRepeatedField
685  else:
686    def EncodeField(write, value):
687      encoded = value.encode('utf-8')
688      write(tag)
689      local_EncodeVarint(write, local_len(encoded))
690      return write(encoded)
691    return EncodeField
692
693
694def BytesEncoder(field_number, is_repeated, is_packed):
695  """Returns an encoder for a bytes field."""
696
697  tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
698  local_EncodeVarint = _EncodeVarint
699  local_len = len
700  assert not is_packed
701  if is_repeated:
702    def EncodeRepeatedField(write, value):
703      for element in value:
704        write(tag)
705        local_EncodeVarint(write, local_len(element))
706        write(element)
707    return EncodeRepeatedField
708  else:
709    def EncodeField(write, value):
710      write(tag)
711      local_EncodeVarint(write, local_len(value))
712      return write(value)
713    return EncodeField
714
715
716def GroupEncoder(field_number, is_repeated, is_packed):
717  """Returns an encoder for a group field."""
718
719  start_tag = TagBytes(field_number, wire_format.WIRETYPE_START_GROUP)
720  end_tag = TagBytes(field_number, wire_format.WIRETYPE_END_GROUP)
721  assert not is_packed
722  if is_repeated:
723    def EncodeRepeatedField(write, value):
724      for element in value:
725        write(start_tag)
726        element._InternalSerialize(write)
727        write(end_tag)
728    return EncodeRepeatedField
729  else:
730    def EncodeField(write, value):
731      write(start_tag)
732      value._InternalSerialize(write)
733      return write(end_tag)
734    return EncodeField
735
736
737def MessageEncoder(field_number, is_repeated, is_packed):
738  """Returns an encoder for a message field."""
739
740  tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
741  local_EncodeVarint = _EncodeVarint
742  assert not is_packed
743  if is_repeated:
744    def EncodeRepeatedField(write, value):
745      for element in value:
746        write(tag)
747        local_EncodeVarint(write, element.ByteSize())
748        element._InternalSerialize(write)
749    return EncodeRepeatedField
750  else:
751    def EncodeField(write, value):
752      write(tag)
753      local_EncodeVarint(write, value.ByteSize())
754      return value._InternalSerialize(write)
755    return EncodeField
756
757
758# --------------------------------------------------------------------
759# As before, MessageSet is special.
760
761
762def MessageSetItemEncoder(field_number):
763  """Encoder for extensions of MessageSet.
764
765  The message set message looks like this:
766    message MessageSet {
767      repeated group Item = 1 {
768        required int32 type_id = 2;
769        required string message = 3;
770      }
771    }
772  """
773  start_bytes = "".encode("latin1").join([  ##PY25
774##!PY25  start_bytes = b"".join([
775      TagBytes(1, wire_format.WIRETYPE_START_GROUP),
776      TagBytes(2, wire_format.WIRETYPE_VARINT),
777      _VarintBytes(field_number),
778      TagBytes(3, wire_format.WIRETYPE_LENGTH_DELIMITED)])
779  end_bytes = TagBytes(1, wire_format.WIRETYPE_END_GROUP)
780  local_EncodeVarint = _EncodeVarint
781
782  def EncodeField(write, value):
783    write(start_bytes)
784    local_EncodeVarint(write, value.ByteSize())
785    value._InternalSerialize(write)
786    return write(end_bytes)
787
788  return EncodeField
789