# 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)):
      return 8
    if isinstance(kind, mojom.Union):
      return 16
    if isinstance(kind, mojom.InterfaceRequest):
      kind = mojom.MSGPIPE
    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]

  def __init__(self, field):
    """
    Args:
      field: the original field.
    """
    self.field = field
    self.index = field.declaration_order
    self.ordinal = field.computed_ordinal
    self.size = self.GetSizeForKind(field.kind)
    self.offset = field.computed_offset
    self.bit = field.computed_bit
    self.min_version = field.computed_min_version


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


class PackedStruct(object):
  def __init__(self, struct):
    self.struct = struct

    # |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):
    self.is_padding = False
    self.packed_fields = []


def GetByteLayout(packed_struct):
  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
  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

