blob: aaf7a844de2edd732d3ccb09561ec38e1b470c37 [file] [log] [blame]
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -07001# Protocol Buffers - Google's data interchange format
2# Copyright 2008 Google Inc. All rights reserved.
3# http://code.google.com/p/protobuf/
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met:
8#
9# * Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11# * Redistributions in binary form must reproduce the above
12# copyright notice, this list of conditions and the following disclaimer
13# in the documentation and/or other materials provided with the
14# distribution.
15# * Neither the name of Google Inc. nor the names of its
16# contributors may be used to endorse or promote products derived from
17# this software without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31"""Provides type checking routines.
32
33This module defines type checking utilities in the forms of dictionaries:
34
35VALUE_CHECKERS: A dictionary of field types and a value validation object.
36TYPE_TO_BYTE_SIZE_FN: A dictionary with field types and a size computing
37 function.
38TYPE_TO_SERIALIZE_METHOD: A dictionary with field types and serialization
39 function.
40FIELD_TYPE_TO_WIRE_TYPE: A dictionary with field typed and their
41 coresponding wire types.
42TYPE_TO_DESERIALIZE_METHOD: A dictionary with field types and deserialization
43 function.
44"""
45
46__author__ = 'robinson@google.com (Will Robinson)'
47
48from froofle.protobuf.internal import decoder
49from froofle.protobuf.internal import encoder
50from froofle.protobuf.internal import wire_format
51from froofle.protobuf import descriptor
52
53_FieldDescriptor = descriptor.FieldDescriptor
54
55
56def GetTypeChecker(cpp_type, field_type):
57 """Returns a type checker for a message field of the specified types.
58
59 Args:
60 cpp_type: C++ type of the field (see descriptor.py).
61 field_type: Protocol message field type (see descriptor.py).
62
63 Returns:
64 An instance of TypeChecker which can be used to verify the types
65 of values assigned to a field of the specified type.
66 """
67 if (cpp_type == _FieldDescriptor.CPPTYPE_STRING and
68 field_type == _FieldDescriptor.TYPE_STRING):
69 return UnicodeValueChecker()
70 return _VALUE_CHECKERS[cpp_type]
71
72
73# None of the typecheckers below make any attempt to guard against people
74# subclassing builtin types and doing weird things. We're not trying to
75# protect against malicious clients here, just people accidentally shooting
76# themselves in the foot in obvious ways.
77
78class TypeChecker(object):
79
80 """Type checker used to catch type errors as early as possible
81 when the client is setting scalar fields in protocol messages.
82 """
83
84 def __init__(self, *acceptable_types):
85 self._acceptable_types = acceptable_types
86
87 def CheckValue(self, proposed_value):
88 if not isinstance(proposed_value, self._acceptable_types):
89 message = ('%.1024r has type %s, but expected one of: %s' %
90 (proposed_value, type(proposed_value), self._acceptable_types))
91 raise TypeError(message)
92
93
94# IntValueChecker and its subclasses perform integer type-checks
95# and bounds-checks.
96class IntValueChecker(object):
97
98 """Checker used for integer fields. Performs type-check and range check."""
99
100 def CheckValue(self, proposed_value):
101 if not isinstance(proposed_value, (int, long)):
102 message = ('%.1024r has type %s, but expected one of: %s' %
103 (proposed_value, type(proposed_value), (int, long)))
104 raise TypeError(message)
105 if not self._MIN <= proposed_value <= self._MAX:
106 raise ValueError('Value out of range: %d' % proposed_value)
107
108
109class UnicodeValueChecker(object):
110
111 """Checker used for string fields."""
112
113 def CheckValue(self, proposed_value):
114 if not isinstance(proposed_value, (str, unicode)):
115 message = ('%.1024r has type %s, but expected one of: %s' %
116 (proposed_value, type(proposed_value), (str, unicode)))
117 raise TypeError(message)
118
119 # If the value is of type 'str' make sure that it is in 7-bit ASCII
120 # encoding.
121 if isinstance(proposed_value, str):
122 try:
123 unicode(proposed_value, 'ascii')
124 except UnicodeDecodeError:
125 raise ValueError('%.1024r isn\'t in 7-bit ASCII encoding.'
126 % (proposed_value))
127
128
129class Int32ValueChecker(IntValueChecker):
130 # We're sure to use ints instead of longs here since comparison may be more
131 # efficient.
132 _MIN = -2147483648
133 _MAX = 2147483647
134
135
136class Uint32ValueChecker(IntValueChecker):
137 _MIN = 0
138 _MAX = (1 << 32) - 1
139
140
141class Int64ValueChecker(IntValueChecker):
142 _MIN = -(1 << 63)
143 _MAX = (1 << 63) - 1
144
145
146class Uint64ValueChecker(IntValueChecker):
147 _MIN = 0
148 _MAX = (1 << 64) - 1
149
150
151# Type-checkers for all scalar CPPTYPEs.
152_VALUE_CHECKERS = {
153 _FieldDescriptor.CPPTYPE_INT32: Int32ValueChecker(),
154 _FieldDescriptor.CPPTYPE_INT64: Int64ValueChecker(),
155 _FieldDescriptor.CPPTYPE_UINT32: Uint32ValueChecker(),
156 _FieldDescriptor.CPPTYPE_UINT64: Uint64ValueChecker(),
157 _FieldDescriptor.CPPTYPE_DOUBLE: TypeChecker(
158 float, int, long),
159 _FieldDescriptor.CPPTYPE_FLOAT: TypeChecker(
160 float, int, long),
161 _FieldDescriptor.CPPTYPE_BOOL: TypeChecker(bool, int),
162 _FieldDescriptor.CPPTYPE_ENUM: Int32ValueChecker(),
163 _FieldDescriptor.CPPTYPE_STRING: TypeChecker(str),
164 }
165
166
167# Map from field type to a function F, such that F(field_num, value)
168# gives the total byte size for a value of the given type. This
169# byte size includes tag information and any other additional space
170# associated with serializing "value".
171TYPE_TO_BYTE_SIZE_FN = {
172 _FieldDescriptor.TYPE_DOUBLE: wire_format.DoubleByteSize,
173 _FieldDescriptor.TYPE_FLOAT: wire_format.FloatByteSize,
174 _FieldDescriptor.TYPE_INT64: wire_format.Int64ByteSize,
175 _FieldDescriptor.TYPE_UINT64: wire_format.UInt64ByteSize,
176 _FieldDescriptor.TYPE_INT32: wire_format.Int32ByteSize,
177 _FieldDescriptor.TYPE_FIXED64: wire_format.Fixed64ByteSize,
178 _FieldDescriptor.TYPE_FIXED32: wire_format.Fixed32ByteSize,
179 _FieldDescriptor.TYPE_BOOL: wire_format.BoolByteSize,
180 _FieldDescriptor.TYPE_STRING: wire_format.StringByteSize,
181 _FieldDescriptor.TYPE_GROUP: wire_format.GroupByteSize,
182 _FieldDescriptor.TYPE_MESSAGE: wire_format.MessageByteSize,
183 _FieldDescriptor.TYPE_BYTES: wire_format.BytesByteSize,
184 _FieldDescriptor.TYPE_UINT32: wire_format.UInt32ByteSize,
185 _FieldDescriptor.TYPE_ENUM: wire_format.EnumByteSize,
186 _FieldDescriptor.TYPE_SFIXED32: wire_format.SFixed32ByteSize,
187 _FieldDescriptor.TYPE_SFIXED64: wire_format.SFixed64ByteSize,
188 _FieldDescriptor.TYPE_SINT32: wire_format.SInt32ByteSize,
189 _FieldDescriptor.TYPE_SINT64: wire_format.SInt64ByteSize
190 }
191
192
193# Maps from field type to an unbound Encoder method F, such that
194# F(encoder, field_number, value) will append the serialization
195# of a value of this type to the encoder.
196_Encoder = encoder.Encoder
197TYPE_TO_SERIALIZE_METHOD = {
198 _FieldDescriptor.TYPE_DOUBLE: _Encoder.AppendDouble,
199 _FieldDescriptor.TYPE_FLOAT: _Encoder.AppendFloat,
200 _FieldDescriptor.TYPE_INT64: _Encoder.AppendInt64,
201 _FieldDescriptor.TYPE_UINT64: _Encoder.AppendUInt64,
202 _FieldDescriptor.TYPE_INT32: _Encoder.AppendInt32,
203 _FieldDescriptor.TYPE_FIXED64: _Encoder.AppendFixed64,
204 _FieldDescriptor.TYPE_FIXED32: _Encoder.AppendFixed32,
205 _FieldDescriptor.TYPE_BOOL: _Encoder.AppendBool,
206 _FieldDescriptor.TYPE_STRING: _Encoder.AppendString,
207 _FieldDescriptor.TYPE_GROUP: _Encoder.AppendGroup,
208 _FieldDescriptor.TYPE_MESSAGE: _Encoder.AppendMessage,
209 _FieldDescriptor.TYPE_BYTES: _Encoder.AppendBytes,
210 _FieldDescriptor.TYPE_UINT32: _Encoder.AppendUInt32,
211 _FieldDescriptor.TYPE_ENUM: _Encoder.AppendEnum,
212 _FieldDescriptor.TYPE_SFIXED32: _Encoder.AppendSFixed32,
213 _FieldDescriptor.TYPE_SFIXED64: _Encoder.AppendSFixed64,
214 _FieldDescriptor.TYPE_SINT32: _Encoder.AppendSInt32,
215 _FieldDescriptor.TYPE_SINT64: _Encoder.AppendSInt64,
216 }
217
218
219# Maps from field type to expected wiretype.
220FIELD_TYPE_TO_WIRE_TYPE = {
221 _FieldDescriptor.TYPE_DOUBLE: wire_format.WIRETYPE_FIXED64,
222 _FieldDescriptor.TYPE_FLOAT: wire_format.WIRETYPE_FIXED32,
223 _FieldDescriptor.TYPE_INT64: wire_format.WIRETYPE_VARINT,
224 _FieldDescriptor.TYPE_UINT64: wire_format.WIRETYPE_VARINT,
225 _FieldDescriptor.TYPE_INT32: wire_format.WIRETYPE_VARINT,
226 _FieldDescriptor.TYPE_FIXED64: wire_format.WIRETYPE_FIXED64,
227 _FieldDescriptor.TYPE_FIXED32: wire_format.WIRETYPE_FIXED32,
228 _FieldDescriptor.TYPE_BOOL: wire_format.WIRETYPE_VARINT,
229 _FieldDescriptor.TYPE_STRING:
230 wire_format.WIRETYPE_LENGTH_DELIMITED,
231 _FieldDescriptor.TYPE_GROUP: wire_format.WIRETYPE_START_GROUP,
232 _FieldDescriptor.TYPE_MESSAGE:
233 wire_format.WIRETYPE_LENGTH_DELIMITED,
234 _FieldDescriptor.TYPE_BYTES:
235 wire_format.WIRETYPE_LENGTH_DELIMITED,
236 _FieldDescriptor.TYPE_UINT32: wire_format.WIRETYPE_VARINT,
237 _FieldDescriptor.TYPE_ENUM: wire_format.WIRETYPE_VARINT,
238 _FieldDescriptor.TYPE_SFIXED32: wire_format.WIRETYPE_FIXED32,
239 _FieldDescriptor.TYPE_SFIXED64: wire_format.WIRETYPE_FIXED64,
240 _FieldDescriptor.TYPE_SINT32: wire_format.WIRETYPE_VARINT,
241 _FieldDescriptor.TYPE_SINT64: wire_format.WIRETYPE_VARINT,
242 }
243
244
245# Maps from field type to an unbound Decoder method F,
246# such that F(decoder) will read a field of the requested type.
247#
248# Note that Message and Group are intentionally missing here.
249# They're handled by _RecursivelyMerge().
250_Decoder = decoder.Decoder
251TYPE_TO_DESERIALIZE_METHOD = {
252 _FieldDescriptor.TYPE_DOUBLE: _Decoder.ReadDouble,
253 _FieldDescriptor.TYPE_FLOAT: _Decoder.ReadFloat,
254 _FieldDescriptor.TYPE_INT64: _Decoder.ReadInt64,
255 _FieldDescriptor.TYPE_UINT64: _Decoder.ReadUInt64,
256 _FieldDescriptor.TYPE_INT32: _Decoder.ReadInt32,
257 _FieldDescriptor.TYPE_FIXED64: _Decoder.ReadFixed64,
258 _FieldDescriptor.TYPE_FIXED32: _Decoder.ReadFixed32,
259 _FieldDescriptor.TYPE_BOOL: _Decoder.ReadBool,
260 _FieldDescriptor.TYPE_STRING: _Decoder.ReadString,
261 _FieldDescriptor.TYPE_BYTES: _Decoder.ReadBytes,
262 _FieldDescriptor.TYPE_UINT32: _Decoder.ReadUInt32,
263 _FieldDescriptor.TYPE_ENUM: _Decoder.ReadEnum,
264 _FieldDescriptor.TYPE_SFIXED32: _Decoder.ReadSFixed32,
265 _FieldDescriptor.TYPE_SFIXED64: _Decoder.ReadSFixed64,
266 _FieldDescriptor.TYPE_SINT32: _Decoder.ReadSInt32,
267 _FieldDescriptor.TYPE_SINT64: _Decoder.ReadSInt64,
268 }