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 |