1# Copyright 2013 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5# This module's classes provide an interface to mojo modules. Modules are 6# collections of interfaces and structs to be used by mojo ipc clients and 7# servers. 8# 9# A simple interface would be created this way: 10# module = mojom.generate.module.Module('Foo') 11# interface = module.AddInterface('Bar') 12# method = interface.AddMethod('Tat', 0) 13# method.AddParameter('baz', 0, mojom.INT32) 14 15 16# We use our own version of __repr__ when displaying the AST, as the 17# AST currently doesn't capture which nodes are reference (e.g. to 18# types) and which nodes are definitions. This allows us to e.g. print 19# the definition of a struct when it's defined inside a module, but 20# only print its name when it's referenced in e.g. a method parameter. 21def Repr(obj, as_ref=True): 22 """A version of __repr__ that can distinguish references. 23 24 Sometimes we like to print an object's full representation 25 (e.g. with its fields) and sometimes we just want to reference an 26 object that was printed in full elsewhere. This function allows us 27 to make that distinction. 28 29 Args: 30 obj: The object whose string representation we compute. 31 as_ref: If True, use the short reference representation. 32 33 Returns: 34 A str representation of |obj|. 35 """ 36 if hasattr(obj, 'Repr'): 37 return obj.Repr(as_ref=as_ref) 38 # Since we cannot implement Repr for existing container types, we 39 # handle them here. 40 elif isinstance(obj, list): 41 if not obj: 42 return '[]' 43 else: 44 return ('[\n%s\n]' % (',\n'.join(' %s' % Repr(elem, as_ref).replace( 45 '\n', '\n ') for elem in obj))) 46 elif isinstance(obj, dict): 47 if not obj: 48 return '{}' 49 else: 50 return ('{\n%s\n}' % (',\n'.join(' %s: %s' % ( 51 Repr(key, as_ref).replace('\n', '\n '), 52 Repr(val, as_ref).replace('\n', '\n ')) 53 for key, val in obj.iteritems()))) 54 else: 55 return repr(obj) 56 57 58def GenericRepr(obj, names): 59 """Compute generic Repr for |obj| based on the attributes in |names|. 60 61 Args: 62 obj: The object to compute a Repr for. 63 names: A dict from attribute names to include, to booleans 64 specifying whether those attributes should be shown as 65 references or not. 66 67 Returns: 68 A str representation of |obj|. 69 """ 70 def ReprIndent(name, as_ref): 71 return ' %s=%s' % (name, Repr(getattr(obj, name), as_ref).replace( 72 '\n', '\n ')) 73 74 return '%s(\n%s\n)' % ( 75 obj.__class__.__name__, 76 ',\n'.join(ReprIndent(name, as_ref) 77 for (name, as_ref) in names.iteritems())) 78 79 80class Kind(object): 81 """Kind represents a type (e.g. int8, string). 82 83 Attributes: 84 spec: A string uniquely identifying the type. May be None. 85 parent_kind: The enclosing type. For example, a struct defined 86 inside an interface has that interface as its parent. May be None. 87 """ 88 def __init__(self, spec=None): 89 self.spec = spec 90 self.parent_kind = None 91 92 def Repr(self, as_ref=True): 93 return '<%s spec=%r>' % (self.__class__.__name__, self.spec) 94 95 def __repr__(self): 96 # Gives us a decent __repr__ for all kinds. 97 return self.Repr() 98 99 100class ReferenceKind(Kind): 101 """ReferenceKind represents pointer and handle types. 102 103 A type is nullable if null (for pointer types) or invalid handle (for handle 104 types) is a legal value for the type. 105 106 Attributes: 107 is_nullable: True if the type is nullable. 108 """ 109 110 def __init__(self, spec=None, is_nullable=False): 111 assert spec is None or is_nullable == spec.startswith('?') 112 Kind.__init__(self, spec) 113 self.is_nullable = is_nullable 114 self.shared_definition = {} 115 116 def Repr(self, as_ref=True): 117 return '<%s spec=%r is_nullable=%r>' % (self.__class__.__name__, self.spec, 118 self.is_nullable) 119 120 def MakeNullableKind(self): 121 assert not self.is_nullable 122 123 if self == STRING: 124 return NULLABLE_STRING 125 if self == HANDLE: 126 return NULLABLE_HANDLE 127 if self == DCPIPE: 128 return NULLABLE_DCPIPE 129 if self == DPPIPE: 130 return NULLABLE_DPPIPE 131 if self == MSGPIPE: 132 return NULLABLE_MSGPIPE 133 if self == SHAREDBUFFER: 134 return NULLABLE_SHAREDBUFFER 135 136 nullable_kind = type(self)() 137 nullable_kind.shared_definition = self.shared_definition 138 if self.spec is not None: 139 nullable_kind.spec = '?' + self.spec 140 nullable_kind.is_nullable = True 141 142 return nullable_kind 143 144 @classmethod 145 def AddSharedProperty(cls, name): 146 """Adds a property |name| to |cls|, which accesses the corresponding item in 147 |shared_definition|. 148 149 The reason of adding such indirection is to enable sharing definition 150 between a reference kind and its nullable variation. For example: 151 a = Struct('test_struct_1') 152 b = a.MakeNullableKind() 153 a.name = 'test_struct_2' 154 print b.name # Outputs 'test_struct_2'. 155 """ 156 def Get(self): 157 return self.shared_definition[name] 158 159 def Set(self, value): 160 self.shared_definition[name] = value 161 162 setattr(cls, name, property(Get, Set)) 163 164 165# Initialize the set of primitive types. These can be accessed by clients. 166BOOL = Kind('b') 167INT8 = Kind('i8') 168INT16 = Kind('i16') 169INT32 = Kind('i32') 170INT64 = Kind('i64') 171UINT8 = Kind('u8') 172UINT16 = Kind('u16') 173UINT32 = Kind('u32') 174UINT64 = Kind('u64') 175FLOAT = Kind('f') 176DOUBLE = Kind('d') 177STRING = ReferenceKind('s') 178HANDLE = ReferenceKind('h') 179DCPIPE = ReferenceKind('h:d:c') 180DPPIPE = ReferenceKind('h:d:p') 181MSGPIPE = ReferenceKind('h:m') 182SHAREDBUFFER = ReferenceKind('h:s') 183NULLABLE_STRING = ReferenceKind('?s', True) 184NULLABLE_HANDLE = ReferenceKind('?h', True) 185NULLABLE_DCPIPE = ReferenceKind('?h:d:c', True) 186NULLABLE_DPPIPE = ReferenceKind('?h:d:p', True) 187NULLABLE_MSGPIPE = ReferenceKind('?h:m', True) 188NULLABLE_SHAREDBUFFER = ReferenceKind('?h:s', True) 189 190 191# Collection of all Primitive types 192PRIMITIVES = ( 193 BOOL, 194 INT8, 195 INT16, 196 INT32, 197 INT64, 198 UINT8, 199 UINT16, 200 UINT32, 201 UINT64, 202 FLOAT, 203 DOUBLE, 204 STRING, 205 HANDLE, 206 DCPIPE, 207 DPPIPE, 208 MSGPIPE, 209 SHAREDBUFFER, 210 NULLABLE_STRING, 211 NULLABLE_HANDLE, 212 NULLABLE_DCPIPE, 213 NULLABLE_DPPIPE, 214 NULLABLE_MSGPIPE, 215 NULLABLE_SHAREDBUFFER 216) 217 218 219ATTRIBUTE_MIN_VERSION = 'MinVersion' 220ATTRIBUTE_EXTENSIBLE = 'Extensible' 221ATTRIBUTE_SYNC = 'Sync' 222 223 224class NamedValue(object): 225 def __init__(self, module, parent_kind, name): 226 self.module = module 227 self.namespace = module.namespace 228 self.parent_kind = parent_kind 229 self.name = name 230 self.imported_from = None 231 232 def GetSpec(self): 233 return (self.namespace + '.' + 234 (self.parent_kind and (self.parent_kind.name + '.') or "") + 235 self.name) 236 237 238class BuiltinValue(object): 239 def __init__(self, value): 240 self.value = value 241 242 243class ConstantValue(NamedValue): 244 def __init__(self, module, parent_kind, constant): 245 NamedValue.__init__(self, module, parent_kind, constant.name) 246 self.constant = constant 247 248 249class EnumValue(NamedValue): 250 def __init__(self, module, enum, field): 251 NamedValue.__init__(self, module, enum.parent_kind, field.name) 252 self.enum = enum 253 254 def GetSpec(self): 255 return (self.namespace + '.' + 256 (self.parent_kind and (self.parent_kind.name + '.') or "") + 257 self.enum.name + '.' + self.name) 258 259 260class Constant(object): 261 def __init__(self, name=None, kind=None, value=None, parent_kind=None): 262 self.name = name 263 self.kind = kind 264 self.value = value 265 self.parent_kind = parent_kind 266 267 268class Field(object): 269 def __init__(self, name=None, kind=None, ordinal=None, default=None, 270 attributes=None): 271 if self.__class__.__name__ == 'Field': 272 raise Exception() 273 self.name = name 274 self.kind = kind 275 self.ordinal = ordinal 276 self.default = default 277 self.attributes = attributes 278 279 def Repr(self, as_ref=True): 280 # Fields are only referenced by objects which define them and thus 281 # they are always displayed as non-references. 282 return GenericRepr(self, {'name': False, 'kind': True}) 283 284 @property 285 def min_version(self): 286 return self.attributes.get(ATTRIBUTE_MIN_VERSION) \ 287 if self.attributes else None 288 289 290class StructField(Field): pass 291 292 293class UnionField(Field): pass 294 295 296class Struct(ReferenceKind): 297 ReferenceKind.AddSharedProperty('name') 298 ReferenceKind.AddSharedProperty('native_only') 299 ReferenceKind.AddSharedProperty('module') 300 ReferenceKind.AddSharedProperty('imported_from') 301 ReferenceKind.AddSharedProperty('fields') 302 ReferenceKind.AddSharedProperty('attributes') 303 304 def __init__(self, name=None, module=None, attributes=None): 305 if name is not None: 306 spec = 'x:' + name 307 else: 308 spec = None 309 ReferenceKind.__init__(self, spec) 310 self.name = name 311 self.native_only = False 312 self.module = module 313 self.imported_from = None 314 self.fields = [] 315 self.attributes = attributes 316 317 def Repr(self, as_ref=True): 318 if as_ref: 319 return '<%s name=%r imported_from=%s>' % ( 320 self.__class__.__name__, self.name, 321 Repr(self.imported_from, as_ref=True)) 322 else: 323 return GenericRepr(self, {'name': False, 'fields': False, 324 'imported_from': True}) 325 326 def AddField(self, name, kind, ordinal=None, default=None, attributes=None): 327 field = StructField(name, kind, ordinal, default, attributes) 328 self.fields.append(field) 329 return field 330 331 332class Union(ReferenceKind): 333 """A union of several kinds. 334 335 Attributes: 336 name: {str} The name of the union type. 337 module: {Module} The defining module. 338 imported_from: {dict} Information about where this union was 339 imported from. 340 fields: {List[UnionField]} The members of the union. 341 attributes: {dict} Additional information about the union, such as 342 which Java class name to use to represent it in the generated 343 bindings. 344 """ 345 ReferenceKind.AddSharedProperty('name') 346 ReferenceKind.AddSharedProperty('module') 347 ReferenceKind.AddSharedProperty('imported_from') 348 ReferenceKind.AddSharedProperty('fields') 349 ReferenceKind.AddSharedProperty('attributes') 350 351 def __init__(self, name=None, module=None, attributes=None): 352 if name is not None: 353 spec = 'x:' + name 354 else: 355 spec = None 356 ReferenceKind.__init__(self, spec) 357 self.name = name 358 self.module = module 359 self.imported_from = None 360 self.fields = [] 361 self.attributes = attributes 362 363 def Repr(self, as_ref=True): 364 if as_ref: 365 return '<%s spec=%r is_nullable=%r fields=%s>' % ( 366 self.__class__.__name__, self.spec, self.is_nullable, 367 Repr(self.fields)) 368 else: 369 return GenericRepr(self, {'fields': True, 'is_nullable': False}) 370 371 def AddField(self, name, kind, ordinal=None, attributes=None): 372 field = UnionField(name, kind, ordinal, None, attributes) 373 self.fields.append(field) 374 return field 375 376 377class Array(ReferenceKind): 378 """An array. 379 380 Attributes: 381 kind: {Kind} The type of the elements. May be None. 382 length: The number of elements. None if unknown. 383 """ 384 385 ReferenceKind.AddSharedProperty('kind') 386 ReferenceKind.AddSharedProperty('length') 387 388 def __init__(self, kind=None, length=None): 389 if kind is not None: 390 if length is not None: 391 spec = 'a%d:%s' % (length, kind.spec) 392 else: 393 spec = 'a:%s' % kind.spec 394 395 ReferenceKind.__init__(self, spec) 396 else: 397 ReferenceKind.__init__(self) 398 self.kind = kind 399 self.length = length 400 401 def Repr(self, as_ref=True): 402 if as_ref: 403 return '<%s spec=%r is_nullable=%r kind=%s length=%r>' % ( 404 self.__class__.__name__, self.spec, self.is_nullable, Repr(self.kind), 405 self.length) 406 else: 407 return GenericRepr(self, {'kind': True, 'length': False, 408 'is_nullable': False}) 409 410 411class Map(ReferenceKind): 412 """A map. 413 414 Attributes: 415 key_kind: {Kind} The type of the keys. May be None. 416 value_kind: {Kind} The type of the elements. May be None. 417 """ 418 ReferenceKind.AddSharedProperty('key_kind') 419 ReferenceKind.AddSharedProperty('value_kind') 420 421 def __init__(self, key_kind=None, value_kind=None): 422 if (key_kind is not None and value_kind is not None): 423 ReferenceKind.__init__(self, 424 'm[' + key_kind.spec + '][' + value_kind.spec + 425 ']') 426 if IsNullableKind(key_kind): 427 raise Exception("Nullable kinds cannot be keys in maps.") 428 if IsStructKind(key_kind): 429 # TODO(erg): It would sometimes be nice if we could key on struct 430 # values. However, what happens if the struct has a handle in it? Or 431 # non-copyable data like an array? 432 raise Exception("Structs cannot be keys in maps.") 433 if IsAnyHandleKind(key_kind): 434 raise Exception("Handles cannot be keys in maps.") 435 if IsInterfaceKind(key_kind): 436 raise Exception("Interfaces cannot be keys in maps.") 437 if IsArrayKind(key_kind): 438 raise Exception("Arrays cannot be keys in maps.") 439 else: 440 ReferenceKind.__init__(self) 441 442 self.key_kind = key_kind 443 self.value_kind = value_kind 444 445 def Repr(self, as_ref=True): 446 if as_ref: 447 return '<%s spec=%r is_nullable=%r key_kind=%s value_kind=%s>' % ( 448 self.__class__.__name__, self.spec, self.is_nullable, 449 Repr(self.key_kind), Repr(self.value_kind)) 450 else: 451 return GenericRepr(self, {'key_kind': True, 'value_kind': True}) 452 453 454class InterfaceRequest(ReferenceKind): 455 ReferenceKind.AddSharedProperty('kind') 456 457 def __init__(self, kind=None): 458 if kind is not None: 459 if not isinstance(kind, Interface): 460 raise Exception( 461 "Interface request requires %r to be an interface." % kind.spec) 462 ReferenceKind.__init__(self, 'r:' + kind.spec) 463 else: 464 ReferenceKind.__init__(self) 465 self.kind = kind 466 467 468class AssociatedInterfaceRequest(ReferenceKind): 469 ReferenceKind.AddSharedProperty('kind') 470 471 def __init__(self, kind=None): 472 if kind is not None: 473 if not isinstance(kind, InterfaceRequest): 474 raise Exception( 475 "Associated interface request requires %r to be an interface " 476 "request." % kind.spec) 477 assert not kind.is_nullable 478 ReferenceKind.__init__(self, 'asso:' + kind.spec) 479 else: 480 ReferenceKind.__init__(self) 481 self.kind = kind.kind if kind is not None else None 482 483 484class Parameter(object): 485 def __init__(self, name=None, kind=None, ordinal=None, default=None, 486 attributes=None): 487 self.name = name 488 self.ordinal = ordinal 489 self.kind = kind 490 self.default = default 491 self.attributes = attributes 492 493 def Repr(self, as_ref=True): 494 return '<%s name=%r kind=%s>' % (self.__class__.__name__, self.name, 495 self.kind.Repr(as_ref=True)) 496 497 @property 498 def min_version(self): 499 return self.attributes.get(ATTRIBUTE_MIN_VERSION) \ 500 if self.attributes else None 501 502 503class Method(object): 504 def __init__(self, interface, name, ordinal=None, attributes=None): 505 self.interface = interface 506 self.name = name 507 self.ordinal = ordinal 508 self.parameters = [] 509 self.response_parameters = None 510 self.attributes = attributes 511 512 def Repr(self, as_ref=True): 513 if as_ref: 514 return '<%s name=%r>' % (self.__class__.__name__, self.name) 515 else: 516 return GenericRepr(self, {'name': False, 'parameters': True, 517 'response_parameters': True}) 518 519 def AddParameter(self, name, kind, ordinal=None, default=None, 520 attributes=None): 521 parameter = Parameter(name, kind, ordinal, default, attributes) 522 self.parameters.append(parameter) 523 return parameter 524 525 def AddResponseParameter(self, name, kind, ordinal=None, default=None, 526 attributes=None): 527 if self.response_parameters == None: 528 self.response_parameters = [] 529 parameter = Parameter(name, kind, ordinal, default, attributes) 530 self.response_parameters.append(parameter) 531 return parameter 532 533 @property 534 def min_version(self): 535 return self.attributes.get(ATTRIBUTE_MIN_VERSION) \ 536 if self.attributes else None 537 538 @property 539 def sync(self): 540 return self.attributes.get(ATTRIBUTE_SYNC) \ 541 if self.attributes else None 542 543 544class Interface(ReferenceKind): 545 ReferenceKind.AddSharedProperty('module') 546 ReferenceKind.AddSharedProperty('name') 547 ReferenceKind.AddSharedProperty('imported_from') 548 ReferenceKind.AddSharedProperty('methods') 549 ReferenceKind.AddSharedProperty('attributes') 550 551 def __init__(self, name=None, module=None, attributes=None): 552 if name is not None: 553 spec = 'x:' + name 554 else: 555 spec = None 556 ReferenceKind.__init__(self, spec) 557 self.module = module 558 self.name = name 559 self.imported_from = None 560 self.methods = [] 561 self.attributes = attributes 562 563 def Repr(self, as_ref=True): 564 if as_ref: 565 return '<%s name=%r>' % (self.__class__.__name__, self.name) 566 else: 567 return GenericRepr(self, {'name': False, 'attributes': False, 568 'methods': False}) 569 570 def AddMethod(self, name, ordinal=None, attributes=None): 571 method = Method(self, name, ordinal, attributes) 572 self.methods.append(method) 573 return method 574 575 # TODO(451323): Remove when the language backends no longer rely on this. 576 @property 577 def client(self): 578 return None 579 580 581class AssociatedInterface(ReferenceKind): 582 ReferenceKind.AddSharedProperty('kind') 583 584 def __init__(self, kind=None): 585 if kind is not None: 586 if not isinstance(kind, Interface): 587 raise Exception( 588 "Associated interface requires %r to be an interface." % kind.spec) 589 assert not kind.is_nullable 590 ReferenceKind.__init__(self, 'asso:' + kind.spec) 591 else: 592 ReferenceKind.__init__(self) 593 self.kind = kind 594 595 596class EnumField(object): 597 def __init__(self, name=None, value=None, attributes=None, 598 numeric_value=None): 599 self.name = name 600 self.value = value 601 self.attributes = attributes 602 self.numeric_value = numeric_value 603 604 @property 605 def min_version(self): 606 return self.attributes.get(ATTRIBUTE_MIN_VERSION) \ 607 if self.attributes else None 608 609 610class Enum(Kind): 611 def __init__(self, name=None, module=None, attributes=None): 612 self.module = module 613 self.name = name 614 self.native_only = False 615 self.imported_from = None 616 if name is not None: 617 spec = 'x:' + name 618 else: 619 spec = None 620 Kind.__init__(self, spec) 621 self.fields = [] 622 self.attributes = attributes 623 624 def Repr(self, as_ref=True): 625 if as_ref: 626 return '<%s name=%r>' % (self.__class__.__name__, self.name) 627 else: 628 return GenericRepr(self, {'name': False, 'fields': False}) 629 630 @property 631 def extensible(self): 632 return self.attributes.get(ATTRIBUTE_EXTENSIBLE, False) \ 633 if self.attributes else False 634 635 636class Module(object): 637 def __init__(self, name=None, namespace=None, attributes=None): 638 self.name = name 639 self.path = name 640 self.namespace = namespace 641 self.structs = [] 642 self.unions = [] 643 self.interfaces = [] 644 self.kinds = {} 645 self.attributes = attributes 646 647 def __repr__(self): 648 # Gives us a decent __repr__ for modules. 649 return self.Repr() 650 651 def Repr(self, as_ref=True): 652 if as_ref: 653 return '<%s name=%r namespace=%r>' % ( 654 self.__class__.__name__, self.name, self.namespace) 655 else: 656 return GenericRepr(self, {'name': False, 'namespace': False, 657 'attributes': False, 'structs': False, 658 'interfaces': False, 'unions': False}) 659 660 def AddInterface(self, name, attributes=None): 661 interface = Interface(name, self, attributes) 662 self.interfaces.append(interface) 663 return interface 664 665 def AddStruct(self, name, attributes=None): 666 struct = Struct(name, self, attributes) 667 self.structs.append(struct) 668 return struct 669 670 def AddUnion(self, name, attributes=None): 671 union = Union(name, self, attributes) 672 self.unions.append(union) 673 return union 674 675 676def IsBoolKind(kind): 677 return kind.spec == BOOL.spec 678 679 680def IsFloatKind(kind): 681 return kind.spec == FLOAT.spec 682 683 684def IsIntegralKind(kind): 685 return (kind.spec == BOOL.spec or 686 kind.spec == INT8.spec or 687 kind.spec == INT16.spec or 688 kind.spec == INT32.spec or 689 kind.spec == INT64.spec or 690 kind.spec == UINT8.spec or 691 kind.spec == UINT16.spec or 692 kind.spec == UINT32.spec or 693 kind.spec == UINT64.spec) 694 695 696def IsStringKind(kind): 697 return kind.spec == STRING.spec or kind.spec == NULLABLE_STRING.spec 698 699 700def IsGenericHandleKind(kind): 701 return kind.spec == HANDLE.spec or kind.spec == NULLABLE_HANDLE.spec 702 703 704def IsDataPipeConsumerKind(kind): 705 return kind.spec == DCPIPE.spec or kind.spec == NULLABLE_DCPIPE.spec 706 707 708def IsDataPipeProducerKind(kind): 709 return kind.spec == DPPIPE.spec or kind.spec == NULLABLE_DPPIPE.spec 710 711 712def IsMessagePipeKind(kind): 713 return kind.spec == MSGPIPE.spec or kind.spec == NULLABLE_MSGPIPE.spec 714 715 716def IsSharedBufferKind(kind): 717 return (kind.spec == SHAREDBUFFER.spec or 718 kind.spec == NULLABLE_SHAREDBUFFER.spec) 719 720 721def IsStructKind(kind): 722 return isinstance(kind, Struct) 723 724 725def IsUnionKind(kind): 726 return isinstance(kind, Union) 727 728 729def IsArrayKind(kind): 730 return isinstance(kind, Array) 731 732 733def IsInterfaceKind(kind): 734 return isinstance(kind, Interface) 735 736 737def IsAssociatedInterfaceKind(kind): 738 return isinstance(kind, AssociatedInterface) 739 740 741def IsInterfaceRequestKind(kind): 742 return isinstance(kind, InterfaceRequest) 743 744 745def IsAssociatedInterfaceRequestKind(kind): 746 return isinstance(kind, AssociatedInterfaceRequest) 747 748 749def IsEnumKind(kind): 750 return isinstance(kind, Enum) 751 752 753def IsReferenceKind(kind): 754 return isinstance(kind, ReferenceKind) 755 756 757def IsNullableKind(kind): 758 return IsReferenceKind(kind) and kind.is_nullable 759 760 761def IsMapKind(kind): 762 return isinstance(kind, Map) 763 764 765def IsObjectKind(kind): 766 return IsPointerKind(kind) or IsUnionKind(kind) 767 768 769def IsPointerKind(kind): 770 return (IsStructKind(kind) or IsArrayKind(kind) or IsStringKind(kind) or 771 IsMapKind(kind)) 772 773 774# Please note that interface is not considered as handle kind, since it is an 775# aggregate type consisting of a handle and a version number. 776def IsAnyHandleKind(kind): 777 return (IsGenericHandleKind(kind) or 778 IsDataPipeConsumerKind(kind) or 779 IsDataPipeProducerKind(kind) or 780 IsMessagePipeKind(kind) or 781 IsSharedBufferKind(kind) or 782 IsInterfaceRequestKind(kind)) 783 784 785def IsAnyHandleOrInterfaceKind(kind): 786 return (IsAnyHandleKind(kind) or IsInterfaceKind(kind) or 787 IsAssociatedKind(kind)) 788 789 790def IsAssociatedKind(kind): 791 return (IsAssociatedInterfaceKind(kind) or 792 IsAssociatedInterfaceRequestKind(kind)) 793 794 795def HasCallbacks(interface): 796 for method in interface.methods: 797 if method.response_parameters != None: 798 return True 799 return False 800 801 802# Finds out whether an interface passes associated interfaces and associated 803# interface requests. 804def PassesAssociatedKinds(interface): 805 def _ContainsAssociatedKinds(kind, visited_kinds): 806 if kind in visited_kinds: 807 # No need to examine the kind again. 808 return False 809 visited_kinds.add(kind) 810 if IsAssociatedKind(kind): 811 return True 812 if IsArrayKind(kind): 813 return _ContainsAssociatedKinds(kind.kind, visited_kinds) 814 if IsStructKind(kind) or IsUnionKind(kind): 815 for field in kind.fields: 816 if _ContainsAssociatedKinds(field.kind, visited_kinds): 817 return True 818 if IsMapKind(kind): 819 # No need to examine the key kind, only primitive kinds and non-nullable 820 # string are allowed to be key kinds. 821 return _ContainsAssociatedKinds(kind.value_kind, visited_kinds) 822 return False 823 824 visited_kinds = set() 825 for method in interface.methods: 826 for param in method.parameters: 827 if _ContainsAssociatedKinds(param.kind, visited_kinds): 828 return True 829 if method.response_parameters != None: 830 for param in method.response_parameters: 831 if _ContainsAssociatedKinds(param.kind, visited_kinds): 832 return True 833 return False 834 835 836def HasSyncMethods(interface): 837 for method in interface.methods: 838 if method.sync: 839 return True 840 return False 841