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 import mojom 6 7 # mojom_data provides a mechanism to turn mojom Modules to dictionaries and 8 # back again. This can be used to persist a mojom Module created progromatically 9 # or to read a dictionary from code or a file. 10 # Example: 11 # test_dict = { 12 # 'name': 'test', 13 # 'namespace': 'testspace', 14 # 'structs': [{ 15 # 'name': 'teststruct', 16 # 'fields': [ 17 # {'name': 'testfield1', 'kind': 'i32'}, 18 # {'name': 'testfield2', 'kind': 'a:i32', 'ordinal': 42}]}], 19 # 'interfaces': [{ 20 # 'name': 'Server', 21 # 'methods': [{ 22 # 'name': 'Foo', 23 # 'parameters': [{ 24 # 'name': 'foo', 'kind': 'i32'}, 25 # {'name': 'bar', 'kind': 'a:x:teststruct'}], 26 # 'ordinal': 42}]}] 27 # } 28 # test_module = mojom_data.ModuleFromData(test_dict) 29 30 31 # Used to create a subclass of str that supports sorting by index, to make 32 # pretty printing maintain the order. 33 def istr(index, string): 34 class IndexedString(str): 35 def __lt__(self, other): 36 return self.__index__ < other.__index__ 37 38 istr = IndexedString(string) 39 istr.__index__ = index 40 return istr 41 42 def KindToData(kind): 43 return kind.spec 44 45 def KindFromData(kinds, data): 46 if kinds.has_key(data): 47 return kinds[data] 48 if data.startswith('a:'): 49 kind = mojom.Array() 50 kind.kind = KindFromData(kinds, data[2:]) 51 else: 52 kind = mojom.Kind() 53 kind.spec = data 54 kinds[data] = kind 55 return kind 56 57 def StructToData(struct): 58 return { 59 istr(0, 'name'): struct.name, 60 istr(1, 'fields'): map(FieldToData, struct.fields) 61 } 62 63 def StructFromData(kinds, data): 64 struct = mojom.Struct() 65 struct.name = data['name'] 66 struct.spec = 'x:' + struct.name 67 kinds[struct.spec] = struct 68 struct.fields = map(lambda field: FieldFromData(kinds, field), data['fields']) 69 return struct 70 71 def FieldToData(field): 72 data = { 73 istr(0, 'name'): field.name, 74 istr(1, 'kind'): KindToData(field.kind) 75 } 76 if field.ordinal != None: 77 data[istr(2, 'ordinal')] = field.ordinal 78 if field.default != None: 79 data[istr(3, 'default')] = field.default 80 return data 81 82 def FieldFromData(kinds, data): 83 field = mojom.Field() 84 field.name = data['name'] 85 field.kind = KindFromData(kinds, data['kind']) 86 field.ordinal = data.get('ordinal') 87 field.default = data.get('default') 88 return field 89 90 def ParameterToData(parameter): 91 data = { 92 istr(0, 'name'): parameter.name, 93 istr(1, 'kind'): parameter.kind.spec 94 } 95 if parameter.ordinal != None: 96 data[istr(2, 'ordinal')] = parameter.ordinal 97 if parameter.default != None: 98 data[istr(3, 'default')] = parameter.default 99 return data 100 101 def ParameterFromData(kinds, data): 102 parameter = mojom.Parameter() 103 parameter.name = data['name'] 104 parameter.kind = KindFromData(kinds, data['kind']) 105 parameter.ordinal = data.get('ordinal') 106 parameter.default = data.get('default') 107 return parameter 108 109 def MethodToData(method): 110 data = { 111 istr(0, 'name'): method.name, 112 istr(1, 'parameters'): map(ParameterToData, method.parameters) 113 } 114 if method.ordinal != None: 115 data[istr(2, 'ordinal')] = method.ordinal 116 return data 117 118 def MethodFromData(kinds, data): 119 method = mojom.Method() 120 method.name = data['name'] 121 method.ordinal = data.get('ordinal') 122 method.default = data.get('default') 123 method.parameters = map( 124 lambda parameter: ParameterFromData(kinds, parameter), data['parameters']) 125 return method 126 127 def InterfaceToData(interface): 128 return { 129 istr(0, 'name'): interface.name, 130 istr(1, 'peer'): interface.peer, 131 istr(2, 'methods'): map(MethodToData, interface.methods) 132 } 133 134 def InterfaceFromData(kinds, data): 135 interface = mojom.Interface() 136 interface.name = data['name'] 137 interface.peer = data['peer'] 138 interface.methods = map( 139 lambda method: MethodFromData(kinds, method), data['methods']) 140 return interface 141 142 def EnumFieldFromData(kinds, data): 143 field = mojom.EnumField() 144 field.name = data['name'] 145 field.value = data['value'] 146 return field 147 148 def EnumFromData(kinds, data): 149 enum = mojom.Enum() 150 enum.name = data['name'] 151 enum.fields = map( 152 lambda field: EnumFieldFromData(kinds, field), data['fields']) 153 return enum 154 155 def ModuleToData(module): 156 return { 157 istr(0, 'name'): module.name, 158 istr(1, 'namespace'): module.namespace, 159 istr(2, 'structs'): map(StructToData, module.structs), 160 istr(3, 'interfaces'): map(InterfaceToData, module.interfaces) 161 } 162 163 def ModuleFromData(data): 164 kinds = {} 165 for kind in mojom.PRIMITIVES: 166 kinds[kind.spec] = kind 167 168 module = mojom.Module() 169 module.name = data['name'] 170 module.namespace = data['namespace'] 171 module.structs = map( 172 lambda struct: StructFromData(kinds, struct), data['structs']) 173 module.interfaces = map( 174 lambda interface: InterfaceFromData(kinds, interface), data['interfaces']) 175 module.enums = map( 176 lambda enum: EnumFromData(kinds, enum), data['enums']) 177 return module 178 179 def OrderedModuleFromData(data): 180 module = ModuleFromData(data) 181 next_interface_ordinal = 0 182 for interface in module.interfaces: 183 next_ordinal = 0 184 for method in interface.methods: 185 if method.ordinal is None: 186 method.ordinal = next_ordinal 187 next_ordinal = method.ordinal + 1 188 return module 189