| 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
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..cb68d4a2d2429817614af124c59e4ecb7d3bf573
|
| --- /dev/null
|
| +++ b/mojo/public/python/mojo/bindings/serialization.py
|
| @@ -0,0 +1,98 @@
|
| +# Copyright 2014 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +"""Utility classes for serialization"""
|
| +
|
| +import struct
|
| +
|
| +
|
| +# Format of a header for a struct or an array.
|
| +HEADER_STRUCT = struct.Struct("=II")
|
| +
|
| +
|
| +class SerializationException(Exception):
|
| + """Error when strying to serialize a struct."""
|
| + pass
|
| +
|
| +
|
| +class Serialization(object):
|
| + """
|
| + Helper class to serialize/deserialize a struct.
|
| + """
|
| + def __init__(self, groups):
|
| + self._groups = groups
|
| + self.version = _GetVersion(groups)
|
| + main_struct = _GetStruct(groups)
|
| + self.size = HEADER_STRUCT.size + main_struct.size
|
| + self._struct_per_version = {
|
| + self.version: main_struct,
|
| + }
|
| +
|
| + def _GetMainStruct(self):
|
| + return self._GetStruct(self.version)
|
| +
|
| + def _GetStruct(self, version):
|
| + # If asking for a greater ver
|
| + version = min(version, self.version)
|
| + if version not in self._struct_per_version:
|
| + self._struct_per_version[version] = _GetStruct(_FilterGroups(self._groups,
|
| + version))
|
| + return self._struct_per_version[version]
|
| +
|
| + def Serialize(self, obj, handle_offset):
|
| + """
|
| + Serialize the given obj. handle_offset is the the first value to use when
|
| + encoding handles.
|
| + """
|
| + handles = []
|
| + data = bytearray(self.size)
|
| + HEADER_STRUCT.pack_into(data, 0, self.size, self.version)
|
| + position = HEADER_STRUCT.size
|
| + to_pack = []
|
| + for group in self._groups:
|
| + position = position + NeededPaddingForAlignment(position,
|
| + group.GetByteSize())
|
| + (entry, new_handles) = group.Serialize(
|
| + obj,
|
| + len(data) - position,
|
| + data,
|
| + handle_offset + len(handles))
|
| + to_pack.append(entry)
|
| + handles.extend(new_handles)
|
| + position = position + group.GetByteSize()
|
| + self._GetMainStruct().pack_into(data, HEADER_STRUCT.size, *to_pack)
|
| + return (data, handles)
|
| +
|
| +
|
| +def NeededPaddingForAlignment(value, alignment=8):
|
| + """Returns the padding necessary to align value with the given alignment."""
|
| + if value % alignment:
|
| + return alignment - (value % alignment)
|
| + return 0
|
| +
|
| +
|
| +def _GetVersion(groups):
|
| + return sum([len(x.descriptors) for x in groups])
|
| +
|
| +
|
| +def _FilterGroups(groups, version):
|
| + return [group for group in groups if group.version < version]
|
| +
|
| +
|
| +def _GetStruct(groups):
|
| + index = 0
|
| + codes = [ '=' ]
|
| + for group in groups:
|
| + code = group.GetTypeCode()
|
| + size = group.GetByteSize()
|
| + needed_padding = NeededPaddingForAlignment(index, size)
|
| + if needed_padding:
|
| + codes.append('x' * needed_padding)
|
| + index = index + needed_padding
|
| + codes.append(code)
|
| + index = index + size
|
| + alignment_needed = NeededPaddingForAlignment(index)
|
| + if alignment_needed:
|
| + codes.append('x' * alignment_needed)
|
| + return struct.Struct(''.join(codes))
|
|
|