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