1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# Protocol Buffers - Google's data interchange format
2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# Copyright 2008 Google Inc.  All rights reserved.
3fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# http://code.google.com/p/protobuf/
4fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#
5fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# Redistribution and use in source and binary forms, with or without
6fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# modification, are permitted provided that the following conditions are
7fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# met:
8fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#
9fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#     * Redistributions of source code must retain the above copyright
10fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# notice, this list of conditions and the following disclaimer.
11fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#     * Redistributions in binary form must reproduce the above
12fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# copyright notice, this list of conditions and the following disclaimer
13fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# in the documentation and/or other materials provided with the
14fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# distribution.
15fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#     * Neither the name of Google Inc. nor the names of its
16fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# contributors may be used to endorse or promote products derived from
17fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# this software without specific prior written permission.
18fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#
19fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
31d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville"""Code for encoding protocol message primitives.
32fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
33fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleContains the logic for encoding every logical protocol field type
34fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleinto one of the 5 physical wire types.
35d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
36d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleThis code is designed to push the Python interpreter's performance to the
37d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillelimits.
38d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
39d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleThe basic idea is that at startup time, for every field (i.e. every
40d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleFieldDescriptor) we construct two functions:  a "sizer" and an "encoder".  The
41d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillesizer takes a value of this field's type and computes its byte size.  The
42d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilleencoder takes a writer function and a value.  It encodes the value into byte
43d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillestrings and invokes the writer function to write those strings.  Typically the
44d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillewriter function is the write() method of a cStringIO.
45d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
46d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleWe try to do as much work as possible when constructing the writer and the
47d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillesizer rather than when calling them.  In particular:
48d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville* We copy any needed global functions to local variables, so that we do not need
49d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  to do costly global table lookups at runtime.
50d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville* Similarly, we try to do any attribute lookups at startup time if possible.
51d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville* Every field's tag is encoded to bytes at startup, since it can't change at
52d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  runtime.
53d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville* Whatever component of the field size we can compute at startup, we do.
54d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville* We *avoid* sharing code if doing so would make the code slower and not sharing
55d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  does not burden us too much.  For example, encoders for repeated fields do
56d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  not just call the encoders for singular fields in a loop because this would
57d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  add an extra function call overhead for every loop iteration; instead, we
58d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  manually inline the single-value encoder into the loop.
59d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville* If a Python function lacks a return statement, Python actually generates
60d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  instructions to pop the result of the last statement off the stack, push
61d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  None onto the stack, and then return that.  If we really don't care what
62d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  value is returned, then we can save two instructions by returning the
63d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  result of the last statement.  It looks funny but it helps.
64d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville* We assume that type and bounds checking has happened at a higher level.
65fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville"""
66fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
67d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville__author__ = 'kenton@google.com (Kenton Varda)'
68fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
69fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleimport struct
70fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillefrom google.protobuf.internal import wire_format
71d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
72d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
73d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _VarintSize(value):
74d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Compute the size of a varint value."""
75d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if value <= 0x7f: return 1
76d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if value <= 0x3fff: return 2
77d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if value <= 0x1fffff: return 3
78d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if value <= 0xfffffff: return 4
79d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if value <= 0x7ffffffff: return 5
80d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if value <= 0x3ffffffffff: return 6
81d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if value <= 0x1ffffffffffff: return 7
82d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if value <= 0xffffffffffffff: return 8
83d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if value <= 0x7fffffffffffffff: return 9
84d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return 10
85d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
86d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
87d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _SignedVarintSize(value):
88d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Compute the size of a signed varint value."""
89d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if value < 0: return 10
90d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if value <= 0x7f: return 1
91d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if value <= 0x3fff: return 2
92d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if value <= 0x1fffff: return 3
93d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if value <= 0xfffffff: return 4
94d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if value <= 0x7ffffffff: return 5
95d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if value <= 0x3ffffffffff: return 6
96d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if value <= 0x1ffffffffffff: return 7
97d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if value <= 0xffffffffffffff: return 8
98d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if value <= 0x7fffffffffffffff: return 9
99d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return 10
100d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
101d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
102d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _TagSize(field_number):
103d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Returns the number of bytes required to serialize a tag with this field
104d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  number."""
105d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  # Just pass in type 0, since the type won't affect the tag+type size.
106d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return _VarintSize(wire_format.PackTag(field_number, 0))
107d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
108d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
109d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# --------------------------------------------------------------------
110d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# In this section we define some generic sizers.  Each of these functions
111d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# takes parameters specific to a particular field type, e.g. int32 or fixed64.
112d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# It returns another function which in turn takes parameters specific to a
113d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# particular field, e.g. the field number and whether it is repeated or packed.
114d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# Look at the next section to see how these are used.
115d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
116d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
117d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _SimpleSizer(compute_value_size):
118d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """A sizer which uses the function compute_value_size to compute the size of
119d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  each value.  Typically compute_value_size is _VarintSize."""
120d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
121d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def SpecificSizer(field_number, is_repeated, is_packed):
122d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    tag_size = _TagSize(field_number)
123d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if is_packed:
124d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      local_VarintSize = _VarintSize
125d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def PackedFieldSize(value):
126d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        result = 0
127d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        for element in value:
128d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          result += compute_value_size(element)
129d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        return result + local_VarintSize(result) + tag_size
130d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return PackedFieldSize
131d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    elif is_repeated:
132d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def RepeatedFieldSize(value):
133d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        result = tag_size * len(value)
134d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        for element in value:
135d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          result += compute_value_size(element)
136d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        return result
137d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return RepeatedFieldSize
138d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    else:
139d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def FieldSize(value):
140d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        return tag_size + compute_value_size(value)
141d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return FieldSize
142d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
143d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return SpecificSizer
144d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
145d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
146d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _ModifiedSizer(compute_value_size, modify_value):
147d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Like SimpleSizer, but modify_value is invoked on each value before it is
148d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  passed to compute_value_size.  modify_value is typically ZigZagEncode."""
149d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
150d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def SpecificSizer(field_number, is_repeated, is_packed):
151d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    tag_size = _TagSize(field_number)
152d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if is_packed:
153d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      local_VarintSize = _VarintSize
154d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def PackedFieldSize(value):
155d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        result = 0
156d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        for element in value:
157d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          result += compute_value_size(modify_value(element))
158d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        return result + local_VarintSize(result) + tag_size
159d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return PackedFieldSize
160d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    elif is_repeated:
161d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def RepeatedFieldSize(value):
162d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        result = tag_size * len(value)
163d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        for element in value:
164d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          result += compute_value_size(modify_value(element))
165d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        return result
166d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return RepeatedFieldSize
167d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    else:
168d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def FieldSize(value):
169d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        return tag_size + compute_value_size(modify_value(value))
170d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return FieldSize
171d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
172d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return SpecificSizer
173d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
174d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
175d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _FixedSizer(value_size):
176d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Like _SimpleSizer except for a fixed-size field.  The input is the size
177d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  of one value."""
178d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
179d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def SpecificSizer(field_number, is_repeated, is_packed):
180d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    tag_size = _TagSize(field_number)
181d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if is_packed:
182d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      local_VarintSize = _VarintSize
183d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def PackedFieldSize(value):
184d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        result = len(value) * value_size
185d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        return result + local_VarintSize(result) + tag_size
186d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return PackedFieldSize
187d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    elif is_repeated:
188d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      element_size = value_size + tag_size
189d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def RepeatedFieldSize(value):
190d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        return len(value) * element_size
191d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return RepeatedFieldSize
192d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    else:
193d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      field_size = value_size + tag_size
194d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def FieldSize(value):
195d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        return field_size
196d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return FieldSize
197d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
198d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return SpecificSizer
199d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
200d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
201d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# ====================================================================
202d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# Here we declare a sizer constructor for each field type.  Each "sizer
203d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# constructor" is a function that takes (field_number, is_repeated, is_packed)
204d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# as parameters and returns a sizer, which in turn takes a field value as
205d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# a parameter and returns its encoded size.
206d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
207d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
208d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleInt32Sizer = Int64Sizer = EnumSizer = _SimpleSizer(_SignedVarintSize)
209d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
210d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleUInt32Sizer = UInt64Sizer = _SimpleSizer(_VarintSize)
211d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
212d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleSInt32Sizer = SInt64Sizer = _ModifiedSizer(
213d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    _SignedVarintSize, wire_format.ZigZagEncode)
214d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
215d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleFixed32Sizer = SFixed32Sizer = FloatSizer  = _FixedSizer(4)
216d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleFixed64Sizer = SFixed64Sizer = DoubleSizer = _FixedSizer(8)
217d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
218d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleBoolSizer = _FixedSizer(1)
219d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
220d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
221d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef StringSizer(field_number, is_repeated, is_packed):
222d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Returns a sizer for a string field."""
223d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
224d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  tag_size = _TagSize(field_number)
225d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_VarintSize = _VarintSize
226d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_len = len
227d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  assert not is_packed
228d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if is_repeated:
229d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def RepeatedFieldSize(value):
230d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      result = tag_size * len(value)
231d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      for element in value:
232d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        l = local_len(element.encode('utf-8'))
233d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        result += local_VarintSize(l) + l
234d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return result
235d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return RepeatedFieldSize
236d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  else:
237d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def FieldSize(value):
238d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      l = local_len(value.encode('utf-8'))
239d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return tag_size + local_VarintSize(l) + l
240d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return FieldSize
241d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
242d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
243d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef BytesSizer(field_number, is_repeated, is_packed):
244d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Returns a sizer for a bytes field."""
245d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
246d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  tag_size = _TagSize(field_number)
247d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_VarintSize = _VarintSize
248d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_len = len
249d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  assert not is_packed
250d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if is_repeated:
251d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def RepeatedFieldSize(value):
252d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      result = tag_size * len(value)
253d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      for element in value:
254d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        l = local_len(element)
255d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        result += local_VarintSize(l) + l
256d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return result
257d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return RepeatedFieldSize
258d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  else:
259d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def FieldSize(value):
260d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      l = local_len(value)
261d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return tag_size + local_VarintSize(l) + l
262d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return FieldSize
263d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
264d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
265d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef GroupSizer(field_number, is_repeated, is_packed):
266d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Returns a sizer for a group field."""
267d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
268d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  tag_size = _TagSize(field_number) * 2
269d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  assert not is_packed
270d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if is_repeated:
271d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def RepeatedFieldSize(value):
272d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      result = tag_size * len(value)
273d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      for element in value:
274d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        result += element.ByteSize()
275d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return result
276d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return RepeatedFieldSize
277d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  else:
278d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def FieldSize(value):
279d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return tag_size + value.ByteSize()
280d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return FieldSize
281d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
282d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
283d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef MessageSizer(field_number, is_repeated, is_packed):
284d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Returns a sizer for a message field."""
285d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
286d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  tag_size = _TagSize(field_number)
287d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_VarintSize = _VarintSize
288d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  assert not is_packed
289d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if is_repeated:
290d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def RepeatedFieldSize(value):
291d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      result = tag_size * len(value)
292d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      for element in value:
293d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        l = element.ByteSize()
294d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        result += local_VarintSize(l) + l
295d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return result
296d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return RepeatedFieldSize
297d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  else:
298d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def FieldSize(value):
299d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      l = value.ByteSize()
300d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return tag_size + local_VarintSize(l) + l
301d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return FieldSize
302d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
303d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
304d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# --------------------------------------------------------------------
305d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# MessageSet is special.
306d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
307d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
308d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef MessageSetItemSizer(field_number):
309d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Returns a sizer for extensions of MessageSet.
310d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
311d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  The message set message looks like this:
312d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    message MessageSet {
313d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      repeated group Item = 1 {
314d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        required int32 type_id = 2;
315d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        required string message = 3;
316d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      }
317d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
318d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """
319d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  static_size = (_TagSize(1) * 2 + _TagSize(2) + _VarintSize(field_number) +
320d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                 _TagSize(3))
321d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_VarintSize = _VarintSize
322d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
323d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def FieldSize(value):
324d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    l = value.ByteSize()
325d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return static_size + local_VarintSize(l) + l
326d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
327d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return FieldSize
328d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
329d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
330d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# ====================================================================
331d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# Encoders!
332d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
333d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
334d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _VarintEncoder():
335d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Return an encoder for a basic varint value (does not include tag)."""
336d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
337d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_chr = chr
338d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def EncodeVarint(write, value):
339d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    bits = value & 0x7f
340d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    value >>= 7
341d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    while value:
342d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      write(local_chr(0x80|bits))
343d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      bits = value & 0x7f
344d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      value >>= 7
345d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return write(local_chr(bits))
346d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
347d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return EncodeVarint
348d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
349d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
350d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _SignedVarintEncoder():
351d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Return an encoder for a basic signed varint value (does not include
352d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  tag)."""
353d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
354d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_chr = chr
355d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def EncodeSignedVarint(write, value):
356d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if value < 0:
357d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      value += (1 << 64)
358d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    bits = value & 0x7f
359d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    value >>= 7
360d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    while value:
361d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      write(local_chr(0x80|bits))
362d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      bits = value & 0x7f
363d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      value >>= 7
364d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return write(local_chr(bits))
365d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
366d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return EncodeSignedVarint
367d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
368d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
369d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville_EncodeVarint = _VarintEncoder()
370d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville_EncodeSignedVarint = _SignedVarintEncoder()
371d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
372d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
373d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _VarintBytes(value):
374d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Encode the given integer as a varint and return the bytes.  This is only
375d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  called at startup time so it doesn't need to be fast."""
376d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
377d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  pieces = []
378d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  _EncodeVarint(pieces.append, value)
379d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return "".join(pieces)
380d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
381d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
382d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef TagBytes(field_number, wire_type):
383d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Encode the given tag and return the bytes.  Only called at startup."""
384d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
385d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return _VarintBytes(wire_format.PackTag(field_number, wire_type))
386d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
387d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# --------------------------------------------------------------------
388d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# As with sizers (see above), we have a number of common encoder
389d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# implementations.
390d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
391d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
392d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _SimpleEncoder(wire_type, encode_value, compute_value_size):
393d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Return a constructor for an encoder for fields of a particular type.
394d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
395d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Args:
396d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      wire_type:  The field's wire type, for encoding tags.
397d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      encode_value:  A function which encodes an individual value, e.g.
398d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        _EncodeVarint().
399d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      compute_value_size:  A function which computes the size of an individual
400d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        value, e.g. _VarintSize().
401d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """
402d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
403d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def SpecificEncoder(field_number, is_repeated, is_packed):
404d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if is_packed:
405d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
406d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      local_EncodeVarint = _EncodeVarint
407d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def EncodePackedField(write, value):
408d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        write(tag_bytes)
409d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        size = 0
410d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        for element in value:
411d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          size += compute_value_size(element)
412d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        local_EncodeVarint(write, size)
413d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        for element in value:
414d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          encode_value(write, element)
415d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return EncodePackedField
416d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    elif is_repeated:
417d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      tag_bytes = TagBytes(field_number, wire_type)
418d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def EncodeRepeatedField(write, value):
419d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        for element in value:
420d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          write(tag_bytes)
421d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          encode_value(write, element)
422d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return EncodeRepeatedField
423d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    else:
424d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      tag_bytes = TagBytes(field_number, wire_type)
425d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def EncodeField(write, value):
426d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        write(tag_bytes)
427d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        return encode_value(write, value)
428d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return EncodeField
429d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
430d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return SpecificEncoder
431d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
432d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
433d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _ModifiedEncoder(wire_type, encode_value, compute_value_size, modify_value):
434d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Like SimpleEncoder but additionally invokes modify_value on every value
435d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  before passing it to encode_value.  Usually modify_value is ZigZagEncode."""
436d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
437d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def SpecificEncoder(field_number, is_repeated, is_packed):
438d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if is_packed:
439d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
440d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      local_EncodeVarint = _EncodeVarint
441d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def EncodePackedField(write, value):
442d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        write(tag_bytes)
443d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        size = 0
444d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        for element in value:
445d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          size += compute_value_size(modify_value(element))
446d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        local_EncodeVarint(write, size)
447d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        for element in value:
448d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          encode_value(write, modify_value(element))
449d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return EncodePackedField
450d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    elif is_repeated:
451d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      tag_bytes = TagBytes(field_number, wire_type)
452d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def EncodeRepeatedField(write, value):
453d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        for element in value:
454d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          write(tag_bytes)
455d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          encode_value(write, modify_value(element))
456d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return EncodeRepeatedField
457d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    else:
458d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      tag_bytes = TagBytes(field_number, wire_type)
459d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def EncodeField(write, value):
460d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        write(tag_bytes)
461d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        return encode_value(write, modify_value(value))
462d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return EncodeField
463d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
464d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return SpecificEncoder
465d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
466d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
467d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _StructPackEncoder(wire_type, format):
468d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Return a constructor for an encoder for a fixed-width field.
469d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
470d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Args:
471d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      wire_type:  The field's wire type, for encoding tags.
472d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      format:  The format string to pass to struct.pack().
473d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """
474d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
475d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  value_size = struct.calcsize(format)
476d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
477d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def SpecificEncoder(field_number, is_repeated, is_packed):
478d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    local_struct_pack = struct.pack
479d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if is_packed:
480d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
481d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      local_EncodeVarint = _EncodeVarint
482d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def EncodePackedField(write, value):
483d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        write(tag_bytes)
484d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        local_EncodeVarint(write, len(value) * value_size)
485d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        for element in value:
486d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          write(local_struct_pack(format, element))
487d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return EncodePackedField
488d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    elif is_repeated:
489d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      tag_bytes = TagBytes(field_number, wire_type)
490d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def EncodeRepeatedField(write, value):
491d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        for element in value:
492d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          write(tag_bytes)
493d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          write(local_struct_pack(format, element))
494d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return EncodeRepeatedField
495d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    else:
496d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      tag_bytes = TagBytes(field_number, wire_type)
497d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def EncodeField(write, value):
498d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        write(tag_bytes)
499d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        return write(local_struct_pack(format, value))
500d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return EncodeField
501d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
502d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return SpecificEncoder
503d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
504d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
505d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# ====================================================================
506d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# Here we declare an encoder constructor for each field type.  These work
507d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# very similarly to sizer constructors, described earlier.
508d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
509d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
510d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleInt32Encoder = Int64Encoder = EnumEncoder = _SimpleEncoder(
511d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    wire_format.WIRETYPE_VARINT, _EncodeSignedVarint, _SignedVarintSize)
512d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
513d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleUInt32Encoder = UInt64Encoder = _SimpleEncoder(
514d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize)
515d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
516d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleSInt32Encoder = SInt64Encoder = _ModifiedEncoder(
517d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize,
518d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    wire_format.ZigZagEncode)
519d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
520d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# Note that Python conveniently guarantees that when using the '<' prefix on
521d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# formats, they will also have the same size across all platforms (as opposed
522d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# to without the prefix, where their sizes depend on the C compiler's basic
523d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# type sizes).
524d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleFixed32Encoder  = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<I')
525d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleFixed64Encoder  = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<Q')
526d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleSFixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<i')
527d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleSFixed64Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<q')
528d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleFloatEncoder    = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<f')
529d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleDoubleEncoder   = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<d')
530d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
531d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
532d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef BoolEncoder(field_number, is_repeated, is_packed):
533d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Returns an encoder for a boolean field."""
534d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
535d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  false_byte = chr(0)
536d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  true_byte = chr(1)
537d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if is_packed:
538d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
539d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    local_EncodeVarint = _EncodeVarint
540d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def EncodePackedField(write, value):
541d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      write(tag_bytes)
542d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      local_EncodeVarint(write, len(value))
543d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      for element in value:
544d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if element:
545d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          write(true_byte)
546d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        else:
547d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          write(false_byte)
548d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return EncodePackedField
549d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  elif is_repeated:
550d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT)
551d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def EncodeRepeatedField(write, value):
552d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      for element in value:
553d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        write(tag_bytes)
554d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if element:
555d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          write(true_byte)
556d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        else:
557d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          write(false_byte)
558d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return EncodeRepeatedField
559d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  else:
560d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT)
561d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def EncodeField(write, value):
562d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      write(tag_bytes)
563d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if value:
564d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        return write(true_byte)
565d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return write(false_byte)
566d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return EncodeField
567d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
568d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
569d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef StringEncoder(field_number, is_repeated, is_packed):
570d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Returns an encoder for a string field."""
571d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
572d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
573d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_EncodeVarint = _EncodeVarint
574d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_len = len
575d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  assert not is_packed
576d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if is_repeated:
577d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def EncodeRepeatedField(write, value):
578d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      for element in value:
579d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        encoded = element.encode('utf-8')
580d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        write(tag)
581d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        local_EncodeVarint(write, local_len(encoded))
582d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        write(encoded)
583d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return EncodeRepeatedField
584d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  else:
585d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def EncodeField(write, value):
586d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      encoded = value.encode('utf-8')
587d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      write(tag)
588d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      local_EncodeVarint(write, local_len(encoded))
589d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return write(encoded)
590d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return EncodeField
591d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
592d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
593d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef BytesEncoder(field_number, is_repeated, is_packed):
594d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Returns an encoder for a bytes field."""
595d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
596d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
597d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_EncodeVarint = _EncodeVarint
598d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_len = len
599d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  assert not is_packed
600d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if is_repeated:
601d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def EncodeRepeatedField(write, value):
602d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      for element in value:
603d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        write(tag)
604d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        local_EncodeVarint(write, local_len(element))
605d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        write(element)
606d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return EncodeRepeatedField
607d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  else:
608d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def EncodeField(write, value):
609d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      write(tag)
610d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      local_EncodeVarint(write, local_len(value))
611d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return write(value)
612d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return EncodeField
613d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
614d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
615d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef GroupEncoder(field_number, is_repeated, is_packed):
616d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Returns an encoder for a group field."""
617d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
618d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  start_tag = TagBytes(field_number, wire_format.WIRETYPE_START_GROUP)
619d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  end_tag = TagBytes(field_number, wire_format.WIRETYPE_END_GROUP)
620d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  assert not is_packed
621d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if is_repeated:
622d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def EncodeRepeatedField(write, value):
623d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      for element in value:
624d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        write(start_tag)
625d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        element._InternalSerialize(write)
626d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        write(end_tag)
627d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return EncodeRepeatedField
628d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  else:
629d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def EncodeField(write, value):
630d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      write(start_tag)
631d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      value._InternalSerialize(write)
632d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return write(end_tag)
633d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return EncodeField
634d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
635d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
636d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef MessageEncoder(field_number, is_repeated, is_packed):
637d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Returns an encoder for a message field."""
638d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
639d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
640d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_EncodeVarint = _EncodeVarint
641d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  assert not is_packed
642d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if is_repeated:
643d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def EncodeRepeatedField(write, value):
644d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      for element in value:
645d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        write(tag)
646d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        local_EncodeVarint(write, element.ByteSize())
647d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        element._InternalSerialize(write)
648d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return EncodeRepeatedField
649d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  else:
650d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def EncodeField(write, value):
651d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      write(tag)
652d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      local_EncodeVarint(write, value.ByteSize())
653d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return value._InternalSerialize(write)
654d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return EncodeField
655d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
656d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
657d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# --------------------------------------------------------------------
658d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# As before, MessageSet is special.
659d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
660d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
661d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef MessageSetItemEncoder(field_number):
662d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Encoder for extensions of MessageSet.
663d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
664d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  The message set message looks like this:
665d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    message MessageSet {
666d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      repeated group Item = 1 {
667d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        required int32 type_id = 2;
668d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        required string message = 3;
669fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      }
670d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
671d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """
672d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  start_bytes = "".join([
673d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      TagBytes(1, wire_format.WIRETYPE_START_GROUP),
674d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      TagBytes(2, wire_format.WIRETYPE_VARINT),
675d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      _VarintBytes(field_number),
676d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      TagBytes(3, wire_format.WIRETYPE_LENGTH_DELIMITED)])
677d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  end_bytes = TagBytes(1, wire_format.WIRETYPE_END_GROUP)
678d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_EncodeVarint = _EncodeVarint
679d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
680d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def EncodeField(write, value):
681d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    write(start_bytes)
682d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    local_EncodeVarint(write, value.ByteSize())
683d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    value._InternalSerialize(write)
684d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return write(end_bytes)
685d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
686d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return EncodeField
687