Home | History | Annotate | Download | only in internal
      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 """Provides type checking routines.
     32 
     33 This module defines type checking utilities in the forms of dictionaries:
     34 
     35 VALUE_CHECKERS: A dictionary of field types and a value validation object.
     36 TYPE_TO_BYTE_SIZE_FN: A dictionary with field types and a size computing
     37   function.
     38 TYPE_TO_SERIALIZE_METHOD: A dictionary with field types and serialization
     39   function.
     40 FIELD_TYPE_TO_WIRE_TYPE: A dictionary with field typed and their
     41   coresponding wire types.
     42 TYPE_TO_DESERIALIZE_METHOD: A dictionary with field types and deserialization
     43   function.
     44 """
     45 
     46 __author__ = 'robinson (at] google.com (Will Robinson)'
     47 
     48 from google.protobuf.internal import decoder
     49 from google.protobuf.internal import encoder
     50 from google.protobuf.internal import wire_format
     51 from google.protobuf import descriptor
     52 
     53 _FieldDescriptor = descriptor.FieldDescriptor
     54 
     55 
     56 def 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 
     78 class 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.
     96 class 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 
    109 class 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 has type str, but isn\'t in 7-bit ASCII '
    126                          'encoding. Non-ASCII strings must be converted to '
    127                          'unicode objects before being added.' %
    128                          (proposed_value))
    129 
    130 
    131 class Int32ValueChecker(IntValueChecker):
    132   # We're sure to use ints instead of longs here since comparison may be more
    133   # efficient.
    134   _MIN = -2147483648
    135   _MAX = 2147483647
    136 
    137 
    138 class Uint32ValueChecker(IntValueChecker):
    139   _MIN = 0
    140   _MAX = (1 << 32) - 1
    141 
    142 
    143 class Int64ValueChecker(IntValueChecker):
    144   _MIN = -(1 << 63)
    145   _MAX = (1 << 63) - 1
    146 
    147 
    148 class Uint64ValueChecker(IntValueChecker):
    149   _MIN = 0
    150   _MAX = (1 << 64) - 1
    151 
    152 
    153 # Type-checkers for all scalar CPPTYPEs.
    154 _VALUE_CHECKERS = {
    155     _FieldDescriptor.CPPTYPE_INT32: Int32ValueChecker(),
    156     _FieldDescriptor.CPPTYPE_INT64: Int64ValueChecker(),
    157     _FieldDescriptor.CPPTYPE_UINT32: Uint32ValueChecker(),
    158     _FieldDescriptor.CPPTYPE_UINT64: Uint64ValueChecker(),
    159     _FieldDescriptor.CPPTYPE_DOUBLE: TypeChecker(
    160         float, int, long),
    161     _FieldDescriptor.CPPTYPE_FLOAT: TypeChecker(
    162         float, int, long),
    163     _FieldDescriptor.CPPTYPE_BOOL: TypeChecker(bool, int),
    164     _FieldDescriptor.CPPTYPE_ENUM: Int32ValueChecker(),
    165     _FieldDescriptor.CPPTYPE_STRING: TypeChecker(str),
    166     }
    167 
    168 
    169 # Map from field type to a function F, such that F(field_num, value)
    170 # gives the total byte size for a value of the given type.  This
    171 # byte size includes tag information and any other additional space
    172 # associated with serializing "value".
    173 TYPE_TO_BYTE_SIZE_FN = {
    174     _FieldDescriptor.TYPE_DOUBLE: wire_format.DoubleByteSize,
    175     _FieldDescriptor.TYPE_FLOAT: wire_format.FloatByteSize,
    176     _FieldDescriptor.TYPE_INT64: wire_format.Int64ByteSize,
    177     _FieldDescriptor.TYPE_UINT64: wire_format.UInt64ByteSize,
    178     _FieldDescriptor.TYPE_INT32: wire_format.Int32ByteSize,
    179     _FieldDescriptor.TYPE_FIXED64: wire_format.Fixed64ByteSize,
    180     _FieldDescriptor.TYPE_FIXED32: wire_format.Fixed32ByteSize,
    181     _FieldDescriptor.TYPE_BOOL: wire_format.BoolByteSize,
    182     _FieldDescriptor.TYPE_STRING: wire_format.StringByteSize,
    183     _FieldDescriptor.TYPE_GROUP: wire_format.GroupByteSize,
    184     _FieldDescriptor.TYPE_MESSAGE: wire_format.MessageByteSize,
    185     _FieldDescriptor.TYPE_BYTES: wire_format.BytesByteSize,
    186     _FieldDescriptor.TYPE_UINT32: wire_format.UInt32ByteSize,
    187     _FieldDescriptor.TYPE_ENUM: wire_format.EnumByteSize,
    188     _FieldDescriptor.TYPE_SFIXED32: wire_format.SFixed32ByteSize,
    189     _FieldDescriptor.TYPE_SFIXED64: wire_format.SFixed64ByteSize,
    190     _FieldDescriptor.TYPE_SINT32: wire_format.SInt32ByteSize,
    191     _FieldDescriptor.TYPE_SINT64: wire_format.SInt64ByteSize
    192     }
    193 
    194 
    195 # Maps from field types to encoder constructors.
    196 TYPE_TO_ENCODER = {
    197     _FieldDescriptor.TYPE_DOUBLE: encoder.DoubleEncoder,
    198     _FieldDescriptor.TYPE_FLOAT: encoder.FloatEncoder,
    199     _FieldDescriptor.TYPE_INT64: encoder.Int64Encoder,
    200     _FieldDescriptor.TYPE_UINT64: encoder.UInt64Encoder,
    201     _FieldDescriptor.TYPE_INT32: encoder.Int32Encoder,
    202     _FieldDescriptor.TYPE_FIXED64: encoder.Fixed64Encoder,
    203     _FieldDescriptor.TYPE_FIXED32: encoder.Fixed32Encoder,
    204     _FieldDescriptor.TYPE_BOOL: encoder.BoolEncoder,
    205     _FieldDescriptor.TYPE_STRING: encoder.StringEncoder,
    206     _FieldDescriptor.TYPE_GROUP: encoder.GroupEncoder,
    207     _FieldDescriptor.TYPE_MESSAGE: encoder.MessageEncoder,
    208     _FieldDescriptor.TYPE_BYTES: encoder.BytesEncoder,
    209     _FieldDescriptor.TYPE_UINT32: encoder.UInt32Encoder,
    210     _FieldDescriptor.TYPE_ENUM: encoder.EnumEncoder,
    211     _FieldDescriptor.TYPE_SFIXED32: encoder.SFixed32Encoder,
    212     _FieldDescriptor.TYPE_SFIXED64: encoder.SFixed64Encoder,
    213     _FieldDescriptor.TYPE_SINT32: encoder.SInt32Encoder,
    214     _FieldDescriptor.TYPE_SINT64: encoder.SInt64Encoder,
    215     }
    216 
    217 
    218 # Maps from field types to sizer constructors.
    219 TYPE_TO_SIZER = {
    220     _FieldDescriptor.TYPE_DOUBLE: encoder.DoubleSizer,
    221     _FieldDescriptor.TYPE_FLOAT: encoder.FloatSizer,
    222     _FieldDescriptor.TYPE_INT64: encoder.Int64Sizer,
    223     _FieldDescriptor.TYPE_UINT64: encoder.UInt64Sizer,
    224     _FieldDescriptor.TYPE_INT32: encoder.Int32Sizer,
    225     _FieldDescriptor.TYPE_FIXED64: encoder.Fixed64Sizer,
    226     _FieldDescriptor.TYPE_FIXED32: encoder.Fixed32Sizer,
    227     _FieldDescriptor.TYPE_BOOL: encoder.BoolSizer,
    228     _FieldDescriptor.TYPE_STRING: encoder.StringSizer,
    229     _FieldDescriptor.TYPE_GROUP: encoder.GroupSizer,
    230     _FieldDescriptor.TYPE_MESSAGE: encoder.MessageSizer,
    231     _FieldDescriptor.TYPE_BYTES: encoder.BytesSizer,
    232     _FieldDescriptor.TYPE_UINT32: encoder.UInt32Sizer,
    233     _FieldDescriptor.TYPE_ENUM: encoder.EnumSizer,
    234     _FieldDescriptor.TYPE_SFIXED32: encoder.SFixed32Sizer,
    235     _FieldDescriptor.TYPE_SFIXED64: encoder.SFixed64Sizer,
    236     _FieldDescriptor.TYPE_SINT32: encoder.SInt32Sizer,
    237     _FieldDescriptor.TYPE_SINT64: encoder.SInt64Sizer,
    238     }
    239 
    240 
    241 # Maps from field type to a decoder constructor.
    242 TYPE_TO_DECODER = {
    243     _FieldDescriptor.TYPE_DOUBLE: decoder.DoubleDecoder,
    244     _FieldDescriptor.TYPE_FLOAT: decoder.FloatDecoder,
    245     _FieldDescriptor.TYPE_INT64: decoder.Int64Decoder,
    246     _FieldDescriptor.TYPE_UINT64: decoder.UInt64Decoder,
    247     _FieldDescriptor.TYPE_INT32: decoder.Int32Decoder,
    248     _FieldDescriptor.TYPE_FIXED64: decoder.Fixed64Decoder,
    249     _FieldDescriptor.TYPE_FIXED32: decoder.Fixed32Decoder,
    250     _FieldDescriptor.TYPE_BOOL: decoder.BoolDecoder,
    251     _FieldDescriptor.TYPE_STRING: decoder.StringDecoder,
    252     _FieldDescriptor.TYPE_GROUP: decoder.GroupDecoder,
    253     _FieldDescriptor.TYPE_MESSAGE: decoder.MessageDecoder,
    254     _FieldDescriptor.TYPE_BYTES: decoder.BytesDecoder,
    255     _FieldDescriptor.TYPE_UINT32: decoder.UInt32Decoder,
    256     _FieldDescriptor.TYPE_ENUM: decoder.EnumDecoder,
    257     _FieldDescriptor.TYPE_SFIXED32: decoder.SFixed32Decoder,
    258     _FieldDescriptor.TYPE_SFIXED64: decoder.SFixed64Decoder,
    259     _FieldDescriptor.TYPE_SINT32: decoder.SInt32Decoder,
    260     _FieldDescriptor.TYPE_SINT64: decoder.SInt64Decoder,
    261     }
    262 
    263 # Maps from field type to expected wiretype.
    264 FIELD_TYPE_TO_WIRE_TYPE = {
    265     _FieldDescriptor.TYPE_DOUBLE: wire_format.WIRETYPE_FIXED64,
    266     _FieldDescriptor.TYPE_FLOAT: wire_format.WIRETYPE_FIXED32,
    267     _FieldDescriptor.TYPE_INT64: wire_format.WIRETYPE_VARINT,
    268     _FieldDescriptor.TYPE_UINT64: wire_format.WIRETYPE_VARINT,
    269     _FieldDescriptor.TYPE_INT32: wire_format.WIRETYPE_VARINT,
    270     _FieldDescriptor.TYPE_FIXED64: wire_format.WIRETYPE_FIXED64,
    271     _FieldDescriptor.TYPE_FIXED32: wire_format.WIRETYPE_FIXED32,
    272     _FieldDescriptor.TYPE_BOOL: wire_format.WIRETYPE_VARINT,
    273     _FieldDescriptor.TYPE_STRING:
    274       wire_format.WIRETYPE_LENGTH_DELIMITED,
    275     _FieldDescriptor.TYPE_GROUP: wire_format.WIRETYPE_START_GROUP,
    276     _FieldDescriptor.TYPE_MESSAGE:
    277       wire_format.WIRETYPE_LENGTH_DELIMITED,
    278     _FieldDescriptor.TYPE_BYTES:
    279       wire_format.WIRETYPE_LENGTH_DELIMITED,
    280     _FieldDescriptor.TYPE_UINT32: wire_format.WIRETYPE_VARINT,
    281     _FieldDescriptor.TYPE_ENUM: wire_format.WIRETYPE_VARINT,
    282     _FieldDescriptor.TYPE_SFIXED32: wire_format.WIRETYPE_FIXED32,
    283     _FieldDescriptor.TYPE_SFIXED64: wire_format.WIRETYPE_FIXED64,
    284     _FieldDescriptor.TYPE_SINT32: wire_format.WIRETYPE_VARINT,
    285     _FieldDescriptor.TYPE_SINT64: wire_format.WIRETYPE_VARINT,
    286     }
    287