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 |