github.com/alimy/mir/v4@v4.1.0/internal/generator/templates.go (about) 1 // Copyright 2020 Michael Li <alimy@gility.net>. All rights reserved. 2 // Use of this source code is governed by Apache License 2.0 that 3 // can be found in the LICENSE file. 4 5 package generator 6 7 import ( 8 "bytes" 9 "embed" 10 "fmt" 11 "reflect" 12 "strings" 13 "text/template" 14 15 "github.com/alimy/mir/v4/core" 16 "github.com/alimy/mir/v4/internal/reflex" 17 "github.com/alimy/mir/v4/internal/utils" 18 ) 19 20 //go:embed templates 21 var content embed.FS 22 23 // tmplInfos generator name map assets name 24 var tmplInfos = map[string]string{ 25 core.GeneratorGin: "templates/gin_iface.tmpl", 26 core.GeneratorChi: "templates/chi_iface.tmpl", 27 core.GeneratorMux: "templates/mux_iface.tmpl", 28 core.GeneratorHertz: "templates/hertz_iface.tmpl", 29 core.GeneratorEcho: "templates/echo_iface.tmpl", 30 core.GeneratorIris: "templates/iris_iface.tmpl", 31 core.GeneratorFiber: "templates/fiber_iface.tmpl", 32 core.GeneratorMacaron: "templates/macaron_iface.tmpl", 33 core.GeneratorHttpRouter: "templates/httprouter_iface.tmpl", 34 } 35 36 func templateFrom(name string) (*template.Template, error) { 37 tmplName, exist := tmplInfos[name] 38 if !exist { 39 return nil, fmt.Errorf("not exist templates for genererator:%s", name) 40 } 41 data, err := content.ReadFile(tmplName) 42 if err != nil { 43 return nil, err 44 } 45 t := template.New("mir").Funcs(template.FuncMap{ 46 "declareImports": declareImports, 47 "declareTypes": declareTypes, 48 "notEmptyStr": notEmptyStr, 49 "joinPath": joinPath, 50 "valideQuery": valideQuery, 51 "inflateQuery": inflateQuery, 52 "upperFirstName": upperFirstName, 53 }) 54 if tmpl, err := t.Parse(string(data)); err == nil { 55 return tmpl, nil 56 } else { 57 return nil, err 58 } 59 } 60 61 func notEmptyStr(s string) bool { 62 return s != "" 63 } 64 65 func joinPath(group, subpath string) string { 66 if group == "" { 67 return subpath 68 } 69 b := &strings.Builder{} 70 if !strings.HasPrefix(group, "/") { 71 b.WriteByte('/') 72 } 73 b.WriteString(group) 74 if !strings.HasSuffix(group, "/") && !strings.HasPrefix(subpath, "/") { 75 b.WriteByte('/') 76 } 77 b.WriteString(subpath) 78 return b.String() 79 } 80 81 func valideQuery(qs []string) bool { 82 size := len(qs) 83 return size != 0 && size%2 == 0 84 } 85 86 func inflateQuery(qs []string) string { 87 var b strings.Builder 88 last := len(qs) - 1 89 b.Grow(last * 10) 90 for _, s := range qs { 91 b.WriteRune('"') 92 b.WriteString(s) 93 b.WriteString(`",`) 94 } 95 return strings.TrimRight(b.String(), ",") 96 } 97 98 func upperFirstName(name string) string { 99 return utils.UpperFirst(strings.ToLower(name)) 100 } 101 102 func declareImports(imports map[string]string) string { 103 // write import declare to buffer 104 buf := &bytes.Buffer{} 105 for pkg, alias := range imports { 106 if alias != "" { 107 if _, err := buf.WriteString(alias + " "); err != nil { 108 break 109 } 110 } 111 if _, err := buf.WriteString(`"` + pkg + "\"\n"); err != nil { 112 break 113 } 114 } 115 return buf.String() 116 } 117 118 func declareTypes(inOuts []reflect.Type, pkgPath string, imports map[string]string) string { 119 if len(inOuts) == 0 { 120 return "" 121 } 122 var err error 123 124 // write types that in inOuts to buffer 125 indent := " " 126 buf := &bytes.Buffer{} 127 for _, t := range inOuts { 128 err := reflex.WriteStruct(buf, t, pkgPath, imports, indent) 129 if err != nil { 130 break 131 } 132 if _, err = buf.WriteString("\n"); err != nil { 133 break 134 } 135 } 136 if err != nil { 137 core.Logus("write declare types error: %s", err) 138 return "" 139 } 140 return buf.String() 141 }