The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 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@google.com (Will Robinson)' |
| 47 | |
| 48 | from froofle.protobuf.internal import decoder |
| 49 | from froofle.protobuf.internal import encoder |
| 50 | from froofle.protobuf.internal import wire_format |
| 51 | from froofle.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 isn\'t in 7-bit ASCII encoding.' |
| 126 | % (proposed_value)) |
| 127 | |
| 128 | |
| 129 | class 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 | |
| 136 | class Uint32ValueChecker(IntValueChecker): |
| 137 | _MIN = 0 |
| 138 | _MAX = (1 << 32) - 1 |
| 139 | |
| 140 | |
| 141 | class Int64ValueChecker(IntValueChecker): |
| 142 | _MIN = -(1 << 63) |
| 143 | _MAX = (1 << 63) - 1 |
| 144 | |
| 145 | |
| 146 | class 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". |
| 171 | TYPE_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 |
| 197 | TYPE_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. |
| 220 | FIELD_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 |
| 251 | TYPE_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 | } |