1 # Protocol Buffers - Google's data interchange format
2 # Copyright 2008 Google Inc.
3 # http://code.google.com/p/protobuf/
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 """Constants and static functions to support protocol buffer wire format."""
19 __author__
= 'robinson@google.com (Will Robinson)'
22 from google
.protobuf
import message
25 TAG_TYPE_BITS
= 3 # Number of bits used to hold type info in a proto tag.
26 _TAG_TYPE_MASK
= (1 << TAG_TYPE_BITS
) - 1 # 0x7
28 # These numbers identify the wire type of a protocol buffer value.
29 # We use the least-significant TAG_TYPE_BITS bits of the varint-encoded
30 # tag-and-type to store one of these WIRETYPE_* constants.
31 # These values must match WireType enum in //net/proto2/public/wire_format.h.
34 WIRETYPE_LENGTH_DELIMITED
= 2
35 WIRETYPE_START_GROUP
= 3
36 WIRETYPE_END_GROUP
= 4
41 # Bounds for various integer types.
42 INT32_MAX
= int((1 << 31) - 1)
43 INT32_MIN
= int(-(1 << 31))
44 UINT32_MAX
= (1 << 32) - 1
46 INT64_MAX
= (1 << 63) - 1
47 INT64_MIN
= -(1 << 63)
48 UINT64_MAX
= (1 << 64) - 1
50 # "struct" format strings that will encode/decode the specified formats.
51 FORMAT_UINT32_LITTLE_ENDIAN
= '<I'
52 FORMAT_UINT64_LITTLE_ENDIAN
= '<Q'
55 # We'll have to provide alternate implementations of AppendLittleEndian*() on
56 # any architectures where these checks fail.
57 if struct
.calcsize(FORMAT_UINT32_LITTLE_ENDIAN
) != 4:
58 raise AssertionError('Format "I" is not a 32-bit number.')
59 if struct
.calcsize(FORMAT_UINT64_LITTLE_ENDIAN
) != 8:
60 raise AssertionError('Format "Q" is not a 64-bit number.')
63 def PackTag(field_number
, wire_type
):
64 """Returns an unsigned 32-bit integer that encodes the field number and
65 wire type information in standard protocol message wire format.
68 field_number: Expected to be an integer in the range [1, 1 << 29)
69 wire_type: One of the WIRETYPE_* constants.
71 if not 0 <= wire_type
<= _WIRETYPE_MAX
:
72 raise message
.EncodeError('Unknown wire type: %d' % wire_type
)
73 return (field_number
<< TAG_TYPE_BITS
) | wire_type
77 """The inverse of PackTag(). Given an unsigned 32-bit number,
78 returns a (field_number, wire_type) tuple.
80 return (tag
>> TAG_TYPE_BITS
), (tag
& _TAG_TYPE_MASK
)
83 def ZigZagEncode(value
):
84 """ZigZag Transform: Encodes signed integers so that they can be
85 effectively used with varint encoding. See wire_format.h for
90 return ((value
<< 1) ^
(~
0)) |
0x1
93 def ZigZagDecode(value
):
94 """Inverse of ZigZagEncode()."""
97 return (value
>> 1) ^
(~
0)
101 # The *ByteSize() functions below return the number of bytes required to
102 # serialize "field number + type" information and then serialize the value.
105 def Int32ByteSize(field_number
, int32
):
106 return Int64ByteSize(field_number
, int32
)
109 def Int64ByteSize(field_number
, int64
):
110 # Have to convert to uint before calling UInt64ByteSize().
111 return UInt64ByteSize(field_number
, 0xffffffffffffffff & int64
)
114 def UInt32ByteSize(field_number
, uint32
):
115 return UInt64ByteSize(field_number
, uint32
)
118 def UInt64ByteSize(field_number
, uint64
):
119 return _TagByteSize(field_number
) + _VarUInt64ByteSizeNoTag(uint64
)
122 def SInt32ByteSize(field_number
, int32
):
123 return UInt32ByteSize(field_number
, ZigZagEncode(int32
))
126 def SInt64ByteSize(field_number
, int64
):
127 return UInt64ByteSize(field_number
, ZigZagEncode(int64
))
130 def Fixed32ByteSize(field_number
, fixed32
):
131 return _TagByteSize(field_number
) + 4
134 def Fixed64ByteSize(field_number
, fixed64
):
135 return _TagByteSize(field_number
) + 8
138 def SFixed32ByteSize(field_number
, sfixed32
):
139 return _TagByteSize(field_number
) + 4
142 def SFixed64ByteSize(field_number
, sfixed64
):
143 return _TagByteSize(field_number
) + 8
146 def FloatByteSize(field_number
, flt
):
147 return _TagByteSize(field_number
) + 4
150 def DoubleByteSize(field_number
, double
):
151 return _TagByteSize(field_number
) + 8
154 def BoolByteSize(field_number
, b
):
155 return _TagByteSize(field_number
) + 1
158 def EnumByteSize(field_number
, enum
):
159 return UInt32ByteSize(field_number
, enum
)
162 def StringByteSize(field_number
, string
):
163 return (_TagByteSize(field_number
)
164 + _VarUInt64ByteSizeNoTag(len(string
))
168 def BytesByteSize(field_number
, b
):
169 return StringByteSize(field_number
, b
)
172 def GroupByteSize(field_number
, message
):
173 return (2 * _TagByteSize(field_number
) # START and END group.
174 + message
.ByteSize())
177 def MessageByteSize(field_number
, message
):
178 return (_TagByteSize(field_number
)
179 + _VarUInt64ByteSizeNoTag(message
.ByteSize())
180 + message
.ByteSize())
183 def MessageSetItemByteSize(field_number
, msg
):
184 # First compute the sizes of the tags.
185 # There are 2 tags for the beginning and ending of the repeated group, that
186 # is field number 1, one with field number 2 (type_id) and one with field
187 # number 3 (message).
188 total_size
= (2 * _TagByteSize(1) + _TagByteSize(2) + _TagByteSize(3))
190 # Add the number of bytes for type_id.
191 total_size
+= _VarUInt64ByteSizeNoTag(field_number
)
193 message_size
= msg
.ByteSize()
195 # The number of bytes for encoding the length of the message.
196 total_size
+= _VarUInt64ByteSizeNoTag(message_size
)
198 # The size of the message.
199 total_size
+= message_size
203 # Private helper functions for the *ByteSize() functions above.
206 def _TagByteSize(field_number
):
207 """Returns the bytes required to serialize a tag with this field number."""
208 # Just pass in type 0, since the type won't affect the tag+type size.
209 return _VarUInt64ByteSizeNoTag(PackTag(field_number
, 0))
212 def _VarUInt64ByteSizeNoTag(uint64
):
213 """Returns the bytes required to serialize a single varint.
214 uint64 must be unsigned.
216 if uint64
> UINT64_MAX
:
217 raise message
.EncodeError('Value out of range: %d' % uint64
)