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 16class Kind(object): 17 def __init__(self, spec=None): 18 self.spec = spec 19 self.parent_kind = None 20 21 22class ReferenceKind(Kind): 23 """ReferenceKind represents pointer types and handle types. 24 A type is nullable means that NULL (for pointer types) or invalid handle 25 (for handle 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. 80BOOL = Kind('b') 81INT8 = Kind('i8') 82INT16 = Kind('i16') 83INT32 = Kind('i32') 84INT64 = Kind('i64') 85UINT8 = Kind('u8') 86UINT16 = Kind('u16') 87UINT32 = Kind('u32') 88UINT64 = Kind('u64') 89FLOAT = Kind('f') 90DOUBLE = Kind('d') 91STRING = ReferenceKind('s') 92HANDLE = ReferenceKind('h') 93DCPIPE = ReferenceKind('h:d:c') 94DPPIPE = ReferenceKind('h:d:p') 95MSGPIPE = ReferenceKind('h:m') 96SHAREDBUFFER = ReferenceKind('h:s') 97NULLABLE_STRING = ReferenceKind('?s', True) 98NULLABLE_HANDLE = ReferenceKind('?h', True) 99NULLABLE_DCPIPE = ReferenceKind('?h:d:c', True) 100NULLABLE_DPPIPE = ReferenceKind('?h:d:p', True) 101NULLABLE_MSGPIPE = ReferenceKind('?h:m', True) 102NULLABLE_SHAREDBUFFER = ReferenceKind('?h:s', True) 103 104 105# Collection of all Primitive types 106PRIMITIVES = ( 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 133class 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 147class BuiltinValue(object): 148 def __init__(self, value): 149 self.value = value 150 151 152class 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 158class 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 169class 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 176class 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 184class 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 207class Array(ReferenceKind): 208 ReferenceKind.AddSharedProperty('kind') 209 210 def __init__(self, kind=None): 211 if kind is not None: 212 ReferenceKind.__init__(self, 'a:' + kind.spec) 213 else: 214 ReferenceKind.__init__(self) 215 self.kind = kind 216 217 218class FixedArray(ReferenceKind): 219 ReferenceKind.AddSharedProperty('kind') 220 ReferenceKind.AddSharedProperty('length') 221 222 def __init__(self, length=-1, kind=None): 223 if kind is not None: 224 ReferenceKind.__init__(self, 'a%d:%s' % (length, kind.spec)) 225 else: 226 ReferenceKind.__init__(self) 227 self.kind = kind 228 self.length = length 229 230 231class InterfaceRequest(ReferenceKind): 232 ReferenceKind.AddSharedProperty('kind') 233 234 def __init__(self, kind=None): 235 if kind is not None: 236 ReferenceKind.__init__(self, 'r:' + kind.spec) 237 else: 238 ReferenceKind.__init__(self) 239 self.kind = kind 240 241 242class Parameter(object): 243 def __init__(self, name=None, kind=None, ordinal=None, default=None): 244 self.name = name 245 self.ordinal = ordinal 246 self.kind = kind 247 self.default = default 248 249 250class Method(object): 251 def __init__(self, interface, name, ordinal=None): 252 self.interface = interface 253 self.name = name 254 self.ordinal = ordinal 255 self.parameters = [] 256 self.response_parameters = None 257 258 def AddParameter(self, name, kind, ordinal=None, default=None): 259 parameter = Parameter(name, kind, ordinal, default) 260 self.parameters.append(parameter) 261 return parameter 262 263 def AddResponseParameter(self, name, kind, ordinal=None, default=None): 264 if self.response_parameters == None: 265 self.response_parameters = [] 266 parameter = Parameter(name, kind, ordinal, default) 267 self.response_parameters.append(parameter) 268 return parameter 269 270 271class Interface(ReferenceKind): 272 ReferenceKind.AddSharedProperty('module') 273 ReferenceKind.AddSharedProperty('name') 274 ReferenceKind.AddSharedProperty('imported_from') 275 ReferenceKind.AddSharedProperty('client') 276 ReferenceKind.AddSharedProperty('methods') 277 278 def __init__(self, name=None, client=None, module=None): 279 if name is not None: 280 spec = 'x:' + name 281 else: 282 spec = None 283 ReferenceKind.__init__(self, spec) 284 self.module = module 285 self.name = name 286 self.imported_from = None 287 self.client = client 288 self.methods = [] 289 290 def AddMethod(self, name, ordinal=None): 291 method = Method(self, name, ordinal=ordinal) 292 self.methods.append(method) 293 return method 294 295 296class EnumField(object): 297 def __init__(self, name=None, value=None): 298 self.name = name 299 self.value = value 300 301 302class Enum(Kind): 303 def __init__(self, name=None, module=None): 304 self.module = module 305 self.name = name 306 self.imported_from = None 307 if name is not None: 308 spec = 'x:' + name 309 else: 310 spec = None 311 Kind.__init__(self, spec) 312 self.fields = [] 313 314 315class Module(object): 316 def __init__(self, name=None, namespace=None): 317 self.name = name 318 self.path = name 319 self.namespace = namespace 320 self.structs = [] 321 self.interfaces = [] 322 323 def AddInterface(self, name): 324 self.interfaces.append(Interface(name, module=self)) 325 return interface 326 327 def AddStruct(self, name): 328 struct=Struct(name, module=self) 329 self.structs.append(struct) 330 return struct 331 332 333def IsBoolKind(kind): 334 return kind.spec == BOOL.spec 335 336 337def IsFloatKind(kind): 338 return kind.spec == FLOAT.spec 339 340 341def IsStringKind(kind): 342 return kind.spec == STRING.spec or kind.spec == NULLABLE_STRING.spec 343 344 345def IsHandleKind(kind): 346 return kind.spec == HANDLE.spec or kind.spec == NULLABLE_HANDLE.spec 347 348 349def IsDataPipeConsumerKind(kind): 350 return kind.spec == DCPIPE.spec or kind.spec == NULLABLE_DCPIPE.spec 351 352 353def IsDataPipeProducerKind(kind): 354 return kind.spec == DPPIPE.spec or kind.spec == NULLABLE_DPPIPE.spec 355 356 357def IsMessagePipeKind(kind): 358 return kind.spec == MSGPIPE.spec or kind.spec == NULLABLE_MSGPIPE.spec 359 360 361def IsSharedBufferKind(kind): 362 return (kind.spec == SHAREDBUFFER.spec or 363 kind.spec == NULLABLE_SHAREDBUFFER.spec) 364 365 366def IsStructKind(kind): 367 return isinstance(kind, Struct) 368 369 370def IsArrayKind(kind): 371 return isinstance(kind, Array) 372 373 374def IsFixedArrayKind(kind): 375 return isinstance(kind, FixedArray) 376 377 378def IsInterfaceKind(kind): 379 return isinstance(kind, Interface) 380 381 382def IsInterfaceRequestKind(kind): 383 return isinstance(kind, InterfaceRequest) 384 385 386def IsEnumKind(kind): 387 return isinstance(kind, Enum) 388 389 390def IsReferenceKind(kind): 391 return isinstance(kind, ReferenceKind) 392 393 394def IsNullableKind(kind): 395 return IsReferenceKind(kind) and kind.is_nullable 396 397 398def IsAnyArrayKind(kind): 399 return IsArrayKind(kind) or IsFixedArrayKind(kind) 400 401 402def IsObjectKind(kind): 403 return IsStructKind(kind) or IsAnyArrayKind(kind) or IsStringKind(kind) 404 405 406def IsNonInterfaceHandleKind(kind): 407 return (IsHandleKind(kind) or 408 IsDataPipeConsumerKind(kind) or 409 IsDataPipeProducerKind(kind) or 410 IsMessagePipeKind(kind) or 411 IsSharedBufferKind(kind)) 412 413 414def IsAnyHandleKind(kind): 415 return (IsNonInterfaceHandleKind(kind) or 416 IsInterfaceKind(kind) or 417 IsInterfaceRequestKind(kind)) 418 419 420def IsMoveOnlyKind(kind): 421 return IsObjectKind(kind) or IsAnyHandleKind(kind) 422 423 424def HasCallbacks(interface): 425 for method in interface.methods: 426 if method.response_parameters != None: 427 return True 428 return False 429 430