OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package serialization | 5 package serialization |
6 | 6 |
7 import ( | 7 import ( |
8 "fmt" | 8 "fmt" |
9 "mojo/public/go/bindings" | 9 "mojo/public/go/bindings" |
10 "mojom/mojom_parser/generated/mojom_files" | 10 "mojom/mojom_parser/generated/mojom_files" |
11 "mojom/mojom_parser/generated/mojom_types" | 11 "mojom/mojom_parser/generated/mojom_types" |
12 "mojom/mojom_parser/mojom" | 12 "mojom/mojom_parser/mojom" |
13 myfmt "third_party/golang/src/fmt" | 13 myfmt "third_party/golang/src/fmt" |
14 ) | 14 ) |
15 | 15 |
16 ////////////////////////////////////////////////// | 16 ////////////////////////////////////////////////// |
17 /// Mojom Descriptor Serialization | 17 /// Mojom Descriptor Serialization |
18 ////////////////////////////////////////////////// | 18 ////////////////////////////////////////////////// |
19 | 19 |
20 // This variable may be set to false in order to omit emitting line and | 20 // This variable may be set to false in order to omit emitting line and |
21 // column numbers. | 21 // column numbers. |
22 var EmitLineAndColumnNumbers bool = true | 22 var g_emitLineAndColumnNumbers bool = true |
23 | |
24 // This variable may be set to false in order to omit emitting serialized | |
25 // runtime type info. | |
26 var g_emitSerializedRuntimeTypeInfo bool = true | |
azani
2016/02/11 22:21:05
change the param name and change back to emitSeria
rudominer
2016/02/11 22:56:51
Done.
| |
23 | 27 |
24 // Serialize serializes the MojomDescriptor into a binary form that is passed to the | 28 // Serialize serializes the MojomDescriptor into a binary form that is passed to the |
25 // backend of the compiler in order to invoke the code generators. | 29 // backend of the compiler in order to invoke the code generators. |
26 // To do this we use Mojo serialization. | 30 // To do this we use Mojo serialization. |
27 // If |debug| is true we also return a human-readable representation | 31 // If |debug| is true we also return a human-readable representation |
28 // of the serialized mojom_types.FileGraph. | 32 // of the serialized mojom_types.FileGraph. |
33 // This function is not thread safe. | |
29 func Serialize(d *mojom.MojomDescriptor, debug bool) (bytes []byte, debugString string, err error) { | 34 func Serialize(d *mojom.MojomDescriptor, debug bool) (bytes []byte, debugString string, err error) { |
35 return serialize(d, debug, true, true) | |
36 } | |
37 | |
38 // serialize() is a package-private version of the public method Serialize(). | |
39 // It is intended for use in tests because it allows setting of the variables | |
40 // emitLineAndColumnNumbers and emitSerializedRuntimeTypeInfo. | |
41 // This function is not thread safe because it accesses the global variables | |
42 // g_emitLineAndColumnNumbers and g_emitSerializedRuntimeTypeInfo. | |
43 func serialize(d *mojom.MojomDescriptor, debug, | |
44 emitLineAndColumnNumbers, emitSerializedRuntimeTypeInfo bool) (bytes []b yte, debugString string, err error) { | |
45 saveEmitLineAndColumnNumbers := g_emitLineAndColumnNumbers | |
46 g_emitLineAndColumnNumbers = emitLineAndColumnNumbers | |
47 savEemitSerializedRuntimeTypeInfo := g_emitSerializedRuntimeTypeInfo | |
azani
2016/02/11 22:21:05
saveEmit...
rudominer
2016/02/11 22:56:51
Done.
| |
48 g_emitSerializedRuntimeTypeInfo = emitSerializedRuntimeTypeInfo | |
49 | |
30 fileGraph := translateDescriptor(d) | 50 fileGraph := translateDescriptor(d) |
31 if debug { | 51 if debug { |
32 debugString = myfmt.Sprintf("%#v", fileGraph) | 52 debugString = myfmt.Sprintf("%#v", fileGraph) |
33 } | 53 } |
34 encoder := bindings.NewEncoder() | 54 encoder := bindings.NewEncoder() |
35 fileGraph.Encode(encoder) | 55 fileGraph.Encode(encoder) |
36 bytes, _, err = encoder.Data() | 56 bytes, _, err = encoder.Data() |
57 | |
58 g_emitLineAndColumnNumbers = saveEmitLineAndColumnNumbers | |
59 g_emitSerializedRuntimeTypeInfo = savEemitSerializedRuntimeTypeInfo | |
37 return | 60 return |
38 } | 61 } |
39 | 62 |
40 // translateDescriptor translates from a mojom.MojomDescriptor (the pure Go | 63 // translateDescriptor translates from a mojom.MojomDescriptor (the pure Go |
41 // representation used by the parser) to a mojom_files.MojomFileGraph (the | 64 // representation used by the parser) to a mojom_files.MojomFileGraph (the |
42 // Mojo Go representation used for serialization.) | 65 // Mojo Go representation used for serialization.) |
43 func translateDescriptor(d *mojom.MojomDescriptor) *mojom_files.MojomFileGraph { | 66 func translateDescriptor(d *mojom.MojomDescriptor) *mojom_files.MojomFileGraph { |
44 fileGraph := mojom_files.MojomFileGraph{} | 67 fileGraph := mojom_files.MojomFileGraph{} |
45 | 68 |
46 // Add |files| field. | |
47 fileGraph.Files = make(map[string]mojom_files.MojomFile) | |
48 for name, file := range d.MojomFilesByName { | |
49 fileGraph.Files[name] = translateMojomFile(file) | |
50 } | |
51 | |
52 // Add |resolved_types| field. | 69 // Add |resolved_types| field. |
53 fileGraph.ResolvedTypes = make(map[string]mojom_types.UserDefinedType) | 70 fileGraph.ResolvedTypes = make(map[string]mojom_types.UserDefinedType) |
54 for key, userDefinedType := range d.TypesByKey { | 71 for key, userDefinedType := range d.TypesByKey { |
55 fileGraph.ResolvedTypes[key] = translateUserDefinedType(userDefi nedType) | 72 fileGraph.ResolvedTypes[key] = translateUserDefinedType(userDefi nedType) |
56 } | 73 } |
57 | 74 |
58 // Add |resolved_values| field. | 75 // Add |resolved_values| field. |
59 fileGraph.ResolvedValues = make(map[string]mojom_types.UserDefinedValue) | 76 fileGraph.ResolvedValues = make(map[string]mojom_types.UserDefinedValue) |
60 for key, userDefinedValue := range d.ValuesByKey { | 77 for key, userDefinedValue := range d.ValuesByKey { |
61 fileGraph.ResolvedValues[key] = translateUserDefinedValue(userDe finedValue) | 78 fileGraph.ResolvedValues[key] = translateUserDefinedValue(userDe finedValue) |
62 } | 79 } |
63 | 80 |
81 // Add |files| field. | |
82 fileGraph.Files = make(map[string]mojom_files.MojomFile) | |
83 for name, file := range d.MojomFilesByName { | |
84 fileGraph.Files[name] = translateMojomFile(file, &fileGraph) | |
85 } | |
86 | |
64 return &fileGraph | 87 return &fileGraph |
65 } | 88 } |
66 | 89 |
67 // translateMojomFile translates from a mojom.MojomFile (the pure Go | 90 // translateMojomFile translates from a mojom.MojomFile (the pure Go |
68 // representation used by the parser) to a mojom_files.MojomFile (the | 91 // representation used by the parser) to a mojom_files.MojomFile (the |
69 // Mojo Go representation used for serialization.) | 92 // Mojo Go representation used for serialization.) |
70 func translateMojomFile(f *mojom.MojomFile) (file mojom_files.MojomFile) { | 93 func translateMojomFile(f *mojom.MojomFile, fileGraph *mojom_files.MojomFileGrap h) (file mojom_files.MojomFile) { |
71 // file_name field | 94 // file_name field |
72 file.FileName = f.CanonicalFileName | 95 file.FileName = f.CanonicalFileName |
73 | 96 |
74 // specified_file_name_field | 97 // specified_file_name_field |
75 file.SpecifiedFileName = &f.SpecifiedFileName | 98 file.SpecifiedFileName = &f.SpecifiedFileName |
76 | 99 |
77 // module_namespace field | 100 // module_namespace field |
78 file.ModuleNamespace = &f.ModuleNamespace.Identifier | 101 file.ModuleNamespace = &f.ModuleNamespace.Identifier |
79 | 102 |
80 // attributes field | 103 // attributes field |
81 if f.Attributes != nil { | 104 if f.Attributes != nil { |
82 file.Attributes = new([]mojom_types.Attribute) | 105 file.Attributes = new([]mojom_types.Attribute) |
83 for _, attr := range f.Attributes.List { | 106 for _, attr := range f.Attributes.List { |
84 *(file.Attributes) = append(*(file.Attributes), translat eMojomAttribute(&attr)) | 107 *(file.Attributes) = append(*(file.Attributes), translat eMojomAttribute(&attr)) |
85 } | 108 } |
86 } | 109 } |
87 | 110 |
88 // imports field | 111 // imports field |
89 if len(f.Imports) > 0 { | 112 if len(f.Imports) > 0 { |
90 file.Imports = new([]string) | 113 file.Imports = new([]string) |
91 for _, importName := range f.Imports { | 114 for _, importName := range f.Imports { |
92 *(file.Imports) = append(*(file.Imports), importName.Can onicalFileName) | 115 *(file.Imports) = append(*(file.Imports), importName.Can onicalFileName) |
93 } | 116 } |
94 } | 117 } |
95 | 118 |
96 » // declared_mojom_objects field... | 119 » // We will populate a RuntimeTypeInfo structure and then serialize it an d |
120 » // the serialized bytes will form the |serialized_runtime_type_info| fie ld | |
121 » // of the MojomFile. | |
122 » typeInfo := mojom_files.RuntimeTypeInfo{} | |
123 » typeInfo.ServicesByName = make(map[string]mojom_files.ServiceTypeInfo) | |
124 » typeInfo.TypeMap = make(map[string]mojom_types.UserDefinedType) | |
125 | |
126 » // We populate the declared_mojom_objects field | |
127 » // and simultaneously we populate typeInfo.TypeMap. | |
97 | 128 |
98 // Interfaces | 129 // Interfaces |
99 if f.Interfaces != nil && len(f.Interfaces) > 0 { | 130 if f.Interfaces != nil && len(f.Interfaces) > 0 { |
100 file.DeclaredMojomObjects.Interfaces = new([]string) | 131 file.DeclaredMojomObjects.Interfaces = new([]string) |
101 for _, intrfc := range f.Interfaces { | 132 for _, intrfc := range f.Interfaces { |
102 » » » *(file.DeclaredMojomObjects.Interfaces) = append(*(file. DeclaredMojomObjects.Interfaces), intrfc.TypeKey()) | 133 » » » typeKey := intrfc.TypeKey() |
134 » » » *(file.DeclaredMojomObjects.Interfaces) = append(*(file. DeclaredMojomObjects.Interfaces), typeKey) | |
135 | |
136 » » » addServiceTypeInfo(intrfc, &typeInfo) | |
137 » » » typeInfo.TypeMap[typeKey] = fileGraph.ResolvedTypes[type Key] | |
138 » » » if intrfc.Enums != nil { | |
139 » » » » // Add embedded enums to typeInfo.TypeMap. | |
140 » » » » for _, enum := range intrfc.Enums { | |
141 » » » » » typeKey := enum.TypeKey() | |
142 » » » » » typeInfo.TypeMap[typeKey] = fileGraph.Re solvedTypes[typeKey] | |
143 » » » » } | |
144 » » » } | |
103 } | 145 } |
104 } | 146 } |
105 | 147 |
106 // Structs | 148 // Structs |
107 if f.Structs != nil && len(f.Structs) > 0 { | 149 if f.Structs != nil && len(f.Structs) > 0 { |
108 file.DeclaredMojomObjects.Structs = new([]string) | 150 file.DeclaredMojomObjects.Structs = new([]string) |
109 for _, strct := range f.Structs { | 151 for _, strct := range f.Structs { |
110 » » » *(file.DeclaredMojomObjects.Structs) = append(*(file.Dec laredMojomObjects.Structs), strct.TypeKey()) | 152 » » » typeKey := strct.TypeKey() |
153 » » » *(file.DeclaredMojomObjects.Structs) = append(*(file.Dec laredMojomObjects.Structs), typeKey) | |
154 » » » typeInfo.TypeMap[typeKey] = fileGraph.ResolvedTypes[type Key] | |
155 » » » if strct.Enums != nil { | |
156 » » » » // Add embedded enums to typeInfo.TypeMap. | |
157 » » » » for _, enum := range strct.Enums { | |
158 » » » » » typeKey := enum.TypeKey() | |
159 » » » » » typeInfo.TypeMap[typeKey] = fileGraph.Re solvedTypes[typeKey] | |
160 » » » » } | |
161 » » » } | |
111 } | 162 } |
112 } | 163 } |
113 | 164 |
114 // Unions | 165 // Unions |
115 if f.Unions != nil && len(f.Unions) > 0 { | 166 if f.Unions != nil && len(f.Unions) > 0 { |
116 file.DeclaredMojomObjects.Unions = new([]string) | 167 file.DeclaredMojomObjects.Unions = new([]string) |
117 for _, union := range f.Unions { | 168 for _, union := range f.Unions { |
118 » » » *(file.DeclaredMojomObjects.Unions) = append(*(file.Decl aredMojomObjects.Unions), union.TypeKey()) | 169 » » » typeKey := union.TypeKey() |
170 » » » *(file.DeclaredMojomObjects.Unions) = append(*(file.Decl aredMojomObjects.Unions), typeKey) | |
171 » » » typeInfo.TypeMap[typeKey] = fileGraph.ResolvedTypes[type Key] | |
119 } | 172 } |
120 } | 173 } |
121 | 174 |
122 // TopLevelEnums | 175 // TopLevelEnums |
123 if f.Enums != nil && len(f.Enums) > 0 { | 176 if f.Enums != nil && len(f.Enums) > 0 { |
124 file.DeclaredMojomObjects.TopLevelEnums = new([]string) | 177 file.DeclaredMojomObjects.TopLevelEnums = new([]string) |
125 for _, enum := range f.Enums { | 178 for _, enum := range f.Enums { |
126 » » » *(file.DeclaredMojomObjects.TopLevelEnums) = append(*(fi le.DeclaredMojomObjects.TopLevelEnums), enum.TypeKey()) | 179 » » » typeKey := enum.TypeKey() |
180 » » » *(file.DeclaredMojomObjects.TopLevelEnums) = append(*(fi le.DeclaredMojomObjects.TopLevelEnums), typeKey) | |
181 » » » typeInfo.TypeMap[typeKey] = fileGraph.ResolvedTypes[type Key] | |
127 } | 182 } |
128 } | 183 } |
129 | 184 |
130 // TopLevelConstants | 185 // TopLevelConstants |
131 if f.Constants != nil && len(f.Constants) > 0 { | 186 if f.Constants != nil && len(f.Constants) > 0 { |
132 file.DeclaredMojomObjects.TopLevelConstants = new([]string) | 187 file.DeclaredMojomObjects.TopLevelConstants = new([]string) |
133 for _, constant := range f.Constants { | 188 for _, constant := range f.Constants { |
134 *(file.DeclaredMojomObjects.TopLevelConstants) = append( *(file.DeclaredMojomObjects.TopLevelConstants), constant.ValueKey()) | 189 *(file.DeclaredMojomObjects.TopLevelConstants) = append( *(file.DeclaredMojomObjects.TopLevelConstants), constant.ValueKey()) |
135 } | 190 } |
136 } | 191 } |
137 | 192 |
138 // TODO(rudominer) Do we need the EmbeddedEnums and EmbeddedConstants | 193 // TODO(rudominer) Do we need the EmbeddedEnums and EmbeddedConstants |
139 // fields in KeysByType. It seems these fields are not currently being | 194 // fields in KeysByType. It seems these fields are not currently being |
140 // used in mojom_translator.py. | 195 // used in mojom_translator.py. |
141 | 196 |
197 // SerializedRuntimeTypeInfo | |
198 if g_emitSerializedRuntimeTypeInfo { | |
199 encoder := bindings.NewEncoder() | |
200 typeInfo.Encode(encoder) | |
201 bytes, _, err := encoder.Data() | |
202 if err != nil { | |
203 panic(fmt.Sprintf("Error while serializing runtimeTypeIn fo: %s", err.Error())) | |
204 } | |
205 file.SerializedRuntimeTypeInfo = &bytes | |
206 } | |
207 | |
142 return | 208 return |
143 } | 209 } |
144 | 210 |
211 // addServiceTypeInfo will add a ServiceTypeInfo to the ServicesByName field of |typeInfo| corresponding | |
212 // to |intrfc| if |intrfc| is a top-level interface, meaning that it has a non-n il service name. In that | |
213 // case this method returns true. Otherwise this method will do nothing and retu rn fals. | |
214 func addServiceTypeInfo(intrfc *mojom.MojomInterface, typeInfo *mojom_files.Runt imeTypeInfo) (isTopLevel bool) { | |
215 isTopLevel = intrfc.ServiceName != nil | |
216 if isTopLevel { | |
217 serviceTypeInfo := mojom_files.ServiceTypeInfo{} | |
218 serviceTypeInfo.TopLevelInterface = intrfc.TypeKey() | |
219 serviceTypeInfo.CompleteTypeSet = intrfc.FindReachableTypes() | |
220 typeInfo.ServicesByName[*intrfc.ServiceName] = serviceTypeInfo | |
221 } | |
222 return | |
223 } | |
224 | |
145 // translateUserDefinedType translates from a mojom.UserDefinedType (the pure Go | 225 // translateUserDefinedType translates from a mojom.UserDefinedType (the pure Go |
146 // representation used by the parser) to a mojom_types.UserDefinedType (the | 226 // representation used by the parser) to a mojom_types.UserDefinedType (the |
147 // Mojo Go representation used for serialization.) | 227 // Mojo Go representation used for serialization.) |
148 func translateUserDefinedType(t mojom.UserDefinedType) mojom_types.UserDefinedTy pe { | 228 func translateUserDefinedType(t mojom.UserDefinedType) mojom_types.UserDefinedTy pe { |
149 switch p := t.(type) { | 229 switch p := t.(type) { |
150 case *mojom.MojomStruct: | 230 case *mojom.MojomStruct: |
151 return &mojom_types.UserDefinedTypeStructType{translateMojomStru ct(p)} | 231 return &mojom_types.UserDefinedTypeStructType{translateMojomStru ct(p)} |
152 case *mojom.MojomInterface: | 232 case *mojom.MojomInterface: |
153 return translateMojomInterface(p) | 233 return translateMojomInterface(p) |
154 case *mojom.MojomEnum: | 234 case *mojom.MojomEnum: |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
537 // in a different field. | 617 // in a different field. |
538 case *mojom.EnumValue: | 618 case *mojom.EnumValue: |
539 default: | 619 default: |
540 declData.ContainerTypeKey = stringPointer(containingType .TypeKey()) | 620 declData.ContainerTypeKey = stringPointer(containingType .TypeKey()) |
541 } | 621 } |
542 } | 622 } |
543 | 623 |
544 // source_file_info | 624 // source_file_info |
545 declData.SourceFileInfo = new(mojom_types.SourceFileInfo) | 625 declData.SourceFileInfo = new(mojom_types.SourceFileInfo) |
546 declData.SourceFileInfo.FileName = d.OwningFile().CanonicalFileName | 626 declData.SourceFileInfo.FileName = d.OwningFile().CanonicalFileName |
547 » if EmitLineAndColumnNumbers { | 627 » if g_emitLineAndColumnNumbers { |
548 declData.SourceFileInfo.LineNumber = d.LineNumber() | 628 declData.SourceFileInfo.LineNumber = d.LineNumber() |
549 declData.SourceFileInfo.ColumnNumber = d.ColumnNumber() | 629 declData.SourceFileInfo.ColumnNumber = d.ColumnNumber() |
550 } | 630 } |
551 return &declData | 631 return &declData |
552 } | 632 } |
553 | 633 |
554 // Returns nil if there are no contained declarations | 634 // Returns nil if there are no contained declarations |
555 func translateContainedDeclarations(container *mojom.NestedDeclarations) *mojom_ types.ContainedDeclarations { | 635 func translateContainedDeclarations(container *mojom.NestedDeclarations) *mojom_ types.ContainedDeclarations { |
556 if container.Enums == nil && container.Constants == nil { | 636 if container.Enums == nil && container.Constants == nil { |
557 return nil | 637 return nil |
(...skipping 20 matching lines...) Expand all Loading... | |
578 | 658 |
579 // stringPointer is a convenience function for creating a pointer to a string wh ose value | 659 // stringPointer is a convenience function for creating a pointer to a string wh ose value |
580 // is the specified string. It may be used in situations where the compiler will | 660 // is the specified string. It may be used in situations where the compiler will |
581 // not allow you to take the address of a string value directly, such as the | 661 // not allow you to take the address of a string value directly, such as the |
582 // return value of a function. It is necessary to create pointers to strings bec ause | 662 // return value of a function. It is necessary to create pointers to strings bec ause |
583 // that is how the Mojom type |string?| (i.e. nullable string) is represented in | 663 // that is how the Mojom type |string?| (i.e. nullable string) is represented in |
584 // in the Mojom Go bindings. | 664 // in the Mojom Go bindings. |
585 func stringPointer(s string) *string { | 665 func stringPointer(s string) *string { |
586 return &s | 666 return &s |
587 } | 667 } |
OLD | NEW |