diff options
Diffstat (limited to 'mojo/public/tools/bindings/pylib/mojom/generate/pack.py')
-rw-r--r-- | mojo/public/tools/bindings/pylib/mojom/generate/pack.py | 250 |
1 files changed, 0 insertions, 250 deletions
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/pack.py b/mojo/public/tools/bindings/pylib/mojom/generate/pack.py deleted file mode 100644 index 37dc8f3..0000000 --- a/mojo/public/tools/bindings/pylib/mojom/generate/pack.py +++ /dev/null @@ -1,250 +0,0 @@ -# Copyright 2013 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. - -import module as mojom - -# This module provides a mechanism for determining the packed order and offsets -# of a mojom.Struct. -# -# ps = pack.PackedStruct(struct) -# ps.packed_fields will access a list of PackedField objects, each of which -# will have an offset, a size and a bit (for mojom.BOOLs). - -# Size of struct header in bytes: num_bytes [4B] + version [4B]. -HEADER_SIZE = 8 - -class PackedField(object): - kind_to_size = { - mojom.BOOL: 1, - mojom.INT8: 1, - mojom.UINT8: 1, - mojom.INT16: 2, - mojom.UINT16: 2, - mojom.INT32: 4, - mojom.UINT32: 4, - mojom.FLOAT: 4, - mojom.HANDLE: 4, - mojom.MSGPIPE: 4, - mojom.SHAREDBUFFER: 4, - mojom.DCPIPE: 4, - mojom.DPPIPE: 4, - mojom.NULLABLE_HANDLE: 4, - mojom.NULLABLE_MSGPIPE: 4, - mojom.NULLABLE_SHAREDBUFFER: 4, - mojom.NULLABLE_DCPIPE: 4, - mojom.NULLABLE_DPPIPE: 4, - mojom.INT64: 8, - mojom.UINT64: 8, - mojom.DOUBLE: 8, - mojom.STRING: 8, - mojom.NULLABLE_STRING: 8 - } - - @classmethod - def GetSizeForKind(cls, kind): - if isinstance(kind, (mojom.Array, mojom.Map, mojom.Struct, - mojom.Interface, mojom.AssociatedInterface)): - return 8 - if isinstance(kind, mojom.Union): - return 16 - if isinstance(kind, mojom.InterfaceRequest): - kind = mojom.MSGPIPE - if isinstance(kind, mojom.AssociatedInterfaceRequest): - return 4 - if isinstance(kind, mojom.Enum): - # TODO(mpcomplete): what about big enums? - return cls.kind_to_size[mojom.INT32] - if not kind in cls.kind_to_size: - raise Exception("Invalid kind: %s" % kind.spec) - return cls.kind_to_size[kind] - - @classmethod - def GetAlignmentForKind(cls, kind): - if isinstance(kind, (mojom.Interface, mojom.AssociatedInterface)): - return 4 - if isinstance(kind, mojom.Union): - return 8 - return cls.GetSizeForKind(kind) - - def __init__(self, field, index, ordinal): - """ - Args: - field: the original field. - index: the position of the original field in the struct. - ordinal: the ordinal of the field for serialization. - """ - self.field = field - self.index = index - self.ordinal = ordinal - self.size = self.GetSizeForKind(field.kind) - self.alignment = self.GetAlignmentForKind(field.kind) - self.offset = None - self.bit = None - self.min_version = None - - -def GetPad(offset, alignment): - """Returns the pad necessary to reserve space so that |offset + pad| equals to - some multiple of |alignment|.""" - return (alignment - (offset % alignment)) % alignment - - -def GetFieldOffset(field, last_field): - """Returns a 2-tuple of the field offset and bit (for BOOLs).""" - if (field.field.kind == mojom.BOOL and - last_field.field.kind == mojom.BOOL and - last_field.bit < 7): - return (last_field.offset, last_field.bit + 1) - - offset = last_field.offset + last_field.size - pad = GetPad(offset, field.alignment) - return (offset + pad, 0) - - -def GetPayloadSizeUpToField(field): - """Returns the payload size (not including struct header) if |field| is the - last field. - """ - if not field: - return 0 - offset = field.offset + field.size - pad = GetPad(offset, 8) - return offset + pad - - -class PackedStruct(object): - def __init__(self, struct): - self.struct = struct - # |packed_fields| contains all the fields, in increasing offset order. - self.packed_fields = [] - # |packed_fields_in_ordinal_order| refers to the same fields as - # |packed_fields|, but in ordinal order. - self.packed_fields_in_ordinal_order = [] - - # No fields. - if (len(struct.fields) == 0): - return - - # Start by sorting by ordinal. - src_fields = self.packed_fields_in_ordinal_order - ordinal = 0 - for index, field in enumerate(struct.fields): - if field.ordinal is not None: - ordinal = field.ordinal - src_fields.append(PackedField(field, index, ordinal)) - ordinal += 1 - src_fields.sort(key=lambda field: field.ordinal) - - # Set |min_version| for each field. - next_min_version = 0 - for packed_field in src_fields: - if packed_field.field.min_version is None: - assert next_min_version == 0 - else: - assert packed_field.field.min_version >= next_min_version - next_min_version = packed_field.field.min_version - packed_field.min_version = next_min_version - - if (packed_field.min_version != 0 and - mojom.IsReferenceKind(packed_field.field.kind) and - not packed_field.field.kind.is_nullable): - raise Exception("Non-nullable fields are only allowed in version 0 of " - "a struct. %s.%s is defined with [MinVersion=%d]." - % (self.struct.name, packed_field.field.name, - packed_field.min_version)) - - src_field = src_fields[0] - src_field.offset = 0 - src_field.bit = 0 - dst_fields = self.packed_fields - dst_fields.append(src_field) - - # Then find first slot that each field will fit. - for src_field in src_fields[1:]: - last_field = dst_fields[0] - for i in xrange(1, len(dst_fields)): - next_field = dst_fields[i] - offset, bit = GetFieldOffset(src_field, last_field) - if offset + src_field.size <= next_field.offset: - # Found hole. - src_field.offset = offset - src_field.bit = bit - dst_fields.insert(i, src_field) - break - last_field = next_field - if src_field.offset is None: - # Add to end - src_field.offset, src_field.bit = GetFieldOffset(src_field, last_field) - dst_fields.append(src_field) - - -class ByteInfo(object): - def __init__(self): - self.is_padding = False - self.packed_fields = [] - - -def GetByteLayout(packed_struct): - total_payload_size = GetPayloadSizeUpToField( - packed_struct.packed_fields[-1] if packed_struct.packed_fields else None) - bytes = [ByteInfo() for i in xrange(total_payload_size)] - - limit_of_previous_field = 0 - for packed_field in packed_struct.packed_fields: - for i in xrange(limit_of_previous_field, packed_field.offset): - bytes[i].is_padding = True - bytes[packed_field.offset].packed_fields.append(packed_field) - limit_of_previous_field = packed_field.offset + packed_field.size - - for i in xrange(limit_of_previous_field, len(bytes)): - bytes[i].is_padding = True - - for byte in bytes: - # A given byte cannot both be padding and have a fields packed into it. - assert not (byte.is_padding and byte.packed_fields) - - return bytes - - -class VersionInfo(object): - def __init__(self, version, num_fields, num_bytes): - self.version = version - self.num_fields = num_fields - self.num_bytes = num_bytes - - -def GetVersionInfo(packed_struct): - """Get version information for a struct. - - Args: - packed_struct: A PackedStruct instance. - - Returns: - A non-empty list of VersionInfo instances, sorted by version in increasing - order. - Note: The version numbers may not be consecutive. - """ - versions = [] - last_version = 0 - last_num_fields = 0 - last_payload_size = 0 - - for packed_field in packed_struct.packed_fields_in_ordinal_order: - if packed_field.min_version != last_version: - versions.append( - VersionInfo(last_version, last_num_fields, - last_payload_size + HEADER_SIZE)) - last_version = packed_field.min_version - - last_num_fields += 1 - # The fields are iterated in ordinal order here. However, the size of a - # version is determined by the last field of that version in pack order, - # instead of ordinal order. Therefore, we need to calculate the max value. - last_payload_size = max(GetPayloadSizeUpToField(packed_field), - last_payload_size) - - assert len(versions) == 0 or last_num_fields != versions[-1].num_fields - versions.append(VersionInfo(last_version, last_num_fields, - last_payload_size + HEADER_SIZE)) - return versions |