1 // Copyright (c) 2020 Cisco and/or its affiliates.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at:
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
23 "git.fd.io/govpp.git/binapigen/vppapi"
40 imports map[string]string
41 refmap map[string]string
44 func newFile(gen *Generator, apifile *vppapi.File) (*File, error) {
47 PackageName: sanitizedName(apifile.Name),
48 imports: make(map[string]string),
49 refmap: make(map[string]string),
52 sortFileObjects(&file.File)
54 for _, imp := range apifile.Imports {
55 file.Imports = append(file.Imports, normalizeImport(imp))
57 for _, enum := range apifile.EnumTypes {
58 file.Enums = append(file.Enums, newEnum(gen, file, enum))
60 for _, alias := range apifile.AliasTypes {
61 file.Aliases = append(file.Aliases, newAlias(gen, file, alias))
63 for _, structType := range apifile.StructTypes {
64 file.Structs = append(file.Structs, newStruct(gen, file, structType))
66 for _, union := range apifile.UnionTypes {
67 file.Unions = append(file.Unions, newUnion(gen, file, union))
69 for _, msg := range apifile.Messages {
70 file.Messages = append(file.Messages, newMessage(gen, file, msg))
76 func (file *File) isTypes() bool {
77 return strings.HasSuffix(file.File.Name, "_types")
80 func (file *File) hasService() bool {
81 return file.Service != nil && len(file.Service.RPCs) > 0
84 func (file *File) addRef(typ string, name string, ref interface{}) {
85 apiName := toApiType(name)
86 if _, ok := file.refmap[apiName]; ok {
87 logf("%s type %v already in refmap", typ, apiName)
90 file.refmap[apiName] = name
93 func (file *File) importedFiles(gen *Generator) []*File {
95 for _, imp := range file.Imports {
96 impFile, ok := gen.FilesByName[imp]
98 logf("file %s import %s not found API files", file.Name, imp)
101 files = append(files, impFile)
106 func (file *File) loadTypeImports(gen *Generator, typeFiles []*File) {
107 if len(typeFiles) == 0 {
110 for _, t := range file.Structs {
111 for _, imp := range typeFiles {
112 if _, ok := file.imports[t.Name]; ok {
115 for _, at := range imp.File.StructTypes {
116 if at.Name != t.Name {
119 if len(at.Fields) != len(t.Fields) {
122 file.imports[t.Name] = imp.PackageName
126 for _, t := range file.AliasTypes {
127 for _, imp := range typeFiles {
128 if _, ok := file.imports[t.Name]; ok {
131 for _, at := range imp.File.AliasTypes {
132 if at.Name != t.Name {
135 if at.Length != t.Length {
138 if at.Type != t.Type {
141 file.imports[t.Name] = imp.PackageName
145 for _, t := range file.EnumTypes {
146 for _, imp := range typeFiles {
147 if _, ok := file.imports[t.Name]; ok {
150 for _, at := range imp.File.EnumTypes {
151 if at.Name != t.Name {
154 if at.Type != t.Type {
157 file.imports[t.Name] = imp.PackageName
161 for _, t := range file.UnionTypes {
162 for _, imp := range typeFiles {
163 if _, ok := file.imports[t.Name]; ok {
166 for _, at := range imp.File.UnionTypes {
167 if at.Name != t.Name {
170 file.imports[t.Name] = imp.PackageName
171 /*if gen.ImportTypes {
185 func newEnum(gen *Generator, file *File, apitype vppapi.EnumType) *Enum {
188 GoName: camelCaseName(apitype.Name),
190 gen.enumsByName[fmt.Sprintf("%s.%s", file.Name, typ.Name)] = typ
191 file.addRef("enum", typ.Name, typ)
201 func newAlias(gen *Generator, file *File, apitype vppapi.AliasType) *Alias {
204 GoName: camelCaseName(apitype.Name),
206 gen.aliasesByName[fmt.Sprintf("%s.%s", file.Name, typ.Name)] = typ
207 file.addRef("alias", typ.Name, typ)
219 func newStruct(gen *Generator, file *File, apitype vppapi.StructType) *Struct {
222 GoName: camelCaseName(apitype.Name),
224 for _, fieldType := range apitype.Fields {
225 field := newField(gen, file, fieldType)
226 field.ParentStruct = typ
227 typ.Fields = append(typ.Fields, field)
229 gen.structsByName[fmt.Sprintf("%s.%s", file.Name, typ.Name)] = typ
230 file.addRef("struct", typ.Name, typ)
242 func newUnion(gen *Generator, file *File, apitype vppapi.UnionType) *Union {
245 GoName: camelCaseName(apitype.Name),
247 gen.unionsByName[fmt.Sprintf("%s.%s", file.Name, typ.Name)] = typ
248 for _, fieldType := range apitype.Fields {
249 field := newField(gen, file, fieldType)
250 field.ParentUnion = typ
251 typ.Fields = append(typ.Fields, field)
253 file.addRef("union", typ.Name, typ)
257 type Message struct {
265 func newMessage(gen *Generator, file *File, apitype vppapi.Message) *Message {
268 GoName: camelCaseName(apitype.Name),
270 for _, fieldType := range apitype.Fields {
271 field := newField(gen, file, fieldType)
272 field.ParentMessage = msg
273 msg.Fields = append(msg.Fields, field)
284 ParentMessage *Message
295 func newField(gen *Generator, file *File, apitype vppapi.Field) *Field {
298 GoName: camelCaseName(apitype.Name),
303 type Service = vppapi.Service
304 type RPC = vppapi.RPC
306 func sortFileObjects(file *vppapi.File) {
308 sort.SliceStable(file.Imports, func(i, j int) bool {
309 return file.Imports[i] < file.Imports[j]
312 sort.SliceStable(file.EnumTypes, func(i, j int) bool {
313 return file.EnumTypes[i].Name < file.EnumTypes[j].Name
316 sort.Slice(file.AliasTypes, func(i, j int) bool {
317 return file.AliasTypes[i].Name < file.AliasTypes[j].Name
320 sort.SliceStable(file.StructTypes, func(i, j int) bool {
321 return file.StructTypes[i].Name < file.StructTypes[j].Name
324 sort.SliceStable(file.UnionTypes, func(i, j int) bool {
325 return file.UnionTypes[i].Name < file.UnionTypes[j].Name
328 sort.SliceStable(file.Messages, func(i, j int) bool {
329 return file.Messages[i].Name < file.Messages[j].Name
332 if file.Service != nil {
333 sort.Slice(file.Service.RPCs, func(i, j int) bool {
335 if file.Service.RPCs[i].Stream != file.Service.RPCs[j].Stream {
336 return file.Service.RPCs[i].Stream
338 return file.Service.RPCs[i].RequestMsg < file.Service.RPCs[j].RequestMsg
343 func sanitizedName(name string) string {
354 func normalizeImport(imp string) string {
356 if idx := strings.Index(imp, "."); idx >= 0 {