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 emitLineAndColumnNumbers bool = true |
| 23 |
| 24 // This variable may be set to false in order to omit emitting serialized |
| 25 // runtime type info. |
| 26 var emitSerializedRuntimeTypeInfo bool = true |
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 // emitLineAndColumnNumbers and emitSerializedRuntimeTypeInfo. |
| 43 func serialize(d *mojom.MojomDescriptor, debug, |
| 44 emitLineAndColumnNumbersParam, emitSerializedRuntimeTypeInfoParam bool)
(bytes []byte, debugString string, err error) { |
| 45 saveEmitLineAndColumnNumbers := emitLineAndColumnNumbers |
| 46 emitLineAndColumnNumbers = emitLineAndColumnNumbersParam |
| 47 saveEmitSerializedRuntimeTypeInfo := emitSerializedRuntimeTypeInfo |
| 48 emitSerializedRuntimeTypeInfo = emitSerializedRuntimeTypeInfoParam |
| 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 emitLineAndColumnNumbers = saveEmitLineAndColumnNumbers |
| 59 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 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 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 |