| OLD | NEW |
| (Empty) |
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 # Use of this source code is governed by a BSD-style license that can be | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 """ | |
| 6 The descriptors used to define generated elements of the mojo python bindings. | |
| 7 """ | |
| 8 | |
| 9 import array | |
| 10 import itertools | |
| 11 import struct | |
| 12 | |
| 13 import mojo_bindings.reflection as reflection | |
| 14 import mojo_bindings.serialization as serialization | |
| 15 | |
| 16 # pylint: disable=E0611,F0401 | |
| 17 import mojo_system | |
| 18 | |
| 19 | |
| 20 class Type(object): | |
| 21 """Describes the type of a struct field or a method parameter,""" | |
| 22 | |
| 23 def Convert(self, value): # pylint: disable=R0201 | |
| 24 """ | |
| 25 Convert the given value into its canonical representation, raising an | |
| 26 exception if the value cannot be converted. | |
| 27 """ | |
| 28 return value | |
| 29 | |
| 30 def GetDefaultValue(self, value): | |
| 31 """ | |
| 32 Returns the default value for this type associated with the given value. | |
| 33 This method must be able to correcly handle value being None. | |
| 34 """ | |
| 35 return self.Convert(value) | |
| 36 | |
| 37 def IsUnion(self): | |
| 38 """ | |
| 39 Returns true if the type is a union. This is necessary to be able to | |
| 40 identify a union when descriptor.py cannot be imported. | |
| 41 """ | |
| 42 return False | |
| 43 | |
| 44 | |
| 45 class SerializableType(Type): | |
| 46 """Describe a type that can be serialized by itself.""" | |
| 47 | |
| 48 def __init__(self, typecode): | |
| 49 Type.__init__(self) | |
| 50 self.typecode = typecode | |
| 51 self.byte_size = struct.calcsize('<%s' % self.GetTypeCode()) | |
| 52 | |
| 53 def GetTypeCode(self): | |
| 54 """ | |
| 55 Returns the type code (as defined by the struct module) used to encode | |
| 56 this type. | |
| 57 """ | |
| 58 return self.typecode | |
| 59 | |
| 60 def GetByteSize(self): | |
| 61 """ | |
| 62 Returns the size of the encoding of this type. | |
| 63 """ | |
| 64 return self.byte_size | |
| 65 | |
| 66 def GetAlignment(self): | |
| 67 """ | |
| 68 Returns the alignment required by the encoding of this type. By default it | |
| 69 is set to the byte size of the biggest packed value. | |
| 70 """ | |
| 71 return max([struct.calcsize('<%s' % c) for c in self.GetTypeCode()]) | |
| 72 | |
| 73 def Serialize(self, value, data_offset, data, handle_offset): | |
| 74 """ | |
| 75 Serialize a value of this type. | |
| 76 | |
| 77 Args: | |
| 78 value: the value to serialize. | |
| 79 data_offset: the offset to the end of the data bytearray. Used to encode | |
| 80 pointers. | |
| 81 data: the bytearray to append additional data to. | |
| 82 handle_offset: the offset to use to encode handles. | |
| 83 | |
| 84 Returns a a tuple where the first element is the value to encode, and the | |
| 85 second is the array of handles to add to the message. | |
| 86 """ | |
| 87 raise NotImplementedError() | |
| 88 | |
| 89 def Deserialize(self, value, context): | |
| 90 """ | |
| 91 Deserialize a value of this type. | |
| 92 | |
| 93 Args: | |
| 94 value: the base value for this type. This is always a numeric type, and | |
| 95 corresponds to the first element in the tuple returned by | |
| 96 Serialize. | |
| 97 data: the bytearray to retrieve additional data from. | |
| 98 handles: the array of handles contained in the message to deserialize. | |
| 99 | |
| 100 Returns the deserialized value. | |
| 101 """ | |
| 102 raise NotImplementedError() | |
| 103 | |
| 104 | |
| 105 class BooleanType(SerializableType): | |
| 106 """Type object for booleans""" | |
| 107 | |
| 108 def Convert(self, value): | |
| 109 return bool(value) | |
| 110 | |
| 111 def Serialize(self, value, data_offset, data, handle_offset): | |
| 112 return (_ConvertBooleansToByte([value]), []) | |
| 113 | |
| 114 def Deserialize(self, value, context): | |
| 115 return _ConvertByteToBooleans(value, 1)[0] | |
| 116 | |
| 117 | |
| 118 class NumericType(SerializableType): | |
| 119 """Base Type object for all numeric types""" | |
| 120 | |
| 121 def GetDefaultValue(self, value): | |
| 122 if value is None: | |
| 123 return self.Convert(0) | |
| 124 return self.Convert(value) | |
| 125 | |
| 126 def Serialize(self, value, data_offset, data, handle_offset): | |
| 127 return (value, []) | |
| 128 | |
| 129 def Deserialize(self, value, context): | |
| 130 return value | |
| 131 | |
| 132 | |
| 133 class IntegerType(NumericType): | |
| 134 """Type object for integer types.""" | |
| 135 | |
| 136 def __init__(self, typecode): | |
| 137 NumericType.__init__(self, typecode) | |
| 138 size = 8 * self.byte_size | |
| 139 signed = typecode.islower() | |
| 140 if signed: | |
| 141 self._min_value = -(1 << (size - 1)) | |
| 142 self._max_value = (1 << (size - 1)) - 1 | |
| 143 else: | |
| 144 self._min_value = 0 | |
| 145 self._max_value = (1 << size) - 1 | |
| 146 | |
| 147 def Convert(self, value): | |
| 148 if value is None: | |
| 149 raise TypeError('None is not an integer.') | |
| 150 if not isinstance(value, (int, long)): | |
| 151 raise TypeError('%r is not an integer type' % value) | |
| 152 if value < self._min_value or value > self._max_value: | |
| 153 raise OverflowError('%r is not in the range [%d, %d]' % | |
| 154 (value, self._min_value, self._max_value)) | |
| 155 return value | |
| 156 | |
| 157 | |
| 158 class FloatType(NumericType): | |
| 159 """Type object for floating point number types.""" | |
| 160 | |
| 161 def Convert(self, value): | |
| 162 if value is None: | |
| 163 raise TypeError('None is not an floating point number.') | |
| 164 if not isinstance(value, (int, long, float)): | |
| 165 raise TypeError('%r is not a numeric type' % value) | |
| 166 return float(value) | |
| 167 | |
| 168 | |
| 169 class UnionType(SerializableType): | |
| 170 """Base Type object for union.""" | |
| 171 | |
| 172 def __init__(self, union_type_getter, nullable=False): | |
| 173 SerializableType.__init__(self, 'IIQ') | |
| 174 self.nullable = nullable | |
| 175 self._union_type_getter = union_type_getter | |
| 176 self._union_type = None | |
| 177 | |
| 178 def IsUnion(self): | |
| 179 return True | |
| 180 | |
| 181 @property | |
| 182 def union_type(self): | |
| 183 if not self._union_type: | |
| 184 self._union_type = self._union_type_getter() | |
| 185 return self._union_type | |
| 186 | |
| 187 def Serialize(self, value, data_offset, data, handle_offset): | |
| 188 if not value: | |
| 189 if not self.nullable: | |
| 190 raise serialization.SerializationException( | |
| 191 'Trying to serialize null for non nullable type.') | |
| 192 return ((0, 0, 0), []) | |
| 193 | |
| 194 ((size, tag, entry, new_data), new_handles) = ( | |
| 195 value.SerializeInline(handle_offset)) | |
| 196 if len(new_data) > 0: | |
| 197 data.extend(new_data) | |
| 198 entry = data_offset - 8 | |
| 199 | |
| 200 return ((size, tag, entry), new_handles) | |
| 201 | |
| 202 def Deserialize(self, value, context): | |
| 203 result = self.union_type.Deserialize(context) | |
| 204 if not result and not self.nullable: | |
| 205 raise serialization.DeserializationException( | |
| 206 'Trying to deserialize null for non nullable type.') | |
| 207 return result | |
| 208 | |
| 209 | |
| 210 class PointerType(SerializableType): | |
| 211 """Base Type object for pointers.""" | |
| 212 | |
| 213 def __init__(self, nullable=False): | |
| 214 SerializableType.__init__(self, 'Q') | |
| 215 self.nullable = nullable | |
| 216 | |
| 217 def Serialize(self, value, data_offset, data, handle_offset): | |
| 218 if value is None and not self.nullable: | |
| 219 raise serialization.SerializationException( | |
| 220 'Trying to serialize null for non nullable type.') | |
| 221 if value is None: | |
| 222 return (0, []) | |
| 223 return self.SerializePointer(value, data_offset, data, handle_offset) | |
| 224 | |
| 225 def Deserialize(self, value, context): | |
| 226 if value == 0: | |
| 227 if not self.nullable: | |
| 228 raise serialization.DeserializationException( | |
| 229 'Trying to deserialize null for non nullable type.') | |
| 230 return None | |
| 231 if value % 8 != 0: | |
| 232 raise serialization.DeserializationException( | |
| 233 'Pointer alignment is incorrect.') | |
| 234 sub_context = context.GetSubContext(value) | |
| 235 if len(sub_context.data) < serialization.HEADER_STRUCT.size: | |
| 236 raise serialization.DeserializationException( | |
| 237 'Available data too short to contain header.') | |
| 238 (size, nb_elements) = serialization.HEADER_STRUCT.unpack_from( | |
| 239 sub_context.data) | |
| 240 if len(sub_context.data) < size or size < serialization.HEADER_STRUCT.size: | |
| 241 raise serialization.DeserializationException('Header size is incorrect.') | |
| 242 sub_context.ClaimMemory(0, size) | |
| 243 return self.DeserializePointer(size, nb_elements, sub_context) | |
| 244 | |
| 245 def SerializePointer(self, value, data_offset, data, handle_offset): | |
| 246 """Serialize the not null value.""" | |
| 247 raise NotImplementedError() | |
| 248 | |
| 249 def DeserializePointer(self, size, nb_elements, context): | |
| 250 raise NotImplementedError() | |
| 251 | |
| 252 | |
| 253 class StringType(PointerType): | |
| 254 """ | |
| 255 Type object for strings. | |
| 256 | |
| 257 Strings are represented as unicode, and the conversion is done using the | |
| 258 default encoding if a string instance is used. | |
| 259 """ | |
| 260 | |
| 261 def __init__(self, nullable=False): | |
| 262 PointerType.__init__(self, nullable) | |
| 263 self._array_type = NativeArrayType('B', nullable) | |
| 264 | |
| 265 def Convert(self, value): | |
| 266 if value is None or isinstance(value, unicode): | |
| 267 return value | |
| 268 if isinstance(value, str): | |
| 269 return unicode(value) | |
| 270 raise TypeError('%r is not a string' % value) | |
| 271 | |
| 272 def SerializePointer(self, value, data_offset, data, handle_offset): | |
| 273 string_array = array.array('b') | |
| 274 string_array.fromstring(value.encode('utf8')) | |
| 275 return self._array_type.SerializeArray( | |
| 276 string_array, data_offset, data, handle_offset) | |
| 277 | |
| 278 def DeserializePointer(self, size, nb_elements, context): | |
| 279 string_array = self._array_type.DeserializeArray(size, nb_elements, context) | |
| 280 return unicode(string_array.tostring(), 'utf8') | |
| 281 | |
| 282 | |
| 283 class BaseHandleType(SerializableType): | |
| 284 """Type object for handles.""" | |
| 285 | |
| 286 def __init__(self, nullable=False, type_code='i'): | |
| 287 SerializableType.__init__(self, type_code) | |
| 288 self.nullable = nullable | |
| 289 | |
| 290 def Serialize(self, value, data_offset, data, handle_offset): | |
| 291 handle = self.ToHandle(value) | |
| 292 if not handle.IsValid() and not self.nullable: | |
| 293 raise serialization.SerializationException( | |
| 294 'Trying to serialize null for non nullable type.') | |
| 295 if not handle.IsValid(): | |
| 296 return (-1, []) | |
| 297 return (handle_offset, [handle]) | |
| 298 | |
| 299 def Deserialize(self, value, context): | |
| 300 if value == -1: | |
| 301 if not self.nullable: | |
| 302 raise serialization.DeserializationException( | |
| 303 'Trying to deserialize null for non nullable type.') | |
| 304 return self.FromHandle(mojo_system.Handle()) | |
| 305 return self.FromHandle(context.ClaimHandle(value)) | |
| 306 | |
| 307 def FromHandle(self, handle): | |
| 308 raise NotImplementedError() | |
| 309 | |
| 310 def ToHandle(self, value): | |
| 311 raise NotImplementedError() | |
| 312 | |
| 313 | |
| 314 class HandleType(BaseHandleType): | |
| 315 """Type object for handles.""" | |
| 316 | |
| 317 def Convert(self, value): | |
| 318 if value is None: | |
| 319 return mojo_system.Handle() | |
| 320 if not isinstance(value, mojo_system.Handle): | |
| 321 raise TypeError('%r is not a handle' % value) | |
| 322 return value | |
| 323 | |
| 324 def FromHandle(self, handle): | |
| 325 return handle | |
| 326 | |
| 327 def ToHandle(self, value): | |
| 328 return value | |
| 329 | |
| 330 | |
| 331 class InterfaceRequestType(BaseHandleType): | |
| 332 """Type object for interface requests.""" | |
| 333 | |
| 334 def Convert(self, value): | |
| 335 if value is None: | |
| 336 return reflection.InterfaceRequest(mojo_system.Handle()) | |
| 337 if not isinstance(value, reflection.InterfaceRequest): | |
| 338 raise TypeError('%r is not an interface request' % value) | |
| 339 return value | |
| 340 | |
| 341 def FromHandle(self, handle): | |
| 342 return reflection.InterfaceRequest(handle) | |
| 343 | |
| 344 def ToHandle(self, value): | |
| 345 return value.PassMessagePipe() | |
| 346 | |
| 347 | |
| 348 class InterfaceType(BaseHandleType): | |
| 349 """Type object for interfaces.""" | |
| 350 | |
| 351 def __init__(self, interface_getter, nullable=False): | |
| 352 # handle (4 bytes) + version (4 bytes) | |
| 353 BaseHandleType.__init__(self, nullable, 'iI') | |
| 354 self._interface_getter = interface_getter | |
| 355 self._interface = None | |
| 356 | |
| 357 def Convert(self, value): | |
| 358 if value is None or isinstance(value, self.interface): | |
| 359 return value | |
| 360 raise TypeError('%r is not an instance of ' % self.interface) | |
| 361 | |
| 362 @property | |
| 363 def interface(self): | |
| 364 if not self._interface: | |
| 365 self._interface = self._interface_getter() | |
| 366 return self._interface | |
| 367 | |
| 368 def Serialize(self, value, data_offset, data, handle_offset): | |
| 369 (encoded_handle, handles) = super(InterfaceType, self).Serialize( | |
| 370 value, data_offset, data, handle_offset) | |
| 371 if encoded_handle == -1: | |
| 372 version = 0 | |
| 373 else: | |
| 374 version = self.interface.manager.version | |
| 375 if value and isinstance(value, reflection.InterfaceProxy): | |
| 376 version = value.manager.version | |
| 377 return ((encoded_handle, version), handles) | |
| 378 | |
| 379 def Deserialize(self, value, context): | |
| 380 proxy = super(InterfaceType, self).Deserialize(value[0], context) | |
| 381 if proxy: | |
| 382 proxy.manager.version = value[1] | |
| 383 return proxy | |
| 384 | |
| 385 def FromHandle(self, handle): | |
| 386 if handle.IsValid(): | |
| 387 return self.interface.manager.Proxy(handle) | |
| 388 return None | |
| 389 | |
| 390 def ToHandle(self, value): | |
| 391 if not value: | |
| 392 return mojo_system.Handle() | |
| 393 if isinstance(value, reflection.InterfaceProxy): | |
| 394 return value.manager.PassMessagePipe() | |
| 395 pipe = mojo_system.MessagePipe() | |
| 396 self.interface.manager.Bind(value, pipe.handle0) | |
| 397 return pipe.handle1 | |
| 398 | |
| 399 | |
| 400 class BaseArrayType(PointerType): | |
| 401 """Abstract Type object for arrays.""" | |
| 402 | |
| 403 def __init__(self, nullable=False, length=0): | |
| 404 PointerType.__init__(self, nullable) | |
| 405 self.length = length | |
| 406 | |
| 407 def SerializePointer(self, value, data_offset, data, handle_offset): | |
| 408 if self.length != 0 and len(value) != self.length: | |
| 409 raise serialization.SerializationException('Incorrect array size') | |
| 410 return self.SerializeArray(value, data_offset, data, handle_offset) | |
| 411 | |
| 412 def SerializeArray(self, value, data_offset, data, handle_offset): | |
| 413 """Serialize the not null array.""" | |
| 414 raise NotImplementedError() | |
| 415 | |
| 416 def DeserializePointer(self, size, nb_elements, context): | |
| 417 if self.length != 0 and nb_elements != self.length: | |
| 418 raise serialization.DeserializationException('Incorrect array size') | |
| 419 if (size < | |
| 420 serialization.HEADER_STRUCT.size + self.SizeForLength(nb_elements)): | |
| 421 raise serialization.DeserializationException('Incorrect array size') | |
| 422 return self.DeserializeArray(size, nb_elements, context) | |
| 423 | |
| 424 def DeserializeArray(self, size, nb_elements, context): | |
| 425 raise NotImplementedError() | |
| 426 | |
| 427 def SizeForLength(self, nb_elements): | |
| 428 raise NotImplementedError() | |
| 429 | |
| 430 | |
| 431 class BooleanArrayType(BaseArrayType): | |
| 432 | |
| 433 def __init__(self, nullable=False, length=0): | |
| 434 BaseArrayType.__init__(self, nullable, length) | |
| 435 self._array_type = NativeArrayType('B', nullable) | |
| 436 | |
| 437 def Convert(self, value): | |
| 438 if value is None: | |
| 439 return value | |
| 440 return [TYPE_BOOL.Convert(x) for x in value] | |
| 441 | |
| 442 def SerializeArray(self, value, data_offset, data, handle_offset): | |
| 443 groups = [value[i:i+8] for i in range(0, len(value), 8)] | |
| 444 converted = array.array('B', [_ConvertBooleansToByte(x) for x in groups]) | |
| 445 return _SerializeNativeArray(converted, data_offset, data, len(value)) | |
| 446 | |
| 447 def DeserializeArray(self, size, nb_elements, context): | |
| 448 converted = self._array_type.DeserializeArray(size, nb_elements, context) | |
| 449 elements = list(itertools.islice( | |
| 450 itertools.chain.from_iterable( | |
| 451 [_ConvertByteToBooleans(x, 8) for x in converted]), | |
| 452 0, | |
| 453 nb_elements)) | |
| 454 return elements | |
| 455 | |
| 456 def SizeForLength(self, nb_elements): | |
| 457 return (nb_elements + 7) // 8 | |
| 458 | |
| 459 | |
| 460 class GenericArrayType(BaseArrayType): | |
| 461 """Type object for arrays of pointers.""" | |
| 462 | |
| 463 def __init__(self, sub_type, nullable=False, length=0): | |
| 464 BaseArrayType.__init__(self, nullable, length) | |
| 465 assert isinstance(sub_type, SerializableType) | |
| 466 self.sub_type = sub_type | |
| 467 | |
| 468 def Convert(self, value): | |
| 469 if value is None: | |
| 470 return value | |
| 471 return [self.sub_type.Convert(x) for x in value] | |
| 472 | |
| 473 def SerializeArray(self, value, data_offset, data, handle_offset): | |
| 474 size = (serialization.HEADER_STRUCT.size + | |
| 475 self.sub_type.GetByteSize() * len(value)) | |
| 476 data_end = len(data) | |
| 477 position = len(data) + serialization.HEADER_STRUCT.size | |
| 478 data.extend(bytearray(size + | |
| 479 serialization.NeededPaddingForAlignment(size))) | |
| 480 returned_handles = [] | |
| 481 to_pack = [] | |
| 482 for item in value: | |
| 483 (new_data, new_handles) = self.sub_type.Serialize( | |
| 484 item, | |
| 485 len(data) - position, | |
| 486 data, | |
| 487 handle_offset + len(returned_handles)) | |
| 488 to_pack.extend(serialization.Flatten(new_data)) | |
| 489 returned_handles.extend(new_handles) | |
| 490 position = position + self.sub_type.GetByteSize() | |
| 491 | |
| 492 serialization.HEADER_STRUCT.pack_into(data, data_end, size, len(value)) | |
| 493 # TODO(azani): Refactor so we don't have to create big formatting strings. | |
| 494 struct.pack_into(('%s' % self.sub_type.GetTypeCode()) * len(value), | |
| 495 data, | |
| 496 data_end + serialization.HEADER_STRUCT.size, | |
| 497 *to_pack) | |
| 498 return (data_offset, returned_handles) | |
| 499 | |
| 500 def DeserializeArray(self, size, nb_elements, context): | |
| 501 # TODO(azani): Refactor so the format string isn't so big. | |
| 502 values = struct.unpack_from( | |
| 503 nb_elements * self.sub_type.GetTypeCode(), | |
| 504 buffer(context.data, serialization.HEADER_STRUCT.size)) | |
| 505 values_per_element = len(self.sub_type.GetTypeCode()) | |
| 506 assert nb_elements * values_per_element == len(values) | |
| 507 | |
| 508 result = [] | |
| 509 sub_context = context.GetSubContext(serialization.HEADER_STRUCT.size) | |
| 510 for index in xrange(nb_elements): | |
| 511 if values_per_element == 1: | |
| 512 value = values[index] | |
| 513 else: | |
| 514 value = tuple(values[index * values_per_element : | |
| 515 (index + 1) * values_per_element]) | |
| 516 result.append(self.sub_type.Deserialize( | |
| 517 value, | |
| 518 sub_context)) | |
| 519 sub_context = sub_context.GetSubContext(self.sub_type.GetByteSize()) | |
| 520 return result | |
| 521 | |
| 522 def SizeForLength(self, nb_elements): | |
| 523 return nb_elements * self.sub_type.GetByteSize(); | |
| 524 | |
| 525 | |
| 526 class NativeArrayType(BaseArrayType): | |
| 527 """Type object for arrays of native types.""" | |
| 528 | |
| 529 def __init__(self, typecode, nullable=False, length=0): | |
| 530 BaseArrayType.__init__(self, nullable, length) | |
| 531 self.array_typecode = typecode | |
| 532 self.element_size = struct.calcsize('<%s' % self.array_typecode) | |
| 533 | |
| 534 def Convert(self, value): | |
| 535 if value is None: | |
| 536 return value | |
| 537 if (isinstance(value, array.array) and | |
| 538 value.array_typecode == self.array_typecode): | |
| 539 return value | |
| 540 return array.array(self.array_typecode, value) | |
| 541 | |
| 542 def SerializeArray(self, value, data_offset, data, handle_offset): | |
| 543 return _SerializeNativeArray(value, data_offset, data, len(value)) | |
| 544 | |
| 545 def DeserializeArray(self, size, nb_elements, context): | |
| 546 result = array.array(self.array_typecode) | |
| 547 result.fromstring(buffer(context.data, | |
| 548 serialization.HEADER_STRUCT.size, | |
| 549 size - serialization.HEADER_STRUCT.size)) | |
| 550 return result | |
| 551 | |
| 552 def SizeForLength(self, nb_elements): | |
| 553 return nb_elements * self.element_size | |
| 554 | |
| 555 | |
| 556 class StructType(PointerType): | |
| 557 """Type object for structs.""" | |
| 558 | |
| 559 def __init__(self, struct_type_getter, nullable=False): | |
| 560 PointerType.__init__(self) | |
| 561 self._struct_type_getter = struct_type_getter | |
| 562 self._struct_type = None | |
| 563 self.nullable = nullable | |
| 564 | |
| 565 @property | |
| 566 def struct_type(self): | |
| 567 if not self._struct_type: | |
| 568 self._struct_type = self._struct_type_getter() | |
| 569 return self._struct_type | |
| 570 | |
| 571 def Convert(self, value): | |
| 572 if value is None or isinstance(value, self.struct_type): | |
| 573 return value | |
| 574 raise TypeError('%r is not an instance of %r' % (value, self.struct_type)) | |
| 575 | |
| 576 def GetDefaultValue(self, value): | |
| 577 if value: | |
| 578 return self.struct_type() | |
| 579 return None | |
| 580 | |
| 581 def SerializePointer(self, value, data_offset, data, handle_offset): | |
| 582 (new_data, new_handles) = value.Serialize(handle_offset) | |
| 583 data.extend(new_data) | |
| 584 return (data_offset, new_handles) | |
| 585 | |
| 586 def DeserializePointer(self, size, nb_elements, context): | |
| 587 return self.struct_type.Deserialize(context) | |
| 588 | |
| 589 | |
| 590 class MapType(SerializableType): | |
| 591 """Type objects for maps.""" | |
| 592 | |
| 593 def __init__(self, key_type, value_type, nullable=False): | |
| 594 self._key_type = key_type | |
| 595 self._value_type = value_type | |
| 596 dictionary = { | |
| 597 '__metaclass__': reflection.MojoStructType, | |
| 598 '__module__': __name__, | |
| 599 'DESCRIPTOR': { | |
| 600 'fields': [ | |
| 601 SingleFieldGroup('keys', MapType._GetArrayType(key_type), 0, 0), | |
| 602 SingleFieldGroup('values', MapType._GetArrayType(value_type), 1, 0), | |
| 603 ], | |
| 604 } | |
| 605 } | |
| 606 self.struct = reflection.MojoStructType('MapStruct', (object,), dictionary) | |
| 607 self.struct_type = StructType(lambda: self.struct, nullable) | |
| 608 SerializableType.__init__(self, self.struct_type.typecode) | |
| 609 | |
| 610 def Convert(self, value): | |
| 611 if value is None: | |
| 612 return value | |
| 613 if isinstance(value, dict): | |
| 614 return dict([(self._key_type.Convert(x), self._value_type.Convert(y)) for | |
| 615 x, y in value.iteritems()]) | |
| 616 raise TypeError('%r is not a dictionary.') | |
| 617 | |
| 618 def Serialize(self, value, data_offset, data, handle_offset): | |
| 619 s = None | |
| 620 if value is not None: | |
| 621 keys, values = [], [] | |
| 622 for key, value in value.iteritems(): | |
| 623 keys.append(key) | |
| 624 values.append(value) | |
| 625 s = self.struct(keys=keys, values=values) | |
| 626 return self.struct_type.Serialize(s, data_offset, data, handle_offset) | |
| 627 | |
| 628 def Deserialize(self, value, context): | |
| 629 s = self.struct_type.Deserialize(value, context) | |
| 630 if s: | |
| 631 if len(s.keys) != len(s.values): | |
| 632 raise serialization.DeserializationException( | |
| 633 'keys and values do not have the same length.') | |
| 634 return dict(zip(s.keys, s.values)) | |
| 635 return None | |
| 636 | |
| 637 @staticmethod | |
| 638 def _GetArrayType(t): | |
| 639 if t == TYPE_BOOL: | |
| 640 return BooleanArrayType() | |
| 641 else: | |
| 642 return GenericArrayType(t) | |
| 643 | |
| 644 | |
| 645 TYPE_BOOL = BooleanType('B') | |
| 646 | |
| 647 TYPE_INT8 = IntegerType('b') | |
| 648 TYPE_INT16 = IntegerType('h') | |
| 649 TYPE_INT32 = IntegerType('i') | |
| 650 TYPE_INT64 = IntegerType('q') | |
| 651 | |
| 652 TYPE_UINT8 = IntegerType('B') | |
| 653 TYPE_UINT16 = IntegerType('H') | |
| 654 TYPE_UINT32 = IntegerType('I') | |
| 655 TYPE_UINT64 = IntegerType('Q') | |
| 656 | |
| 657 TYPE_FLOAT = FloatType('f') | |
| 658 TYPE_DOUBLE = FloatType('d') | |
| 659 | |
| 660 TYPE_STRING = StringType() | |
| 661 TYPE_NULLABLE_STRING = StringType(True) | |
| 662 | |
| 663 TYPE_HANDLE = HandleType() | |
| 664 TYPE_NULLABLE_HANDLE = HandleType(True) | |
| 665 | |
| 666 TYPE_INTERFACE_REQUEST = InterfaceRequestType() | |
| 667 TYPE_NULLABLE_INTERFACE_REQUEST = InterfaceRequestType(True) | |
| 668 | |
| 669 | |
| 670 class FieldDescriptor(object): | |
| 671 """Describes a field in a generated struct.""" | |
| 672 | |
| 673 def __init__(self, name, field_type, index, version, default_value=None): | |
| 674 self.name = name | |
| 675 self.field_type = field_type | |
| 676 self.version = version | |
| 677 self.index = index | |
| 678 self._default_value = default_value | |
| 679 | |
| 680 def GetDefaultValue(self): | |
| 681 return self.field_type.GetDefaultValue(self._default_value) | |
| 682 | |
| 683 | |
| 684 class FieldGroup(object): | |
| 685 """ | |
| 686 Describe a list of field in the generated struct that must be | |
| 687 serialized/deserialized together. | |
| 688 """ | |
| 689 def __init__(self, descriptors): | |
| 690 self.descriptors = descriptors | |
| 691 | |
| 692 def GetDescriptors(self): | |
| 693 return self.descriptors | |
| 694 | |
| 695 def GetTypeCode(self): | |
| 696 raise NotImplementedError() | |
| 697 | |
| 698 def GetByteSize(self): | |
| 699 raise NotImplementedError() | |
| 700 | |
| 701 def GetAlignment(self): | |
| 702 raise NotImplementedError() | |
| 703 | |
| 704 def GetMinVersion(self): | |
| 705 raise NotImplementedError() | |
| 706 | |
| 707 def GetMaxVersion(self): | |
| 708 raise NotImplementedError() | |
| 709 | |
| 710 def Serialize(self, obj, data_offset, data, handle_offset): | |
| 711 raise NotImplementedError() | |
| 712 | |
| 713 def Deserialize(self, value, context): | |
| 714 raise NotImplementedError() | |
| 715 | |
| 716 def Filter(self, version): | |
| 717 raise NotImplementedError() | |
| 718 | |
| 719 | |
| 720 class SingleFieldGroup(FieldGroup, FieldDescriptor): | |
| 721 """A FieldGroup that contains a single FieldDescriptor.""" | |
| 722 | |
| 723 def __init__(self, name, field_type, index, version, default_value=None): | |
| 724 FieldDescriptor.__init__( | |
| 725 self, name, field_type, index, version, default_value) | |
| 726 FieldGroup.__init__(self, [self]) | |
| 727 | |
| 728 def GetTypeCode(self): | |
| 729 return self.field_type.GetTypeCode() | |
| 730 | |
| 731 def GetByteSize(self): | |
| 732 return self.field_type.GetByteSize() | |
| 733 | |
| 734 def GetAlignment(self): | |
| 735 return self.field_type.GetAlignment() | |
| 736 | |
| 737 def GetMinVersion(self): | |
| 738 return self.version | |
| 739 | |
| 740 def GetMaxVersion(self): | |
| 741 return self.version | |
| 742 | |
| 743 def Serialize(self, obj, data_offset, data, handle_offset): | |
| 744 value = getattr(obj, self.name) | |
| 745 return self.field_type.Serialize(value, data_offset, data, handle_offset) | |
| 746 | |
| 747 def Deserialize(self, value, context): | |
| 748 entity = self.field_type.Deserialize(value, context) | |
| 749 return { self.name: entity } | |
| 750 | |
| 751 def Filter(self, version): | |
| 752 return self | |
| 753 | |
| 754 | |
| 755 class BooleanGroup(FieldGroup): | |
| 756 """A FieldGroup to pack booleans.""" | |
| 757 def __init__(self, descriptors): | |
| 758 FieldGroup.__init__(self, descriptors) | |
| 759 self.min_version = min([descriptor.version for descriptor in descriptors]) | |
| 760 self.max_version = max([descriptor.version for descriptor in descriptors]) | |
| 761 | |
| 762 def GetTypeCode(self): | |
| 763 return 'B' | |
| 764 | |
| 765 def GetByteSize(self): | |
| 766 return 1 | |
| 767 | |
| 768 def GetAlignment(self): | |
| 769 return 1 | |
| 770 | |
| 771 def GetMinVersion(self): | |
| 772 return self.min_version | |
| 773 | |
| 774 def GetMaxVersion(self): | |
| 775 return self.max_version | |
| 776 | |
| 777 def Serialize(self, obj, data_offset, data, handle_offset): | |
| 778 value = _ConvertBooleansToByte( | |
| 779 [getattr(obj, field.name) for field in self.GetDescriptors()]) | |
| 780 return (value, []) | |
| 781 | |
| 782 def Deserialize(self, value, context): | |
| 783 values = itertools.izip_longest([x.name for x in self.descriptors], | |
| 784 _ConvertByteToBooleans(value), | |
| 785 fillvalue=False) | |
| 786 return dict(values) | |
| 787 | |
| 788 def Filter(self, version): | |
| 789 return BooleanGroup( | |
| 790 filter(lambda d: d.version <= version, self.descriptors)) | |
| 791 | |
| 792 | |
| 793 def _SerializeNativeArray(value, data_offset, data, length): | |
| 794 data_size = len(data) | |
| 795 data.extend(bytearray(serialization.HEADER_STRUCT.size)) | |
| 796 data.extend(buffer(value)) | |
| 797 data_length = len(data) - data_size | |
| 798 data.extend(bytearray(serialization.NeededPaddingForAlignment(data_length))) | |
| 799 serialization.HEADER_STRUCT.pack_into(data, data_size, data_length, length) | |
| 800 return (data_offset, []) | |
| 801 | |
| 802 | |
| 803 def _ConvertBooleansToByte(booleans): | |
| 804 """Pack a list of booleans into an integer.""" | |
| 805 return reduce(lambda x, y: x * 2 + y, reversed(booleans), 0) | |
| 806 | |
| 807 | |
| 808 def _ConvertByteToBooleans(value, min_size=0): | |
| 809 """Unpack an integer into a list of booleans.""" | |
| 810 res = [] | |
| 811 while value: | |
| 812 res.append(bool(value&1)) | |
| 813 value = value / 2 | |
| 814 res.extend([False] * (min_size - len(res))) | |
| 815 return res | |
| OLD | NEW |