github.com/vcilabs/webrpc@v0.5.2-0.20201116131534-162e27b1b33b/gen/golang/funcmap.go (about) 1 package golang 2 3 import ( 4 "errors" 5 "fmt" 6 "sort" 7 "strconv" 8 "strings" 9 10 "github.com/webrpc/webrpc/schema" 11 ) 12 13 var fieldTypeMap = map[schema.DataType]string{ 14 schema.T_Uint: "uint", 15 schema.T_Uint8: "uint8", 16 schema.T_Uint16: "uint16", 17 schema.T_Uint32: "uint32", 18 schema.T_Uint64: "uint64", 19 schema.T_Int: "int", 20 schema.T_Int8: "int8", 21 schema.T_Int16: "int16", 22 schema.T_Int32: "int32", 23 schema.T_Int64: "int64", 24 schema.T_Float32: "float32", 25 schema.T_Float64: "float64", 26 schema.T_String: "string", 27 schema.T_Timestamp: "time.Time", 28 schema.T_Null: "struct{}", 29 schema.T_Any: "interface{}", 30 schema.T_Byte: "byte", 31 schema.T_Bool: "bool", 32 } 33 34 func serviceMethodName(in schema.VarName) (string, error) { 35 s := string(in) 36 return "serve" + strings.ToUpper(s[0:1]) + s[1:], nil 37 } 38 39 func serviceMethodJSONName(in schema.VarName) (string, error) { 40 s := string(in) 41 return "serve" + strings.ToUpper(s[0:1]) + s[1:] + "JSON", nil 42 } 43 44 func newServerServiceName(in schema.VarName) (string, error) { 45 return "New" + string(in) + "Server", nil 46 } 47 48 func newClientServiceName(in schema.VarName) (string, error) { 49 return "New" + string(in) + "Client", nil 50 } 51 52 func fieldType(in *schema.VarType) (string, error) { 53 switch in.Type { 54 case schema.T_Map: 55 typK, ok := fieldTypeMap[in.Map.Key] 56 if !ok { 57 return "", fmt.Errorf("unknown type mapping %v", in.Map.Key) 58 } 59 typV, err := fieldType(in.Map.Value) 60 if err != nil { 61 return "", err 62 } 63 return fmt.Sprintf("map[%v]%s", typK, typV), nil 64 65 case schema.T_List: 66 z, err := fieldType(in.List.Elem) 67 if err != nil { 68 return "", err 69 } 70 return "[]" + z, nil 71 72 case schema.T_Struct: 73 return "*" + in.Struct.Name, nil 74 75 case schema.T_UserDefined: 76 return in.UserDefined.Name, nil 77 78 default: 79 if fieldTypeMap[in.Type] != "" { 80 return fieldTypeMap[in.Type], nil 81 } 82 } 83 return "", fmt.Errorf("could not represent type: %#v", in) 84 } 85 86 func fieldOptional(field *schema.MessageField) (string, error) { 87 if !field.Optional { 88 return "", nil 89 } 90 switch field.Type.Type { 91 case schema.T_Map: 92 return "", nil // noop 93 case schema.T_List: 94 return "", nil // noop 95 case schema.T_Struct: 96 return "", nil // noop because by default struct uses '*' prefix 97 default: 98 if fieldTypeMap[field.Type.Type] != "" { 99 return "*", nil 100 } 101 } 102 return "", fmt.Errorf("could not represent type: %#v", field) 103 } 104 105 func fieldTypeDef(in *schema.MessageField) (string, error) { 106 goFieldType := "" 107 108 meta := in.Meta 109 for kk := range meta { 110 for k, v := range meta[kk] { 111 if k == "go.field.type" { 112 goFieldType = fmt.Sprintf("%v", v) 113 } 114 } 115 } 116 117 if goFieldType != "" { 118 return goFieldType, nil 119 } 120 121 return fieldType(in.Type) 122 } 123 124 func fieldTags(in *schema.MessageField) (string, error) { 125 fieldTags := map[string]interface{}{} 126 127 jsonFieldName, err := downcaseName(in.Name) 128 if err != nil { 129 return "", err 130 } 131 fieldTags["json"] = fmt.Sprintf("%s", jsonFieldName) 132 133 goTagJSON := "" 134 135 meta := in.Meta 136 for kk := range meta { 137 for k, v := range meta[kk] { 138 139 switch { 140 case k == "json": 141 if goTagJSON == "" { 142 fieldTags["json"] = fmt.Sprintf("%v", v) 143 } 144 145 case strings.HasPrefix(k, "go.tag.json"): 146 goTagJSON = fmt.Sprintf("%v", v) 147 if !strings.HasPrefix(goTagJSON, fmt.Sprintf("%v", fieldTags["json"])) { 148 return "", errors.New("go.tag.json is invalid, it must match the json fieldname") 149 } 150 fieldTags[k[7:]] = fmt.Sprintf("%v", v) 151 152 case strings.HasPrefix(k, "go.tag."): 153 if k == "go.tag.json" { 154 goTagJSON = fmt.Sprintf("%v", v) 155 } 156 fieldTags[k[7:]] = fmt.Sprintf("%v", v) 157 } 158 159 } 160 } 161 162 tagKeys := []string{} 163 for k, _ := range fieldTags { 164 if k != "json" { 165 tagKeys = append(tagKeys, k) 166 } 167 } 168 sort.StringSlice(tagKeys).Sort() 169 tagKeys = append([]string{"json"}, tagKeys...) 170 171 tags := []string{} 172 for _, k := range tagKeys { 173 tags = append(tags, fmt.Sprintf(`%s:"%v"`, k, fieldTags[k])) 174 } 175 176 return "`" + strings.Join(tags, " ") + "`", nil 177 } 178 179 func constPathPrefix(in schema.VarName) (string, error) { 180 return string(in) + "PathPrefix", nil 181 } 182 183 func countMethods(in []*schema.Method) (string, error) { 184 return strconv.Itoa(len(in)), nil 185 } 186 187 func clientServiceName(in schema.VarName) (string, error) { 188 s := string(in) 189 return strings.ToLower(s[0:1]) + s[1:] + "Client", nil 190 } 191 192 func serverServiceName(in schema.VarName) (string, error) { 193 s := string(in) 194 return strings.ToLower(s[0:1]) + s[1:] + "Server", nil 195 } 196 197 func methodArgName(in *schema.MethodArgument) string { 198 name := string(in.Name) 199 if name == "" && in.Type != nil { 200 name = in.Type.String() 201 } 202 if name != "" { 203 return name 204 } 205 return "" 206 } 207 208 func methodArgType(in *schema.MethodArgument) string { 209 z, err := fieldType(in.Type) 210 if err != nil { 211 panic(err.Error()) 212 } 213 214 var prefix string 215 typ := in.Type.Type 216 217 if in.Optional { 218 prefix = "*" 219 } 220 if typ == schema.T_Struct { 221 prefix = "" // noop, as already pointer applied elsewhere 222 } 223 if typ == schema.T_List || typ == schema.T_Map { 224 prefix = "" 225 } 226 227 return prefix + z 228 } 229 230 func methodInputs(in []*schema.MethodArgument) (string, error) { 231 inputs := []string{"ctx context.Context"} 232 for i := range in { 233 inputs = append(inputs, fmt.Sprintf("%s %s", methodArgName(in[i]), methodArgType(in[i]))) 234 } 235 return strings.Join(inputs, ", "), nil 236 } 237 238 func methodOutputs(in []*schema.MethodArgument) (string, error) { 239 outputs := []string{} 240 for i := range in { 241 outputs = append(outputs, methodArgType(in[i])) 242 } 243 outputs = append(outputs, "error") 244 return strings.Join(outputs, ", "), nil 245 } 246 247 func methodArgNames(in []*schema.MethodArgument) (string, error) { 248 inputs := []string{} 249 for i := range in { 250 inputs = append(inputs, fmt.Sprintf("%s", methodArgName(in[i]))) 251 } 252 return strings.Join(inputs, ", "), nil 253 } 254 255 func argsList(in []*schema.MethodArgument, prefix string) (string, error) { 256 ins := []string{} 257 for i := range in { 258 ins = append(ins, fmt.Sprintf("%s%d", prefix, i)) 259 } 260 return strings.Join(ins, ", "), nil 261 } 262 263 func commaIfLen(in []*schema.MethodArgument) string { 264 if len(in) > 0 { 265 return "," 266 } 267 return "" 268 } 269 270 func isStruct(t schema.MessageType) bool { 271 return t == "struct" 272 } 273 274 func isAdvancedType(t schema.MessageType) bool { 275 return t == "advance" 276 } 277 278 func exportedField(in *schema.MessageField) (string, error) { 279 s := string(in.Name) 280 s = strings.ToUpper(s[0:1]) + s[1:] 281 282 nameTag := "go.field.name" 283 for k := range in.Meta { 284 for k, v := range in.Meta[k] { 285 if k == nameTag { 286 s = fmt.Sprintf("%v", v) 287 } 288 } 289 } 290 291 return s, nil 292 } 293 294 func downcaseName(v interface{}) (string, error) { 295 downFn := func(s string) string { 296 if s == "" { 297 return "" 298 } 299 return strings.ToLower(s[0:1]) + s[1:] 300 } 301 switch t := v.(type) { 302 case schema.VarName: 303 return downFn(string(t)), nil 304 case string: 305 return downFn(t), nil 306 default: 307 return "", errors.New("downcaseFieldName, unknown arg type") 308 } 309 } 310 311 func isEnum(t schema.MessageType) bool { 312 return t == "enum" 313 } 314 315 func hasFieldType(proto *schema.WebRPCSchema) func(fieldType string) (bool, error) { 316 return func(fieldType string) (bool, error) { 317 return proto.HasFieldType(fieldType) 318 } 319 } 320 321 func templateFuncMap(proto *schema.WebRPCSchema) map[string]interface{} { 322 return map[string]interface{}{ 323 "serviceMethodName": serviceMethodName, 324 "serviceMethodJSONName": serviceMethodJSONName, 325 "hasFieldType": hasFieldType(proto), 326 "fieldTags": fieldTags, 327 "fieldType": fieldType, 328 "fieldOptional": fieldOptional, 329 "fieldTypeDef": fieldTypeDef, 330 "newClientServiceName": newClientServiceName, 331 "newServerServiceName": newServerServiceName, 332 "constPathPrefix": constPathPrefix, 333 "countMethods": countMethods, 334 "clientServiceName": clientServiceName, 335 "serverServiceName": serverServiceName, 336 "methodInputs": methodInputs, 337 "methodOutputs": methodOutputs, 338 "methodArgName": methodArgName, 339 "methodArgType": methodArgType, 340 "methodArgNames": methodArgNames, 341 "argsList": argsList, 342 "commaIfLen": commaIfLen, 343 "isStruct": isStruct, 344 "isAdvancedType": isAdvancedType, 345 "isEnum": isEnum, 346 "exportedField": exportedField, 347 "downcaseName": downcaseName, 348 } 349 }