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