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 |