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 |