17e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# Protocol Buffers - Google's data interchange format
27e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# Copyright 2008 Google Inc.  All rights reserved.
37e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# http://code.google.com/p/protobuf/
47e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#
57e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# Redistribution and use in source and binary forms, with or without
67e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# modification, are permitted provided that the following conditions are
77e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# met:
87e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#
97e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#     * Redistributions of source code must retain the above copyright
107e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# notice, this list of conditions and the following disclaimer.
117e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#     * Redistributions in binary form must reproduce the above
127e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# copyright notice, this list of conditions and the following disclaimer
137e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# in the documentation and/or other materials provided with the
147e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# distribution.
157e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#     * Neither the name of Google Inc. nor the names of its
167e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# contributors may be used to endorse or promote products derived from
177e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# this software without specific prior written permission.
187e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#
197e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
207e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
217e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
227e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
237e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
247e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
257e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
267e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
277e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
287e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
297e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
307e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
317e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang"""Constants and static functions to support protocol buffer wire format."""
327e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
337e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang__author__ = 'robinson@google.com (Will Robinson)'
347e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
357e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangimport struct
367e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangfrom google.protobuf import descriptor
377e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangfrom google.protobuf import message
387e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
397e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
407e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangTAG_TYPE_BITS = 3  # Number of bits used to hold type info in a proto tag.
417e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangTAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1  # 0x7
427e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
437e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# These numbers identify the wire type of a protocol buffer value.
447e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# We use the least-significant TAG_TYPE_BITS bits of the varint-encoded
457e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# tag-and-type to store one of these WIRETYPE_* constants.
467e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# These values must match WireType enum in google/protobuf/wire_format.h.
477e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangWIRETYPE_VARINT = 0
487e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangWIRETYPE_FIXED64 = 1
497e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangWIRETYPE_LENGTH_DELIMITED = 2
507e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangWIRETYPE_START_GROUP = 3
517e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangWIRETYPE_END_GROUP = 4
527e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangWIRETYPE_FIXED32 = 5
537e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang_WIRETYPE_MAX = 5
547e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
557e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
567e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# Bounds for various integer types.
577e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangINT32_MAX = int((1 << 31) - 1)
587e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangINT32_MIN = int(-(1 << 31))
597e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangUINT32_MAX = (1 << 32) - 1
607e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
617e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangINT64_MAX = (1 << 63) - 1
627e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangINT64_MIN = -(1 << 63)
637e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangUINT64_MAX = (1 << 64) - 1
647e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
657e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# "struct" format strings that will encode/decode the specified formats.
667e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangFORMAT_UINT32_LITTLE_ENDIAN = '<I'
677e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangFORMAT_UINT64_LITTLE_ENDIAN = '<Q'
687e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangFORMAT_FLOAT_LITTLE_ENDIAN = '<f'
697e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangFORMAT_DOUBLE_LITTLE_ENDIAN = '<d'
707e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
717e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
727e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# We'll have to provide alternate implementations of AppendLittleEndian*() on
737e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# any architectures where these checks fail.
747e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangif struct.calcsize(FORMAT_UINT32_LITTLE_ENDIAN) != 4:
757e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  raise AssertionError('Format "I" is not a 32-bit number.')
767e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangif struct.calcsize(FORMAT_UINT64_LITTLE_ENDIAN) != 8:
777e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  raise AssertionError('Format "Q" is not a 64-bit number.')
787e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
797e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
807e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef PackTag(field_number, wire_type):
817e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """Returns an unsigned 32-bit integer that encodes the field number and
827e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  wire type information in standard protocol message wire format.
837e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
847e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  Args:
857e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    field_number: Expected to be an integer in the range [1, 1 << 29)
867e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    wire_type: One of the WIRETYPE_* constants.
877e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """
887e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  if not 0 <= wire_type <= _WIRETYPE_MAX:
897e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    raise message.EncodeError('Unknown wire type: %d' % wire_type)
907e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return (field_number << TAG_TYPE_BITS) | wire_type
917e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
927e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
937e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef UnpackTag(tag):
947e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """The inverse of PackTag().  Given an unsigned 32-bit number,
957e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  returns a (field_number, wire_type) tuple.
967e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """
977e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return (tag >> TAG_TYPE_BITS), (tag & TAG_TYPE_MASK)
987e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
997e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1007e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef ZigZagEncode(value):
1017e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """ZigZag Transform:  Encodes signed integers so that they can be
1027e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  effectively used with varint encoding.  See wire_format.h for
1037e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  more details.
1047e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """
1057e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  if value >= 0:
1067e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    return value << 1
1077e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return (value << 1) ^ (~0)
1087e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1097e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1107e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef ZigZagDecode(value):
1117e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """Inverse of ZigZagEncode()."""
1127e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  if not value & 0x1:
1137e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    return value >> 1
1147e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return (value >> 1) ^ (~0)
1157e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1167e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1177e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1187e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# The *ByteSize() functions below return the number of bytes required to
1197e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# serialize "field number + type" information and then serialize the value.
1207e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1217e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1227e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef Int32ByteSize(field_number, int32):
1237e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return Int64ByteSize(field_number, int32)
1247e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1257e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1267e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef Int32ByteSizeNoTag(int32):
1277e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return _VarUInt64ByteSizeNoTag(0xffffffffffffffff & int32)
1287e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1297e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1307e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef Int64ByteSize(field_number, int64):
1317e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  # Have to convert to uint before calling UInt64ByteSize().
1327e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return UInt64ByteSize(field_number, 0xffffffffffffffff & int64)
1337e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1347e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1357e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef UInt32ByteSize(field_number, uint32):
1367e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return UInt64ByteSize(field_number, uint32)
1377e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1387e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1397e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef UInt64ByteSize(field_number, uint64):
1407e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return TagByteSize(field_number) + _VarUInt64ByteSizeNoTag(uint64)
1417e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1427e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1437e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef SInt32ByteSize(field_number, int32):
1447e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return UInt32ByteSize(field_number, ZigZagEncode(int32))
1457e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1467e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1477e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef SInt64ByteSize(field_number, int64):
1487e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return UInt64ByteSize(field_number, ZigZagEncode(int64))
1497e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1507e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1517e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef Fixed32ByteSize(field_number, fixed32):
1527e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return TagByteSize(field_number) + 4
1537e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1547e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1557e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef Fixed64ByteSize(field_number, fixed64):
1567e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return TagByteSize(field_number) + 8
1577e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1587e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1597e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef SFixed32ByteSize(field_number, sfixed32):
1607e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return TagByteSize(field_number) + 4
1617e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1627e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1637e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef SFixed64ByteSize(field_number, sfixed64):
1647e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return TagByteSize(field_number) + 8
1657e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1667e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1677e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef FloatByteSize(field_number, flt):
1687e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return TagByteSize(field_number) + 4
1697e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1707e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1717e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef DoubleByteSize(field_number, double):
1727e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return TagByteSize(field_number) + 8
1737e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1747e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1757e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef BoolByteSize(field_number, b):
1767e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return TagByteSize(field_number) + 1
1777e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1787e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1797e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef EnumByteSize(field_number, enum):
1807e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return UInt32ByteSize(field_number, enum)
1817e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1827e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1837e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef StringByteSize(field_number, string):
1847e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return BytesByteSize(field_number, string.encode('utf-8'))
1857e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1867e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1877e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef BytesByteSize(field_number, b):
1887e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return (TagByteSize(field_number)
1897e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang          + _VarUInt64ByteSizeNoTag(len(b))
1907e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang          + len(b))
1917e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1927e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1937e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef GroupByteSize(field_number, message):
1947e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return (2 * TagByteSize(field_number)  # START and END group.
1957e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang          + message.ByteSize())
1967e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1977e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1987e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef MessageByteSize(field_number, message):
1997e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return (TagByteSize(field_number)
2007e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang          + _VarUInt64ByteSizeNoTag(message.ByteSize())
2017e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang          + message.ByteSize())
2027e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2037e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2047e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef MessageSetItemByteSize(field_number, msg):
2057e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  # First compute the sizes of the tags.
2067e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  # There are 2 tags for the beginning and ending of the repeated group, that
2077e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  # is field number 1, one with field number 2 (type_id) and one with field
2087e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  # number 3 (message).
2097e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  total_size = (2 * TagByteSize(1) + TagByteSize(2) + TagByteSize(3))
2107e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2117e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  # Add the number of bytes for type_id.
2127e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  total_size += _VarUInt64ByteSizeNoTag(field_number)
2137e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2147e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  message_size = msg.ByteSize()
2157e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2167e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  # The number of bytes for encoding the length of the message.
2177e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  total_size += _VarUInt64ByteSizeNoTag(message_size)
2187e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2197e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  # The size of the message.
2207e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  total_size += message_size
2217e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return total_size
2227e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2237e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2247e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef TagByteSize(field_number):
2257e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """Returns the bytes required to serialize a tag with this field number."""
2267e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  # Just pass in type 0, since the type won't affect the tag+type size.
2277e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return _VarUInt64ByteSizeNoTag(PackTag(field_number, 0))
2287e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2297e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2307e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# Private helper function for the *ByteSize() functions above.
2317e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2327e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef _VarUInt64ByteSizeNoTag(uint64):
2337e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """Returns the number of bytes required to serialize a single varint
2347e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  using boundary value comparisons. (unrolled loop optimization -WPierce)
2357e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  uint64 must be unsigned.
2367e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """
2377e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  if uint64 <= 0x7f: return 1
2387e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  if uint64 <= 0x3fff: return 2
2397e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  if uint64 <= 0x1fffff: return 3
2407e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  if uint64 <= 0xfffffff: return 4
2417e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  if uint64 <= 0x7ffffffff: return 5
2427e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  if uint64 <= 0x3ffffffffff: return 6
2437e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  if uint64 <= 0x1ffffffffffff: return 7
2447e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  if uint64 <= 0xffffffffffffff: return 8
2457e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  if uint64 <= 0x7fffffffffffffff: return 9
2467e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  if uint64 > UINT64_MAX:
2477e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    raise message.EncodeError('Value out of range: %d' % uint64)
2487e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return 10
2497e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2507e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2517e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangNON_PACKABLE_TYPES = (
2527e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  descriptor.FieldDescriptor.TYPE_STRING,
2537e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  descriptor.FieldDescriptor.TYPE_GROUP,
2547e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  descriptor.FieldDescriptor.TYPE_MESSAGE,
2557e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  descriptor.FieldDescriptor.TYPE_BYTES
2567e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang)
2577e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2587e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2597e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef IsTypePackable(field_type):
2607e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """Return true iff packable = true is valid for fields of this type.
2617e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2627e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  Args:
2637e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    field_type: a FieldDescriptor::Type value.
2647e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2657e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  Returns:
2667e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    True iff fields of this type are packable.
2677e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """
2687e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return field_type not in NON_PACKABLE_TYPES
269