Index: mojo/public/python/mojo_bindings/serialization.py |
diff --git a/mojo/public/python/mojo_bindings/serialization.py b/mojo/public/python/mojo_bindings/serialization.py |
index 32f60f066dbad9a320b08fb40b81d59532f60433..b84bfc1124bef6e4991669942f3d6e2254e02d8c 100644 |
--- a/mojo/public/python/mojo_bindings/serialization.py |
+++ b/mojo/public/python/mojo_bindings/serialization.py |
@@ -7,9 +7,12 @@ |
import struct |
-# Format of a header for a struct or an array. |
+# Format of a header for a struct, array or union. |
HEADER_STRUCT = struct.Struct("<II") |
+# Format for a pointer. |
+POINTER_STRUCT = struct.Struct("<Q") |
+ |
def Flatten(value): |
"""Flattens nested lists/tuples into an one-level list. If value is not a |
@@ -218,3 +221,69 @@ def _GetStruct(groups): |
if alignment_needed: |
codes.append('x' * alignment_needed) |
return struct.Struct(''.join(codes)) |
+ |
+ |
+class UnionSerializer(object): |
qsr
2015/07/17 10:53:58
This code needs comments. I find it really hard to
azani
2015/07/17 20:38:15
I have added some comments. Let me know if they pr
|
+ """ |
+ Helper class to serialize/deserialize a union. |
+ """ |
+ def __init__(self, fields): |
+ self._fields = {field.index: field for field in fields} |
+ |
+ def SerializeInline(self, union, handle_offset): |
+ data = bytearray() |
+ field = self._fields[union.tag] |
+ |
+ (entry, handles) = field.field_type.Serialize( |
+ union.data, 8, data, handle_offset) |
+ |
+ if hasattr(field.field_type, 'union_type'): |
qsr
2015/07/17 10:53:58
If you cannot do usual instanceof calls, then adds
azani
2015/07/17 20:38:15
Done.
|
+ nested_union = bytearray(16) |
+ HEADER_STRUCT.pack_into(nested_union, 0, entry[0], entry[1]) |
+ POINTER_STRUCT.pack_into(nested_union, 8, entry[2]) |
+ |
+ data = nested_union + data |
+ entry = 8 |
+ |
+ return (16, union.tag, entry, data), handles |
qsr
2015/07/17 10:53:58
I am clearly missing something.
Let say that you
azani
2015/07/17 20:38:16
In your exampled Serialize is PointerType.Serializ
|
+ |
+ def Serialize(self, union, handle_offset): |
+ (size, tag, entry, extra_data), handles = self.SerializeInline( |
+ union, handle_offset) |
+ data = bytearray(16) |
+ data.extend(extra_data) |
+ |
+ field = self._fields[union.tag] |
+ |
+ HEADER_STRUCT.pack_into(data, 0, size, tag) |
+ typecode = field.GetTypeCode() |
+ if hasattr(field.field_type, 'union_type'): |
+ typecode = 'Q' |
+ |
+ struct.pack_into('<%s' % typecode, data, 8, entry) |
+ return data, handles |
+ |
+ def Deserialize(self, context, union_class): |
+ if len(context.data) < HEADER_STRUCT.size: |
+ raise DeserializationException( |
+ 'Available data too short to contain header.') |
+ (size, tag) = HEADER_STRUCT.unpack_from(context.data) |
+ if size == 0: |
+ return None |
+ |
+ if size != 16: |
+ raise DeserializationException('Invalid union size %s' % size) |
+ |
+ field = self._fields[tag] |
+ if hasattr(field.field_type, 'union_type'): |
+ ptr = POINTER_STRUCT.unpack_from(context.data, 8)[0] |
+ value = field.field_type.Deserialize(ptr, context.GetSubContext(ptr+8)) |
+ else: |
+ raw_value = struct.unpack_from( |
+ field.GetTypeCode(), context.data, 8)[0] |
+ value = field.field_type.Deserialize(raw_value, context.GetSubContext(8)) |
+ |
+ union = union_class.__new__(union_class) |
+ union._tag = tag |
+ union._data = value |
+ return union |