| Index: mojo/public/tools/bindings/pylib/mojom/generate/pack.py
|
| diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/pack.py b/mojo/public/tools/bindings/pylib/mojom/generate/pack.py
|
| index b034f97a086a146f138c81c53e746b2e1487ee93..c898be0dd1f7ff6577fa0888cc814ec67de471a8 100644
|
| --- a/mojo/public/tools/bindings/pylib/mojom/generate/pack.py
|
| +++ b/mojo/public/tools/bindings/pylib/mojom/generate/pack.py
|
| @@ -57,29 +57,18 @@ class PackedField(object):
|
| raise Exception("Invalid kind: %s" % kind.spec)
|
| return cls.kind_to_size[kind]
|
|
|
| - @classmethod
|
| - def GetAlignmentForKind(cls, kind):
|
| - if isinstance(kind, mojom.Interface):
|
| - return 4
|
| - if isinstance(kind, mojom.Union):
|
| - return 8
|
| - return cls.GetSizeForKind(kind)
|
| -
|
| - def __init__(self, field, index, ordinal):
|
| + def __init__(self, field):
|
| """
|
| 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.index = field.declaration_order
|
| + self.ordinal = field.computed_ordinal
|
| self.size = self.GetSizeForKind(field.kind)
|
| - self.alignment = self.GetAlignmentForKind(field.kind)
|
| - self.offset = None
|
| - self.bit = None
|
| - self.min_version = None
|
| + self.offset = field.computed_offset
|
| + self.bit = field.computed_bit
|
| + self.min_version = field.computed_min_version
|
|
|
|
|
| def GetPad(offset, alignment):
|
| @@ -88,94 +77,20 @@ def GetPad(offset, 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)
|
|
|
| + # |packed_fields_in_ordinal_order| contains all the fields,
|
| + # in ordinal order.
|
| + self.packed_fields_in_ordinal_order = [PackedField(field)
|
| + for field in struct.fields_in_ordinal_order]
|
| +
|
| + # |packed_fields| refers to the same fields as
|
| + # |packed_fields_in_ordinal_order|, but in increasing offset order.
|
| + self.packed_fields = [field for field in
|
| + self.packed_fields_in_ordinal_order]
|
| + self.packed_fields.sort(key=lambda f: (f.offset, f.bit))
|
|
|
| class ByteInfo(object):
|
| def __init__(self):
|
| @@ -184,8 +99,7 @@ class ByteInfo(object):
|
|
|
|
|
| def GetByteLayout(packed_struct):
|
| - total_payload_size = GetPayloadSizeUpToField(
|
| - packed_struct.packed_fields[-1] if packed_struct.packed_fields else None)
|
| + total_payload_size = packed_struct.struct.versions[-1].num_bytes - HEADER_SIZE
|
| bytes = [ByteInfo() for i in xrange(total_payload_size)]
|
|
|
| limit_of_previous_field = 0
|
| @@ -211,38 +125,3 @@ class VersionInfo(object):
|
| 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
|
|
|