Chromium Code Reviews| 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..52cb451efda787a1a0c21110e6232f4e4126e01a 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,77 @@ def _GetStruct(groups): |
| if alignment_needed: |
| codes.append('x' * alignment_needed) |
| return struct.Struct(''.join(codes)) |
| + |
| + |
| +class UnionSerializer(object): |
| + """ |
| + 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] |
| + |
| + # Serialize the unions value and either |
| + # 1. Return the serialized value itself as entry. |
| + # 2. Append the serialized value to data and return 8 a pointer to the |
| + # serialized value. (Assumes the data will immediately follow the union.) |
| + (entry, handles) = field.field_type.Serialize( |
| + union.data, 8, data, handle_offset) |
| + |
| + # If the value contained in the union is itself a union, we append its |
| + # serialized value to data and set entry to 8, a pointer to the data. |
| + if field.field_type.IsUnion(): |
| + 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 |
| + |
| + 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 the value is a nested union, we store a 64 bits pointer to it. |
| + if field.field_type.IsUnion(): |
| + 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] |
|
qsr
2015/07/20 21:29:59
1) You should not be using private variable outsid
azani
2015/07/20 22:17:52
Done.
|
| + if field.field_type.IsUnion(): |
| + 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._cur_field = field |
| + union._data = value |
| + return union |