1d0dae53ec566fa37e72f0c4411a5c014466a3db
[govpp.git] / binapigen / types.go
1 //  Copyright (c) 2020 Cisco and/or its affiliates.
2 //
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:
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
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.
14
15 package binapigen
16
17 import (
18         "fmt"
19         "strings"
20
21         "github.com/sirupsen/logrus"
22 )
23
24 // define api
25 const (
26         defineApiPrefix = "vl_api_"
27         defineApiSuffix = "_t"
28 )
29
30 // toApiType returns name that is used as type reference in VPP binary API
31 func toApiType(name string) string {
32         return defineApiPrefix + name + defineApiSuffix
33 }
34
35 func fromApiType(typ string) string {
36         name := typ
37         name = strings.TrimPrefix(name, defineApiPrefix)
38         name = strings.TrimSuffix(name, defineApiSuffix)
39         return name
40 }
41
42 const (
43         U8     = "u8"
44         I8     = "i8"
45         U16    = "u16"
46         I16    = "i16"
47         U32    = "u32"
48         I32    = "i32"
49         U64    = "u64"
50         I64    = "i64"
51         F64    = "f64"
52         BOOL   = "bool"
53         STRING = "string"
54 )
55
56 var BaseTypeSizes = map[string]int{
57         U8:     1,
58         I8:     1,
59         U16:    2,
60         I16:    2,
61         U32:    4,
62         I32:    4,
63         U64:    8,
64         I64:    8,
65         F64:    8,
66         BOOL:   1,
67         STRING: 1,
68 }
69
70 var BaseTypesGo = map[string]string{
71         U8:     "uint8",
72         I8:     "int8",
73         U16:    "uint16",
74         I16:    "int16",
75         U32:    "uint32",
76         I32:    "int32",
77         U64:    "uint64",
78         I64:    "int64",
79         F64:    "float64",
80         BOOL:   "bool",
81         STRING: "string",
82 }
83
84 func fieldActualType(field *Field) (actual string) {
85         switch {
86         case field.TypeAlias != nil:
87                 actual = field.TypeAlias.Type
88         case field.TypeEnum != nil:
89                 actual = field.TypeEnum.Type
90         default:
91                 actual = field.Type
92         }
93         return
94 }
95
96 func fieldGoType(g *GenFile, field *Field) string {
97         switch {
98         case field.TypeAlias != nil:
99                 return g.GoIdent(field.TypeAlias.GoIdent)
100         case field.TypeEnum != nil:
101                 return g.GoIdent(field.TypeEnum.GoIdent)
102         case field.TypeStruct != nil:
103                 return g.GoIdent(field.TypeStruct.GoIdent)
104         case field.TypeUnion != nil:
105                 return g.GoIdent(field.TypeUnion.GoIdent)
106         }
107         t, ok := BaseTypesGo[field.Type]
108         if !ok {
109                 logrus.Panicf("type %s is not base type", field.Type)
110         }
111         return t
112 }
113
114 func getFieldType(g *GenFile, field *Field) string {
115         gotype := fieldGoType(g, field)
116         if field.Array {
117                 switch gotype {
118                 case "uint8":
119                         return "[]byte"
120                 case "string":
121                         return "string"
122                 }
123                 if _, ok := BaseTypesGo[field.Type]; !ok && field.Length > 0 {
124                         return fmt.Sprintf("[%d]%s", field.Length, gotype)
125                 }
126                 return "[]" + gotype
127         }
128         return gotype
129 }
130
131 func getSizeOfBinapiTypeLength(typ string, length int) (size int) {
132         if n := BaseTypeSizes[typ]; n > 0 {
133                 if length > 0 {
134                         return n * length
135                 } else {
136                         return n
137                 }
138         }
139         return
140 }
141
142 func getSizeOfType(typ *Struct) (size int) {
143         for _, field := range typ.Fields {
144                 if enum := field.TypeEnum; enum != nil {
145                         size += getSizeOfBinapiTypeLength(enum.Type, field.Length)
146                         continue
147                 }
148                 size += getSizeOfBinapiTypeLength(field.Type, field.Length)
149         }
150         return size
151 }
152
153 func getUnionSize(union *Union) (maxSize int) {
154         for _, field := range union.Fields {
155                 if typ := field.TypeStruct; typ != nil {
156                         if size := getSizeOfType(typ); size > maxSize {
157                                 maxSize = size
158                         }
159                         continue
160                 }
161                 if alias := field.TypeAlias; alias != nil {
162                         if size := getSizeOfBinapiTypeLength(alias.Type, alias.Length); size > maxSize {
163                                 maxSize = size
164                         }
165                         continue
166                 } else {
167                         logrus.Panicf("no type or alias found for union %s field type %q", union.Name, field.Type)
168                 }
169         }
170         //logf("getUnionSize: %s %+v max=%v", union.Name, union.Fields, maxSize)
171         return
172 }