summaryrefslogtreecommitdiff
path: root/utils/ipc/mojo/public/tools/mojom/mojom/generate/module.py
diff options
context:
space:
mode:
Diffstat (limited to 'utils/ipc/mojo/public/tools/mojom/mojom/generate/module.py')
-rw-r--r--utils/ipc/mojo/public/tools/mojom/mojom/generate/module.py1758
1 files changed, 0 insertions, 1758 deletions
diff --git a/utils/ipc/mojo/public/tools/mojom/mojom/generate/module.py b/utils/ipc/mojo/public/tools/mojom/mojom/generate/module.py
deleted file mode 100644
index 9bdb28e0..00000000
--- a/utils/ipc/mojo/public/tools/mojom/mojom/generate/module.py
+++ /dev/null
@@ -1,1758 +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.
-
-# This module's classes provide an interface to mojo modules. Modules are
-# collections of interfaces and structs to be used by mojo ipc clients and
-# servers.
-#
-# A simple interface would be created this way:
-# module = mojom.generate.module.Module('Foo')
-# interface = module.AddInterface('Bar')
-# method = interface.AddMethod('Tat', 0)
-# method.AddParameter('baz', 0, mojom.INT32)
-
-import sys
-if sys.version_info.major == 2:
- import cPickle as pickle
-else:
- import pickle
-from uuid import UUID
-
-
-class BackwardCompatibilityChecker(object):
- """Used for memoization while recursively checking two type definitions for
- backward-compatibility."""
-
- def __init__(self):
- self._cache = {}
-
- def IsBackwardCompatible(self, new_kind, old_kind):
- key = (new_kind, old_kind)
- result = self._cache.get(key)
- if result is None:
- # Assume they're compatible at first to effectively ignore recursive
- # checks between these types, e.g. if both kinds are a struct or union
- # that references itself in a field.
- self._cache[key] = True
- result = new_kind.IsBackwardCompatible(old_kind, self)
- self._cache[key] = result
- return result
-
-
-# We use our own version of __repr__ when displaying the AST, as the
-# AST currently doesn't capture which nodes are reference (e.g. to
-# types) and which nodes are definitions. This allows us to e.g. print
-# the definition of a struct when it's defined inside a module, but
-# only print its name when it's referenced in e.g. a method parameter.
-def Repr(obj, as_ref=True):
- """A version of __repr__ that can distinguish references.
-
- Sometimes we like to print an object's full representation
- (e.g. with its fields) and sometimes we just want to reference an
- object that was printed in full elsewhere. This function allows us
- to make that distinction.
-
- Args:
- obj: The object whose string representation we compute.
- as_ref: If True, use the short reference representation.
-
- Returns:
- A str representation of |obj|.
- """
- if hasattr(obj, 'Repr'):
- return obj.Repr(as_ref=as_ref)
- # Since we cannot implement Repr for existing container types, we
- # handle them here.
- elif isinstance(obj, list):
- if not obj:
- return '[]'
- else:
- return ('[\n%s\n]' % (',\n'.join(
- ' %s' % Repr(elem, as_ref).replace('\n', '\n ')
- for elem in obj)))
- elif isinstance(obj, dict):
- if not obj:
- return '{}'
- else:
- return ('{\n%s\n}' % (',\n'.join(
- ' %s: %s' % (Repr(key, as_ref).replace('\n', '\n '),
- Repr(val, as_ref).replace('\n', '\n '))
- for key, val in obj.items())))
- else:
- return repr(obj)
-
-
-def GenericRepr(obj, names):
- """Compute generic Repr for |obj| based on the attributes in |names|.
-
- Args:
- obj: The object to compute a Repr for.
- names: A dict from attribute names to include, to booleans
- specifying whether those attributes should be shown as
- references or not.
-
- Returns:
- A str representation of |obj|.
- """
-
- def ReprIndent(name, as_ref):
- return ' %s=%s' % (name, Repr(getattr(obj, name), as_ref).replace(
- '\n', '\n '))
-
- return '%s(\n%s\n)' % (obj.__class__.__name__, ',\n'.join(
- ReprIndent(name, as_ref) for (name, as_ref) in names.items()))
-
-
-class Kind(object):
- """Kind represents a type (e.g. int8, string).
-
- Attributes:
- spec: A string uniquely identifying the type. May be None.
- module: {Module} The defining module. Set to None for built-in types.
- parent_kind: The enclosing type. For example, an enum defined
- inside an interface has that interface as its parent. May be None.
- """
-
- def __init__(self, spec=None, module=None):
- self.spec = spec
- self.module = module
- self.parent_kind = None
-
- def Repr(self, as_ref=True):
- # pylint: disable=unused-argument
- return '<%s spec=%r>' % (self.__class__.__name__, self.spec)
-
- def __repr__(self):
- # Gives us a decent __repr__ for all kinds.
- return self.Repr()
-
- def __eq__(self, rhs):
- # pylint: disable=unidiomatic-typecheck
- return (type(self) == type(rhs)
- and (self.spec, self.parent_kind) == (rhs.spec, rhs.parent_kind))
-
- def __hash__(self):
- # TODO(crbug.com/1060471): Remove this and other __hash__ methods on Kind
- # and its subclasses. This is to support existing generator code which uses
- # some primitive Kinds as dict keys. The default hash (object identity)
- # breaks these dicts when a pickled Module instance is unpickled and used
- # during a subsequent run of the parser.
- return hash((self.spec, self.parent_kind))
-
- # pylint: disable=unused-argument
- def IsBackwardCompatible(self, rhs, checker):
- return self == rhs
-
-
-class ReferenceKind(Kind):
- """ReferenceKind represents pointer and handle types.
-
- A type is nullable if null (for pointer types) or invalid handle (for handle
- types) is a legal value for the type.
-
- Attributes:
- is_nullable: True if the type is nullable.
- """
-
- def __init__(self, spec=None, is_nullable=False, module=None):
- assert spec is None or is_nullable == spec.startswith('?')
- Kind.__init__(self, spec, module)
- self.is_nullable = is_nullable
- self.shared_definition = {}
-
- def Repr(self, as_ref=True):
- return '<%s spec=%r is_nullable=%r>' % (self.__class__.__name__, self.spec,
- self.is_nullable)
-
- def MakeNullableKind(self):
- assert not self.is_nullable
-
- if self == STRING:
- return NULLABLE_STRING
- if self == HANDLE:
- return NULLABLE_HANDLE
- if self == DCPIPE:
- return NULLABLE_DCPIPE
- if self == DPPIPE:
- return NULLABLE_DPPIPE
- if self == MSGPIPE:
- return NULLABLE_MSGPIPE
- if self == SHAREDBUFFER:
- return NULLABLE_SHAREDBUFFER
- if self == PLATFORMHANDLE:
- return NULLABLE_PLATFORMHANDLE
-
- nullable_kind = type(self)()
- nullable_kind.shared_definition = self.shared_definition
- if self.spec is not None:
- nullable_kind.spec = '?' + self.spec
- nullable_kind.is_nullable = True
- nullable_kind.parent_kind = self.parent_kind
- nullable_kind.module = self.module
-
- return nullable_kind
-
- @classmethod
- def AddSharedProperty(cls, name):
- """Adds a property |name| to |cls|, which accesses the corresponding item in
- |shared_definition|.
-
- The reason of adding such indirection is to enable sharing definition
- between a reference kind and its nullable variation. For example:
- a = Struct('test_struct_1')
- b = a.MakeNullableKind()
- a.name = 'test_struct_2'
- print(b.name) # Outputs 'test_struct_2'.
- """
-
- def Get(self):
- try:
- return self.shared_definition[name]
- except KeyError: # Must raise AttributeError if property doesn't exist.
- raise AttributeError
-
- def Set(self, value):
- self.shared_definition[name] = value
-
- setattr(cls, name, property(Get, Set))
-
- def __eq__(self, rhs):
- return (isinstance(rhs, ReferenceKind)
- and super(ReferenceKind, self).__eq__(rhs)
- and self.is_nullable == rhs.is_nullable)
-
- def __hash__(self):
- return hash((super(ReferenceKind, self).__hash__(), self.is_nullable))
-
- def IsBackwardCompatible(self, rhs, checker):
- return (super(ReferenceKind, self).IsBackwardCompatible(rhs, checker)
- and self.is_nullable == rhs.is_nullable)
-
-
-# Initialize the set of primitive types. These can be accessed by clients.
-BOOL = Kind('b')
-INT8 = Kind('i8')
-INT16 = Kind('i16')
-INT32 = Kind('i32')
-INT64 = Kind('i64')
-UINT8 = Kind('u8')
-UINT16 = Kind('u16')
-UINT32 = Kind('u32')
-UINT64 = Kind('u64')
-FLOAT = Kind('f')
-DOUBLE = Kind('d')
-STRING = ReferenceKind('s')
-HANDLE = ReferenceKind('h')
-DCPIPE = ReferenceKind('h:d:c')
-DPPIPE = ReferenceKind('h:d:p')
-MSGPIPE = ReferenceKind('h:m')
-SHAREDBUFFER = ReferenceKind('h:s')
-PLATFORMHANDLE = ReferenceKind('h:p')
-NULLABLE_STRING = ReferenceKind('?s', True)
-NULLABLE_HANDLE = ReferenceKind('?h', True)
-NULLABLE_DCPIPE = ReferenceKind('?h:d:c', True)
-NULLABLE_DPPIPE = ReferenceKind('?h:d:p', True)
-NULLABLE_MSGPIPE = ReferenceKind('?h:m', True)
-NULLABLE_SHAREDBUFFER = ReferenceKind('?h:s', True)
-NULLABLE_PLATFORMHANDLE = ReferenceKind('?h:p', True)
-
-# Collection of all Primitive types
-PRIMITIVES = (
- BOOL,
- INT8,
- INT16,
- INT32,
- INT64,
- UINT8,
- UINT16,
- UINT32,
- UINT64,
- FLOAT,
- DOUBLE,
- STRING,
- HANDLE,
- DCPIPE,
- DPPIPE,
- MSGPIPE,
- SHAREDBUFFER,
- PLATFORMHANDLE,
- NULLABLE_STRING,
- NULLABLE_HANDLE,
- NULLABLE_DCPIPE,
- NULLABLE_DPPIPE,
- NULLABLE_MSGPIPE,
- NULLABLE_SHAREDBUFFER,
- NULLABLE_PLATFORMHANDLE,
-)
-
-ATTRIBUTE_MIN_VERSION = 'MinVersion'
-ATTRIBUTE_DEFAULT = 'Default'
-ATTRIBUTE_EXTENSIBLE = 'Extensible'
-ATTRIBUTE_NO_INTERRUPT = 'NoInterrupt'
-ATTRIBUTE_STABLE = 'Stable'
-ATTRIBUTE_SYNC = 'Sync'
-ATTRIBUTE_UNLIMITED_SIZE = 'UnlimitedSize'
-ATTRIBUTE_UUID = 'Uuid'
-
-
-class NamedValue(object):
- def __init__(self, module, parent_kind, mojom_name):
- self.module = module
- self.parent_kind = parent_kind
- self.mojom_name = mojom_name
-
- def GetSpec(self):
- return (self.module.GetNamespacePrefix() +
- (self.parent_kind and
- (self.parent_kind.mojom_name + '.') or "") + self.mojom_name)
-
- def __eq__(self, rhs):
- return (isinstance(rhs, NamedValue)
- and (self.parent_kind, self.mojom_name) == (rhs.parent_kind,
- rhs.mojom_name))
-
- def __hash__(self):
- return hash((self.parent_kind, self.mojom_name))
-
-
-class BuiltinValue(object):
- def __init__(self, value):
- self.value = value
-
- def __eq__(self, rhs):
- return isinstance(rhs, BuiltinValue) and self.value == rhs.value
-
-
-class ConstantValue(NamedValue):
- def __init__(self, module, parent_kind, constant):
- NamedValue.__init__(self, module, parent_kind, constant.mojom_name)
- self.constant = constant
-
- @property
- def name(self):
- return self.constant.name
-
-
-class EnumValue(NamedValue):
- def __init__(self, module, enum, field):
- NamedValue.__init__(self, module, enum.parent_kind, field.mojom_name)
- self.field = field
- self.enum = enum
-
- def GetSpec(self):
- return (self.module.GetNamespacePrefix() +
- (self.parent_kind and (self.parent_kind.mojom_name + '.') or "") +
- self.enum.mojom_name + '.' + self.mojom_name)
-
- @property
- def name(self):
- return self.field.name
-
-
-class Constant(object):
- def __init__(self, mojom_name=None, kind=None, value=None, parent_kind=None):
- self.mojom_name = mojom_name
- self.name = None
- self.kind = kind
- self.value = value
- self.parent_kind = parent_kind
-
- def Stylize(self, stylizer):
- self.name = stylizer.StylizeConstant(self.mojom_name)
-
- def __eq__(self, rhs):
- return (isinstance(rhs, Constant)
- and (self.mojom_name, self.kind, self.value,
- self.parent_kind) == (rhs.mojom_name, rhs.kind, rhs.value,
- rhs.parent_kind))
-
-
-class Field(object):
- def __init__(self,
- mojom_name=None,
- kind=None,
- ordinal=None,
- default=None,
- attributes=None):
- if self.__class__.__name__ == 'Field':
- raise Exception()
- self.mojom_name = mojom_name
- self.name = None
- self.kind = kind
- self.ordinal = ordinal
- self.default = default
- self.attributes = attributes
-
- def Repr(self, as_ref=True):
- # pylint: disable=unused-argument
- # Fields are only referenced by objects which define them and thus
- # they are always displayed as non-references.
- return GenericRepr(self, {'mojom_name': False, 'kind': True})
-
- def Stylize(self, stylizer):
- self.name = stylizer.StylizeField(self.mojom_name)
-
- @property
- def min_version(self):
- return self.attributes.get(ATTRIBUTE_MIN_VERSION) \
- if self.attributes else None
-
- def __eq__(self, rhs):
- return (isinstance(rhs, Field)
- and (self.mojom_name, self.kind, self.ordinal, self.default,
- self.attributes) == (rhs.mojom_name, rhs.kind, rhs.ordinal,
- rhs.default, rhs.attributes))
-
- def __hash__(self):
- return hash((self.mojom_name, self.kind, self.ordinal, self.default))
-
-
-class StructField(Field):
- def __hash__(self):
- return super(Field, self).__hash__()
-
-
-class UnionField(Field):
- pass
-
-
-def _IsFieldBackwardCompatible(new_field, old_field, checker):
- if (new_field.min_version or 0) != (old_field.min_version or 0):
- return False
-
- return checker.IsBackwardCompatible(new_field.kind, old_field.kind)
-
-
-class Struct(ReferenceKind):
- """A struct with typed fields.
-
- Attributes:
- mojom_name: {str} The name of the struct type as defined in mojom.
- name: {str} The stylized name.
- native_only: {bool} Does the struct have a body (i.e. any fields) or is it
- purely a native struct.
- custom_serializer: {bool} Should we generate a serializer for the struct or
- will one be provided by non-generated code.
- fields: {List[StructField]} The members of the struct.
- enums: {List[Enum]} The enums defined in the struct scope.
- constants: {List[Constant]} The constants defined in the struct scope.
- attributes: {dict} Additional information about the struct, such as
- if it's a native struct.
- """
-
- ReferenceKind.AddSharedProperty('mojom_name')
- ReferenceKind.AddSharedProperty('name')
- ReferenceKind.AddSharedProperty('native_only')
- ReferenceKind.AddSharedProperty('custom_serializer')
- ReferenceKind.AddSharedProperty('fields')
- ReferenceKind.AddSharedProperty('enums')
- ReferenceKind.AddSharedProperty('constants')
- ReferenceKind.AddSharedProperty('attributes')
-
- def __init__(self, mojom_name=None, module=None, attributes=None):
- if mojom_name is not None:
- spec = 'x:' + mojom_name
- else:
- spec = None
- ReferenceKind.__init__(self, spec, False, module)
- self.mojom_name = mojom_name
- self.name = None
- self.native_only = False
- self.custom_serializer = False
- self.fields = []
- self.enums = []
- self.constants = []
- self.attributes = attributes
-
- def Repr(self, as_ref=True):
- if as_ref:
- return '<%s mojom_name=%r module=%s>' % (self.__class__.__name__,
- self.mojom_name,
- Repr(self.module, as_ref=True))
- else:
- return GenericRepr(self, {
- 'mojom_name': False,
- 'fields': False,
- 'module': True
- })
-
- def AddField(self,
- mojom_name,
- kind,
- ordinal=None,
- default=None,
- attributes=None):
- field = StructField(mojom_name, kind, ordinal, default, attributes)
- self.fields.append(field)
- return field
-
- def Stylize(self, stylizer):
- self.name = stylizer.StylizeStruct(self.mojom_name)
- for field in self.fields:
- field.Stylize(stylizer)
- for enum in self.enums:
- enum.Stylize(stylizer)
- for constant in self.constants:
- constant.Stylize(stylizer)
-
- def IsBackwardCompatible(self, older_struct, checker):
- """This struct is backward-compatible with older_struct if and only if all
- of the following conditions hold:
- - Any newly added field is tagged with a [MinVersion] attribute specifying
- a version number greater than all previously used [MinVersion]
- attributes within the struct.
- - All fields present in older_struct remain present in the new struct,
- with the same ordinal position, same optional or non-optional status,
- same (or backward-compatible) type and where applicable, the same
- [MinVersion] attribute value.
- - All [MinVersion] attributes must be non-decreasing in ordinal order.
- - All reference-typed (string, array, map, struct, or union) fields tagged
- with a [MinVersion] greater than zero must be optional.
- """
-
- def buildOrdinalFieldMap(struct):
- fields_by_ordinal = {}
- for field in struct.fields:
- if field.ordinal in fields_by_ordinal:
- raise Exception('Multiple fields with ordinal %s in struct %s.' %
- (field.ordinal, struct.mojom_name))
- fields_by_ordinal[field.ordinal] = field
- return fields_by_ordinal
-
- new_fields = buildOrdinalFieldMap(self)
- old_fields = buildOrdinalFieldMap(older_struct)
- if len(new_fields) < len(old_fields):
- # At least one field was removed, which is not OK.
- return False
-
- # If there are N fields, existing ordinal values must exactly cover the
- # range from 0 to N-1.
- num_old_ordinals = len(old_fields)
- max_old_min_version = 0
- for ordinal in range(num_old_ordinals):
- new_field = new_fields[ordinal]
- old_field = old_fields[ordinal]
- if (old_field.min_version or 0) > max_old_min_version:
- max_old_min_version = old_field.min_version
- if not _IsFieldBackwardCompatible(new_field, old_field, checker):
- # Type or min-version mismatch between old and new versions of the same
- # ordinal field.
- return False
-
- # At this point we know all old fields are intact in the new struct
- # definition. Now verify that all new fields have a high enough min version
- # and are appropriately optional where required.
- num_new_ordinals = len(new_fields)
- last_min_version = max_old_min_version
- for ordinal in range(num_old_ordinals, num_new_ordinals):
- new_field = new_fields[ordinal]
- min_version = new_field.min_version or 0
- if min_version <= max_old_min_version:
- # A new field is being added to an existing version, which is not OK.
- return False
- if min_version < last_min_version:
- # The [MinVersion] of a field cannot be lower than the [MinVersion] of
- # a field with lower ordinal value.
- return False
- if IsReferenceKind(new_field.kind) and not IsNullableKind(new_field.kind):
- # New fields whose type can be nullable MUST be nullable.
- return False
-
- return True
-
- @property
- def stable(self):
- return self.attributes.get(ATTRIBUTE_STABLE, False) \
- if self.attributes else False
-
- @property
- def qualified_name(self):
- if self.parent_kind:
- prefix = self.parent_kind.qualified_name + '.'
- else:
- prefix = self.module.GetNamespacePrefix()
- return '%s%s' % (prefix, self.mojom_name)
-
- def __eq__(self, rhs):
- return (isinstance(rhs, Struct) and
- (self.mojom_name, self.native_only, self.fields, self.constants,
- self.attributes) == (rhs.mojom_name, rhs.native_only, rhs.fields,
- rhs.constants, rhs.attributes))
-
- def __hash__(self):
- return id(self)
-
-
-class Union(ReferenceKind):
- """A union of several kinds.
-
- Attributes:
- mojom_name: {str} The name of the union type as defined in mojom.
- name: {str} The stylized name.
- fields: {List[UnionField]} The members of the union.
- attributes: {dict} Additional information about the union, such as
- which Java class name to use to represent it in the generated
- bindings.
- """
- ReferenceKind.AddSharedProperty('mojom_name')
- ReferenceKind.AddSharedProperty('name')
- ReferenceKind.AddSharedProperty('fields')
- ReferenceKind.AddSharedProperty('attributes')
-
- def __init__(self, mojom_name=None, module=None, attributes=None):
- if mojom_name is not None:
- spec = 'x:' + mojom_name
- else:
- spec = None
- ReferenceKind.__init__(self, spec, False, module)
- self.mojom_name = mojom_name
- self.name = None
- self.fields = []
- self.attributes = attributes
-
- def Repr(self, as_ref=True):
- if as_ref:
- return '<%s spec=%r is_nullable=%r fields=%s>' % (
- self.__class__.__name__, self.spec, self.is_nullable, Repr(
- self.fields))
- else:
- return GenericRepr(self, {'fields': True, 'is_nullable': False})
-
- def AddField(self, mojom_name, kind, ordinal=None, attributes=None):
- field = UnionField(mojom_name, kind, ordinal, None, attributes)
- self.fields.append(field)
- return field
-
- def Stylize(self, stylizer):
- self.name = stylizer.StylizeUnion(self.mojom_name)
- for field in self.fields:
- field.Stylize(stylizer)
-
- def IsBackwardCompatible(self, older_union, checker):
- """This union is backward-compatible with older_union if and only if all
- of the following conditions hold:
- - Any newly added field is tagged with a [MinVersion] attribute specifying
- a version number greater than all previously used [MinVersion]
- attributes within the union.
- - All fields present in older_union remain present in the new union,
- with the same ordinal value, same optional or non-optional status,
- same (or backward-compatible) type, and where applicable, the same
- [MinVersion] attribute value.
- """
-
- def buildOrdinalFieldMap(union):
- fields_by_ordinal = {}
- for field in union.fields:
- if field.ordinal in fields_by_ordinal:
- raise Exception('Multiple fields with ordinal %s in union %s.' %
- (field.ordinal, union.mojom_name))
- fields_by_ordinal[field.ordinal] = field
- return fields_by_ordinal
-
- new_fields = buildOrdinalFieldMap(self)
- old_fields = buildOrdinalFieldMap(older_union)
- if len(new_fields) < len(old_fields):
- # At least one field was removed, which is not OK.
- return False
-
- max_old_min_version = 0
- for ordinal, old_field in old_fields.items():
- new_field = new_fields.get(ordinal)
- if not new_field:
- # A field was removed, which is not OK.
- return False
- if not _IsFieldBackwardCompatible(new_field, old_field, checker):
- # An field changed its type or MinVersion, which is not OK.
- return False
- old_min_version = old_field.min_version or 0
- if old_min_version > max_old_min_version:
- max_old_min_version = old_min_version
-
- new_ordinals = set(new_fields.keys()) - set(old_fields.keys())
- for ordinal in new_ordinals:
- if (new_fields[ordinal].min_version or 0) <= max_old_min_version:
- # New fields must use a MinVersion greater than any old fields.
- return False
-
- return True
-
- @property
- def stable(self):
- return self.attributes.get(ATTRIBUTE_STABLE, False) \
- if self.attributes else False
-
- @property
- def qualified_name(self):
- if self.parent_kind:
- prefix = self.parent_kind.qualified_name + '.'
- else:
- prefix = self.module.GetNamespacePrefix()
- return '%s%s' % (prefix, self.mojom_name)
-
- def __eq__(self, rhs):
- return (isinstance(rhs, Union) and
- (self.mojom_name, self.fields,
- self.attributes) == (rhs.mojom_name, rhs.fields, rhs.attributes))
-
- def __hash__(self):
- return id(self)
-
-
-class Array(ReferenceKind):
- """An array.
-
- Attributes:
- kind: {Kind} The type of the elements. May be None.
- length: The number of elements. None if unknown.
- """
-
- ReferenceKind.AddSharedProperty('kind')
- ReferenceKind.AddSharedProperty('length')
-
- def __init__(self, kind=None, length=None):
- if kind is not None:
- if length is not None:
- spec = 'a%d:%s' % (length, kind.spec)
- else:
- spec = 'a:%s' % kind.spec
-
- ReferenceKind.__init__(self, spec)
- else:
- ReferenceKind.__init__(self)
- self.kind = kind
- self.length = length
-
- def Repr(self, as_ref=True):
- if as_ref:
- return '<%s spec=%r is_nullable=%r kind=%s length=%r>' % (
- self.__class__.__name__, self.spec, self.is_nullable, Repr(
- self.kind), self.length)
- else:
- return GenericRepr(self, {
- 'kind': True,
- 'length': False,
- 'is_nullable': False
- })
-
- def __eq__(self, rhs):
- return (isinstance(rhs, Array)
- and (self.kind, self.length) == (rhs.kind, rhs.length))
-
- def __hash__(self):
- return id(self)
-
- def IsBackwardCompatible(self, rhs, checker):
- return (isinstance(rhs, Array) and self.length == rhs.length
- and checker.IsBackwardCompatible(self.kind, rhs.kind))
-
-
-class Map(ReferenceKind):
- """A map.
-
- Attributes:
- key_kind: {Kind} The type of the keys. May be None.
- value_kind: {Kind} The type of the elements. May be None.
- """
- ReferenceKind.AddSharedProperty('key_kind')
- ReferenceKind.AddSharedProperty('value_kind')
-
- def __init__(self, key_kind=None, value_kind=None):
- if (key_kind is not None and value_kind is not None):
- ReferenceKind.__init__(
- self, 'm[' + key_kind.spec + '][' + value_kind.spec + ']')
- if IsNullableKind(key_kind):
- raise Exception("Nullable kinds cannot be keys in maps.")
- if IsAnyHandleKind(key_kind):
- raise Exception("Handles cannot be keys in maps.")
- if IsAnyInterfaceKind(key_kind):
- raise Exception("Interfaces cannot be keys in maps.")
- if IsArrayKind(key_kind):
- raise Exception("Arrays cannot be keys in maps.")
- else:
- ReferenceKind.__init__(self)
-
- self.key_kind = key_kind
- self.value_kind = value_kind
-
- def Repr(self, as_ref=True):
- if as_ref:
- return '<%s spec=%r is_nullable=%r key_kind=%s value_kind=%s>' % (
- self.__class__.__name__, self.spec, self.is_nullable,
- Repr(self.key_kind), Repr(self.value_kind))
- else:
- return GenericRepr(self, {'key_kind': True, 'value_kind': True})
-
- def __eq__(self, rhs):
- return (isinstance(rhs, Map) and
- (self.key_kind, self.value_kind) == (rhs.key_kind, rhs.value_kind))
-
- def __hash__(self):
- return id(self)
-
- def IsBackwardCompatible(self, rhs, checker):
- return (isinstance(rhs, Map)
- and checker.IsBackwardCompatible(self.key_kind, rhs.key_kind)
- and checker.IsBackwardCompatible(self.value_kind, rhs.value_kind))
-
-
-class PendingRemote(ReferenceKind):
- ReferenceKind.AddSharedProperty('kind')
-
- def __init__(self, kind=None):
- if kind is not None:
- if not isinstance(kind, Interface):
- raise Exception(
- 'pending_remote<T> requires T to be an interface type. Got %r' %
- kind.spec)
- ReferenceKind.__init__(self, 'rmt:' + kind.spec)
- else:
- ReferenceKind.__init__(self)
- self.kind = kind
-
- def __eq__(self, rhs):
- return isinstance(rhs, PendingRemote) and self.kind == rhs.kind
-
- def __hash__(self):
- return id(self)
-
- def IsBackwardCompatible(self, rhs, checker):
- return (isinstance(rhs, PendingRemote)
- and checker.IsBackwardCompatible(self.kind, rhs.kind))
-
-
-class PendingReceiver(ReferenceKind):
- ReferenceKind.AddSharedProperty('kind')
-
- def __init__(self, kind=None):
- if kind is not None:
- if not isinstance(kind, Interface):
- raise Exception(
- 'pending_receiver<T> requires T to be an interface type. Got %r' %
- kind.spec)
- ReferenceKind.__init__(self, 'rcv:' + kind.spec)
- else:
- ReferenceKind.__init__(self)
- self.kind = kind
-
- def __eq__(self, rhs):
- return isinstance(rhs, PendingReceiver) and self.kind == rhs.kind
-
- def __hash__(self):
- return id(self)
-
- def IsBackwardCompatible(self, rhs, checker):
- return isinstance(rhs, PendingReceiver) and checker.IsBackwardCompatible(
- self.kind, rhs.kind)
-
-
-class PendingAssociatedRemote(ReferenceKind):
- ReferenceKind.AddSharedProperty('kind')
-
- def __init__(self, kind=None):
- if kind is not None:
- if not isinstance(kind, Interface):
- raise Exception(
- 'pending_associated_remote<T> requires T to be an interface ' +
- 'type. Got %r' % kind.spec)
- ReferenceKind.__init__(self, 'rma:' + kind.spec)
- else:
- ReferenceKind.__init__(self)
- self.kind = kind
-
- def __eq__(self, rhs):
- return isinstance(rhs, PendingAssociatedRemote) and self.kind == rhs.kind
-
- def __hash__(self):
- return id(self)
-
- def IsBackwardCompatible(self, rhs, checker):
- return isinstance(rhs,
- PendingAssociatedRemote) and checker.IsBackwardCompatible(
- self.kind, rhs.kind)
-
-
-class PendingAssociatedReceiver(ReferenceKind):
- ReferenceKind.AddSharedProperty('kind')
-
- def __init__(self, kind=None):
- if kind is not None:
- if not isinstance(kind, Interface):
- raise Exception(
- 'pending_associated_receiver<T> requires T to be an interface' +
- 'type. Got %r' % kind.spec)
- ReferenceKind.__init__(self, 'rca:' + kind.spec)
- else:
- ReferenceKind.__init__(self)
- self.kind = kind
-
- def __eq__(self, rhs):
- return isinstance(rhs, PendingAssociatedReceiver) and self.kind == rhs.kind
-
- def __hash__(self):
- return id(self)
-
- def IsBackwardCompatible(self, rhs, checker):
- return isinstance(
- rhs, PendingAssociatedReceiver) and checker.IsBackwardCompatible(
- self.kind, rhs.kind)
-
-
-class InterfaceRequest(ReferenceKind):
- ReferenceKind.AddSharedProperty('kind')
-
- def __init__(self, kind=None):
- if kind is not None:
- if not isinstance(kind, Interface):
- raise Exception(
- "Interface request requires %r to be an interface." % kind.spec)
- ReferenceKind.__init__(self, 'r:' + kind.spec)
- else:
- ReferenceKind.__init__(self)
- self.kind = kind
-
- def __eq__(self, rhs):
- return isinstance(rhs, InterfaceRequest) and self.kind == rhs.kind
-
- def __hash__(self):
- return id(self)
-
- def IsBackwardCompatible(self, rhs, checker):
- return isinstance(rhs, InterfaceRequest) and checker.IsBackwardCompatible(
- self.kind, rhs.kind)
-
-
-class AssociatedInterfaceRequest(ReferenceKind):
- ReferenceKind.AddSharedProperty('kind')
-
- def __init__(self, kind=None):
- if kind is not None:
- if not isinstance(kind, InterfaceRequest):
- raise Exception(
- "Associated interface request requires %r to be an interface "
- "request." % kind.spec)
- assert not kind.is_nullable
- ReferenceKind.__init__(self, 'asso:' + kind.spec)
- else:
- ReferenceKind.__init__(self)
- self.kind = kind.kind if kind is not None else None
-
- def __eq__(self, rhs):
- return isinstance(rhs, AssociatedInterfaceRequest) and self.kind == rhs.kind
-
- def __hash__(self):
- return id(self)
-
- def IsBackwardCompatible(self, rhs, checker):
- return isinstance(
- rhs, AssociatedInterfaceRequest) and checker.IsBackwardCompatible(
- self.kind, rhs.kind)
-
-
-class Parameter(object):
- def __init__(self,
- mojom_name=None,
- kind=None,
- ordinal=None,
- default=None,
- attributes=None):
- self.mojom_name = mojom_name
- self.name = None
- self.ordinal = ordinal
- self.kind = kind
- self.default = default
- self.attributes = attributes
-
- def Repr(self, as_ref=True):
- # pylint: disable=unused-argument
- return '<%s mojom_name=%r kind=%s>' % (
- self.__class__.__name__, self.mojom_name, self.kind.Repr(as_ref=True))
-
- def Stylize(self, stylizer):
- self.name = stylizer.StylizeParameter(self.mojom_name)
-
- @property
- def min_version(self):
- return self.attributes.get(ATTRIBUTE_MIN_VERSION) \
- if self.attributes else None
-
- def __eq__(self, rhs):
- return (isinstance(rhs, Parameter)
- and (self.mojom_name, self.ordinal, self.kind, self.default,
- self.attributes) == (rhs.mojom_name, rhs.ordinal, rhs.kind,
- rhs.default, rhs.attributes))
-
-
-class Method(object):
- def __init__(self, interface, mojom_name, ordinal=None, attributes=None):
- self.interface = interface
- self.mojom_name = mojom_name
- self.name = None
- self.explicit_ordinal = ordinal
- self.ordinal = ordinal
- self.parameters = []
- self.param_struct = None
- self.response_parameters = None
- self.response_param_struct = None
- self.attributes = attributes
-
- def Repr(self, as_ref=True):
- if as_ref:
- return '<%s mojom_name=%r>' % (self.__class__.__name__, self.mojom_name)
- else:
- return GenericRepr(self, {
- 'mojom_name': False,
- 'parameters': True,
- 'response_parameters': True
- })
-
- def AddParameter(self,
- mojom_name,
- kind,
- ordinal=None,
- default=None,
- attributes=None):
- parameter = Parameter(mojom_name, kind, ordinal, default, attributes)
- self.parameters.append(parameter)
- return parameter
-
- def AddResponseParameter(self,
- mojom_name,
- kind,
- ordinal=None,
- default=None,
- attributes=None):
- if self.response_parameters == None:
- self.response_parameters = []
- parameter = Parameter(mojom_name, kind, ordinal, default, attributes)
- self.response_parameters.append(parameter)
- return parameter
-
- def Stylize(self, stylizer):
- self.name = stylizer.StylizeMethod(self.mojom_name)
- for param in self.parameters:
- param.Stylize(stylizer)
- if self.response_parameters is not None:
- for param in self.response_parameters:
- param.Stylize(stylizer)
-
- if self.param_struct:
- self.param_struct.Stylize(stylizer)
- if self.response_param_struct:
- self.response_param_struct.Stylize(stylizer)
-
- @property
- def min_version(self):
- return self.attributes.get(ATTRIBUTE_MIN_VERSION) \
- if self.attributes else None
-
- @property
- def sync(self):
- return self.attributes.get(ATTRIBUTE_SYNC) \
- if self.attributes else None
-
- @property
- def allow_interrupt(self):
- return not self.attributes.get(ATTRIBUTE_NO_INTERRUPT) \
- if self.attributes else True
-
- @property
- def unlimited_message_size(self):
- return self.attributes.get(ATTRIBUTE_UNLIMITED_SIZE) \
- if self.attributes else False
-
- def __eq__(self, rhs):
- return (isinstance(rhs, Method) and
- (self.mojom_name, self.ordinal, self.parameters,
- self.response_parameters,
- self.attributes) == (rhs.mojom_name, rhs.ordinal, rhs.parameters,
- rhs.response_parameters, rhs.attributes))
-
-
-class Interface(ReferenceKind):
- ReferenceKind.AddSharedProperty('mojom_name')
- ReferenceKind.AddSharedProperty('name')
- ReferenceKind.AddSharedProperty('methods')
- ReferenceKind.AddSharedProperty('enums')
- ReferenceKind.AddSharedProperty('constants')
- ReferenceKind.AddSharedProperty('attributes')
-
- def __init__(self, mojom_name=None, module=None, attributes=None):
- if mojom_name is not None:
- spec = 'x:' + mojom_name
- else:
- spec = None
- ReferenceKind.__init__(self, spec, False, module)
- self.mojom_name = mojom_name
- self.name = None
- self.methods = []
- self.enums = []
- self.constants = []
- self.attributes = attributes
-
- def Repr(self, as_ref=True):
- if as_ref:
- return '<%s mojom_name=%r>' % (self.__class__.__name__, self.mojom_name)
- else:
- return GenericRepr(self, {
- 'mojom_name': False,
- 'attributes': False,
- 'methods': False
- })
-
- def AddMethod(self, mojom_name, ordinal=None, attributes=None):
- method = Method(self, mojom_name, ordinal, attributes)
- self.methods.append(method)
- return method
-
- def Stylize(self, stylizer):
- self.name = stylizer.StylizeInterface(self.mojom_name)
- for method in self.methods:
- method.Stylize(stylizer)
- for enum in self.enums:
- enum.Stylize(stylizer)
- for constant in self.constants:
- constant.Stylize(stylizer)
-
- def IsBackwardCompatible(self, older_interface, checker):
- """This interface is backward-compatible with older_interface if and only
- if all of the following conditions hold:
- - All defined methods in older_interface (when identified by ordinal) have
- backward-compatible definitions in this interface. For each method this
- means:
- - The parameter list is backward-compatible, according to backward-
- compatibility rules for structs, where each parameter is essentially
- a struct field.
- - If the old method definition does not specify a reply message, the
- new method definition must not specify a reply message.
- - If the old method definition specifies a reply message, the new
- method definition must also specify a reply message with a parameter
- list that is backward-compatible according to backward-compatibility
- rules for structs.
- - All newly introduced methods in this interface have a [MinVersion]
- attribute specifying a version greater than any method in
- older_interface.
- """
-
- def buildOrdinalMethodMap(interface):
- methods_by_ordinal = {}
- for method in interface.methods:
- if method.ordinal in methods_by_ordinal:
- raise Exception('Multiple methods with ordinal %s in interface %s.' %
- (method.ordinal, interface.mojom_name))
- methods_by_ordinal[method.ordinal] = method
- return methods_by_ordinal
-
- new_methods = buildOrdinalMethodMap(self)
- old_methods = buildOrdinalMethodMap(older_interface)
- max_old_min_version = 0
- for ordinal, old_method in old_methods.items():
- new_method = new_methods.get(ordinal)
- if not new_method:
- # A method was removed, which is not OK.
- return False
-
- if not checker.IsBackwardCompatible(new_method.param_struct,
- old_method.param_struct):
- # The parameter list is not backward-compatible, which is not OK.
- return False
-
- if old_method.response_param_struct is None:
- if new_method.response_param_struct is not None:
- # A reply was added to a message which didn't have one before, and
- # this is not OK.
- return False
- else:
- if new_method.response_param_struct is None:
- # A reply was removed from a message, which is not OK.
- return False
- if not checker.IsBackwardCompatible(new_method.response_param_struct,
- old_method.response_param_struct):
- # The new message's reply is not backward-compatible with the old
- # message's reply, which is not OK.
- return False
-
- if (old_method.min_version or 0) > max_old_min_version:
- max_old_min_version = old_method.min_version
-
- # All the old methods are compatible with their new counterparts. Now verify
- # that newly added methods are properly versioned.
- new_ordinals = set(new_methods.keys()) - set(old_methods.keys())
- for ordinal in new_ordinals:
- new_method = new_methods[ordinal]
- if (new_method.min_version or 0) <= max_old_min_version:
- # A method was added to an existing version, which is not OK.
- return False
-
- return True
-
- @property
- def stable(self):
- return self.attributes.get(ATTRIBUTE_STABLE, False) \
- if self.attributes else False
-
- @property
- def qualified_name(self):
- if self.parent_kind:
- prefix = self.parent_kind.qualified_name + '.'
- else:
- prefix = self.module.GetNamespacePrefix()
- return '%s%s' % (prefix, self.mojom_name)
-
- def __eq__(self, rhs):
- return (isinstance(rhs, Interface)
- and (self.mojom_name, self.methods, self.enums, self.constants,
- self.attributes) == (rhs.mojom_name, rhs.methods, rhs.enums,
- rhs.constants, rhs.attributes))
-
- @property
- def uuid(self):
- uuid_str = self.attributes.get(ATTRIBUTE_UUID) if self.attributes else None
- if uuid_str is None:
- return None
-
- try:
- u = UUID(uuid_str)
- except:
- raise ValueError('Invalid format for Uuid attribute on interface {}. '
- 'Expected standard RFC 4122 string representation of '
- 'a UUID.'.format(self.mojom_name))
- return (int(u.hex[:16], 16), int(u.hex[16:], 16))
-
- def __hash__(self):
- return id(self)
-
-
-class AssociatedInterface(ReferenceKind):
- ReferenceKind.AddSharedProperty('kind')
-
- def __init__(self, kind=None):
- if kind is not None:
- if not isinstance(kind, Interface):
- raise Exception(
- "Associated interface requires %r to be an interface." % kind.spec)
- assert not kind.is_nullable
- ReferenceKind.__init__(self, 'asso:' + kind.spec)
- else:
- ReferenceKind.__init__(self)
- self.kind = kind
-
- def __eq__(self, rhs):
- return isinstance(rhs, AssociatedInterface) and self.kind == rhs.kind
-
- def __hash__(self):
- return id(self)
-
- def IsBackwardCompatible(self, rhs, checker):
- return isinstance(rhs,
- AssociatedInterface) and checker.IsBackwardCompatible(
- self.kind, rhs.kind)
-
-
-class EnumField(object):
- def __init__(self,
- mojom_name=None,
- value=None,
- attributes=None,
- numeric_value=None):
- self.mojom_name = mojom_name
- self.name = None
- self.value = value
- self.attributes = attributes
- self.numeric_value = numeric_value
-
- def Stylize(self, stylizer):
- self.name = stylizer.StylizeEnumField(self.mojom_name)
-
- @property
- def default(self):
- return self.attributes.get(ATTRIBUTE_DEFAULT, False) \
- if self.attributes else False
-
- @property
- def min_version(self):
- return self.attributes.get(ATTRIBUTE_MIN_VERSION) \
- if self.attributes else None
-
- def __eq__(self, rhs):
- return (isinstance(rhs, EnumField)
- and (self.mojom_name, self.value, self.attributes,
- self.numeric_value) == (rhs.mojom_name, rhs.value,
- rhs.attributes, rhs.numeric_value))
-
-
-class Enum(Kind):
- def __init__(self, mojom_name=None, module=None, attributes=None):
- self.mojom_name = mojom_name
- self.name = None
- self.native_only = False
- if mojom_name is not None:
- spec = 'x:' + mojom_name
- else:
- spec = None
- Kind.__init__(self, spec, module)
- self.fields = []
- self.attributes = attributes
- self.min_value = None
- self.max_value = None
- self.default_field = None
-
- def Repr(self, as_ref=True):
- if as_ref:
- return '<%s mojom_name=%r>' % (self.__class__.__name__, self.mojom_name)
- else:
- return GenericRepr(self, {'mojom_name': False, 'fields': False})
-
- def Stylize(self, stylizer):
- self.name = stylizer.StylizeEnum(self.mojom_name)
- for field in self.fields:
- field.Stylize(stylizer)
-
- @property
- def extensible(self):
- return self.attributes.get(ATTRIBUTE_EXTENSIBLE, False) \
- if self.attributes else False
-
- @property
- def stable(self):
- return self.attributes.get(ATTRIBUTE_STABLE, False) \
- if self.attributes else False
-
- @property
- def qualified_name(self):
- if self.parent_kind:
- prefix = self.parent_kind.qualified_name + '.'
- else:
- prefix = self.module.GetNamespacePrefix()
- return '%s%s' % (prefix, self.mojom_name)
-
- # pylint: disable=unused-argument
- def IsBackwardCompatible(self, older_enum, checker):
- """This enum is backward-compatible with older_enum if and only if one of
- the following conditions holds:
- - Neither enum is [Extensible] and both have the exact same set of valid
- numeric values. Field names and aliases for the same numeric value do
- not affect compatibility.
- - older_enum is [Extensible], and for every version defined by
- older_enum, this enum has the exact same set of valid numeric values.
- """
-
- def buildVersionFieldMap(enum):
- fields_by_min_version = {}
- for field in enum.fields:
- if field.min_version not in fields_by_min_version:
- fields_by_min_version[field.min_version] = set()
- fields_by_min_version[field.min_version].add(field.numeric_value)
- return fields_by_min_version
-
- old_fields = buildVersionFieldMap(older_enum)
- new_fields = buildVersionFieldMap(self)
-
- if new_fields.keys() != old_fields.keys() and not older_enum.extensible:
- return False
-
- for min_version, valid_values in old_fields.items():
- if (min_version not in new_fields
- or new_fields[min_version] != valid_values):
- return False
-
- return True
-
- def __eq__(self, rhs):
- return (isinstance(rhs, Enum) and
- (self.mojom_name, self.native_only, self.fields, self.attributes,
- self.min_value, self.max_value,
- self.default_field) == (rhs.mojom_name, rhs.native_only,
- rhs.fields, rhs.attributes, rhs.min_value,
- rhs.max_value, rhs.default_field))
-
- def __hash__(self):
- return id(self)
-
-
-class Module(object):
- def __init__(self, path=None, mojom_namespace=None, attributes=None):
- self.path = path
- self.mojom_namespace = mojom_namespace
- self.namespace = None
- self.structs = []
- self.unions = []
- self.interfaces = []
- self.enums = []
- self.constants = []
- self.kinds = {}
- self.attributes = attributes
- self.imports = []
- self.imported_kinds = {}
- self.metadata = {}
-
- def __repr__(self):
- # Gives us a decent __repr__ for modules.
- return self.Repr()
-
- def __eq__(self, rhs):
- return (isinstance(rhs, Module) and
- (self.path, self.attributes, self.mojom_namespace, self.imports,
- self.constants, self.enums, self.structs, self.unions,
- self.interfaces) == (rhs.path, rhs.attributes, rhs.mojom_namespace,
- rhs.imports, rhs.constants, rhs.enums,
- rhs.structs, rhs.unions, rhs.interfaces))
-
- def __hash__(self):
- return id(self)
-
- def Repr(self, as_ref=True):
- if as_ref:
- return '<%s path=%r mojom_namespace=%r>' % (
- self.__class__.__name__, self.path, self.mojom_namespace)
- else:
- return GenericRepr(
- self, {
- 'path': False,
- 'mojom_namespace': False,
- 'attributes': False,
- 'structs': False,
- 'interfaces': False,
- 'unions': False
- })
-
- def GetNamespacePrefix(self):
- return '%s.' % self.mojom_namespace if self.mojom_namespace else ''
-
- def AddInterface(self, mojom_name, attributes=None):
- interface = Interface(mojom_name, self, attributes)
- self.interfaces.append(interface)
- return interface
-
- def AddStruct(self, mojom_name, attributes=None):
- struct = Struct(mojom_name, self, attributes)
- self.structs.append(struct)
- return struct
-
- def AddUnion(self, mojom_name, attributes=None):
- union = Union(mojom_name, self, attributes)
- self.unions.append(union)
- return union
-
- def Stylize(self, stylizer):
- self.namespace = stylizer.StylizeModule(self.mojom_namespace)
- for struct in self.structs:
- struct.Stylize(stylizer)
- for union in self.unions:
- union.Stylize(stylizer)
- for interface in self.interfaces:
- interface.Stylize(stylizer)
- for enum in self.enums:
- enum.Stylize(stylizer)
- for constant in self.constants:
- constant.Stylize(stylizer)
-
- for imported_module in self.imports:
- imported_module.Stylize(stylizer)
-
- def Dump(self, f):
- pickle.dump(self, f, 2)
-
- @classmethod
- def Load(cls, f):
- result = pickle.load(f)
- assert isinstance(result, Module)
- return result
-
-
-def IsBoolKind(kind):
- return kind.spec == BOOL.spec
-
-
-def IsFloatKind(kind):
- return kind.spec == FLOAT.spec
-
-
-def IsDoubleKind(kind):
- return kind.spec == DOUBLE.spec
-
-
-def IsIntegralKind(kind):
- return (kind.spec == BOOL.spec or kind.spec == INT8.spec
- or kind.spec == INT16.spec or kind.spec == INT32.spec
- or kind.spec == INT64.spec or kind.spec == UINT8.spec
- or kind.spec == UINT16.spec or kind.spec == UINT32.spec
- or kind.spec == UINT64.spec)
-
-
-def IsStringKind(kind):
- return kind.spec == STRING.spec or kind.spec == NULLABLE_STRING.spec
-
-
-def IsGenericHandleKind(kind):
- return kind.spec == HANDLE.spec or kind.spec == NULLABLE_HANDLE.spec
-
-
-def IsDataPipeConsumerKind(kind):
- return kind.spec == DCPIPE.spec or kind.spec == NULLABLE_DCPIPE.spec
-
-
-def IsDataPipeProducerKind(kind):
- return kind.spec == DPPIPE.spec or kind.spec == NULLABLE_DPPIPE.spec
-
-
-def IsMessagePipeKind(kind):
- return kind.spec == MSGPIPE.spec or kind.spec == NULLABLE_MSGPIPE.spec
-
-
-def IsSharedBufferKind(kind):
- return (kind.spec == SHAREDBUFFER.spec
- or kind.spec == NULLABLE_SHAREDBUFFER.spec)
-
-
-def IsPlatformHandleKind(kind):
- return (kind.spec == PLATFORMHANDLE.spec
- or kind.spec == NULLABLE_PLATFORMHANDLE.spec)
-
-
-def IsStructKind(kind):
- return isinstance(kind, Struct)
-
-
-def IsUnionKind(kind):
- return isinstance(kind, Union)
-
-
-def IsArrayKind(kind):
- return isinstance(kind, Array)
-
-
-def IsInterfaceKind(kind):
- return isinstance(kind, Interface)
-
-
-def IsAssociatedInterfaceKind(kind):
- return isinstance(kind, AssociatedInterface)
-
-
-def IsInterfaceRequestKind(kind):
- return isinstance(kind, InterfaceRequest)
-
-
-def IsAssociatedInterfaceRequestKind(kind):
- return isinstance(kind, AssociatedInterfaceRequest)
-
-
-def IsPendingRemoteKind(kind):
- return isinstance(kind, PendingRemote)
-
-
-def IsPendingReceiverKind(kind):
- return isinstance(kind, PendingReceiver)
-
-
-def IsPendingAssociatedRemoteKind(kind):
- return isinstance(kind, PendingAssociatedRemote)
-
-
-def IsPendingAssociatedReceiverKind(kind):
- return isinstance(kind, PendingAssociatedReceiver)
-
-
-def IsEnumKind(kind):
- return isinstance(kind, Enum)
-
-
-def IsReferenceKind(kind):
- return isinstance(kind, ReferenceKind)
-
-
-def IsNullableKind(kind):
- return IsReferenceKind(kind) and kind.is_nullable
-
-
-def IsMapKind(kind):
- return isinstance(kind, Map)
-
-
-def IsObjectKind(kind):
- return IsPointerKind(kind) or IsUnionKind(kind)
-
-
-def IsPointerKind(kind):
- return (IsStructKind(kind) or IsArrayKind(kind) or IsStringKind(kind)
- or IsMapKind(kind))
-
-
-# Please note that it doesn't include any interface kind.
-def IsAnyHandleKind(kind):
- return (IsGenericHandleKind(kind) or IsDataPipeConsumerKind(kind)
- or IsDataPipeProducerKind(kind) or IsMessagePipeKind(kind)
- or IsSharedBufferKind(kind) or IsPlatformHandleKind(kind))
-
-
-def IsAnyInterfaceKind(kind):
- return (IsInterfaceKind(kind) or IsInterfaceRequestKind(kind)
- or IsAssociatedKind(kind) or IsPendingRemoteKind(kind)
- or IsPendingReceiverKind(kind))
-
-
-def IsAnyHandleOrInterfaceKind(kind):
- return IsAnyHandleKind(kind) or IsAnyInterfaceKind(kind)
-
-
-def IsAssociatedKind(kind):
- return (IsAssociatedInterfaceKind(kind)
- or IsAssociatedInterfaceRequestKind(kind)
- or IsPendingAssociatedRemoteKind(kind)
- or IsPendingAssociatedReceiverKind(kind))
-
-
-def HasCallbacks(interface):
- for method in interface.methods:
- if method.response_parameters != None:
- return True
- return False
-
-
-# Finds out whether an interface passes associated interfaces and associated
-# interface requests.
-def PassesAssociatedKinds(interface):
- visited_kinds = set()
- for method in interface.methods:
- if MethodPassesAssociatedKinds(method, visited_kinds):
- return True
- return False
-
-
-def _AnyMethodParameterRecursive(method, predicate, visited_kinds=None):
- def _HasProperty(kind):
- if kind in visited_kinds:
- # No need to examine the kind again.
- return False
- visited_kinds.add(kind)
- if predicate(kind):
- return True
- if IsArrayKind(kind):
- return _HasProperty(kind.kind)
- if IsStructKind(kind) or IsUnionKind(kind):
- for field in kind.fields:
- if _HasProperty(field.kind):
- return True
- if IsMapKind(kind):
- if _HasProperty(kind.key_kind) or _HasProperty(kind.value_kind):
- return True
- return False
-
- if visited_kinds is None:
- visited_kinds = set()
-
- for param in method.parameters:
- if _HasProperty(param.kind):
- return True
- if method.response_parameters != None:
- for param in method.response_parameters:
- if _HasProperty(param.kind):
- return True
- return False
-
-
-# Finds out whether a method passes associated interfaces and associated
-# interface requests.
-def MethodPassesAssociatedKinds(method, visited_kinds=None):
- return _AnyMethodParameterRecursive(
- method, IsAssociatedKind, visited_kinds=visited_kinds)
-
-
-# Determines whether a method passes interfaces.
-def MethodPassesInterfaces(method):
- return _AnyMethodParameterRecursive(method, IsInterfaceKind)
-
-
-def HasSyncMethods(interface):
- for method in interface.methods:
- if method.sync:
- return True
- return False
-
-
-def HasUninterruptableMethods(interface):
- for method in interface.methods:
- if not method.allow_interrupt:
- return True
- return False
-
-
-def ContainsHandlesOrInterfaces(kind):
- """Check if the kind contains any handles.
-
- This check is recursive so it checks all struct fields, containers elements,
- etc.
-
- Args:
- struct: {Kind} The kind to check.
-
- Returns:
- {bool}: True if the kind contains handles.
- """
- # We remember the types we already checked to avoid infinite recursion when
- # checking recursive (or mutually recursive) types:
- checked = set()
-
- def Check(kind):
- if kind.spec in checked:
- return False
- checked.add(kind.spec)
- if IsStructKind(kind):
- return any(Check(field.kind) for field in kind.fields)
- elif IsUnionKind(kind):
- return any(Check(field.kind) for field in kind.fields)
- elif IsAnyHandleKind(kind):
- return True
- elif IsAnyInterfaceKind(kind):
- return True
- elif IsArrayKind(kind):
- return Check(kind.kind)
- elif IsMapKind(kind):
- return Check(kind.key_kind) or Check(kind.value_kind)
- else:
- return False
-
- return Check(kind)
-
-
-def ContainsNativeTypes(kind):
- """Check if the kind contains any native type (struct or enum).
-
- This check is recursive so it checks all struct fields, scoped interface
- enums, etc.
-
- Args:
- struct: {Kind} The kind to check.
-
- Returns:
- {bool}: True if the kind contains native types.
- """
- # We remember the types we already checked to avoid infinite recursion when
- # checking recursive (or mutually recursive) types:
- checked = set()
-
- def Check(kind):
- if kind.spec in checked:
- return False
- checked.add(kind.spec)
- if IsEnumKind(kind):
- return kind.native_only
- elif IsStructKind(kind):
- if kind.native_only:
- return True
- if any(enum.native_only for enum in kind.enums):
- return True
- return any(Check(field.kind) for field in kind.fields)
- elif IsUnionKind(kind):
- return any(Check(field.kind) for field in kind.fields)
- elif IsInterfaceKind(kind):
- return any(enum.native_only for enum in kind.enums)
- elif IsArrayKind(kind):
- return Check(kind.kind)
- elif IsMapKind(kind):
- return Check(kind.key_kind) or Check(kind.value_kind)
- else:
- return False
-
- return Check(kind)