| OLD | NEW |
| (Empty) |
| 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 class Kind(object): | |
| 17 def __init__(self, spec=None): | |
| 18 self.spec = spec | |
| 19 self.parent_kind = None | |
| 20 | |
| 21 | |
| 22 class ReferenceKind(Kind): | |
| 23 """ReferenceKind represents pointer types and handle types. | |
| 24 A type is nullable if null (for pointer types) or invalid handle (for handle | |
| 25 types) is a legal value for the type. | |
| 26 """ | |
| 27 | |
| 28 def __init__(self, spec=None, is_nullable=False): | |
| 29 assert spec is None or is_nullable == spec.startswith('?') | |
| 30 Kind.__init__(self, spec) | |
| 31 self.is_nullable = is_nullable | |
| 32 self.shared_definition = {} | |
| 33 | |
| 34 def MakeNullableKind(self): | |
| 35 assert not self.is_nullable | |
| 36 | |
| 37 if self == STRING: | |
| 38 return NULLABLE_STRING | |
| 39 if self == HANDLE: | |
| 40 return NULLABLE_HANDLE | |
| 41 if self == DCPIPE: | |
| 42 return NULLABLE_DCPIPE | |
| 43 if self == DPPIPE: | |
| 44 return NULLABLE_DPPIPE | |
| 45 if self == MSGPIPE: | |
| 46 return NULLABLE_MSGPIPE | |
| 47 if self == SHAREDBUFFER: | |
| 48 return NULLABLE_SHAREDBUFFER | |
| 49 | |
| 50 nullable_kind = type(self)() | |
| 51 nullable_kind.shared_definition = self.shared_definition | |
| 52 if self.spec is not None: | |
| 53 nullable_kind.spec = '?' + self.spec | |
| 54 nullable_kind.is_nullable = True | |
| 55 | |
| 56 return nullable_kind | |
| 57 | |
| 58 @classmethod | |
| 59 def AddSharedProperty(cls, name): | |
| 60 """Adds a property |name| to |cls|, which accesses the corresponding item in | |
| 61 |shared_definition|. | |
| 62 | |
| 63 The reason of adding such indirection is to enable sharing definition | |
| 64 between a reference kind and its nullable variation. For example: | |
| 65 a = Struct('test_struct_1') | |
| 66 b = a.MakeNullableKind() | |
| 67 a.name = 'test_struct_2' | |
| 68 print b.name # Outputs 'test_struct_2'. | |
| 69 """ | |
| 70 def Get(self): | |
| 71 return self.shared_definition[name] | |
| 72 | |
| 73 def Set(self, value): | |
| 74 self.shared_definition[name] = value | |
| 75 | |
| 76 setattr(cls, name, property(Get, Set)) | |
| 77 | |
| 78 | |
| 79 # Initialize the set of primitive types. These can be accessed by clients. | |
| 80 BOOL = Kind('b') | |
| 81 INT8 = Kind('i8') | |
| 82 INT16 = Kind('i16') | |
| 83 INT32 = Kind('i32') | |
| 84 INT64 = Kind('i64') | |
| 85 UINT8 = Kind('u8') | |
| 86 UINT16 = Kind('u16') | |
| 87 UINT32 = Kind('u32') | |
| 88 UINT64 = Kind('u64') | |
| 89 FLOAT = Kind('f') | |
| 90 DOUBLE = Kind('d') | |
| 91 STRING = ReferenceKind('s') | |
| 92 HANDLE = ReferenceKind('h') | |
| 93 DCPIPE = ReferenceKind('h:d:c') | |
| 94 DPPIPE = ReferenceKind('h:d:p') | |
| 95 MSGPIPE = ReferenceKind('h:m') | |
| 96 SHAREDBUFFER = ReferenceKind('h:s') | |
| 97 NULLABLE_STRING = ReferenceKind('?s', True) | |
| 98 NULLABLE_HANDLE = ReferenceKind('?h', True) | |
| 99 NULLABLE_DCPIPE = ReferenceKind('?h:d:c', True) | |
| 100 NULLABLE_DPPIPE = ReferenceKind('?h:d:p', True) | |
| 101 NULLABLE_MSGPIPE = ReferenceKind('?h:m', True) | |
| 102 NULLABLE_SHAREDBUFFER = ReferenceKind('?h:s', True) | |
| 103 | |
| 104 | |
| 105 # Collection of all Primitive types | |
| 106 PRIMITIVES = ( | |
| 107 BOOL, | |
| 108 INT8, | |
| 109 INT16, | |
| 110 INT32, | |
| 111 INT64, | |
| 112 UINT8, | |
| 113 UINT16, | |
| 114 UINT32, | |
| 115 UINT64, | |
| 116 FLOAT, | |
| 117 DOUBLE, | |
| 118 STRING, | |
| 119 HANDLE, | |
| 120 DCPIPE, | |
| 121 DPPIPE, | |
| 122 MSGPIPE, | |
| 123 SHAREDBUFFER, | |
| 124 NULLABLE_STRING, | |
| 125 NULLABLE_HANDLE, | |
| 126 NULLABLE_DCPIPE, | |
| 127 NULLABLE_DPPIPE, | |
| 128 NULLABLE_MSGPIPE, | |
| 129 NULLABLE_SHAREDBUFFER | |
| 130 ) | |
| 131 | |
| 132 | |
| 133 class NamedValue(object): | |
| 134 def __init__(self, module, parent_kind, name): | |
| 135 self.module = module | |
| 136 self.namespace = module.namespace | |
| 137 self.parent_kind = parent_kind | |
| 138 self.name = name | |
| 139 self.imported_from = None | |
| 140 | |
| 141 def GetSpec(self): | |
| 142 return (self.namespace + '.' + | |
| 143 (self.parent_kind and (self.parent_kind.name + '.') or "") + | |
| 144 self.name) | |
| 145 | |
| 146 | |
| 147 class BuiltinValue(object): | |
| 148 def __init__(self, value): | |
| 149 self.value = value | |
| 150 | |
| 151 | |
| 152 class ConstantValue(NamedValue): | |
| 153 def __init__(self, module, parent_kind, constant): | |
| 154 NamedValue.__init__(self, module, parent_kind, constant.name) | |
| 155 self.constant = constant | |
| 156 | |
| 157 | |
| 158 class EnumValue(NamedValue): | |
| 159 def __init__(self, module, enum, field): | |
| 160 NamedValue.__init__(self, module, enum.parent_kind, field.name) | |
| 161 self.enum = enum | |
| 162 | |
| 163 def GetSpec(self): | |
| 164 return (self.namespace + '.' + | |
| 165 (self.parent_kind and (self.parent_kind.name + '.') or "") + | |
| 166 self.enum.name + '.' + self.name) | |
| 167 | |
| 168 | |
| 169 class Constant(object): | |
| 170 def __init__(self, name=None, kind=None, value=None): | |
| 171 self.name = name | |
| 172 self.kind = kind | |
| 173 self.value = value | |
| 174 | |
| 175 | |
| 176 class Field(object): | |
| 177 def __init__(self, name=None, kind=None, ordinal=None, default=None): | |
| 178 self.name = name | |
| 179 self.kind = kind | |
| 180 self.ordinal = ordinal | |
| 181 self.default = default | |
| 182 | |
| 183 | |
| 184 class Struct(ReferenceKind): | |
| 185 ReferenceKind.AddSharedProperty('name') | |
| 186 ReferenceKind.AddSharedProperty('module') | |
| 187 ReferenceKind.AddSharedProperty('imported_from') | |
| 188 ReferenceKind.AddSharedProperty('fields') | |
| 189 | |
| 190 def __init__(self, name=None, module=None): | |
| 191 if name is not None: | |
| 192 spec = 'x:' + name | |
| 193 else: | |
| 194 spec = None | |
| 195 ReferenceKind.__init__(self, spec) | |
| 196 self.name = name | |
| 197 self.module = module | |
| 198 self.imported_from = None | |
| 199 self.fields = [] | |
| 200 | |
| 201 def AddField(self, name, kind, ordinal=None, default=None): | |
| 202 field = Field(name, kind, ordinal, default) | |
| 203 self.fields.append(field) | |
| 204 return field | |
| 205 | |
| 206 | |
| 207 class Union(ReferenceKind): | |
| 208 ReferenceKind.AddSharedProperty('name') | |
| 209 ReferenceKind.AddSharedProperty('module') | |
| 210 ReferenceKind.AddSharedProperty('imported_from') | |
| 211 ReferenceKind.AddSharedProperty('fields') | |
| 212 | |
| 213 def __init__(self, name=None, module=None): | |
| 214 if name is not None: | |
| 215 spec = 'x:' + name | |
| 216 else: | |
| 217 spec = None | |
| 218 ReferenceKind.__init__(self, spec) | |
| 219 self.name = name | |
| 220 self.module = module | |
| 221 self.imported_from = None | |
| 222 self.fields = [] | |
| 223 | |
| 224 def AddField(self, name, kind, ordinal=None): | |
| 225 field = Field(name, kind, ordinal, default=None) | |
| 226 self.fields.append(field) | |
| 227 return field | |
| 228 | |
| 229 | |
| 230 class Array(ReferenceKind): | |
| 231 ReferenceKind.AddSharedProperty('kind') | |
| 232 ReferenceKind.AddSharedProperty('length') | |
| 233 | |
| 234 def __init__(self, kind=None, length=None): | |
| 235 if kind is not None: | |
| 236 if length is not None: | |
| 237 spec = 'a%d:%s' % (length, kind.spec) | |
| 238 else: | |
| 239 spec = 'a:%s' % kind.spec | |
| 240 | |
| 241 ReferenceKind.__init__(self, spec) | |
| 242 else: | |
| 243 ReferenceKind.__init__(self) | |
| 244 self.kind = kind | |
| 245 self.length = length | |
| 246 | |
| 247 | |
| 248 class Map(ReferenceKind): | |
| 249 ReferenceKind.AddSharedProperty('key_kind') | |
| 250 ReferenceKind.AddSharedProperty('value_kind') | |
| 251 | |
| 252 def __init__(self, key_kind=None, value_kind=None): | |
| 253 if (key_kind is not None and value_kind is not None): | |
| 254 ReferenceKind.__init__(self, | |
| 255 'm[' + key_kind.spec + '][' + value_kind.spec + | |
| 256 ']') | |
| 257 if IsNullableKind(key_kind): | |
| 258 raise Exception("Nullable kinds can not be keys in maps.") | |
| 259 if IsStructKind(key_kind): | |
| 260 # TODO(erg): It would sometimes be nice if we could key on struct | |
| 261 # values. However, what happens if the struct has a handle in it? Or | |
| 262 # non-copyable data like an array? | |
| 263 raise Exception("Structs can not be keys in maps.") | |
| 264 if IsAnyHandleKind(key_kind): | |
| 265 raise Exception("Handles can not be keys in maps.") | |
| 266 if IsArrayKind(key_kind): | |
| 267 raise Exception("Arrays can not be keys in maps.") | |
| 268 else: | |
| 269 ReferenceKind.__init__(self) | |
| 270 | |
| 271 self.key_kind = key_kind | |
| 272 self.value_kind = value_kind | |
| 273 | |
| 274 | |
| 275 class InterfaceRequest(ReferenceKind): | |
| 276 ReferenceKind.AddSharedProperty('kind') | |
| 277 | |
| 278 def __init__(self, kind=None): | |
| 279 if kind is not None: | |
| 280 if not isinstance(kind, Interface): | |
| 281 raise Exception( | |
| 282 "Interface request requires %r to be an interface." % kind.spec) | |
| 283 ReferenceKind.__init__(self, 'r:' + kind.spec) | |
| 284 else: | |
| 285 ReferenceKind.__init__(self) | |
| 286 self.kind = kind | |
| 287 | |
| 288 | |
| 289 class Parameter(object): | |
| 290 def __init__(self, name=None, kind=None, ordinal=None, default=None): | |
| 291 self.name = name | |
| 292 self.ordinal = ordinal | |
| 293 self.kind = kind | |
| 294 self.default = default | |
| 295 | |
| 296 | |
| 297 class Method(object): | |
| 298 def __init__(self, interface, name, ordinal=None): | |
| 299 self.interface = interface | |
| 300 self.name = name | |
| 301 self.ordinal = ordinal | |
| 302 self.parameters = [] | |
| 303 self.response_parameters = None | |
| 304 | |
| 305 def AddParameter(self, name, kind, ordinal=None, default=None): | |
| 306 parameter = Parameter(name, kind, ordinal, default) | |
| 307 self.parameters.append(parameter) | |
| 308 return parameter | |
| 309 | |
| 310 def AddResponseParameter(self, name, kind, ordinal=None, default=None): | |
| 311 if self.response_parameters == None: | |
| 312 self.response_parameters = [] | |
| 313 parameter = Parameter(name, kind, ordinal, default) | |
| 314 self.response_parameters.append(parameter) | |
| 315 return parameter | |
| 316 | |
| 317 | |
| 318 class Interface(ReferenceKind): | |
| 319 ReferenceKind.AddSharedProperty('module') | |
| 320 ReferenceKind.AddSharedProperty('name') | |
| 321 ReferenceKind.AddSharedProperty('imported_from') | |
| 322 ReferenceKind.AddSharedProperty('client') | |
| 323 ReferenceKind.AddSharedProperty('methods') | |
| 324 | |
| 325 def __init__(self, name=None, client=None, module=None): | |
| 326 if name is not None: | |
| 327 spec = 'x:' + name | |
| 328 else: | |
| 329 spec = None | |
| 330 ReferenceKind.__init__(self, spec) | |
| 331 self.module = module | |
| 332 self.name = name | |
| 333 self.imported_from = None | |
| 334 self.client = client | |
| 335 self.methods = [] | |
| 336 | |
| 337 def AddMethod(self, name, ordinal=None): | |
| 338 method = Method(self, name, ordinal=ordinal) | |
| 339 self.methods.append(method) | |
| 340 return method | |
| 341 | |
| 342 | |
| 343 class EnumField(object): | |
| 344 def __init__(self, name=None, value=None): | |
| 345 self.name = name | |
| 346 self.value = value | |
| 347 | |
| 348 | |
| 349 class Enum(Kind): | |
| 350 def __init__(self, name=None, module=None): | |
| 351 self.module = module | |
| 352 self.name = name | |
| 353 self.imported_from = None | |
| 354 if name is not None: | |
| 355 spec = 'x:' + name | |
| 356 else: | |
| 357 spec = None | |
| 358 Kind.__init__(self, spec) | |
| 359 self.fields = [] | |
| 360 | |
| 361 | |
| 362 class Module(object): | |
| 363 def __init__(self, name=None, namespace=None): | |
| 364 self.name = name | |
| 365 self.path = name | |
| 366 self.namespace = namespace | |
| 367 self.structs = [] | |
| 368 self.unions = [] | |
| 369 self.interfaces = [] | |
| 370 self.kinds = {} | |
| 371 | |
| 372 def AddInterface(self, name): | |
| 373 interface = Interface(name, module=self) | |
| 374 self.interfaces.append(interface) | |
| 375 return interface | |
| 376 | |
| 377 def AddStruct(self, name): | |
| 378 struct = Struct(name, module=self) | |
| 379 self.structs.append(struct) | |
| 380 return struct | |
| 381 | |
| 382 def AddUnion(self, name): | |
| 383 union = Union(name, module=self) | |
| 384 self.unions.append(union) | |
| 385 return union | |
| 386 | |
| 387 | |
| 388 def IsBoolKind(kind): | |
| 389 return kind.spec == BOOL.spec | |
| 390 | |
| 391 | |
| 392 def IsFloatKind(kind): | |
| 393 return kind.spec == FLOAT.spec | |
| 394 | |
| 395 | |
| 396 def IsStringKind(kind): | |
| 397 return kind.spec == STRING.spec or kind.spec == NULLABLE_STRING.spec | |
| 398 | |
| 399 | |
| 400 def IsHandleKind(kind): | |
| 401 return kind.spec == HANDLE.spec or kind.spec == NULLABLE_HANDLE.spec | |
| 402 | |
| 403 | |
| 404 def IsDataPipeConsumerKind(kind): | |
| 405 return kind.spec == DCPIPE.spec or kind.spec == NULLABLE_DCPIPE.spec | |
| 406 | |
| 407 | |
| 408 def IsDataPipeProducerKind(kind): | |
| 409 return kind.spec == DPPIPE.spec or kind.spec == NULLABLE_DPPIPE.spec | |
| 410 | |
| 411 | |
| 412 def IsMessagePipeKind(kind): | |
| 413 return kind.spec == MSGPIPE.spec or kind.spec == NULLABLE_MSGPIPE.spec | |
| 414 | |
| 415 | |
| 416 def IsSharedBufferKind(kind): | |
| 417 return (kind.spec == SHAREDBUFFER.spec or | |
| 418 kind.spec == NULLABLE_SHAREDBUFFER.spec) | |
| 419 | |
| 420 | |
| 421 def IsStructKind(kind): | |
| 422 return isinstance(kind, Struct) | |
| 423 | |
| 424 | |
| 425 def IsArrayKind(kind): | |
| 426 return isinstance(kind, Array) | |
| 427 | |
| 428 | |
| 429 def IsInterfaceKind(kind): | |
| 430 return isinstance(kind, Interface) | |
| 431 | |
| 432 | |
| 433 def IsInterfaceRequestKind(kind): | |
| 434 return isinstance(kind, InterfaceRequest) | |
| 435 | |
| 436 | |
| 437 def IsEnumKind(kind): | |
| 438 return isinstance(kind, Enum) | |
| 439 | |
| 440 | |
| 441 def IsReferenceKind(kind): | |
| 442 return isinstance(kind, ReferenceKind) | |
| 443 | |
| 444 | |
| 445 def IsNullableKind(kind): | |
| 446 return IsReferenceKind(kind) and kind.is_nullable | |
| 447 | |
| 448 | |
| 449 def IsMapKind(kind): | |
| 450 return isinstance(kind, Map) | |
| 451 | |
| 452 | |
| 453 def IsObjectKind(kind): | |
| 454 return (IsStructKind(kind) or IsArrayKind(kind) or IsStringKind(kind) or | |
| 455 IsMapKind(kind)) | |
| 456 | |
| 457 | |
| 458 def IsNonInterfaceHandleKind(kind): | |
| 459 return (IsHandleKind(kind) or | |
| 460 IsDataPipeConsumerKind(kind) or | |
| 461 IsDataPipeProducerKind(kind) or | |
| 462 IsMessagePipeKind(kind) or | |
| 463 IsSharedBufferKind(kind)) | |
| 464 | |
| 465 | |
| 466 def IsAnyHandleKind(kind): | |
| 467 return (IsNonInterfaceHandleKind(kind) or | |
| 468 IsInterfaceKind(kind) or | |
| 469 IsInterfaceRequestKind(kind)) | |
| 470 | |
| 471 | |
| 472 def IsMoveOnlyKind(kind): | |
| 473 return IsObjectKind(kind) or IsAnyHandleKind(kind) | |
| 474 | |
| 475 | |
| 476 def IsCloneableKind(kind): | |
| 477 def ContainsHandles(kind, visited_kinds): | |
| 478 if kind in visited_kinds: | |
| 479 # No need to examine the kind again. | |
| 480 return False | |
| 481 visited_kinds.add(kind) | |
| 482 if IsAnyHandleKind(kind): | |
| 483 return True | |
| 484 if IsArrayKind(kind): | |
| 485 return ContainsHandles(kind.kind, visited_kinds) | |
| 486 if IsStructKind(kind): | |
| 487 for field in kind.fields: | |
| 488 if ContainsHandles(field.kind, visited_kinds): | |
| 489 return True | |
| 490 return False | |
| 491 | |
| 492 return not ContainsHandles(kind, set()) | |
| 493 | |
| 494 | |
| 495 def HasCallbacks(interface): | |
| 496 for method in interface.methods: | |
| 497 if method.response_parameters != None: | |
| 498 return True | |
| 499 return False | |
| 500 | |
| OLD | NEW |