OLD | NEW |
| (Empty) |
1 # 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 #PY25 compatible for GAE. | |
32 # | |
33 # Copyright 2008 Google Inc. All Rights Reserved. | |
34 | |
35 """Provides type checking routines. | |
36 | |
37 This module defines type checking utilities in the forms of dictionaries: | |
38 | |
39 VALUE_CHECKERS: A dictionary of field types and a value validation object. | |
40 TYPE_TO_BYTE_SIZE_FN: A dictionary with field types and a size computing | |
41 function. | |
42 TYPE_TO_SERIALIZE_METHOD: A dictionary with field types and serialization | |
43 function. | |
44 FIELD_TYPE_TO_WIRE_TYPE: A dictionary with field typed and their | |
45 coresponding wire types. | |
46 TYPE_TO_DESERIALIZE_METHOD: A dictionary with field types and deserialization | |
47 function. | |
48 """ | |
49 | |
50 __author__ = 'robinson@google.com (Will Robinson)' | |
51 | |
52 import sys ##PY25 | |
53 if sys.version < '2.6': bytes = str ##PY25 | |
54 from google.protobuf.internal import api_implementation | |
55 from google.protobuf.internal import decoder | |
56 from google.protobuf.internal import encoder | |
57 from google.protobuf.internal import wire_format | |
58 from google.protobuf import descriptor | |
59 | |
60 _FieldDescriptor = descriptor.FieldDescriptor | |
61 | |
62 | |
63 def GetTypeChecker(field): | |
64 """Returns a type checker for a message field of the specified types. | |
65 | |
66 Args: | |
67 field: FieldDescriptor object for this field. | |
68 | |
69 Returns: | |
70 An instance of TypeChecker which can be used to verify the types | |
71 of values assigned to a field of the specified type. | |
72 """ | |
73 if (field.cpp_type == _FieldDescriptor.CPPTYPE_STRING and | |
74 field.type == _FieldDescriptor.TYPE_STRING): | |
75 return UnicodeValueChecker() | |
76 if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM: | |
77 return EnumValueChecker(field.enum_type) | |
78 return _VALUE_CHECKERS[field.cpp_type] | |
79 | |
80 | |
81 # None of the typecheckers below make any attempt to guard against people | |
82 # subclassing builtin types and doing weird things. We're not trying to | |
83 # protect against malicious clients here, just people accidentally shooting | |
84 # themselves in the foot in obvious ways. | |
85 | |
86 class TypeChecker(object): | |
87 | |
88 """Type checker used to catch type errors as early as possible | |
89 when the client is setting scalar fields in protocol messages. | |
90 """ | |
91 | |
92 def __init__(self, *acceptable_types): | |
93 self._acceptable_types = acceptable_types | |
94 | |
95 def CheckValue(self, proposed_value): | |
96 """Type check the provided value and return it. | |
97 | |
98 The returned value might have been normalized to another type. | |
99 """ | |
100 if not isinstance(proposed_value, self._acceptable_types): | |
101 message = ('%.1024r has type %s, but expected one of: %s' % | |
102 (proposed_value, type(proposed_value), self._acceptable_types)) | |
103 raise TypeError(message) | |
104 return proposed_value | |
105 | |
106 | |
107 # IntValueChecker and its subclasses perform integer type-checks | |
108 # and bounds-checks. | |
109 class IntValueChecker(object): | |
110 | |
111 """Checker used for integer fields. Performs type-check and range check.""" | |
112 | |
113 def CheckValue(self, proposed_value): | |
114 if not isinstance(proposed_value, (int, long)): | |
115 message = ('%.1024r has type %s, but expected one of: %s' % | |
116 (proposed_value, type(proposed_value), (int, long))) | |
117 raise TypeError(message) | |
118 if not self._MIN <= proposed_value <= self._MAX: | |
119 raise ValueError('Value out of range: %d' % proposed_value) | |
120 # We force 32-bit values to int and 64-bit values to long to make | |
121 # alternate implementations where the distinction is more significant | |
122 # (e.g. the C++ implementation) simpler. | |
123 proposed_value = self._TYPE(proposed_value) | |
124 return proposed_value | |
125 | |
126 | |
127 class EnumValueChecker(object): | |
128 | |
129 """Checker used for enum fields. Performs type-check and range check.""" | |
130 | |
131 def __init__(self, enum_type): | |
132 self._enum_type = enum_type | |
133 | |
134 def CheckValue(self, proposed_value): | |
135 if not isinstance(proposed_value, (int, long)): | |
136 message = ('%.1024r has type %s, but expected one of: %s' % | |
137 (proposed_value, type(proposed_value), (int, long))) | |
138 raise TypeError(message) | |
139 if proposed_value not in self._enum_type.values_by_number: | |
140 raise ValueError('Unknown enum value: %d' % proposed_value) | |
141 return proposed_value | |
142 | |
143 | |
144 class UnicodeValueChecker(object): | |
145 | |
146 """Checker used for string fields. | |
147 | |
148 Always returns a unicode value, even if the input is of type str. | |
149 """ | |
150 | |
151 def CheckValue(self, proposed_value): | |
152 if not isinstance(proposed_value, (bytes, unicode)): | |
153 message = ('%.1024r has type %s, but expected one of: %s' % | |
154 (proposed_value, type(proposed_value), (bytes, unicode))) | |
155 raise TypeError(message) | |
156 | |
157 # If the value is of type 'bytes' make sure that it is in 7-bit ASCII | |
158 # encoding. | |
159 if isinstance(proposed_value, bytes): | |
160 try: | |
161 proposed_value = proposed_value.decode('ascii') | |
162 except UnicodeDecodeError: | |
163 raise ValueError('%.1024r has type bytes, but isn\'t in 7-bit ASCII ' | |
164 'encoding. Non-ASCII strings must be converted to ' | |
165 'unicode objects before being added.' % | |
166 (proposed_value)) | |
167 return proposed_value | |
168 | |
169 | |
170 class Int32ValueChecker(IntValueChecker): | |
171 # We're sure to use ints instead of longs here since comparison may be more | |
172 # efficient. | |
173 _MIN = -2147483648 | |
174 _MAX = 2147483647 | |
175 _TYPE = int | |
176 | |
177 | |
178 class Uint32ValueChecker(IntValueChecker): | |
179 _MIN = 0 | |
180 _MAX = (1 << 32) - 1 | |
181 _TYPE = int | |
182 | |
183 | |
184 class Int64ValueChecker(IntValueChecker): | |
185 _MIN = -(1 << 63) | |
186 _MAX = (1 << 63) - 1 | |
187 _TYPE = long | |
188 | |
189 | |
190 class Uint64ValueChecker(IntValueChecker): | |
191 _MIN = 0 | |
192 _MAX = (1 << 64) - 1 | |
193 _TYPE = long | |
194 | |
195 | |
196 # Type-checkers for all scalar CPPTYPEs. | |
197 _VALUE_CHECKERS = { | |
198 _FieldDescriptor.CPPTYPE_INT32: Int32ValueChecker(), | |
199 _FieldDescriptor.CPPTYPE_INT64: Int64ValueChecker(), | |
200 _FieldDescriptor.CPPTYPE_UINT32: Uint32ValueChecker(), | |
201 _FieldDescriptor.CPPTYPE_UINT64: Uint64ValueChecker(), | |
202 _FieldDescriptor.CPPTYPE_DOUBLE: TypeChecker( | |
203 float, int, long), | |
204 _FieldDescriptor.CPPTYPE_FLOAT: TypeChecker( | |
205 float, int, long), | |
206 _FieldDescriptor.CPPTYPE_BOOL: TypeChecker(bool, int), | |
207 _FieldDescriptor.CPPTYPE_STRING: TypeChecker(bytes), | |
208 } | |
209 | |
210 | |
211 # Map from field type to a function F, such that F(field_num, value) | |
212 # gives the total byte size for a value of the given type. This | |
213 # byte size includes tag information and any other additional space | |
214 # associated with serializing "value". | |
215 TYPE_TO_BYTE_SIZE_FN = { | |
216 _FieldDescriptor.TYPE_DOUBLE: wire_format.DoubleByteSize, | |
217 _FieldDescriptor.TYPE_FLOAT: wire_format.FloatByteSize, | |
218 _FieldDescriptor.TYPE_INT64: wire_format.Int64ByteSize, | |
219 _FieldDescriptor.TYPE_UINT64: wire_format.UInt64ByteSize, | |
220 _FieldDescriptor.TYPE_INT32: wire_format.Int32ByteSize, | |
221 _FieldDescriptor.TYPE_FIXED64: wire_format.Fixed64ByteSize, | |
222 _FieldDescriptor.TYPE_FIXED32: wire_format.Fixed32ByteSize, | |
223 _FieldDescriptor.TYPE_BOOL: wire_format.BoolByteSize, | |
224 _FieldDescriptor.TYPE_STRING: wire_format.StringByteSize, | |
225 _FieldDescriptor.TYPE_GROUP: wire_format.GroupByteSize, | |
226 _FieldDescriptor.TYPE_MESSAGE: wire_format.MessageByteSize, | |
227 _FieldDescriptor.TYPE_BYTES: wire_format.BytesByteSize, | |
228 _FieldDescriptor.TYPE_UINT32: wire_format.UInt32ByteSize, | |
229 _FieldDescriptor.TYPE_ENUM: wire_format.EnumByteSize, | |
230 _FieldDescriptor.TYPE_SFIXED32: wire_format.SFixed32ByteSize, | |
231 _FieldDescriptor.TYPE_SFIXED64: wire_format.SFixed64ByteSize, | |
232 _FieldDescriptor.TYPE_SINT32: wire_format.SInt32ByteSize, | |
233 _FieldDescriptor.TYPE_SINT64: wire_format.SInt64ByteSize | |
234 } | |
235 | |
236 | |
237 # Maps from field types to encoder constructors. | |
238 TYPE_TO_ENCODER = { | |
239 _FieldDescriptor.TYPE_DOUBLE: encoder.DoubleEncoder, | |
240 _FieldDescriptor.TYPE_FLOAT: encoder.FloatEncoder, | |
241 _FieldDescriptor.TYPE_INT64: encoder.Int64Encoder, | |
242 _FieldDescriptor.TYPE_UINT64: encoder.UInt64Encoder, | |
243 _FieldDescriptor.TYPE_INT32: encoder.Int32Encoder, | |
244 _FieldDescriptor.TYPE_FIXED64: encoder.Fixed64Encoder, | |
245 _FieldDescriptor.TYPE_FIXED32: encoder.Fixed32Encoder, | |
246 _FieldDescriptor.TYPE_BOOL: encoder.BoolEncoder, | |
247 _FieldDescriptor.TYPE_STRING: encoder.StringEncoder, | |
248 _FieldDescriptor.TYPE_GROUP: encoder.GroupEncoder, | |
249 _FieldDescriptor.TYPE_MESSAGE: encoder.MessageEncoder, | |
250 _FieldDescriptor.TYPE_BYTES: encoder.BytesEncoder, | |
251 _FieldDescriptor.TYPE_UINT32: encoder.UInt32Encoder, | |
252 _FieldDescriptor.TYPE_ENUM: encoder.EnumEncoder, | |
253 _FieldDescriptor.TYPE_SFIXED32: encoder.SFixed32Encoder, | |
254 _FieldDescriptor.TYPE_SFIXED64: encoder.SFixed64Encoder, | |
255 _FieldDescriptor.TYPE_SINT32: encoder.SInt32Encoder, | |
256 _FieldDescriptor.TYPE_SINT64: encoder.SInt64Encoder, | |
257 } | |
258 | |
259 | |
260 # Maps from field types to sizer constructors. | |
261 TYPE_TO_SIZER = { | |
262 _FieldDescriptor.TYPE_DOUBLE: encoder.DoubleSizer, | |
263 _FieldDescriptor.TYPE_FLOAT: encoder.FloatSizer, | |
264 _FieldDescriptor.TYPE_INT64: encoder.Int64Sizer, | |
265 _FieldDescriptor.TYPE_UINT64: encoder.UInt64Sizer, | |
266 _FieldDescriptor.TYPE_INT32: encoder.Int32Sizer, | |
267 _FieldDescriptor.TYPE_FIXED64: encoder.Fixed64Sizer, | |
268 _FieldDescriptor.TYPE_FIXED32: encoder.Fixed32Sizer, | |
269 _FieldDescriptor.TYPE_BOOL: encoder.BoolSizer, | |
270 _FieldDescriptor.TYPE_STRING: encoder.StringSizer, | |
271 _FieldDescriptor.TYPE_GROUP: encoder.GroupSizer, | |
272 _FieldDescriptor.TYPE_MESSAGE: encoder.MessageSizer, | |
273 _FieldDescriptor.TYPE_BYTES: encoder.BytesSizer, | |
274 _FieldDescriptor.TYPE_UINT32: encoder.UInt32Sizer, | |
275 _FieldDescriptor.TYPE_ENUM: encoder.EnumSizer, | |
276 _FieldDescriptor.TYPE_SFIXED32: encoder.SFixed32Sizer, | |
277 _FieldDescriptor.TYPE_SFIXED64: encoder.SFixed64Sizer, | |
278 _FieldDescriptor.TYPE_SINT32: encoder.SInt32Sizer, | |
279 _FieldDescriptor.TYPE_SINT64: encoder.SInt64Sizer, | |
280 } | |
281 | |
282 | |
283 # Maps from field type to a decoder constructor. | |
284 TYPE_TO_DECODER = { | |
285 _FieldDescriptor.TYPE_DOUBLE: decoder.DoubleDecoder, | |
286 _FieldDescriptor.TYPE_FLOAT: decoder.FloatDecoder, | |
287 _FieldDescriptor.TYPE_INT64: decoder.Int64Decoder, | |
288 _FieldDescriptor.TYPE_UINT64: decoder.UInt64Decoder, | |
289 _FieldDescriptor.TYPE_INT32: decoder.Int32Decoder, | |
290 _FieldDescriptor.TYPE_FIXED64: decoder.Fixed64Decoder, | |
291 _FieldDescriptor.TYPE_FIXED32: decoder.Fixed32Decoder, | |
292 _FieldDescriptor.TYPE_BOOL: decoder.BoolDecoder, | |
293 _FieldDescriptor.TYPE_STRING: decoder.StringDecoder, | |
294 _FieldDescriptor.TYPE_GROUP: decoder.GroupDecoder, | |
295 _FieldDescriptor.TYPE_MESSAGE: decoder.MessageDecoder, | |
296 _FieldDescriptor.TYPE_BYTES: decoder.BytesDecoder, | |
297 _FieldDescriptor.TYPE_UINT32: decoder.UInt32Decoder, | |
298 _FieldDescriptor.TYPE_ENUM: decoder.EnumDecoder, | |
299 _FieldDescriptor.TYPE_SFIXED32: decoder.SFixed32Decoder, | |
300 _FieldDescriptor.TYPE_SFIXED64: decoder.SFixed64Decoder, | |
301 _FieldDescriptor.TYPE_SINT32: decoder.SInt32Decoder, | |
302 _FieldDescriptor.TYPE_SINT64: decoder.SInt64Decoder, | |
303 } | |
304 | |
305 # Maps from field type to expected wiretype. | |
306 FIELD_TYPE_TO_WIRE_TYPE = { | |
307 _FieldDescriptor.TYPE_DOUBLE: wire_format.WIRETYPE_FIXED64, | |
308 _FieldDescriptor.TYPE_FLOAT: wire_format.WIRETYPE_FIXED32, | |
309 _FieldDescriptor.TYPE_INT64: wire_format.WIRETYPE_VARINT, | |
310 _FieldDescriptor.TYPE_UINT64: wire_format.WIRETYPE_VARINT, | |
311 _FieldDescriptor.TYPE_INT32: wire_format.WIRETYPE_VARINT, | |
312 _FieldDescriptor.TYPE_FIXED64: wire_format.WIRETYPE_FIXED64, | |
313 _FieldDescriptor.TYPE_FIXED32: wire_format.WIRETYPE_FIXED32, | |
314 _FieldDescriptor.TYPE_BOOL: wire_format.WIRETYPE_VARINT, | |
315 _FieldDescriptor.TYPE_STRING: | |
316 wire_format.WIRETYPE_LENGTH_DELIMITED, | |
317 _FieldDescriptor.TYPE_GROUP: wire_format.WIRETYPE_START_GROUP, | |
318 _FieldDescriptor.TYPE_MESSAGE: | |
319 wire_format.WIRETYPE_LENGTH_DELIMITED, | |
320 _FieldDescriptor.TYPE_BYTES: | |
321 wire_format.WIRETYPE_LENGTH_DELIMITED, | |
322 _FieldDescriptor.TYPE_UINT32: wire_format.WIRETYPE_VARINT, | |
323 _FieldDescriptor.TYPE_ENUM: wire_format.WIRETYPE_VARINT, | |
324 _FieldDescriptor.TYPE_SFIXED32: wire_format.WIRETYPE_FIXED32, | |
325 _FieldDescriptor.TYPE_SFIXED64: wire_format.WIRETYPE_FIXED64, | |
326 _FieldDescriptor.TYPE_SINT32: wire_format.WIRETYPE_VARINT, | |
327 _FieldDescriptor.TYPE_SINT64: wire_format.WIRETYPE_VARINT, | |
328 } | |
OLD | NEW |