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 decoding protocol buffer primitives.
32d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
33d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleThis code is very similar to encoder.py -- read the docs for that module first.
34d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
35d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleA "decoder" is a function with the signature:
36d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Decode(buffer, pos, end, message, field_dict)
37d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleThe arguments are:
38d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  buffer:     The string containing the encoded message.
39d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  pos:        The current position in the string.
40d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  end:        The position in the string where the current message ends.  May be
41d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville              less than len(buffer) if we're reading a sub-message.
42d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  message:    The message object into which we're parsing.
43d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  field_dict: message._fields (avoids a hashtable lookup).
44d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleThe decoder reads the field and stores it into field_dict, returning the new
45d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillebuffer position.  A decoder for a repeated field may proactively decode all of
46d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillethe elements of that field, if they appear consecutively.
47d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
48d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleNote that decoders may throw any of the following:
49d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  IndexError:  Indicates a truncated message.
50d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  struct.error:  Unpacking of a fixed-width field failed.
51d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  message.DecodeError:  Other errors.
52d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
53d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleDecoders are expected to raise an exception if they are called with pos > end.
54d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleThis allows callers to be lax about bounds checking:  it's fineto read past
55d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville"end" as long as you are sure that someone else will notice and throw an
56d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilleexception later on.
57d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
58d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleSomething up the call stack is expected to catch IndexError and struct.error
59d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilleand convert them to message.DecodeError.
60d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
61d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleDecoders are constructed using decoder constructors with the signature:
62d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  MakeDecoder(field_number, is_repeated, is_packed, key, new_default)
63d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleThe arguments are:
64d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  field_number:  The field number of the field we want to decode.
65d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  is_repeated:   Is the field a repeated field? (bool)
66d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  is_packed:     Is the field a packed field? (bool)
67d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  key:           The key to use when looking up the field within field_dict.
68d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                 (This is actually the FieldDescriptor but nothing in this
69d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                 file should depend on that.)
70d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  new_default:   A function which takes a message object as a parameter and
71d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                 returns a new instance of the default value for this field.
72d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                 (This is called for repeated fields and sub-messages, when an
73d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                 instance does not already exist.)
74d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
75d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleAs with encoders, we define a decoder constructor for every type of field.
76d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleThen, for every field of every message class we construct an actual decoder.
77d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleThat decoder goes into a dict indexed by tag, so when we decode a message
78d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillewe repeatedly read a tag, look up the corresponding decoder, and invoke it.
79fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville"""
80fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
81d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville__author__ = 'kenton@google.com (Kenton Varda)'
82fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
83fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleimport struct
84d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillefrom google.protobuf.internal import encoder
85fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillefrom google.protobuf.internal import wire_format
86d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillefrom google.protobuf import message
87fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
88fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
89d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# This is not for optimization, but rather to avoid conflicts with local
90d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# variables named "message".
91d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville_DecodeError = message.DecodeError
92d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
93d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
94d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _VarintDecoder(mask):
95d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Return an encoder for a basic varint value (does not include tag).
96d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
97d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Decoded values will be bitwise-anded with the given mask before being
98d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  returned, e.g. to limit them to 32 bits.  The returned decoder does not
99d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  take the usual "end" parameter -- the caller is expected to do bounds checking
100d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  after the fact (often the caller can defer such checking until later).  The
101d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  decoder returns a (value, new_pos) pair.
102d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """
103d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
104d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_ord = ord
105d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def DecodeVarint(buffer, pos):
106d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    result = 0
107d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    shift = 0
108d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    while 1:
109d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      b = local_ord(buffer[pos])
110d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      result |= ((b & 0x7f) << shift)
111d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      pos += 1
112d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if not (b & 0x80):
113d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        result &= mask
114d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        return (result, pos)
115d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      shift += 7
116d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if shift >= 64:
117d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        raise _DecodeError('Too many bytes when decoding varint.')
118d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return DecodeVarint
119d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
120d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
121d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _SignedVarintDecoder(mask):
122d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Like _VarintDecoder() but decodes signed values."""
123d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
124d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_ord = ord
125d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def DecodeVarint(buffer, pos):
126d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    result = 0
127d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    shift = 0
128d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    while 1:
129d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      b = local_ord(buffer[pos])
130d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      result |= ((b & 0x7f) << shift)
131d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      pos += 1
132d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if not (b & 0x80):
133d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if result > 0x7fffffffffffffff:
134d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          result -= (1 << 64)
135d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          result |= ~mask
136d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        else:
137d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          result &= mask
138d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        return (result, pos)
139d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      shift += 7
140d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if shift >= 64:
141d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        raise _DecodeError('Too many bytes when decoding varint.')
142d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return DecodeVarint
143d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
144d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
145d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville_DecodeVarint = _VarintDecoder((1 << 64) - 1)
146d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville_DecodeSignedVarint = _SignedVarintDecoder((1 << 64) - 1)
147d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
148d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# Use these versions for values which must be limited to 32 bits.
149d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville_DecodeVarint32 = _VarintDecoder((1 << 32) - 1)
150d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville_DecodeSignedVarint32 = _SignedVarintDecoder((1 << 32) - 1)
151d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
152d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
153d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef ReadTag(buffer, pos):
154d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Read a tag from the buffer, and return a (tag_bytes, new_pos) tuple.
155d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
156d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  We return the raw bytes of the tag rather than decoding them.  The raw
157d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  bytes can then be used to look up the proper decoder.  This effectively allows
158d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  us to trade some work that would be done in pure-python (decoding a varint)
159d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  for work that is done in C (searching for a byte string in a hash table).
160d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  In a low-level language it would be much cheaper to decode the varint and
161d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  use that, but not in Python.
162d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """
163d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
164d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  start = pos
165d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  while ord(buffer[pos]) & 0x80:
166d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    pos += 1
167d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  pos += 1
168d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return (buffer[start:pos], pos)
169d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
170d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
171d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# --------------------------------------------------------------------
172d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
173d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
174d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _SimpleDecoder(wire_type, decode_value):
175d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Return a constructor for a decoder for fields of a particular type.
176d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
177d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Args:
178d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      wire_type:  The field's wire type.
179d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      decode_value:  A function which decodes an individual value, e.g.
180d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        _DecodeVarint()
181d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """
182d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
183d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def SpecificDecoder(field_number, is_repeated, is_packed, key, new_default):
184d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if is_packed:
185d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      local_DecodeVarint = _DecodeVarint
186d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def DecodePackedField(buffer, pos, end, message, field_dict):
187d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        value = field_dict.get(key)
188d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if value is None:
189d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          value = field_dict.setdefault(key, new_default(message))
190d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        (endpoint, pos) = local_DecodeVarint(buffer, pos)
191d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        endpoint += pos
192d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if endpoint > end:
193d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          raise _DecodeError('Truncated message.')
194d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        while pos < endpoint:
195d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          (element, pos) = decode_value(buffer, pos)
196d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          value.append(element)
197d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if pos > endpoint:
198d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          del value[-1]   # Discard corrupt value.
199d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          raise _DecodeError('Packed element was truncated.')
200d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        return pos
201d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return DecodePackedField
202d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    elif is_repeated:
203d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      tag_bytes = encoder.TagBytes(field_number, wire_type)
204d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      tag_len = len(tag_bytes)
205d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def DecodeRepeatedField(buffer, pos, end, message, field_dict):
206d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        value = field_dict.get(key)
207d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if value is None:
208d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          value = field_dict.setdefault(key, new_default(message))
209d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        while 1:
210d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          (element, new_pos) = decode_value(buffer, pos)
211d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          value.append(element)
212d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          # Predict that the next tag is another copy of the same repeated
213d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          # field.
214d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          pos = new_pos + tag_len
215d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          if buffer[new_pos:pos] != tag_bytes or new_pos >= end:
216d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville            # Prediction failed.  Return.
217d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville            if new_pos > end:
218d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville              raise _DecodeError('Truncated message.')
219d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville            return new_pos
220d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return DecodeRepeatedField
221d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    else:
222d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def DecodeField(buffer, pos, end, message, field_dict):
223d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        (field_dict[key], pos) = decode_value(buffer, pos)
224d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if pos > end:
225d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          del field_dict[key]  # Discard corrupt value.
226d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          raise _DecodeError('Truncated message.')
227d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        return pos
228d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return DecodeField
229d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
230d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return SpecificDecoder
231d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
232d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
233d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _ModifiedDecoder(wire_type, decode_value, modify_value):
234d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Like SimpleDecoder but additionally invokes modify_value on every value
235d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  before storing it.  Usually modify_value is ZigZagDecode.
236d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """
237d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
238d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  # Reusing _SimpleDecoder is slightly slower than copying a bunch of code, but
239d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  # not enough to make a significant difference.
240d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
241d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def InnerDecode(buffer, pos):
242d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    (result, new_pos) = decode_value(buffer, pos)
243d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return (modify_value(result), new_pos)
244d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return _SimpleDecoder(wire_type, InnerDecode)
245d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
246d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
247d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _StructPackDecoder(wire_type, format):
248d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Return a constructor for a decoder for a fixed-width field.
249d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
250d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  Args:
251d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      wire_type:  The field's wire type.
252d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      format:  The format string to pass to struct.unpack().
253d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """
254d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
255d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  value_size = struct.calcsize(format)
256d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_unpack = struct.unpack
257d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
258d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  # Reusing _SimpleDecoder is slightly slower than copying a bunch of code, but
259d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  # not enough to make a significant difference.
260d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
261d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  # Note that we expect someone up-stack to catch struct.error and convert
262d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  # it to _DecodeError -- this way we don't have to set up exception-
263d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  # handling blocks every time we parse one value.
264d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
265d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def InnerDecode(buffer, pos):
266d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    new_pos = pos + value_size
267d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    result = local_unpack(format, buffer[pos:new_pos])[0]
268d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return (result, new_pos)
269d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return _SimpleDecoder(wire_type, InnerDecode)
270d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
271d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
272d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# --------------------------------------------------------------------
273d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
274d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
275d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleInt32Decoder = EnumDecoder = _SimpleDecoder(
276d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    wire_format.WIRETYPE_VARINT, _DecodeSignedVarint32)
277d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
278d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleInt64Decoder = _SimpleDecoder(
279d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    wire_format.WIRETYPE_VARINT, _DecodeSignedVarint)
280d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
281d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleUInt32Decoder = _SimpleDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint32)
282d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleUInt64Decoder = _SimpleDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint)
283d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
284d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleSInt32Decoder = _ModifiedDecoder(
285d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    wire_format.WIRETYPE_VARINT, _DecodeVarint32, wire_format.ZigZagDecode)
286d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleSInt64Decoder = _ModifiedDecoder(
287d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    wire_format.WIRETYPE_VARINT, _DecodeVarint, wire_format.ZigZagDecode)
288d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
289d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# Note that Python conveniently guarantees that when using the '<' prefix on
290d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# formats, they will also have the same size across all platforms (as opposed
291d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# to without the prefix, where their sizes depend on the C compiler's basic
292d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# type sizes).
293d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleFixed32Decoder  = _StructPackDecoder(wire_format.WIRETYPE_FIXED32, '<I')
294d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleFixed64Decoder  = _StructPackDecoder(wire_format.WIRETYPE_FIXED64, '<Q')
295d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleSFixed32Decoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED32, '<i')
296d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleSFixed64Decoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED64, '<q')
297d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleFloatDecoder    = _StructPackDecoder(wire_format.WIRETYPE_FIXED32, '<f')
298d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleDoubleDecoder   = _StructPackDecoder(wire_format.WIRETYPE_FIXED64, '<d')
299d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
300d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleBoolDecoder = _ModifiedDecoder(
301d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    wire_format.WIRETYPE_VARINT, _DecodeVarint, bool)
302d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
303d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
304d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef StringDecoder(field_number, is_repeated, is_packed, key, new_default):
305d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Returns a decoder for a string field."""
306d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
307d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_DecodeVarint = _DecodeVarint
308d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_unicode = unicode
309d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
310d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  assert not is_packed
311d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if is_repeated:
312d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    tag_bytes = encoder.TagBytes(field_number,
313d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                                 wire_format.WIRETYPE_LENGTH_DELIMITED)
314d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    tag_len = len(tag_bytes)
315d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def DecodeRepeatedField(buffer, pos, end, message, field_dict):
316d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      value = field_dict.get(key)
317d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if value is None:
318d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        value = field_dict.setdefault(key, new_default(message))
319d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      while 1:
320d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        (size, pos) = local_DecodeVarint(buffer, pos)
321d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        new_pos = pos + size
322d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if new_pos > end:
323d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          raise _DecodeError('Truncated string.')
324d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        value.append(local_unicode(buffer[pos:new_pos], 'utf-8'))
325d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        # Predict that the next tag is another copy of the same repeated field.
326d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        pos = new_pos + tag_len
327d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if buffer[new_pos:pos] != tag_bytes or new_pos == end:
328d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          # Prediction failed.  Return.
329d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          return new_pos
330d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return DecodeRepeatedField
331d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  else:
332d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def DecodeField(buffer, pos, end, message, field_dict):
333d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      (size, pos) = local_DecodeVarint(buffer, pos)
334d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      new_pos = pos + size
335d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if new_pos > end:
336d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        raise _DecodeError('Truncated string.')
337d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      field_dict[key] = local_unicode(buffer[pos:new_pos], 'utf-8')
338d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return new_pos
339d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return DecodeField
340d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
341d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
342d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef BytesDecoder(field_number, is_repeated, is_packed, key, new_default):
343d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Returns a decoder for a bytes field."""
344d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
345d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_DecodeVarint = _DecodeVarint
346d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
347d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  assert not is_packed
348d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if is_repeated:
349d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    tag_bytes = encoder.TagBytes(field_number,
350d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                                 wire_format.WIRETYPE_LENGTH_DELIMITED)
351d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    tag_len = len(tag_bytes)
352d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def DecodeRepeatedField(buffer, pos, end, message, field_dict):
353d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      value = field_dict.get(key)
354d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if value is None:
355d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        value = field_dict.setdefault(key, new_default(message))
356d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      while 1:
357d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        (size, pos) = local_DecodeVarint(buffer, pos)
358d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        new_pos = pos + size
359d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if new_pos > end:
360d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          raise _DecodeError('Truncated string.')
361d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        value.append(buffer[pos:new_pos])
362d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        # Predict that the next tag is another copy of the same repeated field.
363d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        pos = new_pos + tag_len
364d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if buffer[new_pos:pos] != tag_bytes or new_pos == end:
365d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          # Prediction failed.  Return.
366d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          return new_pos
367d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return DecodeRepeatedField
368d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  else:
369d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def DecodeField(buffer, pos, end, message, field_dict):
370d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      (size, pos) = local_DecodeVarint(buffer, pos)
371d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      new_pos = pos + size
372d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if new_pos > end:
373d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        raise _DecodeError('Truncated string.')
374d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      field_dict[key] = buffer[pos:new_pos]
375d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return new_pos
376d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return DecodeField
377d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
378d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
379d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef GroupDecoder(field_number, is_repeated, is_packed, key, new_default):
380d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Returns a decoder for a group field."""
381d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
382d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  end_tag_bytes = encoder.TagBytes(field_number,
383d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                                   wire_format.WIRETYPE_END_GROUP)
384d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  end_tag_len = len(end_tag_bytes)
385d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
386d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  assert not is_packed
387d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if is_repeated:
388d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    tag_bytes = encoder.TagBytes(field_number,
389d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                                 wire_format.WIRETYPE_START_GROUP)
390d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    tag_len = len(tag_bytes)
391d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def DecodeRepeatedField(buffer, pos, end, message, field_dict):
392d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      value = field_dict.get(key)
393d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if value is None:
394d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        value = field_dict.setdefault(key, new_default(message))
395d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      while 1:
396d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        value = field_dict.get(key)
397d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if value is None:
398d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          value = field_dict.setdefault(key, new_default(message))
399d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        # Read sub-message.
400d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        pos = value.add()._InternalParse(buffer, pos, end)
401d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        # Read end tag.
402d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        new_pos = pos+end_tag_len
403d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if buffer[pos:new_pos] != end_tag_bytes or new_pos > end:
404d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          raise _DecodeError('Missing group end tag.')
405d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        # Predict that the next tag is another copy of the same repeated field.
406d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        pos = new_pos + tag_len
407d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if buffer[new_pos:pos] != tag_bytes or new_pos == end:
408d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          # Prediction failed.  Return.
409d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          return new_pos
410d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return DecodeRepeatedField
411d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  else:
412d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def DecodeField(buffer, pos, end, message, field_dict):
413d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      value = field_dict.get(key)
414d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if value is None:
415d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        value = field_dict.setdefault(key, new_default(message))
416d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      # Read sub-message.
417d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      pos = value._InternalParse(buffer, pos, end)
418d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      # Read end tag.
419d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      new_pos = pos+end_tag_len
420d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if buffer[pos:new_pos] != end_tag_bytes or new_pos > end:
421d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        raise _DecodeError('Missing group end tag.')
422d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return new_pos
423d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return DecodeField
424d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
425d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
426d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef MessageDecoder(field_number, is_repeated, is_packed, key, new_default):
427d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Returns a decoder for a message field."""
428d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
429d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_DecodeVarint = _DecodeVarint
430d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
431d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  assert not is_packed
432d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if is_repeated:
433d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    tag_bytes = encoder.TagBytes(field_number,
434d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                                 wire_format.WIRETYPE_LENGTH_DELIMITED)
435d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    tag_len = len(tag_bytes)
436d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def DecodeRepeatedField(buffer, pos, end, message, field_dict):
437d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      value = field_dict.get(key)
438d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if value is None:
439d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        value = field_dict.setdefault(key, new_default(message))
440d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      while 1:
441d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        value = field_dict.get(key)
442d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if value is None:
443d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          value = field_dict.setdefault(key, new_default(message))
444d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        # Read length.
445d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        (size, pos) = local_DecodeVarint(buffer, pos)
446d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        new_pos = pos + size
447d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if new_pos > end:
448d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          raise _DecodeError('Truncated message.')
449d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        # Read sub-message.
450d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if value.add()._InternalParse(buffer, pos, new_pos) != new_pos:
451d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          # The only reason _InternalParse would return early is if it
452d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          # encountered an end-group tag.
453d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          raise _DecodeError('Unexpected end-group tag.')
454d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        # Predict that the next tag is another copy of the same repeated field.
455d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        pos = new_pos + tag_len
456d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if buffer[new_pos:pos] != tag_bytes or new_pos == end:
457d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          # Prediction failed.  Return.
458d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          return new_pos
459d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return DecodeRepeatedField
460d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  else:
461d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def DecodeField(buffer, pos, end, message, field_dict):
462d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      value = field_dict.get(key)
463d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if value is None:
464d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        value = field_dict.setdefault(key, new_default(message))
465d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      # Read length.
466d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      (size, pos) = local_DecodeVarint(buffer, pos)
467d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      new_pos = pos + size
468d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if new_pos > end:
469d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        raise _DecodeError('Truncated message.')
470d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      # Read sub-message.
471d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if value._InternalParse(buffer, pos, new_pos) != new_pos:
472d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        # The only reason _InternalParse would return early is if it encountered
473d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        # an end-group tag.
474d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        raise _DecodeError('Unexpected end-group tag.')
475d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return new_pos
476d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return DecodeField
477d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
478d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
479d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# --------------------------------------------------------------------
480d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
481d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleMESSAGE_SET_ITEM_TAG = encoder.TagBytes(1, wire_format.WIRETYPE_START_GROUP)
482d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
483d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef MessageSetItemDecoder(extensions_by_number):
484d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Returns a decoder for a MessageSet item.
485d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
486d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  The parameter is the _extensions_by_number map for the message class.
487d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
488d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  The message set message looks like this:
489d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    message MessageSet {
490d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      repeated group Item = 1 {
491d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        required int32 type_id = 2;
492d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        required string message = 3;
493d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      }
494d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
495d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """
496d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
497d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  type_id_tag_bytes = encoder.TagBytes(2, wire_format.WIRETYPE_VARINT)
498d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  message_tag_bytes = encoder.TagBytes(3, wire_format.WIRETYPE_LENGTH_DELIMITED)
499d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  item_end_tag_bytes = encoder.TagBytes(1, wire_format.WIRETYPE_END_GROUP)
500d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
501d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_ReadTag = ReadTag
502d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_DecodeVarint = _DecodeVarint
503d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_SkipField = SkipField
504d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
505d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def DecodeItem(buffer, pos, end, message, field_dict):
506d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    type_id = -1
507d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    message_start = -1
508d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    message_end = -1
509d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
510d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # Technically, type_id and message can appear in any order, so we need
511d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # a little loop here.
512d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    while 1:
513d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      (tag_bytes, pos) = local_ReadTag(buffer, pos)
514d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if tag_bytes == type_id_tag_bytes:
515d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        (type_id, pos) = local_DecodeVarint(buffer, pos)
516d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      elif tag_bytes == message_tag_bytes:
517d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        (size, message_start) = local_DecodeVarint(buffer, pos)
518d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        pos = message_end = message_start + size
519d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      elif tag_bytes == item_end_tag_bytes:
520d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        break
521d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      else:
522d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        pos = SkipField(buffer, pos, end, tag_bytes)
523d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if pos == -1:
524d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          raise _DecodeError('Missing group end tag.')
525d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
526d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if pos > end:
527d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      raise _DecodeError('Truncated message.')
528d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
529d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if type_id == -1:
530d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      raise _DecodeError('MessageSet item missing type_id.')
531d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if message_start == -1:
532d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      raise _DecodeError('MessageSet item missing message.')
533d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
534d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    extension = extensions_by_number.get(type_id)
535d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if extension is not None:
536d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      value = field_dict.get(extension)
537d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if value is None:
538d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        value = field_dict.setdefault(
539d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville            extension, extension.message_type._concrete_class())
540d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if value._InternalParse(buffer, message_start,message_end) != message_end:
541d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        # The only reason _InternalParse would return early is if it encountered
542d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        # an end-group tag.
543d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        raise _DecodeError('Unexpected end-group tag.')
544d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
545d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return pos
546d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
547d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return DecodeItem
548d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
549d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# --------------------------------------------------------------------
550d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# Optimization is not as heavy here because calls to SkipField() are rare,
551d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville# except for handling end-group tags.
552d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
553d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _SkipVarint(buffer, pos, end):
554d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Skip a varint value.  Returns the new position."""
555d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
556d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  while ord(buffer[pos]) & 0x80:
557d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    pos += 1
558d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  pos += 1
559d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if pos > end:
560d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    raise _DecodeError('Truncated message.')
561d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return pos
562d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
563d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _SkipFixed64(buffer, pos, end):
564d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Skip a fixed64 value.  Returns the new position."""
565d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
566d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  pos += 8
567d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if pos > end:
568d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    raise _DecodeError('Truncated message.')
569d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return pos
570d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
571d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _SkipLengthDelimited(buffer, pos, end):
572d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Skip a length-delimited value.  Returns the new position."""
573d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
574d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  (size, pos) = _DecodeVarint(buffer, pos)
575d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  pos += size
576d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if pos > end:
577d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    raise _DecodeError('Truncated message.')
578d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return pos
579d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
580d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _SkipGroup(buffer, pos, end):
581d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Skip sub-group.  Returns the new position."""
582d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
583d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  while 1:
584d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    (tag_bytes, pos) = ReadTag(buffer, pos)
585d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    new_pos = SkipField(buffer, pos, end, tag_bytes)
586d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if new_pos == -1:
587d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return pos
588d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    pos = new_pos
589d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
590d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _EndGroup(buffer, pos, end):
591d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Skipping an END_GROUP tag returns -1 to tell the parent loop to break."""
592d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
593d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return -1
594d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
595d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _SkipFixed32(buffer, pos, end):
596d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Skip a fixed32 value.  Returns the new position."""
597d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
598d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  pos += 4
599d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if pos > end:
600d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    raise _DecodeError('Truncated message.')
601d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return pos
602d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
603d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _RaiseInvalidWireType(buffer, pos, end):
604d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Skip function for unknown wire types.  Raises an exception."""
605d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
606d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  raise _DecodeError('Tag had invalid wire type.')
607d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
608d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _FieldSkipper():
609d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Constructs the SkipField function."""
610d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
611d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  WIRETYPE_TO_SKIPPER = [
612d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      _SkipVarint,
613d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      _SkipFixed64,
614d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      _SkipLengthDelimited,
615d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      _SkipGroup,
616d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      _EndGroup,
617d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      _SkipFixed32,
618d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      _RaiseInvalidWireType,
619d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      _RaiseInvalidWireType,
620d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      ]
621d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
622d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  wiretype_mask = wire_format.TAG_TYPE_MASK
623d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_ord = ord
624d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
625d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def SkipField(buffer, pos, end, tag_bytes):
626d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    """Skips a field with the specified tag.
627d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
628d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    |pos| should point to the byte immediately after the tag.
629d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
630d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    Returns:
631d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        The new position (after the tag value), or -1 if the tag is an end-group
632d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        tag (in which case the calling loop should break).
633d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    """
634fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
635d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # The wire type is always in the first byte since varints are little-endian.
636d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    wire_type = local_ord(tag_bytes[0]) & wiretype_mask
637d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return WIRETYPE_TO_SKIPPER[wire_type](buffer, pos, end)
638fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
639d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return SkipField
640fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
641d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleSkipField = _FieldSkipper()
642